===== arch/ia64/Kconfig.debug 1.2 vs edited ===== --- 1.2/arch/ia64/Kconfig.debug 2005-01-07 16:15:52 -08:00 +++ edited/arch/ia64/Kconfig.debug 2005-02-28 10:07:27 -08:00 @@ -56,6 +56,15 @@ and restore instructions. It's useful for tracking down spinlock problems, but slow! If you're unsure, select N. +config IA64_ALLOW_NMI + bool "Allow non-maskable interrupts" + help + The normal ia64 irq enable/disable code prevents even non-maskable + interrupts from occuring, which can be a problem for kernel + debuggers, watchdogs, and profilers. Say Y here if you're interested + in NMIs and don't mind the small performance penalty this option + imposes. + config SYSVIPC_COMPAT bool depends on COMPAT && SYSVIPC ===== arch/ia64/kernel/head.S 1.31 vs edited ===== --- 1.31/arch/ia64/kernel/head.S 2005-01-28 15:50:13 -08:00 +++ edited/arch/ia64/kernel/head.S 2005-03-01 13:17:51 -08:00 @@ -59,6 +59,14 @@ .save rp, r0 // terminate unwind chain with a NULL rp .body +#ifdef CONFIG_IA64_ALLOW_NMI // disable interrupts initially (re-enabled in start_kernel()) + mov r16=1<<16 + ;; + mov cr.tpr=r16 + ;; + srlz.d + ;; +#endif rsm psr.i | psr.ic ;; srlz.i @@ -129,8 +137,8 @@ /* * Switch into virtual mode: */ - movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \ - |IA64_PSR_DI) + movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_I|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|\ + IA64_PSR_BN|IA64_PSR_DI) ;; mov cr.ipsr=r16 movl r17=1f ===== arch/ia64/kernel/irq_ia64.c 1.25 vs edited ===== --- 1.25/arch/ia64/kernel/irq_ia64.c 2005-01-22 15:54:49 -08:00 +++ edited/arch/ia64/kernel/irq_ia64.c 2005-03-01 12:50:18 -08:00 @@ -103,8 +103,6 @@ void ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) { - unsigned long saved_tpr; - #if IRQ_DEBUG { unsigned long bsp, sp; @@ -135,17 +133,9 @@ } #endif /* IRQ_DEBUG */ - /* - * Always set TPR to limit maximum interrupt nesting depth to - * 16 (without this, it would be ~240, which could easily lead - * to kernel stack overflows). - */ irq_enter(); - saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); - ia64_srlz_d(); while (vector != IA64_SPURIOUS_INT_VECTOR) { if (!IS_RESCHEDULE(vector)) { - ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_srlz_d(); __do_IRQ(local_vector_to_irq(vector), regs); @@ -154,7 +144,6 @@ * Disable interrupts and send EOI: */ local_irq_disable(); - ia64_setreg(_IA64_REG_CR_TPR, saved_tpr); } ia64_eoi(); vector = ia64_get_ivr(); @@ -165,6 +154,7 @@ * come through until ia64_eoi() has been done. */ irq_exit(); + local_irq_enable(); } #ifdef CONFIG_HOTPLUG_CPU ===== include/asm-ia64/hw_irq.h 1.15 vs edited ===== --- 1.15/include/asm-ia64/hw_irq.h 2005-01-22 15:54:52 -08:00 +++ edited/include/asm-ia64/hw_irq.h 2005-03-01 13:01:03 -08:00 @@ -36,6 +36,10 @@ #define AUTO_ASSIGN -1 +#define IA64_NMI_VECTOR 0x02 /* NMI (note that this can be + masked if psr.i or psr.ic + are cleared) */ + #define IA64_SPURIOUS_INT_VECTOR 0x0f /* ===== include/asm-ia64/system.h 1.48 vs edited ===== --- 1.48/include/asm-ia64/system.h 2005-01-04 18:48:18 -08:00 +++ edited/include/asm-ia64/system.h 2005-03-01 15:28:23 -08:00 @@ -107,12 +107,61 @@ #define safe_halt() ia64_pal_halt_light() /* PAL_HALT_LIGHT */ +/* For spinlocks etc */ +#ifdef CONFIG_IA64_ALLOW_NMI + +#define IA64_TPR_MMI_BIT (1<<16) + +#define __local_irq_save(x) \ +do { \ + (x) = ia64_getreg(_IA64_REG_CR_TPR); \ + ia64_stop(); \ + ia64_setreg(_IA64_REG_CR_TPR, IA64_TPR_MMI_BIT); \ + ia64_stop(); \ + ia64_srlz_d(); \ +} while (0) + +static inline void __local_irq_disable(void) +{ + u64 __tpr; + + __tpr = ia64_getreg(_IA64_REG_CR_TPR); + ia64_stop(); + ia64_setreg(_IA64_REG_CR_TPR, IA64_TPR_MMI_BIT); + ia64_stop(); + ia64_srlz_d(); +} + +static inline void __local_irq_restore(unsigned long flags) +{ + ia64_setreg(_IA64_REG_CR_TPR, flags); + ia64_stop(); + ia64_srlz_d(); +} + +static inline void local_irq_enable(void) +{ + ia64_setreg(_IA64_REG_CR_TPR, 0); + ia64_srlz_d(); + ia64_ssm(IA64_PSR_I); ia64_srlz_d(); +} + +#define local_save_flags(flags) ((flags) = ia64_getreg(_IA64_REG_CR_TPR)) + +static inline int irqs_disabled(void) +{ + unsigned long __ia64_id_flags; + local_save_flags(__ia64_id_flags); + return __ia64_id_flags & IA64_TPR_MMI_BIT; +} + +#else /* !CONFIG_IA64_ALLOW_NMI */ + /* * The group barrier in front of the rsm & ssm are necessary to ensure * that none of the previous instructions in the same group are * affected by the rsm/ssm. */ -/* For spinlocks etc */ /* * - clearing psr.i is implicitly serialized (visible by next insn) @@ -137,6 +186,19 @@ #define __local_irq_restore(x) ia64_intrin_local_irq_restore((x) & IA64_PSR_I) +#define local_irq_enable() ({ ia64_ssm(IA64_PSR_I); ia64_srlz_d(); }) +#define local_save_flags(flags) ((flags) = ia64_getreg(_IA64_REG_PSR)) + +#define irqs_disabled() \ +({ \ + unsigned long __ia64_id_flags; \ + local_save_flags(__ia64_id_flags); \ + (__ia64_id_flags & IA64_PSR_I) == 0; \ +}) + +#endif /* CONFIG_IA64_ALLOW_NMI */ + +/* FIXME: need to change for ALLOW_NMI */ #ifdef CONFIG_IA64_DEBUG_IRQ extern unsigned long last_cli_ip; @@ -170,16 +232,6 @@ # define local_irq_disable() __local_irq_disable() # define local_irq_restore(x) __local_irq_restore(x) #endif /* !CONFIG_IA64_DEBUG_IRQ */ - -#define local_irq_enable() ({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); }) -#define local_save_flags(flags) ({ ia64_stop(); (flags) = ia64_getreg(_IA64_REG_PSR); }) - -#define irqs_disabled() \ -({ \ - unsigned long __ia64_id_flags; \ - local_save_flags(__ia64_id_flags); \ - (__ia64_id_flags & IA64_PSR_I) == 0; \ -}) #ifdef __KERNEL__