generic irq subsystem, description
Subsystems (4)
cover generic irq subsystem, description
this is a new release of the generic irq handling subsystem, against 2.6.9-rc3. This snapshot includes new ppc and ppc64 support written and tested by Christoph Hellwig.
the core bits were reworked quite significantly. Changes:
- split up kernel/hardirq.c into individual files in kernel/irq/
- 80-90% of each converted architecture's irq.c file is now eliminated by this patch. The most dramatic one is x64's irq.c - a mere 108 lines remained. The total effect on the 4 architectures covered so
far: more than 3000 lines of irq.c code removed while kernel/irq/*.c remains around 1000 lines of code.
- more irq.h, interrupt.h, asm/hardirq.h and linux/hardirq.h consolidation from Christoph and me.
- thorough cleanup of the generic irq code.
- compile-testing of the following architectures: x86, x64, ppc64, ppc, ia64, s390, s390x. The first four were boot-tested as well.
there are 5 patches that will follow in the next 5 mails:
generic-hardirqs-core.patch
generic-hardirqs-x86.patch
generic-hardirqs-x64.patch
generic-hardirqs-ppc.patch
generic-hardirqs-ppc64.patch
note that it is still a goal of the patchset to not break the building of any non-CONFIG_GENERIC_HARDIRQS platform - 3 such platforms were compile-tested.
comments welcome,
Ingo
PATCH 1/5 generic irq subsystem, core
core bits of generic hardirqs.
kernel/irq/proc.c renamed from kernel/irq/proc.c.orig +183 -0
@@ -0,0 +1,183 @@ +/* +* linux/kernel/irq/proc.c +* +* Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar +* +* This file contains the /proc/irq/ handling code. +*/ + +#include <linux/irq.h> +#include <linux/proc_fs.h> +#include <linux/interrupt.h> + +unsigned long prof_cpu_mask =-1 ; + +static struct proc_dir_entry *root_irq_dir, *irq_dir[NR_IRQS ]; + +#ifdef CONFIG_SMP + +/* +* The /proc/irq/<irq>/smp_affinity values: +*/ +static struct proc_dir_entry *smp_affinity_entry[NR_IRQS ]; + +cpumask_t irq_affinity[NR_IRQS ] = { [0 ...NR_IRQS -1 ] =CPU_MASK_ALL }; + +static int irq_affinity_read_proc (char *page,char **start,off_t off, +int count,int *eof,void *data) +{ +int len =cpumask_scnprintf (page, count, irq_affinity[(long )data]); + +if (count - len <2 ) +return -EINVAL ; + len +=sprintf (page + len,"\n" ); +return len; +} + +static int irq_affinity_write_proc (struct file *file,const char __user *buffer, +unsigned long count,void *data) +{ +unsigned int irq = (int )(long )data, full_count = count, err; +cpumask_t new_value, tmp; + +if (!irq_desc[irq].handler->set_affinity) +return -EIO ; + + err =cpumask_parse (buffer, count, new_value); +if (err) +return err; + +/* +* Do not allow disabling IRQs completely - it's a too easy +* way to make the system unusable accidentally :-) At least +* one online CPU still has to be targeted. +*/ +cpus_and (tmp, new_value, cpu_online_map); +if (cpus_empty (tmp)) +return -EINVAL ; + + irq_affinity[irq] = new_value; + irq_desc[irq].handler->set_affinity (irq, +cpumask_of_cpu (first_cpu (new_value))); + +return full_count; +} + +#endif + +static int prof_cpu_mask_read_proc (char *page,char **start,off_t off, +int count,int *eof,void *data) +{ +int len =cpumask_scnprintf (page, count, *(cpumask_t *)data); + +if (count - len <2 ) +return -EINVAL ; + len +=sprintf (page + len,"\n" ); +return len; +} + +static int prof_cpu_mask_write_proc (struct file *file, +const char __user *buffer, +unsigned long count,void *data) +{ +unsigned long full_count = count, err; +cpumask_t *mask = (cpumask_t *)data; +cpumask_t new_value; + + err =cpumask_parse (buffer, count, new_value); +if (err) +return err; + + *mask = new_value; + +return full_count; +} + +#define MAX_NAMELEN 128 + +void register_handler_proc (unsigned int irq,struct irqaction *action) +{ +char name [MAX_NAMELEN ]; + +if (!irq_dir[irq] || action->dir || !action->name) +return ; + +memset (name,0 ,MAX_NAMELEN ); +snprintf (name,MAX_NAMELEN ,"%s" , action->name); + +/* create /proc/irq/1234/handler/ */ + action->dir =proc_mkdir (name, irq_dir[irq]); +} + +#undef MAX_NAMELEN + +#define MAX_NAMELEN 10 + +void register_irq_proc (unsigned int irq) +{ +char name [MAX_NAMELEN ]; + +if (!root_irq_dir || + (irq_desc[irq].handler == &no_irq_type) || + irq_dir[irq]) +return ; + +memset (name,0 ,MAX_NAMELEN ); +sprintf (name,"%d" , irq); + +/* create /proc/irq/1234 */ + irq_dir[irq] =proc_mkdir (name, root_irq_dir); + +#ifdef CONFIG_SMP + { +struct proc_dir_entry *entry; + +/* create /proc/irq/<irq>/smp_affinity */ + entry =create_proc_entry ("smp_affinity" ,0600 , irq_dir[irq]); + +if (entry) { + entry->nlink =1 ; + entry->data = (void *)(long )irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + } + smp_affinity_entry[irq] = entry; + } +#endif +} + +#undef MAX_NAMELEN + +void unregister_handler_proc (unsigned int irq,struct irqaction *action) +{ +if (action->dir) +remove_proc_entry (action->dir->name, irq_dir[irq]); +} + +void init_irq_proc (void ) +{ +struct proc_dir_entry *entry; +int i; + +/* create /proc/irq */ + root_irq_dir =proc_mkdir ("irq" ,NULL ); +if (!root_irq_dir) +return ; + +/* create /proc/irq/prof_cpu_mask */ + entry =create_proc_entry ("prof_cpu_mask" ,0600 , root_irq_dir); +if (!entry) +return ; + + entry->nlink =1 ; + entry->data = (void *)&prof_cpu_mask; + entry->read_proc = prof_cpu_mask_read_proc; + entry->write_proc = prof_cpu_mask_write_proc; + +/* +* Create entries for all existing IRQs. +*/ +for (i =0 ; i <NR_IRQS ; i++) +register_irq_proc (i); +} +
kernel/irq/manage.c renamed from kernel/irq/manage.c.orig +347 -0
347 lines not on this page · raw message
kernel/irq/spurious.c renamed from kernel/irq/spurious.c.orig +96 -0
96 lines not on this page · raw message
kernel/irq/handle.c renamed from kernel/irq/handle.c.orig +204 -0
204 lines not on this page · raw message
kernel/irq/Makefile renamed from kernel/irq/Makefile.orig +4 -0
@@ -0,0 +1,4 @@ + +obj-y := autoprobe.o handle.o manage.o spurious.o +obj-$(CONFIG_PROC_FS) += proc.o +
kernel/irq/autoprobe.c renamed from kernel/irq/autoprobe.c.orig +188 -0
188 lines not on this page · raw message
kernel/irq/internals.h renamed from kernel/irq/internals.h.orig +18 -0
@@ -0,0 +1,18 @@ +/* +* IRQ subsystem internal functions and variables: +*/ + +extern int noirqdebug; + +#ifdef CONFIG_PROC_FS +extern void register_irq_proc (unsigned int irq); +extern void register_handler_proc (unsigned int irq,struct irqaction *action); +extern void unregister_handler_proc (unsigned int irq,struct irqaction *action); +#else +static inline void register_irq_proc (unsigned int irq) { } +static inline void register_handler_proc (unsigned int irq, +struct irqaction *action) { } +static inline void unregister_handler_proc (unsigned int irq, +struct irqaction *action) { } +#endif +
kernel/Makefile renamed from kernel/Makefile.orig +1 -0
@@ -24,6 +24,7 @@ obj-$(CONFIG_STOP_MACHINE) += stop_machi obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_KPROBES) += kprobes.o +obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ ifneq ($(CONFIG_IA64),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
include/linux/irq.h renamed from include/linux/irq.h.orig +14 -1
@@ -13,6 +13,7 @@#if !defined(CONFIG_ARCH_S390 ) +#include <linux/linkage.h> #include <linux/cache.h> #include <linux/spinlock.h> #include <linux/cpumask.h>
@@ -71,7 +72,19 @@ extern irq_desc_t irq_desc [NR_IRQS];#include <asm/hw_irq.h> /* the arch dependent stuff */ -extern int setup_irq (unsigned int ,struct irqaction * ); +#ifdef CONFIG_GENERIC_HARDIRQS +extern cpumask_t irq_affinity[NR_IRQS ]; + +extern asmlinkage int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, +struct irqaction *action); +extern asmlinkage unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); +extern void note_interrupt (unsigned int irq,irq_desc_t *desc,int action_ret); +extern void report_bad_irq (unsigned int irq,irq_desc_t *desc,int action_ret); +extern int can_request_irq (unsigned int irq,unsigned long irqflags); +extern int setup_irq (unsigned int irq,struct irqaction * new); + +extern void init_irq_proc (void ); +#endif extern hw_irq_controller no_irq_type;/* needed in every arch ? */
include/linux/interrupt.h renamed from include/linux/interrupt.h.orig +9 -0
@@ -40,6 +40,8 @@ struct irqaction {const char *name;void *dev_id;struct irqaction *next; +int irq; +struct proc_dir_entry *dir; };extern irqreturn_t no_action (int cpl,void *dev_id,struct pt_regs *regs);
@@ -48,6 +50,13 @@ extern int request_irq(unsigned int, unsigned long, const char *, void *);extern void free_irq (unsigned int ,void *); + +#ifdef CONFIG_GENERIC_HARDIRQS +extern void disable_irq_nosync (unsigned int irq); +extern void disable_irq (unsigned int irq); +extern void enable_irq (unsigned int irq); +#endif +/* * Temporary defines for UP kernels, until all code gets fixed. */
include/linux/hardirq.h renamed from include/linux/hardirq.h.orig +42 -0
52 lines not on this page · raw message
PATCH 2/5 generic irq subsystem, x86 port
x86 port of generic hardirq handling.
arch/i386/Kconfig renamed from arch/i386/Kconfig.orig +7 -0
@@ -1194,6 +1194,13 @@ source "crypto/Kconfig" source "lib/Kconfig" +# +# Use the generic interrupt handling code in kernel/hardirq.c: +# +config GENERIC_HARDIRQS + bool + default y + config X86_SMP bool depends on SMP && !X86_VOYAGER
arch/i386/kernel/vm86.c renamed from arch/i386/kernel/vm86.c.orig +1 -1
@@ -741,7 +741,7 @@ static inline void free_vm86_irq(int irqspin_unlock_irqrestore (&irqbits_lock, flags); } -void release_x86_irqs (struct task_struct *task) +void release_vm86_irqs (struct task_struct *task) {int i;for (i =FIRST_VM86_IRQ ; i <=LAST_VM86_IRQ ; i++)
arch/i386/kernel/io_apic.c renamed from arch/i386/kernel/io_apic.c.orig +0 -2
@@ -255,8 +255,6 @@ static void set_ioapic_affinity_irq(unsi # define Dprintk(x...) # endif -extern cpumask_t irq_affinity[NR_IRQS ]; - cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];#define IRQBALANCE_CHECK_ARCH -999
arch/i386/kernel/i386_ksyms.c renamed from arch/i386/kernel/i386_ksyms.c.orig +0 -4
@@ -76,9 +76,6 @@ EXPORT_SYMBOL_GPL(kernel_fpu_begin);EXPORT_SYMBOL (__ioremap);EXPORT_SYMBOL (ioremap_nocache);EXPORT_SYMBOL (iounmap); -EXPORT_SYMBOL (enable_irq); -EXPORT_SYMBOL (disable_irq); -EXPORT_SYMBOL (disable_irq_nosync);EXPORT_SYMBOL (probe_irq_mask);EXPORT_SYMBOL (kernel_thread);EXPORT_SYMBOL (pm_idle);
@@ -146,7 +143,6 @@ EXPORT_SYMBOL(__write_lock_failed);EXPORT_SYMBOL (__read_lock_failed);/* Global SMP stuff */ -EXPORT_SYMBOL (synchronize_irq);EXPORT_SYMBOL (smp_call_function);/* TLB flushing */
arch/i386/kernel/process.c renamed from arch/i386/kernel/process.c.orig +1 -1
@@ -344,7 +344,7 @@ void release_thread(struct task_struct * } } -release_x86_irqs (dead_task); +release_vm86_irqs (dead_task); }/*
arch/i386/kernel/irq.c renamed from arch/i386/kernel/irq.c.orig +119 -1027
1,208 lines not on this page · raw message
include/asm-i386/irq.h renamed from include/asm-i386/irq.h.orig +5 -26
@@ -21,38 +21,17 @@ static __inline__ int irq_canonicalize(i return ((irq == 2) ? 9 : irq); } -extern void disable_irq (unsigned int ); -extern void disable_irq_nosync (unsigned int ); -extern void enable_irq (unsigned int ); -extern void release_x86_irqs (struct task_struct *); -extern int can_request_irq (unsigned int ,unsigned long flags); +extern void release_vm86_irqs (struct task_struct *);#ifdef CONFIG_X86_LOCAL_APIC -#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ +# define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #endif #ifdef CONFIG_4KSTACKS -/* -* per-CPU IRQ handling contexts (thread information and stack) -*/ -union irq_ctx { -struct thread_info tinfo; -u32 stack[THREAD_SIZE /sizeof (u32)]; -}; - -extern union irq_ctx *hardirq_ctx[NR_CPUS ]; -extern union irq_ctx *softirq_ctx[NR_CPUS ]; - -extern void irq_ctx_init (int cpu); - -#define __ARCH_HAS_DO_SOFTIRQ +extern void irq_ctx_init (int cpu); +# define __ARCH_HAS_DO_SOFTIRQ#else -#define irq_ctx_init (cpu) do { ; } while (0) +# define irq_ctx_init (cpu) do { } while (0)#endif -struct irqaction ; -struct pt_regs ; -asmlinkage int handle_IRQ_event(unsigned int, struct pt_regs *, -struct irqaction *); -#endif /* _ASM_IRQ_H */
include/asm-i386/hardirq.h renamed from include/asm-i386/hardirq.h.orig +18 -40
65 lines not on this page · raw message
include/asm-i386/hw_irq.h renamed from include/asm-i386/hw_irq.h.orig +0 -2
@@ -45,8 +45,6 @@ asmlinkage void thermal_interrupt(struct#define platform_legacy_irq (irq) ((irq) < 16)#endif -void mask_irq (unsigned int irq); -void unmask_irq (unsigned int irq);void disable_8259A_irq (unsigned int irq);void enable_8259A_irq (unsigned int irq);int i8259A_irq_pending (unsigned int irq);
PATCH 3/5 generic irq subsystem, x64 port
x64 port of generic hardirq handling.
arch/x86_64/Kconfig renamed from arch/x86_64/Kconfig.orig +6 -0
@@ -329,6 +329,12 @@ config X86_MCE endmenu +# +# Use the generic interrupt handling code in kernel/hardirq.c: +# +config GENERIC_HARDIRQS + bool + default y menu "Power management options"
arch/x86_64/kernel/irq.c renamed from arch/x86_64/kernel/irq.c.orig +14 -823
863 lines not on this page · raw message
include/asm-x86_64/irq.h renamed from include/asm-x86_64/irq.h.orig +0 -5
@@ -44,11 +44,6 @@ static __inline__ int irq_canonicalize(ireturn ((irq ==2 ) ?9 : irq); } -extern void disable_irq (unsigned int ); -extern void disable_irq_nosync (unsigned int ); -extern void enable_irq (unsigned int ); -extern int can_request_irq (unsigned int ,unsigned long flags); -#ifdef CONFIG_X86_LOCAL_APIC #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #endif
include/asm-x86_64/hardirq.h renamed from include/asm-x86_64/hardirq.h.orig +19 -41
72 lines not on this page · raw message
PATCH 4/5 generic irq subsystem, ppc port
ppc32 port of generic hardirq handling.
arch/ppc/Kconfig renamed from arch/ppc/Kconfig.orig +4 -0
@@ -11,6 +11,10 @@ config MMU config UID16 bool +config GENERIC_HARDIRQS + bool + default y + config RWSEM_GENERIC_SPINLOCK bool
arch/ppc/syslib/ppc8xx_pic.c renamed from arch/ppc/syslib/ppc8xx_pic.c.orig +2 -2
@@ -105,7 +105,7 @@ m8xx_do_IRQ(struct pt_regs *regs, ppc_spurious_interrupts++; }else { -ppc_irq_dispatch_handler ( regs, irq ); +__do_IRQ (irq, regs); } }
@@ -161,7 +161,7 @@ void mbx_i8259_action(int cpl, void *dev } bits =1UL << irq; irq += i8259_pic.irq_offset; -ppc_irq_dispatch_handler ( regs, irq ); +__do_IRQ (irq, regs); }#endif
arch/ppc/kernel/ppc_ksyms.c renamed from arch/ppc/kernel/ppc_ksyms.c.orig +0 -7
@@ -84,10 +84,6 @@ EXPORT_SYMBOL(SingleStepException);EXPORT_SYMBOL (sys_sigreturn);EXPORT_SYMBOL (ppc_n_lost_interrupts);EXPORT_SYMBOL (ppc_lost_interrupts); -EXPORT_SYMBOL (enable_irq); -EXPORT_SYMBOL (disable_irq); -EXPORT_SYMBOL (disable_irq_nosync); -EXPORT_SYMBOL (probe_irq_mask);EXPORT_SYMBOL (ISA_DMA_THRESHOLD );EXPORT_SYMBOL (DMA_MODE_READ );
@@ -205,7 +201,6 @@ EXPORT_SYMBOL(giveup_spe);#ifdef CONFIG_SMP EXPORT_SYMBOL (smp_call_function);EXPORT_SYMBOL (smp_hw_index); -EXPORT_SYMBOL (synchronize_irq);#endif EXPORT_SYMBOL (ppc_md);
@@ -292,8 +287,6 @@ EXPORT_SYMBOL(local_irq_restore_end);#endif EXPORT_SYMBOL (timer_interrupt);EXPORT_SYMBOL (irq_desc); -void ppc_irq_dispatch_handler (struct pt_regs *,int ); -EXPORT_SYMBOL (ppc_irq_dispatch_handler);EXPORT_SYMBOL (tb_ticks_per_jiffy);EXPORT_SYMBOL (get_wchan);EXPORT_SYMBOL (console_drivers);
arch/ppc/kernel/irq.c renamed from arch/ppc/kernel/irq.c.orig +1 -527
562 lines not on this page · raw message
arch/ppc/platforms/pmac_pic.c renamed from arch/ppc/platforms/pmac_pic.c.orig +31 -9
@@ -214,7 +214,7 @@ static irqreturn_t gatwick_action(int cpif (bits ==0 )continue ; irq +=__ilog2 (bits); -ppc_irq_dispatch_handler (regs, irq); +__do_IRQ (irq, regs);return IRQ_HANDLED ; }printk ("gatwick irq not from gatwick pic\n" );
@@ -383,11 +383,34 @@ static irqreturn_t k2u3_action(int cpl, irq =openpic2_get_irq (regs);if (irq !=-1 ) -ppc_irq_dispatch_handler (regs, irq); +__do_IRQ (irq, regs); return IRQ_HANDLED; } + +static struct irqaction k2u3_cascade_action = { + .handler = k2u3_action, + .flags =0 , + .mask =CPU_MASK_NONE , + .name ="U3->K2 Cascade" , +};#endif /* CONFIG_POWER4 */ +#ifdef CONFIG_XMON +static struct irqaction xmon_action = { + .handler = xmon_irq, + .flags =0 , + .mask =CPU_MASK_NONE , + .name ="NMI - XMON" +}; +#endif + +static struct irqaction gatwick_cascade_action = { + .handler = gatwick_action, + .flags =SA_INTERRUPT , + .mask =CPU_MASK_NONE , + .name ="cascade" , +}; +void __init pmac_pic_init (void ) {int i;
@@ -440,8 +463,9 @@ void __init pmac_pic_init(void) OpenPIC_InitSenses = senses; OpenPIC_NumInitSenses =128 ;openpic2_init (PMAC_OPENPIC2_OFFSET ); -if (request_irq (irqctrler2->intrs[0 ].line, k2u3_action,0 , -"U3->K2 Cascade" ,NULL )) + +if (setup_irq (irqctrler2->intrs[0 ].line, + &k2u3_cascade_action)) printk("Unable to get OpenPIC IRQ for cascade\n"); }#endif /* CONFIG_POWER4 */
@@ -455,8 +479,7 @@ void __init pmac_pic_init(void)if (pswitch && pswitch->n_intrs) { nmi_irq = pswitch->intrs[0 ].line;openpic_init_nmi_irq (nmi_irq); -request_irq (nmi_irq, xmon_irq,0 , -"NMI - XMON" ,NULL ); +setup_irq (nmi_irq, &xmon_action); } }#endif /* CONFIG_XMON */
@@ -553,8 +576,7 @@ void __init pmac_pic_init(void) (int)irq_cascade);for ( i = max_real_irqs ; i < max_irqs ; i++ ) irq_desc[i].handler = &gatwick_pic; -request_irq ( irq_cascade, gatwick_action,SA_INTERRUPT , -"cascade" ,NULL ); +setup_irq (irq_cascade, &gatwick_cascade_action); }printk ("System has %d possible interrupts\n" , max_irqs);if (max_irqs != max_real_irqs)
@@ -562,7 +584,7 @@ void __init pmac_pic_init(void) max_real_irqs);#ifdef CONFIG_XMON -request_irq (20 , xmon_irq,0 ,"NMI - XMON" ,NULL ); +setup_irq (20 , &xmon_action);#endif /* CONFIG_XMON */ }
arch/ppc/platforms/85xx/mpc85xx_cds_common.c renamed from arch/ppc/platforms/85xx/mpc85xx_cds_common.c.orig +1 -3
@@ -191,9 +191,7 @@ mpc85xx_cds_show_cpuinfo(struct seq_filestatic void cpm2_cascade (int irq,void *dev_id,struct pt_regs *regs) {while ((irq =cpm2_get_irq (regs)) >=0 ) - { -ppc_irq_dispatch_handler (regs,irq); - } +__do_IRQ (irq, regs); }#endif /* CONFIG_CPM2 */
arch/ppc/platforms/85xx/mpc8560_ads.c renamed from arch/ppc/platforms/85xx/mpc8560_ads.c.orig +2 -3
@@ -145,9 +145,8 @@ mpc8560ads_setup_arch(void)static irqreturn_t cpm2_cascade (int irq,void *dev_id,struct pt_regs *regs) { -while ((irq =cpm2_get_irq (regs)) >=0 ) { -ppc_irq_dispatch_handler (regs, irq); - } +while ((irq =cpm2_get_irq (regs)) >=0 ) +__do_IRQ (irq, regs);return IRQ_HANDLED ; }
arch/ppc/platforms/adir_pic.c renamed from arch/ppc/platforms/adir_pic.c.orig +9 -11
@@ -11,7 +11,7 @@#include <linux/init.h> #include <linux/sched.h> #include <linux/pci.h> -#include <linux/irq.h> +#include <linux/interrupt.h> #include <asm/io.h> #include <asm/i8259.h>
@@ -20,11 +20,6 @@static void adir_onboard_pic_enable (unsigned int irq);static void adir_onboard_pic_disable (unsigned int irq); -static void -no_action (int cpl,void *dev_id,struct pt_regs *regs) -{ -} -__init static void adir_onboard_pic_init (void ) {
@@ -88,6 +83,13 @@ static struct hw_interrupt_type adir_onb NULL }; +static struct irqaction noop_action = { + .handler = no_action, + .flags =SA_INTERRUPT , + .mask =CPU_MASK_NONE , + .name ="82c59 primary cascade" , +}; +/* * Linux interrupt values are assigned as follows: *
@@ -110,11 +112,7 @@ adir_init_IRQ(void)adir_onboard_pic_init ();/* Enable 8259 interrupt cascade */ -request_irq (ADIR_IRQ_VT82C686_INTR , - no_action, -SA_INTERRUPT , -"82c59 primary cascade" , -NULL ); +setup_irq (ADIR_IRQ_VT82C686_INTR , &noop_action); }int
arch/ppc/platforms/sbc82xx.c renamed from arch/ppc/platforms/sbc82xx.c.orig +1 -1
@@ -142,7 +142,7 @@ static irqreturn_t sbc82xx_i8259_demux(ireturn IRQ_HANDLED ; } } -ppc_irq_dispatch_handler (regs,NR_SIU_INTS + irq); +__do_IRQ (NR_SIU_INTS + irq, regs);return IRQ_HANDLED ; }
include/asm-ppc/irq.h renamed from include/asm-ppc/irq.h.orig +0 -4
@@ -6,10 +6,6 @@#include <asm/machdep.h> /* ppc_md */ #include <asm/atomic.h> -extern void disable_irq (unsigned int ); -extern void disable_irq_nosync (unsigned int ); -extern void enable_irq (unsigned int ); -/* * These constants are used for passing information about interrupt * signal polarity and level/edge sensing to the low-level PIC chip
include/asm-ppc/hardirq.h renamed from include/asm-ppc/hardirq.h.orig +5 -40
51 lines not on this page · raw message
include/asm-ppc/hw_irq.h renamed from include/asm-ppc/hw_irq.h.orig +0 -1
@@ -9,7 +9,6 @@#include <asm/reg.h> extern void timer_interrupt (struct pt_regs *); -extern void ppc_irq_dispatch_handler (struct pt_regs *regs,int irq);#define INLINE_IRQS
PATCH 5/5 generic irq subsystem, ppc64 port
In reply to Ingo Molnarppc64 port of generic hardirq handling.
arch/ppc64/Kconfig renamed from arch/ppc64/Kconfig.orig +7 -0
@@ -207,6 +207,13 @@ config PREEMPT Say Y here if you are building a kernel for a desktop, embedded or real-time system. Say N if you are unsure. +# +# Use the generic interrupt handling code in kernel/hardirq.c: +# +config GENERIC_HARDIRQS + bool + default y + config MSCHUNKS bool depends on PPC_ISERIES
arch/ppc64/kernel/misc.S renamed from arch/ppc64/kernel/misc.S.orig +2 -2
@@ -115,12 +115,12 @@ _GLOBAL(call_do_softirq) mtlr r0 blr -_GLOBAL(call_handle_irq_event) +_GLOBAL(call_handle_IRQ_event) mflr r0 std r0,16(r1) stdu r1,THREAD_SIZE-112(r6) mr r1,r6 - bl .handle_irq_event + bl .handle_IRQ_event ld r1,0(r1) ld r0,16(r1) mtlr r0
arch/ppc64/kernel/irq.c renamed from arch/ppc64/kernel/irq.c.orig +5 -497
548 lines not on this page · raw message
include/asm-ppc64/irq.h renamed from include/asm-ppc64/irq.h.orig +1 -6
@@ -17,10 +17,6 @@*/ #define NR_IRQS 512 -extern void disable_irq (unsigned int ); -extern void disable_irq_nosync (unsigned int ); -extern void enable_irq (unsigned int ); -/* this number is used when no interrupt has been assigned */ #define NO_IRQ (-1)
@@ -80,7 +76,6 @@ static __inline__ int irq_canonicalize(istruct irqaction ;struct pt_regs ; -int handle_irq_event (int ,struct pt_regs *,struct irqaction *);#ifdef CONFIG_IRQSTACKS /*
@@ -91,7 +86,7 @@ extern struct thread_info *softirq_ctx[Nextern void irq_ctx_init (void );extern void call_do_softirq (struct thread_info *tp); -extern int call_handle_irq_event (int irq,struct pt_regs *regs, +extern int call_handle_IRQ_event (int irq,struct pt_regs *regs,struct irqaction *action,struct thread_info *tp);#define __ARCH_HAS_DO_SOFTIRQ
include/asm-ppc64/hardirq.h renamed from include/asm-ppc64/hardirq.h.orig +5 -40
50 lines not on this page · raw message
include/asm-ppc64/smp.h renamed from include/asm-ppc64/smp.h.orig +0 -2
@@ -52,8 +52,6 @@ extern cpumask_t cpu_sibling_map[NR_CPUS#endif #define PPC_MSG_DEBUGGER_BREAK 3 -extern cpumask_t irq_affinity[]; -void smp_init_iSeries (void );void smp_init_pSeries (void );
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 i386 CPU hotplug updated for -mm
Hi Andrew,
Find attached the i386 cpu hotplug patch updated for Ingo's latest
round of goodies. In order to avoid dumping cpu hotplug code into kernel/irq/* i dropped the cpu_online check in do_IRQ() by modifying fixup_irqs(). The difference being that on cpu offline, fixup_irqs() is called before we clear the cpu from cpu_online_map and a long delay in order to ensure that we never have any queued external interrupts on the APICs. Due to my usual test victims being in boxes a continent away this hasn't been tested, but i'll cover bug reports (nudge, Nathan! ;)
1) Add CONFIG_HOTPLUG_CPU
2) disable local APIC timer on dead cpus.
3) Disable preempt around irq balancing to prevent CPUs going down.
4) Print irq stats for all possible cpus.
5) Debugging check for interrupts on offline cpus.
6) Hacky fixup_irqs() to redirect irqs when cpus go off/online.
7) play_dead() for offline cpus to spin inside.
8) Handle offline cpus set in flush_tlb_others().
9) Grab lock earlier in smp_call_function() to prevent CPUs going down.
10) Implement __cpu_disable() and __cpu_die().
11) Enable local interrupts in cpu_enable() after fixup_irqs()
12) Don't fiddle with NMI on dead cpu, but leave intact on other cpus.
13) Program IRQ affinity whilst cpu is still in cpu_online_map on offline.
arch/i386/Kconfig | 9 ++++ arch/i386/kernel/apic.c | 3 - arch/i386/kernel/io_apic.c | 2 arch/i386/kernel/irq.c | 66 +++++++++++++++++++++++++------ arch/i386/kernel/msr.c | 2 arch/i386/kernel/process.c | 34 ++++++++++++++++ arch/i386/kernel/smp.c | 25 +++++++---- arch/i386/kernel/smpboot.c | 94 ++++++++++++++++++++++++++++++++++++++++++--- arch/i386/kernel/traps.c | 8 +++ arch/ia64/kernel/smpboot.c | 3 - arch/ppc64/kernel/smp.c | 4 + arch/s390/kernel/smp.c | 4 + include/asm-i386/cpu.h | 2 include/asm-i386/irq.h | 4 + include/asm-i386/smp.h | 3 + kernel/cpu.c | 14 ++---- 16 files changed, 236 insertions(+), 41 deletions(-)
Index: linux-2.6.9-rc3-mm3/arch/i386/Kconfig
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/i386/Kconfig,v retrieving revision 1.1.1.1
arch/i386/Kconfig +9 -0
@@ -1218,6 +1218,15 @@ config SCx200 This support is also available as a module. If compiled as a module, it will be called scx200. +config HOTPLUG_CPU + bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" + depends on SMP && HOTPLUG && EXPERIMENTAL + ---help--- + Say Y here to experiment with turning CPUs off and on. CPUs + can be controlled through /sys/devices/system/cpu. + + Say N. + source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig"
Index: linux-2.6.9-rc3-mm3/arch/i386/kernel/apic.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/i386/kernel/apic.c,v retrieving revision 1.1.1.1
arch/i386/kernel/apic.c +2 -1
@@ -26,6 +26,7 @@#include <linux/mc146818rtc.h> #include <linux/kernel_stat.h> #include <linux/sysdev.h> +#include <linux/cpu.h> #include <asm/atomic.h> #include <asm/smp.h>
@@ -1055,7 +1056,7 @@ void __init setup_secondary_APIC_clock(vlocal_irq_enable (); } -void __init disable_APIC_timer (void ) +void __devinit disable_APIC_timer (void ) {if (using_apic_timer) {unsigned long v;
Index: linux-2.6.9-rc3-mm3/arch/i386/kernel/io_apic.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/i386/kernel/io_apic.c,v retrieving revision 1.1.1.1
arch/i386/kernel/io_apic.c +2 -0
@@ -574,9 +574,11 @@ static int balanced_irq(void *unused) time_remaining =schedule_timeout (time_remaining);if (time_after (jiffies, prev_balance_time+balanced_irq_interval)) { +preempt_disable ();do_irq_balance (); prev_balance_time = jiffies; time_remaining = balanced_irq_interval; +preempt_enable (); } }return 0 ;
Index: linux-2.6.9-rc3-mm3/arch/i386/kernel/irq.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/i386/kernel/irq.c,v retrieving revision 1.1.1.1
arch/i386/kernel/irq.c +53 -13
96 lines not on this page · raw message
Index: linux-2.6.9-rc3-mm3/arch/i386/kernel/msr.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/i386/kernel/msr.c,v retrieving revision 1.1.1.1
arch/i386/kernel/msr.c +1 -1
@@ -260,7 +260,7 @@ static struct file_operations msr_fops = .open = msr_open, }; -static int msr_class_simple_device_add (int i) +static int __devinit msr_class_simple_device_add (int i) {int err =0 ;struct class_device *class_err;
Index: linux-2.6.9-rc3-mm3/arch/i386/kernel/process.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/i386/kernel/process.c,v retrieving revision 1.1.1.1
arch/i386/kernel/process.c +34 -0
@@ -13,6 +13,7 @@#include <stdarg.h> +#include <linux/cpu.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/fs.h>
@@ -54,6 +55,9 @@#include <linux/irq.h> #include <linux/err.h> +#include <asm/tlbflush.h> +#include <asm/cpu.h> + asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");int hlt_counter;
@@ -132,6 +136,34 @@ static void poll_idle (void) } } +#ifdef CONFIG_HOTPLUG_CPU +#include <asm/nmi.h> +/* We don't actually take CPU down, just spin without interrupts. */ +static inline void play_dead (void ) +{ +/* Ack it */ +__get_cpu_var (cpu_state) =CPU_DEAD ; + +/* We shouldn't have to disable interrupts while dead, but +* some interrupts just don't seem to go away, and this makes +* it "work" for testing purposes. */ +/* Death loop */ +while (__get_cpu_var (cpu_state) !=CPU_UP_PREPARE ) +cpu_relax (); + +local_irq_disable (); +__flush_tlb_all (); +cpu_set (smp_processor_id (), cpu_online_map); +enable_APIC_timer (); +local_irq_enable (); +} +#else +static inline void play_dead (void ) +{ +BUG (); +} +#endif /* CONFIG_HOTPLUG_CPU */ +/* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a
@@ -155,6 +187,8 @@ void cpu_idle (void)if (!idle) idle = default_idle; +if (cpu_is_offline (smp_processor_id ())) +play_dead (); irq_stat[smp_processor_id ()].idle_timestamp = jiffies;idle ();rcu_read_unlock ();
Index: linux-2.6.9-rc3-mm3/arch/i386/kernel/smp.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/i386/kernel/smp.c,v retrieving revision 1.1.1.1
arch/i386/kernel/smp.c +16 -9
@@ -19,6 +19,7 @@#include <linux/mc146818rtc.h> #include <linux/cache.h> #include <linux/interrupt.h> +#include <linux/cpu.h> #include <asm/mtrr.h> #include <asm/tlbflush.h>
@@ -166,7 +167,7 @@ void send_IPI_mask_bitmask(cpumask_t cpuunsigned long flags;local_irq_save (flags); - +WARN_ON (mask & ~cpus_addr (cpu_online_map)[0 ]);/* * Wait for idle. */
@@ -351,21 +352,21 @@ out:static void flush_tlb_others (cpumask_t cpumask,struct mm_struct *mm,unsigned long va) { -cpumask_t tmp;/* * A couple of (to be removed) sanity checks: * -* - we do not send IPIs to not-yet booted CPUs. * - current CPU must not be in mask * - mask must exist :) */ BUG_ON (cpus_empty (cpumask)); - -cpus_and (tmp, cpumask, cpu_online_map); -BUG_ON (!cpus_equal (cpumask, tmp));BUG_ON (cpu_isset (smp_processor_id (), cpumask));BUG_ON (!mm); +/* If a CPU which we ran on has gone down, OK. */ +cpus_and (cpumask, cpumask, cpu_online_map); +if (cpus_empty (cpumask)) +return ; +/* * i'm not happy about this global shared spinlock in the * MM hot path, but we'll see how contended it is.
@@ -490,6 +491,7 @@ void smp_send_nmi_allbutself(void)*/ void smp_send_reschedule (int cpu) { +WARN_ON (cpu_is_offline (cpu));send_IPI_mask (cpumask_of_cpu (cpu),RESCHEDULE_VECTOR ); }
@@ -535,10 +537,16 @@ int smp_call_function (void (*func) (voi*/ {struct call_data_struct data; -int cpus =num_online_cpus ()-1 ; +int cpus; -if (!cpus) +/* Holding any lock stops cpus from going down. */ +spin_lock (&call_lock); + cpus =num_online_cpus ()-1 ; + +if (!cpus) { +spin_unlock (&call_lock);return 0 ; + }/* Can deadlock when called with interrupts disabled */ WARN_ON (irqs_disabled ());
@@ -550,7 +558,6 @@ int smp_call_function (void (*func) (voiif (wait)atomic_set (&data.finished,0 ); -spin_lock (&call_lock); call_data = &data;mb ();
Index: linux-2.6.9-rc3-mm3/arch/i386/kernel/smpboot.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/i386/kernel/smpboot.c,v retrieving revision 1.1.1.1
arch/i386/kernel/smpboot.c +93 -5
131 lines not on this page · raw message
Index: linux-2.6.9-rc3-mm3/arch/i386/kernel/traps.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/i386/kernel/traps.c,v retrieving revision 1.1.1.1
arch/i386/kernel/traps.c +8 -0
@@ -692,6 +692,14 @@ asmlinkage void do_nmi(struct pt_regs *nmi_enter (); cpu =smp_processor_id (); + +#ifdef CONFIG_HOTPLUG_CPU +if (!cpu_online (cpu)) { +nmi_exit (); +return ; + } +#endif + ++nmi_count (cpu);if (!nmi_callback (regs, cpu))
Index: linux-2.6.9-rc3-mm3/arch/ia64/kernel/smpboot.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/ia64/kernel/smpboot.c,v retrieving revision 1.1.1.1
arch/ia64/kernel/smpboot.c +2 -1
@@ -591,9 +591,10 @@ int __cpu_disable(void)if (cpu ==0 )return -EBUSY ; +cpu_clear (cpu, cpu_online_map);fixup_irqs ();local_flush_tlb_all (); -printk ("Disabled cpu %u\n" ,smp_processor_id ()); +printk ("Disabled cpu %u\n" , cpu);return 0 ; }
Index: linux-2.6.9-rc3-mm3/arch/ppc64/kernel/smp.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/ppc64/kernel/smp.c,v retrieving revision 1.1.1.1
arch/ppc64/kernel/smp.c +3 -1
@@ -273,11 +273,13 @@ int __cpu_disable(void) {/* FIXME: go put this in a header somewhere */ extern void xics_migrate_irqs_away (void ); +int cpu =smp_processor_id (); +cpu_clear (cpu, cpu_online_map); systemcfg->processorCount--;/*fix boot_cpuid here*/ -if (smp_processor_id () == boot_cpuid) +if (cpu == boot_cpuid) boot_cpuid =any_online_cpu (cpu_online_map);/* FIXME: abstract this to not be platform specific later on */
Index: linux-2.6.9-rc3-mm3/arch/s390/kernel/smp.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/arch/s390/kernel/smp.c,v retrieving revision 1.1.1.1
arch/s390/kernel/smp.c +3 -1
@@ -688,13 +688,15 @@ __cpu_disable(void) {unsigned long flags;ec_creg_mask_parms cr_parms; +int cpu =smp_processor_id ();spin_lock_irqsave (&smp_reserve_lock, flags); -if (smp_cpu_reserved[smp_processor_id ()] !=0 ) { +if (smp_cpu_reserved[cpu] !=0 ) {spin_unlock_irqrestore (&smp_reserve_lock, flags);return -EBUSY ; } +cpu_clear (cpu, cpu_online_map);/* disable all external interrupts */ cr_parms.start_ctl =0 ;
Index: linux-2.6.9-rc3-mm3/include/asm-i386/cpu.h
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/include/asm-i386/cpu.h,v retrieving revision 1.1.1.1
include/asm-i386/cpu.h +2 -0
@@ -5,6 +5,7 @@#include <linux/cpu.h> #include <linux/topology.h> #include <linux/nodemask.h> +#include <linux/percpu.h> #include <asm/node.h>
@@ -26,4 +27,5 @@ static inline int arch_register_cpu(int return register_cpu(&cpu_devices[num].cpu, num, parent); } +DECLARE_PER_CPU (int, cpu_state);#endif /* _ASM_I386_CPU_H_ */
Index: linux-2.6.9-rc3-mm3/include/asm-i386/irq.h
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/include/asm-i386/irq.h,v retrieving revision 1.1.1.1
include/asm-i386/irq.h +4 -0
@@ -34,4 +34,8 @@ extern void release_vm86_irqs(struct tas# define irq_ctx_init (cpu) do { } while (0)#endif +#ifdef CONFIG_HOTPLUG_CPU +extern void fixup_irqs (cpumask_t map); +#endif +#endif /* _ASM_IRQ_H */
Index: linux-2.6.9-rc3-mm3/include/asm-i386/smp.h
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/include/asm-i386/smp.h,v retrieving revision 1.1.1.1
include/asm-i386/smp.h +3 -0
@@ -85,6 +85,9 @@ static __inline int logical_smp_processo }#endif + +extern int __cpu_disable (void ); +extern void __cpu_die (unsigned int cpu);#endif /* !__ASSEMBLY__ */ #define NO_PROC_ID 0xFF/* No processor magic marker */
Index: linux-2.6.9-rc3-mm3/kernel/cpu.c
===================================================================
RCS file: /home/cvsroot/linux-2.6.9-rc3-mm3/kernel/cpu.c,v retrieving revision 1.1.1.1
kernel/cpu.c +5 -9
@@ -62,19 +62,15 @@ static int take_cpu_down(void *unused) {int err; -/* Take offline: makes arch_cpu_down somewhat easier. */ -cpu_clear (smp_processor_id (), cpu_online_map); -/* Ensure this CPU doesn't handle any more interrupts. */ err =__cpu_disable ();if (err <0 ) -cpu_set (smp_processor_id (), cpu_online_map); -else -/* Force idle task to run as soon as we yield: it should -immediately notice cpu is offline and die quickly. */ -sched_idle_next (); +return err; -return err; +/* Force idle task to run as soon as we yield: it should +immediately notice cpu is offline and die quickly. */ +sched_idle_next (); +return 0 ; }int cpu_down (unsigned int cpu)
Re: [PATCH] i386 CPU hotplug updated for -mm
Quoted 9 lines · Zwane Mwaikambo
Hi Andrew,
Find attached the i386 cpu hotplug patch updated for Ingo's latest
round of goodies. In order to avoid dumping cpu hotplug code intokernel/irq/*i dropped thecpu_onlinecheck indo_IRQ()by modifyingfixup_irqs(). The difference being that on cpu offline,fixup_irqs()is called before we clear the cpu fromcpu_online_mapand a long delay in order to ensure that we never have any queued external interrupts on the APICs. Due to my usual test victims being in boxes a continent away this hasn't been tested, but i'll cover bug reports (nudge, Nathan! ;)
Had to apply the patch to 2.6.9-rc4-mm1 (2.6.9-rc3-mm3 doesn't detect my scsi controller). Tested on a dual Pentium 3. Simple offline/online tests seem ok, except I see these warnings when taking a cpu down:
using smp_processor_id() in preemptible code: bash/3436
[<c0106f37>] dump_stack+0x17/0x20 [<c011a087>] smp_processor_id+0x87/0xa0 [<c0134d54>] cpu_down+0x134/0x240 [<c02770d9>] store_online+0x39/0x70 [<c0274487>] sysdev_store+0x37/0x50 [<c019339e>] flush_write_buffer+0x2e/0x40 [<c0193427>] sysfs_write_file+0x77/0x90 [<c015aa20>] vfs_write+0xe0/0x120 [<c015ab0d>] sys_write+0x3d/0x70 [<c0106123>] syscall_call+0x7/0xb
using smp_processor_id() in preemptible code: ksoftirqd/1/5233
[<c0106f37>] dump_stack+0x17/0x20 [<c011a087>] smp_processor_id+0x87/0xa0 [<c0124128>] ksoftirqd+0x68/0x140 [<c0133326>] kthread+0x96/0xe0 [<c0104275>] kernel_thread_helper+0x5/0x10
Under load (unpacking a kernel source tree while continuous online/offline of a cpu) I got a panic within a couple of minutes:
Unable to handle kernel NULL pointer dereference at virtual address 00000004 printing eip: c0145703 *pde = 00000000 Oops: 0000 [#1] PREEMPT SMP Modules linked in: CPU: 1 EIP: 0060:[<c0145703>] Not tainted VLI EFLAGS: 00010082 (2.6.9-rc4-mm1i386cpuhp)
EIP is at kmem_cache_free+0x33/0x70
eax: cba2cd98 ebx: 00000000 ecx: 00000000 edx: cba2cd98
esi: c1561ac0 edi: cba2cd98 ebp: c058be8c esp: c058be7c
ds: 007b es: 007b ss: 0068
Process swapper (pid: 0, threadinfo=c058b000 task=dff88540)
Stack: 00000082 c1559920 00001000 cba2cd9c c058bea4 c013e491 00000000 cf4abee0
00001000 c015f050 c058beb0 c015f92c cf4abee0 c058beb8 c015fbac c058bec4
c015f07d cf4abee0 c058beec c0160819 c0271a48 c0127c11 00000001 00000002
Call Trace:
[<c0106f0a>] show_stack+0x7a/0x90
[<c0107096>] show_registers+0x156/0x1d0
[<c01072b4>] die+0xf4/0x180
[<c0116bd7>] do_page_fault+0x457/0x66d
[<c0106b8d>] error_code+0x2d/0x38
[<c013e491>] mempool_free+0x81/0x90
[<c015f92c>] bio_destructor+0x3c/0x60
[<c015fbac>] bio_put+0x2c/0x40
[<c015f07d>] end_bio_bh_io_sync+0x2d/0x60
[<c0160819>] bio_endio+0x59/0x90
[<c027c578>] __end_that_request_first+0x188/0x250
[<c029db14>] __ide_end_request+0x54/0x150
[<c029dc68>] ide_end_request+0x58/0xc0
[<c02a3fe1>] task_end_request+0x31/0x70
[<c02a418b>] task_out_intr+0x7b/0x100
[<c029f6cd>] ide_intr+0xbd/0x160
[<c0139d44>] handle_IRQ_event+0x34/0x70
[<c0139e6c>] __do_IRQ+0xec/0x170
[<c0108570>] do_IRQ+0x60/0xa0
=======================
[<c0106a90>] common_interrupt+0x18/0x20
[<00000000>] 0x0
[<dff84fbc>] 0xdff84fbc
Code: f8 89 c6 89 5d f4 89 7d fc 9c 8f 45 f0 fa 89 d7 e8 13 49 fd ff 8b 1c 86 e8 6b ea ff ff 8b 4d 04 89 fa 89 f0 e8 2f f3 ff ff 89 c7 <8b> 43 04 39 03 73 20 f0 ff 86 c4 00 00 00 8b 03 89 7c 83 10 ff
<0>Kernel panic - not syncing: Fatal exception in interruptI fixed up the warning in cpu_down with the following patch and now am running with that + 2.6.9-rc4-mm1 + your patch while doing continuous online/offline and make -j8. It's been running for about 45 minutes and I haven't seen the panic yet, although I'm at a loss to explain why the change would fix it. Will let it run overnight and report back...
Nathan
--
Fix (harmless?) smp_processor_id() usage in preemptible section of cpu_down.
---
2.6.9-rc4-mm1-nathanl/kernel/cpu.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-)
kernel/cpu.c renamed from kernel/cpu.c~cpu_down-fix-smp_processor_id-warning +2 -1
@@ -129,7 +129,8 @@ int cpu_down(unsigned int cpu)__cpu_die (cpu);/* Move it here so it can run. */ -kthread_bind (p,smp_processor_id ()); +kthread_bind (p,get_cpu ()); +put_cpu ();/* CPU is completely dead: tell everyone. Too late to complain. */ if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu)
_
Re: [PATCH] i386 CPU hotplug updated for -mm
Quoted 7 lines · Nathan Lynch
I fixed up the warning in
cpu_downwith the following patch and now am running with that + 2.6.9-rc4-mm1 + your patch while doing continuous online/offline and make -j8. It's been running for about 45 minutes and I haven't seen the panic yet, although I'm at a loss to explain why the change would fix it. Will let it run overnight and report back...
kernel/cpu.c int cpu_down(unsigned int cpu) · line 136
Quoted 7 lines
kernel/cpu.c renamed from kernel/cpu.c~cpu_down-fix-smp_processor_id-warning +2
-1/* Move it here so it can run. */ -kthread_bind (p,smp_processor_id ()); +kthread_bind (p,get_cpu ()); +put_cpu ();/* CPU is completely dead: tell everyone. Too late to complain. */ if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu)
hm, is there any assurance that smp_processor_id() == cpu?
but i agree, this fix shouldnt impact the bio-destruct slab crash you were seeing.
Ingo
Re: [PATCH] i386 CPU hotplug updated for -mm
Quoted 14 lines · Ingo Molnar
Quoted 11 lines · Nathan Lynch
I fixed up the warning in
cpu_downwith the following patch and now am running with that + 2.6.9-rc4-mm1 + your patch while doing continuous online/offline and make -j8. It's been running for about 45 minutes and I haven't seen the panic yet, although I'm at a loss to explain why the change would fix it. Will let it run overnight and report back...kernel/cpu.c renamed from kernel/cpu.c~cpu_down-fix-smp_processor_id-warning +2
-1/* Move it here so it can run. */ -kthread_bind (p,smp_processor_id ()); +kthread_bind (p,get_cpu ()); +put_cpu ();
Quoted 4 lines
kernel/cpu.c int cpu_down(unsigned int cpu) · line 136
Quoted 2 lines
kernel/cpu.c renamed from kernel/cpu.c~cpu_down-fix-smp_processor_id-warning +0
-0/* CPU is completely dead: tell everyone. Too late to complain. */ if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu)hm, is there any assurance that
smp_processor_id()== cpu?
Actually, cpu != smp_processor_id(). cpu is the processor we have just taken down at that point; we want the kthread to run on some other cpu.
Nathan
Re: [PATCH] i386 CPU hotplug updated for -mm
Quoted 15 lines · Nathan Lynch
Quoted 14 lines · Ingo Molnar
Quoted 11 lines · Nathan Lynch
I fixed up the warning in
cpu_downwith the following patch and now am running with that + 2.6.9-rc4-mm1 + your patch while doing continuous online/offline and make -j8. It's been running for about 45 minutes and I haven't seen the panic yet, although I'm at a loss to explain why the change would fix it. Will let it run overnight and report back...kernel/cpu.c renamed from kernel/cpu.c~cpu_down-fix-smp_processor_id-warning +2
-1/* Move it here so it can run. */ -kthread_bind (p,smp_processor_id ()); +kthread_bind (p,get_cpu ()); +put_cpu ();
Quoted 7 lines
Quoted 4 lines
kernel/cpu.c int cpu_down(unsigned int cpu) · line 136
Quoted 2 lines
kernel/cpu.c renamed from kernel/cpu.c~cpu_down-fix-smp_processor_id-warning +0
-0/* CPU is completely dead: tell everyone. Too late to complain. */ if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu)hm, is there any assurance that
smp_processor_id()== cpu?Actually, cpu !=
smp_processor_id(). cpu is the processor we have just taken down at that point; we want the kthread to run on some other cpu.
Nathan, thanks for doing that testing, the warning does indeed look to be a false positive. Looking at the code again, i realised that there might also be cases where someone does the following;
preempt_disable(); cpu = smp_processor_id(); ... preempt_enable(); ... mod_local_cpu_variable[cpu];
So cached values of smp_processor_id() might also be a problem, although i haven't found any cases, but maybe that's just being overly paranoid =)
Re: [PATCH] i386 CPU hotplug updated for -mm
In reply to Nathan LynchQuoted 16 lines · Nathan Lynch
Quoted 9 lines · Zwane Mwaikambo
Hi Andrew,
Find attached the i386 cpu hotplug patch updated for Ingo's latest
round of goodies. In order to avoid dumping cpu hotplug code intokernel/irq/*i dropped thecpu_onlinecheck indo_IRQ()by modifyingfixup_irqs(). The difference being that on cpu offline,fixup_irqs()is called before we clear the cpu fromcpu_online_mapand a long delay in order to ensure that we never have any queued external interrupts on the APICs. Due to my usual test victims being in boxes a continent away this hasn't been tested, but i'll cover bug reports (nudge, Nathan! ;)Had to apply the patch to 2.6.9-rc4-mm1 (2.6.9-rc3-mm3 doesn't detect my scsi controller). Tested on a dual Pentium 3. Simple offline/online tests seem ok, except I see these warnings when taking a cpu down:
using
smp_processor_id()in preemptible code: bash/3436
Quoted 10 lines
[<c0106f37>] dump_stack+0x17/0x20 [<c011a087>] smp_processor_id+0x87/0xa0 [<c0134d54>] cpu_down+0x134/0x240 [<c02770d9>] store_online+0x39/0x70 [<c0274487>] sysdev_store+0x37/0x50 [<c019339e>] flush_write_buffer+0x2e/0x40 [<c0193427>] sysfs_write_file+0x77/0x90 [<c015aa20>] vfs_write+0xe0/0x120 [<c015ab0d>] sys_write+0x3d/0x70 [<c0106123>] syscall_call+0x7/0xb
I think this warning is likely bogus:
/* Move it here so it can run. */
kthread_bind(p, smp_processor_id());That just makes sure that the thread can get cleaned up somewhere on some active cpu. The only problem would be if the cpu that the thread was bound to also went down. But, I think that's prevented by the big cpu hotplug semaphore. (the "down"ing CPU can't be "down"ed in the process of "down"ing :)
kernel/cpu.c int cpu_down(unsigned int cpu) · line 133
Quoted 10 lines
diff -puN
kernel/cpu.c~cpu_down-fix-smp_processor_id-warningkernel/cpu.ckernel/cpu.c renamed from kernel/cpu.c~cpu_down-fix-smp_processor_id-warning +2
-1@@ -129,7 +129,8 @@ int cpu_down(unsigned int cpu)__cpu_die (cpu);/* Move it here so it can run. */ -kthread_bind (p,smp_processor_id ()); +kthread_bind (p,get_cpu ()); +put_cpu ();
This doesn't do much more than suppress the warning. If there was some kind race there before, then it's still there but is now hidden.
-- Dave
Re: [PATCH] i386 CPU hotplug updated for -mm
In reply to Nathan LynchQuoted 8 lines · Nathan Lynch
Unable to handle kernel NULL pointer dereference at virtual address 00000004 printing eip: c0145703 *pde = 00000000 Oops: 0000 [#1] PREEMPT SMP Modules linked in:CPU: 1
Ok, cpu1 took an interrupt and exploded, perhaps put a printk in show_regs() to say whether it was offline, an interrupt must have snuck in whilst it was offline.
Quoted 4 lines
[<c029f6cd>] ide_intr+0xbd/0x160 [<c0139d44>] handle_IRQ_event+0x34/0x70 [<c0139e6c>] __do_IRQ+0xec/0x170 [<c0108570>] do_IRQ+0x60/0xa0
Thanks,
Zwane
Re: [PATCH] i386 CPU hotplug updated for -mm
In reply to Zwane MwaikamboHi!
Quoted 12 lines
arch/i386/kernel/process.c +12
-0+#ifdef CONFIG_HOTPLUG_CPU +#include <asm/nmi.h> +/* We don't actually take CPU down, just spin without interrupts. */ +static inline void play_dead (void ) +{ +/* Ack it */ +__get_cpu_var (cpu_state) =CPU_DEAD ; + +/* We shouldn't have to disable interrupts while dead, but +* some interrupts just don't seem to go away, and this makes +* it "work" for testing purposes. */ +/* Death loop */
arch/i386/kernel/process.c static void poll_idle (void) · line 160
Quoted 10 lines
arch/i386/kernel/process.c +10
-0+while (__get_cpu_var (cpu_state) !=CPU_UP_PREPARE ) +cpu_relax (); + +local_irq_disable (); +__flush_tlb_all (); +cpu_set (smp_processor_id (), cpu_online_map); +enable_APIC_timer (); + local_irq_enable(); +} +#else
Having real implementation of this one would be very welcome for suspend-to-{RAM,disk} on smp machines....
Are there really no i386 machines whose hardware supports hotplug?
Pavel
Signature · 2 lines
People were complaining that M$ turns users into beta-testers... ...jr ghea gurz vagb qrirybcref, naq gurl frrz gb yvxr vg gung jnl!
Re: [PATCH] i386 CPU hotplug updated for -mm
Quoted 2 lines · Pavel Machek
Having real implementation of this one would be very welcome for suspend-to-{RAM,disk} on smp machines....
I actually started working on that already but progress got hindered by non technical related issues, i hope to get back to it very soon. This is indeed handy for P4 HT type laptops.
Quoted 1 line
Are there really no i386 machines whose hardware supports hotplug?
There are i386 systems which do support hardware hotplug, mostly addition of processors. I haven't personally worked with any but have been in contact with people who are interested in the code for that specific reason.
Regards,
Zwane