mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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®