Preemptible kernel for SH
PATCH 1/1 Preemptible kernel for SH
The attached is the fully preemptible linux kernel patch, for the SH arch. This work is thanks to Jeremy Siegel of MontaVista.
You will need an SH-patched kernel tree, available from
http://sf.net/projects/linuxsh -- the CVS module "linux" has a drop-in replacement for 2.4.16.
You will need the base preempt-kernel patch, available from ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel
Feedback is desired.
Robert Love
arch/sh/config.in +2 -0
@@ -124,6 +124,8 @@ hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 hex 'Physical memory size' CONFIG_MEMORY_SIZE 00400000 fi +# Preemptible kernel feature +bool 'Preemptible Kernel' CONFIG_PREEMPT endmenu if [ "$CONFIG_SH_HP690" = "y" ]; then
arch/sh/kernel/entry.S +97 -7
150 lines not on this page · raw message
arch/sh/kernel/irq.c +21 -0
@@ -229,6 +229,16 @@struct irqaction * action;unsigned int status; +#ifdef CONFIG_PREEMPT +/* +* At this point we're now about to actually call handlers, +* and interrupts might get reenabled during them... bump +* preempt_count to prevent any preemption while the handler +* called here is pending... +*/ + current->preempt_count +=1 ; +#endif /* CONFIG_PREEMPT */ +/* Get IRQ number */ asmvolatile ("stc r2_bank, %0\n\t" "shlr2 %0\n\t"
@@ -298,8 +308,19 @@ desc->handler->end (irq);spin_unlock (&desc->lock); +if (softirq_pending (cpu))do_softirq (); + +#ifdef CONFIG_PREEMPT +/* +* We're done with the handlers, interrupts should be +* currently disabled; decrement preempt_count now so +* as we return preemption may be allowed... +*/ + current->preempt_count -=1 ; +#endif /* CONFIG_PREEMPT */ +return 1 ; }
include/asm-sh/hardirq.h +2 -0
@@ -34,6 +34,8 @@#define synchronize_irq () barrier() +#define release_irqlock (cpu) do { } while (0) +#else #error Super-H SMP is not available
include/asm-sh/mmu_context.h +4 -0
@@ -166,6 +166,10 @@struct mm_struct *next, struct task_struct *tsk, unsigned int cpu) { +#ifdef CONFIG_PREEMPT + if (preempt_is_disabled() == 0) + BUG(); +#endif if (prev != next) {unsigned long __pgdir = (unsigned long )next->pgd;
include/asm-sh/smplock.h +79 -6
94 lines not on this page · raw message
include/asm-sh/softirq.h +3 -0
@@ -6,6 +6,7 @@#define local_bh_disable () \ do { \ + preempt_disable(); \ local_bh_count(smp_processor_id())++; \ barrier(); \ } while (0)
@@ -14,6 +15,7 @@do { \barrier (); \local_bh_count (smp_processor_id ())--; \ +preempt_enable (); \ } while (0)#define local_bh_enable () \
@@ -22,6 +24,7 @@if (!--local_bh_count (smp_processor_id ()) \ &&softirq_pending (smp_processor_id ())) { \do_softirq (); \ +preempt_enable (); \ } \ }while (0 )
ftp://ftp.kernel.org/pub/linux/kernel/people/rml/sh/sh-update-rml-2.4.16-1.patch
I went ahead and diffed 2.4.16 against the SH tree. Thus you can patch 2.4.16 directly without checking into CVS. Hopefully this might encourage some testers.
ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel/v2.4/preempt-kernel-rml-2.4.16-1.patch
ftp://ftp.kernel.org/pub/linux/kernel/people/rml/sh/preempt-kernel-sh-2.4.16-1.patch
The above is links to the preempt-kernel patch and the arch-sh specific work.
Users need to patch 2.4.16 with the three patches above and enable CONFIG_PREEMPT to create the preemptible kernel for SH.
Robert Love
Quoted 8 lines · Jeremy Siegel
Just FYI... the preemptible kernel depends on non-preemptible critical regions denoted by spinlock calls (see Robert Love's excellent summary in
Documentation/preempt-locking.txt). Many common drivers are assumed to have correct locking for SMP operation, but non-SMP drivers may not. I've only run the PreK SH kernel on the Solution Engine w/Ethernet and serial, but I did not yet check to see if additional locks might be required indrivers/char/sh-sci.cordrivers/net/stnic.c, which are specific to SH platforms and thus not SMP-safe otherwise.
Ahh, good point. Similar situation occured on ARM when it went preemptive. Thankfully, Russel King and company try to properly lock things even if they are no ops.
Coding under a preemptive kernel means more than what Documentation/preempt-locking.txt implies ... you have to protect data regions as if you are operating under SMP.
It is good practice, anyhow.
This means you can include linux/spinlock.h and use the locking constructs as needed. Under a normal UP kernel, they will compile away. Under a preemptive kernel, they will provide the needed reentrancy protection. If there ever is a an SMP SH kernel (or something like it) the kernel will be ready for the future.
Robert Love
Just FYI... the preemptible kernel depends on non-preemptible critical regions denoted by spinlock calls (see Robert Love's excellent summary in Documentation/preempt-locking.txt). Many common drivers are assumed to have correct locking for SMP operation, but non-SMP drivers may not. I've only run the PreK SH kernel on the Solution Engine w/Ethernet and serial, but I did not yet check to see if additional locks might be required in drivers/char/sh-sci.c or drivers/net/stnic.c, which are specific to SH platforms and thus not SMP-safe otherwise.
--Jeremy
Quoted 13 lines · Robert Love
The attached is the fully preemptible linux kernel patch, for the SH arch. This work is thanks to Jeremy Siegel of MontaVista.
You will need an SH-patched kernel tree, available from
http://sf.net/projects/linuxsh -- the CVS module "linux" has a drop-in replacement for 2.4.16.You will need the base preempt-kernel patch, available from ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel
Feedback is desired.
Robert Love
Users of gcc-3.x will need the attached patch _for gcc_ to compile an SH kernel patched with preempt-kernel. This is _not_ our fault, it is a gcc bug and is now merged into CVS and should be part of gcc-3.1.
gcc-2.9x compiles without problem. It is only 3.x versions that suffer the bug.
Robert Love
P.S. Also of note: yes this works on Sega Dreamcast. You can have a fully preemptible Dreamcast. Impress your friends. Or something.
gcc/alias.c +9 -0
@@ -1041,6 +1041,9 @@/* Some RTL can be compared without a recursive examination. */ switch (code) { +case VALUE : +return CSELIB_VAL_PTR (x) ==CSELIB_VAL_PTR (y); +case REG :return REGNO (x) ==REGNO (y);
@@ -1109,6 +1112,12 @@if (rtx_equal_for_memref_p (XEXP (x, i),XEXP (y, i)) ==0 )return 0 ;break ; + +/* This can happen for asm operands. */ +case 's' : +if (strcmp (XSTR (x, i),XSTR (y, i))) +return 0 ; +break ;/* This can happen for an asm which clobbers memory. */ case '0' :