diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-01 10:37:11 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-01 10:37:11 +1100 |
commit | 68b9bbeaee1d18ef5e1109d79474a4b61d62826c (patch) | |
tree | a35d58fbd5fd44acdb3cd94c985a42eac953fe2b /arch/ia64 | |
parent | 3409dd22c1e6394f245ae329a27b020ed745ee0e (diff) | |
parent | 2546f47024a5b8232ab37853d13836d67f8f5318 (diff) |
Merge remote branch 'ia64/test'
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/Kconfig | 6 | ||||
-rw-r--r-- | arch/ia64/Kconfig.debug | 3 | ||||
-rw-r--r-- | arch/ia64/include/asm/irqflags.h | 101 | ||||
-rw-r--r-- | arch/ia64/include/asm/page.h | 2 | ||||
-rw-r--r-- | arch/ia64/include/asm/rwsem.h | 27 | ||||
-rw-r--r-- | arch/ia64/include/asm/stacktrace.h | 7 | ||||
-rw-r--r-- | arch/ia64/include/asm/system.h | 84 | ||||
-rw-r--r-- | arch/ia64/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 6 | ||||
-rw-r--r-- | arch/ia64/kernel/ivt.S | 29 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 4 | ||||
-rw-r--r-- | arch/ia64/kernel/smpboot.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/stacktrace.c | 24 | ||||
-rw-r--r-- | arch/ia64/kernel/time.c | 4 |
15 files changed, 208 insertions, 98 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 2d7f56a98e0f..cd0f8f9f5a93 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -145,6 +145,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 de9d507ba0fd..b57bab5708f4 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 000000000000..9be07925a55e --- /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 5f271bc712ee..4109f09b47c8 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 e8762688e8e3..a9ea581aa518 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 000000000000..021b6b4dd641 --- /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 927a381c20ca..cc653109fd52 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__ #ifdef CONFIG_IA32_SUPPORT @@ -274,7 +192,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 e1236349c99f..5d63c3148a02 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -36,6 +36,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 d75b872ca4dc..5b895c5da997 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" @@ -897,6 +898,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/ivt.S b/arch/ia64/kernel/ivt.S index ec9a5fdfa1b9..ebf5bcb23360 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -855,6 +855,11 @@ ENTRY(break_fault) mov rp=r3 // I0 set the real return addr (p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT +#ifdef TRACE_IRQFLAGS_SUPPORT + ;; +(p15) br.call.sptk.many rp=trace_hardirqs_on + ;; +#endif SSM_PSR_I(p15, p15, r16) // M2 restore psr.i (p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic @@ -1555,6 +1560,11 @@ ENTRY(page_fault) MOV_FROM_ISR(out1) SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r14, r3) adds r3=8,r2 // set up second base pointer +#ifdef TRACE_IRQFLAGS_SUPPORT + ;; +(p15) br.call.sptk.many rp=trace_hardirqs_on + ;; +#endif SSM_PSR_I(p15, p15, r14) // restore psr.i movl r14=ia64_leave_kernel ;; @@ -1582,6 +1592,11 @@ ENTRY(non_syscall) SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r15, r24) // guarantee that interruption collection is on +#ifdef TRACE_IRQFLAGS_SUPPORT + ;; +(p15) br.call.sptk.many rp=trace_hardirqs_on + ;; +#endif SSM_PSR_I(p15, p15, r15) // restore psr.i movl r15=ia64_leave_kernel ;; @@ -1630,6 +1645,11 @@ ENTRY(dispatch_unaligned_handler) SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24) // guarantee that interruption collection is on +#ifdef TRACE_IRQFLAGS_SUPPORT + ;; +(p15) br.call.sptk.many rp=trace_hardirqs_on + ;; +#endif SSM_PSR_I(p15, p15, r3) // restore psr.i adds r3=8,r2 // set up second base pointer ;; @@ -1665,6 +1685,11 @@ ENTRY(dispatch_to_fault_handler) // guarantee that interruption collection is on mov out0=r15 ;; +#ifdef TRACE_IRQFLAGS_SUPPORT + ;; +(p15) br.call.sptk.many rp=trace_hardirqs_on + ;; +#endif SSM_PSR_I(p15, p15, r3) // restore psr.i adds r3=8,r2 // set up second base pointer for SAVE_REST ;; @@ -1733,7 +1758,11 @@ ENTRY(dispatch_to_ia32_handler) MOV_FROM_ISR(r14) SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24) // guarantee that interruption collection is on +#ifdef TRACE_IRQFLAGS_SUPPORT ;; +(p15) br.call.sptk.many rp=trace_hardirqs_on + ;; +#endif SSM_PSR_I(p15, p15, r3) adds r3=8,r2 // Base pointer for SAVE_REST ;; diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 9bcec9945c12..91214e528d71 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -234,14 +234,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/setup.c b/arch/ia64/kernel/setup.c index a1ea87919777..0f6fd9aae12f 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -1014,7 +1014,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(); #ifdef CONFIG_IA32_SUPPORT ia32_cpu_init(); diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index de100aa7ff03..0efa2e7833d6 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -504,7 +504,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 000000000000..815dd21ca6d9 --- /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@redhat.com> + */ +#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 a35c661e5e89..7a19a5dba25a 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: |