* [PATCH] 2.4: preempt-kernel for PPC
@ 2002-05-30 1:35 Robert Love
0 siblings, 0 replies; only message in thread
From: Robert Love @ 2002-05-30 1:35 UTC (permalink / raw)
To: linux-kernel; +Cc: kpreempt-tech
[-- Attachment #1: Type: text/plain, Size: 454 bytes --]
Attached patch provides preemptive kernel support for the PPC
architecture. This patch is against kernel 2.4.19-pre9 and is meant to
be applied on top of the standard preempt-kernel patch available from:
ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel
If all goes well I will integrate this into the next release of the
preempt-kernel patch.
Much thanks to MontaVista for providing this work to the community.
Enjoy,
Robert Love
[-- Attachment #2: preempt-kernel-ppc-rml-2.4.19-pre9-1.patch --]
[-- Type: text/x-patch, Size: 9943 bytes --]
diff -urN linux-2.4.19-pre9-preempt/arch/ppc/config.in linux/arch/ppc/config.in
--- linux-2.4.19-pre9-preempt/arch/ppc/config.in Wed May 29 18:31:26 2002
+++ linux/arch/ppc/config.in Wed May 29 18:32:00 2002
@@ -109,6 +109,8 @@
bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
fi
+bool 'Preemptible kernel support' CONFIG_PREEMPT
+
if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then
bool 'AltiVec Support' CONFIG_ALTIVEC
bool 'Thermal Management Support' CONFIG_TAU
diff -urN linux-2.4.19-pre9-preempt/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- linux-2.4.19-pre9-preempt/arch/ppc/kernel/entry.S Wed May 29 18:31:24 2002
+++ linux/arch/ppc/kernel/entry.S Wed May 29 18:32:00 2002
@@ -277,6 +277,41 @@
*/
cmpi 0,r3,0
beq restore
+#ifdef CONFIG_PREEMPT
+ lwz r3,PREEMPT_COUNT(r2)
+ cmpi 0,r3,1
+ bge ret_from_except
+ lwz r5,_MSR(r1)
+ andi. r5,r5,MSR_PR
+ bne do_signal_ret
+ lwz r5,NEED_RESCHED(r2)
+ cmpi 0,r5,0
+ beq ret_from_except
+ lis r3,irq_stat@h
+ ori r3,r3,irq_stat@l
+ lwz r5,4(r3)
+ lwz r3,8(r3)
+ add r3,r3,r5
+ cmpi 0,r3,0
+ bne ret_from_except
+ lwz r3,PREEMPT_COUNT(r2)
+ addi r3,r3,1
+ stw r3,PREEMPT_COUNT(r2)
+ mfmsr r0
+ ori r0,r0,MSR_EE
+ mtmsr r0
+ sync
+ bl preempt_schedule
+ mfmsr r0
+ rlwinm r0,r0,0,17,15
+ mtmsr r0
+ sync
+ lwz r3,PREEMPT_COUNT(r2)
+ subi r3,r3,1
+ stw r3,PREEMPT_COUNT(r2)
+ li r3,1
+ b ret_from_intercept
+#endif /* CONFIG_PREEMPT */
.globl ret_from_except
ret_from_except:
lwz r3,_MSR(r1) /* Returning to user mode? */
diff -urN linux-2.4.19-pre9-preempt/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- linux-2.4.19-pre9-preempt/arch/ppc/kernel/irq.c Wed May 29 18:31:24 2002
+++ linux/arch/ppc/kernel/irq.c Wed May 29 18:32:00 2002
@@ -568,6 +568,34 @@
return 1; /* lets ret_from_int know we can do checks */
}
+#ifdef CONFIG_PREEMPT
+int
+preempt_intercept(struct pt_regs *regs)
+{
+ int ret;
+
+ preempt_disable();
+
+ switch(regs->trap) {
+ case 0x500:
+ ret = do_IRQ(regs);
+ break;
+#ifndef CONFIG_4xx
+ case 0x900:
+#else
+ case 0x1000:
+#endif
+ ret = timer_interrupt(regs);
+ break;
+ default:
+ BUG();
+ }
+
+ preempt_enable();
+ return ret;
+}
+#endif /* CONFIG_PREEMPT */
+
unsigned long probe_irq_on (void)
{
return 0;
diff -urN linux-2.4.19-pre9-preempt/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c
--- linux-2.4.19-pre9-preempt/arch/ppc/kernel/mk_defs.c Wed May 29 18:31:24 2002
+++ linux/arch/ppc/kernel/mk_defs.c Wed May 29 18:32:00 2002
@@ -42,6 +42,9 @@
DEFINE(SIGPENDING, offsetof(struct task_struct, sigpending));
DEFINE(THREAD, offsetof(struct task_struct, thread));
DEFINE(MM, offsetof(struct task_struct, mm));
+#ifdef CONFIG_PREEMPT
+ DEFINE(PREEMPT_COUNT, offsetof(struct task_struct, preempt_count));
+#endif
DEFINE(ACTIVE_MM, offsetof(struct task_struct, active_mm));
DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct));
DEFINE(KSP, offsetof(struct thread_struct, ksp));
diff -urN linux-2.4.19-pre9-preempt/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- linux-2.4.19-pre9-preempt/arch/ppc/kernel/setup.c Wed May 29 18:31:24 2002
+++ linux/arch/ppc/kernel/setup.c Wed May 29 18:32:00 2002
@@ -504,6 +504,20 @@
parse_bootinfo();
+#ifdef CONFIG_PREEMPT
+ /* Override the irq routines for external & timer interrupts here,
+ * as the MMU has only been minimally setup at this point and
+ * there are no protections on page zero.
+ */
+ {
+ extern int preempt_intercept(struct pt_regs *);
+
+ do_IRQ_intercept = (unsigned long) &preempt_intercept;
+ timer_interrupt_intercept = (unsigned long) &preempt_intercept;
+
+ }
+#endif /* CONFIG_PREEMPT */
+
platform_init(r3, r4, r5, r6, r7);
if (ppc_md.progress)
diff -urN linux-2.4.19-pre9-preempt/arch/ppc/lib/dec_and_lock.c linux/arch/ppc/lib/dec_and_lock.c
--- linux-2.4.19-pre9-preempt/arch/ppc/lib/dec_and_lock.c Wed May 29 18:31:26 2002
+++ linux/arch/ppc/lib/dec_and_lock.c Wed May 29 18:32:00 2002
@@ -1,4 +1,5 @@
#include <linux/module.h>
+#include <linux/sched.h>
#include <linux/spinlock.h>
#include <asm/atomic.h>
#include <asm/system.h>
diff -urN linux-2.4.19-pre9-preempt/include/asm-ppc/dma.h linux/include/asm-ppc/dma.h
--- linux-2.4.19-pre9-preempt/include/asm-ppc/dma.h Wed May 29 18:30:31 2002
+++ linux/include/asm-ppc/dma.h Wed May 29 18:32:00 2002
@@ -14,6 +14,7 @@
#include <linux/config.h>
#include <asm/io.h>
#include <linux/spinlock.h>
+#include <linux/sched.h>
#include <asm/system.h>
/*
diff -urN linux-2.4.19-pre9-preempt/include/asm-ppc/hardirq.h linux/include/asm-ppc/hardirq.h
--- linux-2.4.19-pre9-preempt/include/asm-ppc/hardirq.h Wed May 29 18:30:31 2002
+++ linux/include/asm-ppc/hardirq.h Wed May 29 18:32:00 2002
@@ -44,6 +44,7 @@
#define hardirq_exit(cpu) (local_irq_count(cpu)--)
#define synchronize_irq() do { } while (0)
+#define release_irqlock(cpu) do { } while (0)
#else /* CONFIG_SMP */
diff -urN linux-2.4.19-pre9-preempt/include/asm-ppc/highmem.h linux/include/asm-ppc/highmem.h
--- linux-2.4.19-pre9-preempt/include/asm-ppc/highmem.h Wed May 29 18:30:31 2002
+++ linux/include/asm-ppc/highmem.h Wed May 29 18:32:00 2002
@@ -84,6 +84,7 @@
unsigned int idx;
unsigned long vaddr;
+ preempt_disable();
if (page < highmem_start_page)
return page_address(page);
@@ -105,8 +106,10 @@
unsigned long vaddr = (unsigned long) kvaddr;
unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
- if (vaddr < KMAP_FIX_BEGIN) // FIXME
+ if (vaddr < KMAP_FIX_BEGIN) { // FIXME
+ preempt_enable();
return;
+ }
if (vaddr != KMAP_FIX_BEGIN + idx * PAGE_SIZE)
BUG();
@@ -118,6 +121,7 @@
pte_clear(kmap_pte+idx);
flush_tlb_page(0, vaddr);
#endif
+ preempt_enable();
}
#endif /* __KERNEL__ */
diff -urN linux-2.4.19-pre9-preempt/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
--- linux-2.4.19-pre9-preempt/include/asm-ppc/mmu_context.h Wed May 29 18:30:31 2002
+++ linux/include/asm-ppc/mmu_context.h Wed May 29 18:32:00 2002
@@ -158,6 +158,10 @@
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk, int cpu)
{
+#ifdef CONFIG_PREEMPT
+ if (preempt_get_count() == 0)
+ BUG();
+#endif
tsk->thread.pgdir = next->pgd;
get_mmu_context(next);
set_context(next->context, next->pgd);
diff -urN linux-2.4.19-pre9-preempt/include/asm-ppc/pgalloc.h linux/include/asm-ppc/pgalloc.h
--- linux-2.4.19-pre9-preempt/include/asm-ppc/pgalloc.h Wed May 29 18:30:31 2002
+++ linux/include/asm-ppc/pgalloc.h Wed May 29 18:32:00 2002
@@ -68,20 +68,25 @@
{
unsigned long *ret;
+ preempt_disable();
if ((ret = pgd_quicklist) != NULL) {
pgd_quicklist = (unsigned long *)(*ret);
ret[0] = 0;
pgtable_cache_size--;
+ preempt_enable();
} else
+ preempt_enable();
ret = (unsigned long *)get_pgd_slow();
return (pgd_t *)ret;
}
extern __inline__ void free_pgd_fast(pgd_t *pgd)
{
+ preempt_disable();
*(unsigned long **)pgd = pgd_quicklist;
pgd_quicklist = (unsigned long *) pgd;
pgtable_cache_size++;
+ preempt_enable();
}
extern __inline__ void free_pgd_slow(pgd_t *pgd)
@@ -120,19 +125,23 @@
{
unsigned long *ret;
+ preempt_disable();
if ((ret = pte_quicklist) != NULL) {
pte_quicklist = (unsigned long *)(*ret);
ret[0] = 0;
pgtable_cache_size--;
}
+ preempt_enable();
return (pte_t *)ret;
}
extern __inline__ void pte_free_fast(pte_t *pte)
{
+ preempt_disable();
*(unsigned long **)pte = pte_quicklist;
pte_quicklist = (unsigned long *) pte;
pgtable_cache_size++;
+ preempt_enable();
}
extern __inline__ void pte_free_slow(pte_t *pte)
diff -urN linux-2.4.19-pre9-preempt/include/asm-ppc/smplock.h linux/include/asm-ppc/smplock.h
--- linux-2.4.19-pre9-preempt/include/asm-ppc/smplock.h Wed May 29 18:30:31 2002
+++ linux/include/asm-ppc/smplock.h Wed May 29 18:32:00 2002
@@ -15,7 +15,15 @@
extern spinlock_t kernel_flag;
+#ifdef CONFIG_SMP
#define kernel_locked() spin_is_locked(&kernel_flag)
+#else
+#ifdef CONFIG_PREEMPT
+#define kernel_locked() preempt_get_count()
+#else
+#define kernel_locked() 1
+#endif
+#endif
/*
* Release global kernel lock and global interrupt lock
@@ -47,8 +55,14 @@
*/
static __inline__ void lock_kernel(void)
{
+#ifdef CONFIG_PREEMPT
+ if (current->lock_depth == -1)
+ spin_lock(&kernel_flag);
+ ++current->lock_depth;
+#else
if (!++current->lock_depth)
spin_lock(&kernel_flag);
+#endif
}
static __inline__ void unlock_kernel(void)
diff -urN linux-2.4.19-pre9-preempt/include/asm-ppc/softirq.h linux/include/asm-ppc/softirq.h
--- linux-2.4.19-pre9-preempt/include/asm-ppc/softirq.h Wed May 29 18:30:31 2002
+++ linux/include/asm-ppc/softirq.h Wed May 29 18:32:00 2002
@@ -10,6 +10,7 @@
#define local_bh_disable() \
do { \
+ preempt_disable(); \
local_bh_count(smp_processor_id())++; \
barrier(); \
} while (0)
@@ -18,9 +19,10 @@
do { \
barrier(); \
local_bh_count(smp_processor_id())--; \
+ preempt_enable(); \
} while (0)
-#define local_bh_enable() \
+#define _local_bh_enable() \
do { \
if (!--local_bh_count(smp_processor_id()) \
&& softirq_pending(smp_processor_id())) { \
@@ -28,6 +30,12 @@
} \
} while (0)
+#define local_bh_enable() \
+do { \
+ _local_bh_enable(); \
+ preempt_enable(); \
+} while (0)
+
#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
#endif /* __ASM_SOFTIRQ_H */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2002-05-30 1:35 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-05-30 1:35 [PATCH] 2.4: preempt-kernel for PPC Robert Love
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®