On Tue, Jun 29, 2010 at 2:53 AM, Tony Luck <tony.luck@xxxxxxxxx> wrote: > Patch is incomplete. I'm seeing errors > > include/linux/irqflags.h:59:26: error: asm/irqflags.h: No such file or directory > > because the patch didn't create arch/ia64/include/asm/irqflags.h Sorry for the inconvenience. Need to git diff HEAD instead of just git diff An update patch has been enclosed in attachment of the reply. > > > Could you provide a bit more detail on what the issues are that > require touching each of the generic files (or at least something I will provide back trace for each of them later > on whether these changes are temporary workarounds that should > go away later, or real stuff that needs changes) > > fs/ioctl.c | 1 In the syscall entry path, I've added hardirqs_on trace, but still saw lockdep wanning complained for not traced hardirq-on event and inconsistent hardware interrupt bit with software bit in hardirq trace. It happened to several other system call as well. All these system call related stuff will be removed in final patch. > fs/open.c | 1 add workaround trace_hardirqs_on_delayed for syscall open > fs/read_write.c | 1 add workaround trace_hardirqs_on_delayed for syscall write > include/linux/irqflags.h | 2 Propose an API trace_hardirqs_on_delayed > include/linux/lockdep.h | 2 -#define MAX_LOCKDEP_KEYS_BITS 13 +#define MAX_LOCKDEP_KEYS_BITS 12 the 12 bits is largest one I can get on ia64 with minimal effort. And it seems to be sufficient for ia64 system for now . The following is the /proc/lockdep_stats on a system with locdekp code running for at least 1 hours on a ia64 system. root@hp-rx8640-03 ~]# cat /proc/lockdep_stats lock-classes: 1199 [max: 4095] direct dependencies: 4448 [max: 16384] indirect dependencies: 12677 all direct dependencies: 92594 dependency chains: 5619 [max: 32768] dependency chain hlocks: 14363 [max: 163840] > kernel/fork.c | 4 + Not sure if the workaround in the copy_process is still needed with the latest patch.. > kernel/lockdep.c | 8 +++ Propose an API trace_hardirqs_on_delayed > kernel/sys.c | 1 add workaround trace_hardirqs_on_delayed for syscall getpgid > kernel/timer.c | 1 add workaround trace_hardirqs_on_delayed for syscall getpid > kernel/trace/trace_irqsoff.c | 6 ++ propose an API trace_hardirqs_on_delayed I know how ugly those workaround are, and are working on a good fix. I share the patch series early for those who are interested in features depends on TRACE_IRQFLAGS and LOCKDEP for ia64... Thanks, Luming
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 9561082..bbb3e91 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -148,6 +148,12 @@ source "arch/ia64/xen/Kconfig" endif +config LOCKDEP_SUPPORT + def_bool y + +config STACKTRACE_SUPPORT + def_bool y + choice prompt "System type" default IA64_GENERIC diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug index de9d507..b57bab5 100644 --- a/arch/ia64/Kconfig.debug +++ b/arch/ia64/Kconfig.debug @@ -2,6 +2,9 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config TRACE_IRQFLAGS_SUPPORT + def_bool y + choice prompt "Physical memory granularity" default IA64_GRANULE_64MB diff --git a/arch/ia64/include/asm/irqflags.h b/arch/ia64/include/asm/irqflags.h new file mode 100644 index 0000000..9be0792 --- /dev/null +++ b/arch/ia64/include/asm/irqflags.h @@ -0,0 +1,101 @@ +#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 + +#define ARCH_LOCKDEP_SYS_EXIT br.call.sptk.many rp=lockdep_sys_exit + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +#define LOCKDEP_SYS_EXIT ARCH_LOCKDEP_SYS_EXIT +#else +#define LOCKDEP_SYS_EXIT +#endif + +#endif + + diff --git a/arch/ia64/include/asm/page.h b/arch/ia64/include/asm/page.h index 5f271bc..4109f09 100644 --- a/arch/ia64/include/asm/page.h +++ b/arch/ia64/include/asm/page.h @@ -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 /*20 log2() of max. size of per-CPU area */ #define PERCPU_PAGE_SIZE (__IA64_UL_CONST(1) << PERCPU_PAGE_SHIFT) diff --git a/arch/ia64/include/asm/rwsem.h b/arch/ia64/include/asm/rwsem.h index e876268..a9ea581 100644 --- a/arch/ia64/include/asm/rwsem.h +++ b/arch/ia64/include/asm/rwsem.h @@ -37,6 +37,9 @@ struct rw_semaphore { 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) @@ -46,9 +49,15 @@ struct rw_semaphore { #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) +#ifdef CONFIG_DEBUG_LOCK_ALLOC +# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname } +#else +# define __RWSEM_DEP_MAP_INIT(lockname) +#endif + #define __RWSEM_INITIALIZER(name) \ { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \ - LIST_HEAD_INIT((name).wait_list) } + LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name)} #define DECLARE_RWSEM(name) \ struct rw_semaphore name = __RWSEM_INITIALIZER(name) @@ -58,13 +67,15 @@ extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); -static inline void -init_rwsem (struct rw_semaphore *sem) -{ - sem->count = RWSEM_UNLOCKED_VALUE; - spin_lock_init(&sem->wait_lock); - INIT_LIST_HEAD(&sem->wait_list); -} +extern void __init_rwsem(struct rw_semaphore *sem, const char *name, + struct lock_class_key *key); + +#define init_rwsem(sem) \ +do { \ + static struct lock_class_key __key; \ + \ + __init_rwsem((sem), #sem, &__key); \ +} while (0) /* * lock for reading diff --git a/arch/ia64/include/asm/stacktrace.h b/arch/ia64/include/asm/stacktrace.h new file mode 100644 index 0000000..021b6b4 --- /dev/null +++ b/arch/ia64/include/asm/stacktrace.h @@ -0,0 +1,7 @@ +#ifndef _ASM_STACKTRACE_H +#define _ASM_STACKTRACE_H 1 + +/* Generic stack tracer with callbacks */ + + +#endif diff --git a/arch/ia64/include/asm/system.h b/arch/ia64/include/asm/system.h index 9f342a5..0c21f6d 100644 --- a/arch/ia64/include/asm/system.h +++ b/arch/ia64/include/asm/system.h @@ -107,88 +107,6 @@ extern struct ia64_boot_param { */ #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__ /* @@ -265,7 +183,7 @@ extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct #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 --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index db10b1e..395c2f2 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_AUDIT) += audit.o 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 --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 9a260b3..393e68d 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -48,6 +48,7 @@ #include <asm/thread_info.h> #include <asm/unistd.h> #include <asm/ftrace.h> +#include <asm/irqflags.h> #include "minstate.h" @@ -583,6 +584,88 @@ strace_error: br.cond.sptk .strace_save_retval END(ia64_trace_syscall) +/* + * Derived from ia64_trace_syscall + */ +GLOBAL_ENTRY(ia64_irqtrace_syscall) + PT_REGS_UNWIND_INFO(0) + /* + * We need to preserve the scratch registers f6-f11 in case the system + * call is sigreturn. + */ + adds r16=PT(F6)+16,sp + adds r17=PT(F7)+16,sp + ;; + stf.spill [r16]=f6,32 + stf.spill [r17]=f7,32 + ;; + stf.spill [r16]=f8,32 + stf.spill [r17]=f9,32 + ;; + stf.spill [r16]=f10 + stf.spill [r17]=f11 + br.call.sptk.many rp=syscall_irqtrace_enter + cmp.lt p6,p0=r8,r0 // check tracehook + adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 + adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10 + mov r10=0 +(p6) br.cond.sptk irqstrace_error // syscall failed -> + adds r16=PT(F6)+16,sp + adds r17=PT(F7)+16,sp + ;; + ldf.fill f6=[r16],32 + ldf.fill f7=[r17],32 + ;; + ldf.fill f8=[r16],32 + ldf.fill f9=[r17],32 + ;; + ldf.fill f10=[r16] + ldf.fill f11=[r17] + // the syscall number may have changed, so re-load it and re-calculate the + // syscall entry-point: + adds r15=PT(R15)+16,sp // r15 = &pt_regs.r15 (syscall #) + ;; + ld8 r15=[r15] + mov r3=NR_syscalls - 1 + ;; + adds r15=-1024,r15 + movl r16=sys_call_table + ;; + shladd r20=r15,3,r16 // r20 = sys_call_table + 8*(syscall-1024) + cmp.leu p6,p7=r15,r3 + ;; +(p6) ld8 r20=[r20] // load address of syscall entry point +(p7) movl r20=sys_ni_syscall + ;; + mov b6=r20 + br.call.sptk.many rp=b6 // do the syscall +.irqstrace_check_retval: + cmp.lt p6,p0=r8,r0 // syscall failed? + adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 + adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10 + mov r10=0 +(p6) br.cond.sptk irqstrace_error // syscall failed -> + ;; // avoid RAW on r10 +.irqstrace_save_retval: +.mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8 +.mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10 + br.call.sptk.many rp=syscall_irqtrace_leave +.irqtraceret3: +(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk +(pUStk) rsm psr.i // disable interrupts + br.cond.sptk ia64_work_pending_syscall_end + +irqstrace_error: + ld8 r3=[r2] // load pt_regs.r8 + sub r9=0,r8 // negate return value to get errno value + ;; + cmp.ne p6,p0=r3,r0 // is pt_regs.r8!=0? + adds r3=16,r2 // r3=&pt_regs.r10 + ;; +(p6) mov r10=-1 +(p6) mov r8=r9 + br.cond.sptk .irqstrace_save_retval +END(ia64_irqtrace_syscall) /* * When traced and returning from sigreturn, we invoke syscall_trace but then * go straight to ia64_leave_kernel rather than ia64_leave_syscall. @@ -858,6 +941,11 @@ GLOBAL_ENTRY(__paravirt_leave_kernel) cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0) #else RSM_PSR_I(pUStk, r17, r31) +#if 0 //Todo: fix lock held when returning to user space + ;; + LOCKDEP_SYS_EXIT + ;; +#endif cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk #endif diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index f14c35f..3732d59 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -453,6 +453,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) struct pt_regs *old_regs = set_irq_regs(regs); unsigned long saved_tpr; + trace_hardirqs_off(); #if IRQ_DEBUG { unsigned long bsp, sp; @@ -523,6 +524,8 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) * come through until ia64_eoi() has been done. */ irq_exit(); + if(!current->hardirq_context) + trace_hardirqs_on_delayed(); set_irq_regs(old_regs); } diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index d93e396..f9731bd 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -855,7 +855,11 @@ ENTRY(break_fault) (p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT SSM_PSR_I(p15, p15, r16) // M2 restore psr.i +#ifdef CONFIG_TRACE_IRQFLAGS +(p14) br.cond.spnt.many ia64_irqtrace_syscall // B do syscall-tracing thingamagic +#else (p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) +#endif br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic // NOT REACHED /////////////////////////////////////////////////////////////////////// diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index a0220dc..ec48cd6 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -536,6 +536,7 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg) static int index; static DEFINE_SPINLOCK(cpe_history_lock); + lockdep_off(); IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n", __func__, cpe_irq, smp_processor_id()); @@ -581,7 +582,7 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg) out: /* Get the CPE error record and log it */ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE); - + lockdep_on(); return IRQ_HANDLED; } @@ -780,7 +781,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg) { .sos = NULL, .monarch_cpu = &monarch_cpu }; /* Mask all interrupts */ - local_irq_save(flags); + raw_local_irq_save(flags); NOTIFY_MCA(DIE_MCA_RENDZVOUS_ENTER, get_irq_regs(), (long)&nd, 1); @@ -800,7 +801,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg) ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; /* Enable all interrupts */ - local_irq_restore(flags); + raw_local_irq_restore(flags); return IRQ_HANDLED; } @@ -1399,7 +1400,7 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg) __func__, cmc_irq, smp_processor_id()); /* SAL spec states this should run w/ interrupts enabled */ - local_irq_enable(); + raw_local_irq_enable(); spin_lock(&cmc_history_lock); if (!cmc_polling_enabled) { @@ -1536,6 +1537,7 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg) static int poll_time = MIN_CPE_POLL_INTERVAL; unsigned int cpuid; + lockdep_off(); cpuid = smp_processor_id(); /* If first cpu, update count */ @@ -1569,6 +1571,7 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg) mod_timer(&cpe_poll_timer, jiffies + poll_time); start_count = -1; } + lockdep_on(); return IRQ_HANDLED; } @@ -1894,10 +1897,10 @@ static void __cpuinit ia64_mca_cmc_vector_adjust(void *dummy) { unsigned long flags; - local_irq_save(flags); + raw_local_irq_save(flags); if (!cmc_polling_enabled) ia64_mca_cmc_vector_enable(NULL); - local_irq_restore(flags); + raw_local_irq_restore(flags); } static int __cpuinit mca_cpu_callback(struct notifier_block *nfb, diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 53f1648..afe0ddf 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -237,14 +237,14 @@ update_pal_halt_status(int status) void default_idle (void) { - local_irq_enable(); + raw_local_irq_enable(); while (!need_resched()) { if (can_do_pal_halt) { - local_irq_disable(); + raw_local_irq_disable(); if (!need_resched()) { safe_halt(); } - local_irq_enable(); + raw_local_irq_enable(); } else cpu_relax(); } diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 7c7909f..a23c683 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -1258,6 +1258,16 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, return 0; } +asmlinkage long +syscall_irqtrace_enter (long arg0, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6, long arg7, + struct pt_regs regs) +{ + raw_local_irq_disable(); + trace_hardirqs_on(); + raw_local_irq_enable(); + return 0; +} /* "asmlinkage" so the input arguments are preserved... */ asmlinkage void @@ -1285,6 +1295,30 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, ia64_sync_krbs(); } +asmlinkage void +syscall_irqtrace_leave (long arg0, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6, long arg7, + struct pt_regs regs) +{ + int step; + + if (unlikely(current->audit_context)) { + int success = AUDITSC_RESULT(regs.r10); + long result = regs.r8; + + if (success != AUDITSC_SUCCESS) + result = -result; + audit_syscall_exit(success, result); + } + + step = test_thread_flag(TIF_SINGLESTEP); + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(®s, step); + + /* copy user rbs to kernel rbs */ + if (test_thread_flag(TIF_RESTORE_RSE)) + ia64_sync_krbs(); +} /* Utrace implementation starts here */ struct regset_get { void *kbuf; diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 41ae6a5..8191631 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -1013,7 +1013,11 @@ cpu_init (void) BUG_ON(current->mm); ia64_mmu_init(ia64_imva(cpu_data)); + + /* Temporarily suppress lockdep WARN_ON irqs disabled*/ + lockdep_off(); ia64_mca_cpu_init(ia64_imva(cpu_data)); + lockdep_on(); /* Clear ITC to eliminate sched_clock() overflows in human time. */ ia64_set_itc(0); diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 6a1380e..bd4ac64 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -507,7 +507,7 @@ do_boot_cpu (int sapicid, int cpu) 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 --git a/arch/ia64/kernel/stacktrace.c b/arch/ia64/kernel/stacktrace.c new file mode 100644 index 0000000..815dd21 --- /dev/null +++ b/arch/ia64/kernel/stacktrace.c @@ -0,0 +1,24 @@ +/* + * 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 --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 653b3c4..39157a7 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -210,8 +210,8 @@ timer_interrupt (int irq, void *dev_id) /* * Allow IPIs to interrupt the timer loop. */ - local_irq_enable(); - local_irq_disable(); + raw_local_irq_enable(); + raw_local_irq_disable(); } skip_process_time_accounting: diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 0799fea..44f37dc 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -82,6 +82,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re unsigned long mask; int fault; + trace_hardirqs_on_delayed(); /* mmap_sem is performance critical.... */ prefetchw(&mm->mmap_sem); diff --git a/fs/ioctl.c b/fs/ioctl.c index 2d140a7..1374920 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -616,6 +616,7 @@ SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) int error = -EBADF; int fput_needed; + trace_hardirqs_on_delayed(); filp = fget_light(fd, &fput_needed); if (!filp) goto out; diff --git a/fs/open.c b/fs/open.c index 5463266..c8a7eca 100644 --- a/fs/open.c +++ b/fs/open.c @@ -973,6 +973,7 @@ SYSCALL_DEFINE1(close, unsigned int, fd) struct fdtable *fdt; int retval; + trace_hardirqs_on_delayed(); spin_lock(&files->file_lock); fdt = files_fdtable(files); if (fd >= fdt->max_fds) diff --git a/fs/read_write.c b/fs/read_write.c index 9c04852..eda37e2 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -412,6 +412,7 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, ssize_t ret = -EBADF; int fput_needed; + trace_hardirqs_on_delayed(); file = fget_light(fd, &fput_needed); if (file) { loff_t pos = file_pos_read(file); diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h index 006bf45..51d0233 100644 --- a/include/linux/irqflags.h +++ b/include/linux/irqflags.h @@ -17,6 +17,7 @@ extern void trace_softirqs_on(unsigned long ip); extern void trace_softirqs_off(unsigned long ip); extern void trace_hardirqs_on(void); + extern void trace_hardirqs_on_delayed(void); extern void trace_hardirqs_off(void); # define trace_hardirq_context(p) ((p)->hardirq_context) # define trace_softirq_context(p) ((p)->softirq_context) @@ -29,6 +30,7 @@ # define INIT_TRACE_IRQFLAGS .softirqs_enabled = 1, #else # define trace_hardirqs_on() do { } while (0) +# define trace_hardirqs_on_delayed() do { } while (0) # define trace_hardirqs_off() do { } while (0) # define trace_softirqs_on(ip) do { } while (0) # define trace_softirqs_off(ip) do { } while (0) diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 06aed83..baa573b 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -174,7 +174,7 @@ struct lock_chain { u64 chain_key; }; -#define MAX_LOCKDEP_KEYS_BITS 13 +#define MAX_LOCKDEP_KEYS_BITS 12 /* * 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 --git a/kernel/fork.c b/kernel/fork.c index b6cce14..0c4ae6d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1012,6 +1012,10 @@ static struct task_struct *copy_process(unsigned long clone_flags, rt_mutex_init_task(p); #ifdef CONFIG_PROVE_LOCKING + //workaround + p->hardirqs_enabled = 1; + p->hardirqs_enabled = 1; + DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled); DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); #endif diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 5428679..f501c10 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -2353,6 +2353,14 @@ void trace_hardirqs_on(void) } EXPORT_SYMBOL(trace_hardirqs_on); +void trace_hardirqs_on_delayed(void) +{ + raw_local_irq_disable(); + trace_hardirqs_on(); + raw_local_irq_enable(); +} +EXPORT_SYMBOL(trace_hardirqs_on_delayed); + /* * Hardirqs were disabled: */ diff --git a/kernel/sys.c b/kernel/sys.c index e83ddbb..e0c67db 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -993,6 +993,7 @@ SYSCALL_DEFINE1(getpgid, pid_t, pid) struct pid *grp; int retval; + trace_hardirqs_on_delayed(); rcu_read_lock(); if (!pid) grp = task_pgrp(current); diff --git a/kernel/timer.c b/kernel/timer.c index ee305c8..7793991 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1336,6 +1336,7 @@ SYSCALL_DEFINE1(alarm, unsigned int, seconds) */ SYSCALL_DEFINE0(getpid) { + trace_hardirqs_on_delayed(); return task_tgid_vnr(current); } diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 6fd486e..3c2a931 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -525,6 +525,12 @@ void trace_hardirqs_on(void) } EXPORT_SYMBOL(trace_hardirqs_on); +void trace_hardirqs_on_delayed(void) +{ + trace_hardirqs_on(); +} +EXPORT_SYMBOL(trace_hardirqs_on_delayed); + void trace_hardirqs_off(void) { if (!preempt_trace() && irq_trace())
![]() |