Hi there, The following rfc patch is to add lockdep support and IRQ-flags state tracing support for ia64 architecture based on instructions described in irqflags-tracing. The next step is to fix issues. I plan to target it for -32 or -33. Ps. Bob Picco had done similar things before. Ps. The patch is enclosed in attachment. The inlined one is c&p of it for reading. Thanks, Luming Signed-off-by: Bob Picco <bob.picco@xxxxxx> Signed-off-by: Yu Luming <luming.yu@xxxxxxxxx> arch/ia64/Kconfig | 7 +++ arch/ia64/Kconfig.debug | 4 + arch/ia64/include/asm/page.h | 2 arch/ia64/include/asm/rwsem.h | 3 + arch/ia64/include/asm/system.h | 84 ------------------------------------- arch/ia64/kernel/Makefile | 1 arch/ia64/kernel/ivt.S | 5 ++ arch/ia64/kernel/smpboot.c | 2 arch/ia64/kernel/stacktrace.c | 23 ++++++++++ include/asm-ia64/irqflags.h | 92 +++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/stacktrace.h | 7 +++ include/linux/lockdep.h | 2 lib/Kconfig.debug | 2 13 files changed, 147 insertions(+), 87 deletions(-) diff -BruN linux-2.6.31-rc6/arch/ia64/include/asm/page.h linux-2.6.31-rc6-lockdep/arch/ia64/include/asm/page.h --- linux-2.6.31-rc6/arch/ia64/include/asm/page.h 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/arch/ia64/include/asm/page.h 2009-08-23 18:59:00.000000000 -0700 @@ -41,7 +41,7 @@ #define PAGE_SIZE (__IA64_UL_CONST(1) << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE - 1)) -#define PERCPU_PAGE_SHIFT 16 /* log2() of max. size of per-CPU area */ +#define PERCPU_PAGE_SHIFT 20 /*16 log2() of max. size of per-CPU area */ #define PERCPU_PAGE_SIZE (__IA64_UL_CONST(1) << PERCPU_PAGE_SHIFT) diff -BruN linux-2.6.31-rc6/arch/ia64/include/asm/rwsem.h linux-2.6.31-rc6-lockdep/arch/ia64/include/asm/rwsem.h --- linux-2.6.31-rc6/arch/ia64/include/asm/rwsem.h 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/arch/ia64/include/asm/rwsem.h 2009-08-23 18:59:00.000000000 -0700 @@ -37,6 +37,9 @@ signed long count; spinlock_t wait_lock; struct list_head wait_list; +#ifdef CONFIG_DEBUG_LOCK_ALLOC + struct lockdep_map dep_map; +#endif }; #define RWSEM_UNLOCKED_VALUE __IA64_UL_CONST(0x0000000000000000) diff -BruN linux-2.6.31-rc6/arch/ia64/include/asm/system.h linux-2.6.31-rc6-lockdep/arch/ia64/include/asm/system.h --- linux-2.6.31-rc6/arch/ia64/include/asm/system.h 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/arch/ia64/include/asm/system.h 2009-08-23 18:59:00.000000000 -0700 @@ -107,88 +107,6 @@ */ #define set_mb(var, value) do { (var) = (value); mb(); } while (0) -#define safe_halt() ia64_pal_halt_light() /* PAL_HALT_LIGHT */ - -/* - * 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) - * - setting psr.i requires data serialization - * - we need a stop-bit before reading PSR because we sometimes - * write a floating-point register right before reading the PSR - * and that writes to PSR.mfl - */ -#ifdef CONFIG_PARAVIRT -#define __local_save_flags() ia64_get_psr_i() -#else -#define __local_save_flags() ia64_getreg(_IA64_REG_PSR) -#endif - -#define __local_irq_save(x) \ -do { \ - ia64_stop(); \ - (x) = __local_save_flags(); \ - ia64_stop(); \ - ia64_rsm(IA64_PSR_I); \ -} while (0) - -#define __local_irq_disable() \ -do { \ - ia64_stop(); \ - ia64_rsm(IA64_PSR_I); \ -} while (0) - -#define __local_irq_restore(x) ia64_intrin_local_irq_restore((x) & IA64_PSR_I) - -#ifdef CONFIG_IA64_DEBUG_IRQ - - extern unsigned long last_cli_ip; - -# define __save_ip() last_cli_ip = ia64_getreg(_IA64_REG_IP) - -# define local_irq_save(x) \ -do { \ - unsigned long __psr; \ - \ - __local_irq_save(__psr); \ - if (__psr & IA64_PSR_I) \ - __save_ip(); \ - (x) = __psr; \ -} while (0) - -# define local_irq_disable() do { unsigned long __x; local_irq_save(__x); } while (0) - -# define local_irq_restore(x) \ -do { \ - unsigned long __old_psr, __psr = (x); \ - \ - local_save_flags(__old_psr); \ - __local_irq_restore(__psr); \ - if ((__old_psr & IA64_PSR_I) && !(__psr & IA64_PSR_I)) \ - __save_ip(); \ -} while (0) - -#else /* !CONFIG_IA64_DEBUG_IRQ */ -# define local_irq_save(x) __local_irq_save(x) -# 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) = __local_save_flags(); }) - -#define irqs_disabled() \ -({ \ - unsigned long __ia64_id_flags; \ - local_save_flags(__ia64_id_flags); \ - (__ia64_id_flags & IA64_PSR_I) == 0; \ -}) - #ifdef __KERNEL__ #ifdef CONFIG_IA32_SUPPORT @@ -274,7 +192,7 @@ #define __ARCH_WANT_UNLOCKED_CTXSW #define ARCH_HAS_PREFETCH_SWITCH_STACK #define ia64_platform_is(x) (strcmp(x, platform_name) == 0) - +#include <linux/irqflags.h> void cpu_idle_wait(void); #define arch_align_stack(x) (x) diff -BruN linux-2.6.31-rc6/arch/ia64/Kconfig linux-2.6.31-rc6-lockdep/arch/ia64/Kconfig --- linux-2.6.31-rc6/arch/ia64/Kconfig 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/arch/ia64/Kconfig 2009-08-23 18:59:00.000000000 -0700 @@ -143,6 +143,13 @@ endif +config LOCKDEP_SUPPORT + bool + default y + +config STACKTRACE_SUPPORT + bool + default y choice prompt "System type" default IA64_GENERIC diff -BruN linux-2.6.31-rc6/arch/ia64/Kconfig.debug linux-2.6.31-rc6-lockdep/arch/ia64/Kconfig.debug --- linux-2.6.31-rc6/arch/ia64/Kconfig.debug 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/arch/ia64/Kconfig.debug 2009-08-23 18:58:59.000000000 -0700 @@ -2,6 +2,10 @@ source "lib/Kconfig.debug" +config TRACE_IRQFLAGS_SUPPORT + bool + default y + choice prompt "Physical memory granularity" default IA64_GRANULE_64MB diff -BruN linux-2.6.31-rc6/arch/ia64/kernel/ivt.S linux-2.6.31-rc6-lockdep/arch/ia64/kernel/ivt.S --- linux-2.6.31-rc6/arch/ia64/kernel/ivt.S 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/arch/ia64/kernel/ivt.S 2009-08-23 18:58:59.000000000 -0700 @@ -1603,6 +1603,11 @@ SAVE_REST ;; MCA_RECOVER_RANGE(interrupt) +#ifdef CONFIG_TRACE_IRQFLAGS + ;; + br.call.sptk.many rp=trace_hardirqs_off + ;; +#endif alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group MOV_FROM_IVR(out0, r8) // pass cr.ivr as first arg add out1=16,sp // pass pointer to pt_regs as second arg diff -BruN linux-2.6.31-rc6/arch/ia64/kernel/Makefile linux-2.6.31-rc6-lockdep/arch/ia64/kernel/Makefile --- linux-2.6.31-rc6/arch/ia64/kernel/Makefile 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/arch/ia64/kernel/Makefile 2009-08-23 18:58:59.000000000 -0700 @@ -40,6 +40,7 @@ obj-$(CONFIG_PCI_MSI) += msi_ia64.o mca_recovery-y += mca_drv.o mca_drv_asm.o obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_PARAVIRT) += paravirt.o paravirtentry.o \ paravirt_patch.o diff -BruN linux-2.6.31-rc6/arch/ia64/kernel/smpboot.c linux-2.6.31-rc6-lockdep/arch/ia64/kernel/smpboot.c --- linux-2.6.31-rc6/arch/ia64/kernel/smpboot.c 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/arch/ia64/kernel/smpboot.c 2009-08-23 18:58:59.000000000 -0700 @@ -504,7 +504,7 @@ struct create_idle c_idle = { .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle), .cpu = cpu, - .done = COMPLETION_INITIALIZER(c_idle.done), + .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), }; c_idle.idle = get_idle_for_cpu(cpu); diff -BruN linux-2.6.31-rc6/arch/ia64/kernel/stacktrace.c linux-2.6.31-rc6-lockdep/arch/ia64/kernel/stacktrace.c --- linux-2.6.31-rc6/arch/ia64/kernel/stacktrace.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.31-rc6-lockdep/arch/ia64/kernel/stacktrace.c 2009-08-23 18:58:59.000000000 -0700 @@ -0,0 +1,23 @@ +/* + * arch/x86_64/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@xxxxxxxxxx> + */ +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <linux/module.h> +#include <asm/stacktrace.h> + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + */ +void save_stack_trace(struct stack_trace *trace) +{ +} +EXPORT_SYMBOL(save_stack_trace); +void __ia64_save_stack_nonlocal(struct stack_trace *trace) +{ +} +EXPORT_SYMBOL(__ia64_save_stack_nonlocal); diff -BruN linux-2.6.31-rc6/include/asm-ia64/irqflags.h linux-2.6.31-rc6-lockdep/include/asm-ia64/irqflags.h --- linux-2.6.31-rc6/include/asm-ia64/irqflags.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.31-rc6-lockdep/include/asm-ia64/irqflags.h 2009-08-23 18:59:14.000000000 -0700 @@ -0,0 +1,92 @@ +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H +#include <asm/kregs.h> +#include <asm/pal.h> +/* + * 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) + * - setting psr.i requires data serialization + * - we need a stop-bit before reading PSR because we sometimes + * write a floating-point register right before reading the PSR + * and that writes to PSR.mfl + */ +#define __local_irq_save(x) \ +do { \ + ia64_stop(); \ + (x) = ia64_getreg(_IA64_REG_PSR); \ + ia64_stop(); \ + ia64_rsm(IA64_PSR_I); \ +} while (0) + +#define __local_irq_disable() \ +do { \ + ia64_stop(); \ + ia64_rsm(IA64_PSR_I); \ +} while (0) + +#define __local_irq_restore(x) ia64_intrin_local_irq_restore((x) & IA64_PSR_I) + +#ifdef CONFIG_IA64_DEBUG_IRQ + + extern unsigned long last_cli_ip; + +# define __save_ip() last_cli_ip = ia64_getreg(_IA64_REG_IP) + +# define raw_local_irq_save(x) \ +do { \ + unsigned long psr; \ + \ + __local_irq_save(psr); \ + if (psr & IA64_PSR_I) \ + __save_ip(); \ + (x) = psr; \ +} while (0) + +# define raw_local_irq_disable() do { unsigned long x; raw_local_irq_save(x); } while (0) + +# define raw_local_irq_restore(x) \ +do { \ + unsigned long old_psr, psr = (x); \ + \ + local_save_flags(old_psr); \ + __local_irq_restore(psr); \ + if ((old_psr & IA64_PSR_I) && !(psr & IA64_PSR_I)) \ + __save_ip(); \ +} while (0) + +#else /* !CONFIG_IA64_DEBUG_IRQ */ +# define raw_local_irq_save(x) __local_irq_save(x) +# define raw_local_irq_disable() __local_irq_disable() +# define raw_local_irq_restore(x) __local_irq_restore(x) +#endif /* !CONFIG_IA64_DEBUG_IRQ */ + +#define raw_local_irq_enable() ({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); }) +#define raw_local_save_flags(flags) ({ ia64_stop(); (flags) = ia64_getreg(_IA64_REG_PSR); }) + +#define raw_irqs_disabled() \ +({ \ + unsigned long __ia64_id_flags; \ + raw_local_save_flags(__ia64_id_flags); \ + (__ia64_id_flags & IA64_PSR_I) == 0; \ +}) + +#define raw_safe_halt() ia64_pal_halt_light() /* PAL_HALT_LIGHT */ +#define raw_irqs_disabled_flags(flags) \ +({ \ + (int)((flags) & IA64_PSR_I) == 0; \ +}) + +#ifdef CONFIG_TRACE_IRQFLAGS +#define TRACE_IRQS_ON br.call.sptk.many b0=trace_hardirqs_on +#define TRACE_IRQS_OFF br.call.sptk.many b0=trace_hardirqs_off +#else +#define TRACE_IRQS_ON +#define TRACE_IRQS_OFF +#endif +#endif diff -BruN linux-2.6.31-rc6/include/asm-ia64/stacktrace.h linux-2.6.31-rc6-lockdep/include/asm-ia64/stacktrace.h --- linux-2.6.31-rc6/include/asm-ia64/stacktrace.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.31-rc6-lockdep/include/asm-ia64/stacktrace.h 2009-08-23 18:59:14.000000000 -0700 @@ -0,0 +1,7 @@ +#ifndef _ASM_STACKTRACE_H +#define _ASM_STACKTRACE_H 1 + +/* Generic stack tracer with callbacks */ + + +#endif diff -BruN linux-2.6.31-rc6/include/linux/lockdep.h linux-2.6.31-rc6-lockdep/include/linux/lockdep.h --- linux-2.6.31-rc6/include/linux/lockdep.h 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/include/linux/lockdep.h 2009-08-23 18:59:20.000000000 -0700 @@ -162,7 +162,7 @@ u64 chain_key; }; -#define MAX_LOCKDEP_KEYS_BITS 13 +#define MAX_LOCKDEP_KEYS_BITS 10 /* * Subtract one because we offset hlock->class_idx by 1 in order * to make 0 mean no class. This avoids overflowing the class_idx diff -BruN linux-2.6.31-rc6/lib/Kconfig.debug linux-2.6.31-rc6-lockdep/lib/Kconfig.debug --- linux-2.6.31-rc6/lib/Kconfig.debug 2009-08-13 15:43:34.000000000 -0700 +++ linux-2.6.31-rc6-lockdep/lib/Kconfig.debug 2009-08-23 18:59:06.000000000 -0700 @@ -504,7 +504,7 @@ config DEBUG_LOCKDEP bool "Lock dependency engine debugging" - depends on DEBUG_KERNEL && LOCKDEP + depends on DEBUG_KERNEL && LOCKDEP && !IA64 help If you say Y here, the lock dependency engine will do additional runtime checks to debug itself, at the price
Attachment:
ia64-lockdep-linux-2.6.31-rc6.patch
Description: Binary data
![]() |