summaryrefslogtreecommitdiff
path: root/arch/ia64
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2010-01-01 10:37:11 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2010-01-01 10:37:11 +1100
commit68b9bbeaee1d18ef5e1109d79474a4b61d62826c (patch)
treea35d58fbd5fd44acdb3cd94c985a42eac953fe2b /arch/ia64
parent3409dd22c1e6394f245ae329a27b020ed745ee0e (diff)
parent2546f47024a5b8232ab37853d13836d67f8f5318 (diff)
Merge remote branch 'ia64/test'
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/Kconfig6
-rw-r--r--arch/ia64/Kconfig.debug3
-rw-r--r--arch/ia64/include/asm/irqflags.h101
-rw-r--r--arch/ia64/include/asm/page.h2
-rw-r--r--arch/ia64/include/asm/rwsem.h27
-rw-r--r--arch/ia64/include/asm/stacktrace.h7
-rw-r--r--arch/ia64/include/asm/system.h84
-rw-r--r--arch/ia64/kernel/Makefile1
-rw-r--r--arch/ia64/kernel/entry.S6
-rw-r--r--arch/ia64/kernel/ivt.S29
-rw-r--r--arch/ia64/kernel/process.c6
-rw-r--r--arch/ia64/kernel/setup.c4
-rw-r--r--arch/ia64/kernel/smpboot.c2
-rw-r--r--arch/ia64/kernel/stacktrace.c24
-rw-r--r--arch/ia64/kernel/time.c4
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: