From b2ee34ccae5a3c24cc86c2d0b03a2986b6b4579b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Sun, 28 Nov 2010 14:57:24 +0000 Subject: [PATCH] --- yaml --- r: 225923 b: refs/heads/master c: 7e20269647169e7ea08a62bdc4979a3ba32e615c h: refs/heads/master i: 225921: c2b1631cc691004348255186d326b8e0df2b6d0d 225919: 03043f647004ed376a0fc21176af023b88d31c1b v: v3 --- [refs] | 2 +- trunk/arch/arm/kernel/entry-armv.S | 4 ++++ trunk/arch/arm/kernel/entry-header.S | 19 +++++++++++++++++++ trunk/arch/arm/kernel/hw_breakpoint.c | 18 +++++++++++++----- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index 0b94b11567c7..6508ee5778c3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6ee33c2712fcdff2568d9bbadb25c8e5a7c36212 +refs/heads/master: 7e20269647169e7ea08a62bdc4979a3ba32e615c diff --git a/trunk/arch/arm/kernel/entry-armv.S b/trunk/arch/arm/kernel/entry-armv.S index c09e3573c5de..34bbef0d2e7e 100644 --- a/trunk/arch/arm/kernel/entry-armv.S +++ b/trunk/arch/arm/kernel/entry-armv.S @@ -198,6 +198,7 @@ __dabt_svc: @ @ set desired IRQ state, then call main handler @ + debug_entry r1 msr cpsr_c, r9 mov r2, sp bl do_DataAbort @@ -324,6 +325,7 @@ __pabt_svc: #else bl CPU_PABORT_HANDLER #endif + debug_entry r1 msr cpsr_c, r9 @ Maybe enable interrupts mov r2, sp @ regs bl do_PrefetchAbort @ call abort handler @@ -439,6 +441,7 @@ __dabt_usr: @ @ IRQs on, then call the main handler @ + debug_entry r1 enable_irq mov r2, sp adr lr, BSYM(ret_from_exception) @@ -703,6 +706,7 @@ __pabt_usr: #else bl CPU_PABORT_HANDLER #endif + debug_entry r1 enable_irq @ Enable interrupts mov r2, sp @ regs bl do_PrefetchAbort @ call abort handler diff --git a/trunk/arch/arm/kernel/entry-header.S b/trunk/arch/arm/kernel/entry-header.S index d93f976fb389..ae9464900168 100644 --- a/trunk/arch/arm/kernel/entry-header.S +++ b/trunk/arch/arm/kernel/entry-header.S @@ -165,6 +165,25 @@ .endm #endif /* !CONFIG_THUMB2_KERNEL */ + @ + @ Debug exceptions are taken as prefetch or data aborts. + @ We must disable preemption during the handler so that + @ we can access the debug registers safely. + @ + .macro debug_entry, fsr +#if defined(CONFIG_HAVE_HW_BREAKPOINT) && defined(CONFIG_PREEMPT) + ldr r4, =0x40f @ mask out fsr.fs + and r5, r4, \fsr + cmp r5, #2 @ debug exception + bne 1f + get_thread_info r10 + ldr r6, [r10, #TI_PREEMPT] @ get preempt count + add r11, r6, #1 @ increment it + str r11, [r10, #TI_PREEMPT] +1: +#endif + .endm + /* * These are the registers used in the syscall handler, and allow us to * have in theory up to 7 arguments to a function - r0 to r6. diff --git a/trunk/arch/arm/kernel/hw_breakpoint.c b/trunk/arch/arm/kernel/hw_breakpoint.c index d37ed3501e57..eeba38008032 100644 --- a/trunk/arch/arm/kernel/hw_breakpoint.c +++ b/trunk/arch/arm/kernel/hw_breakpoint.c @@ -24,6 +24,7 @@ #define pr_fmt(fmt) "hw-breakpoint: " fmt #include +#include #include #include #include @@ -736,14 +737,17 @@ static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs) /* * Called from either the Data Abort Handler [watchpoint] or the - * Prefetch Abort Handler [breakpoint]. + * Prefetch Abort Handler [breakpoint] with preemption disabled. */ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { - int ret = 1; /* Unhandled fault. */ + int ret = 0; u32 dscr; + /* We must be called with preemption disabled. */ + WARN_ON(preemptible()); + /* We only handle watchpoints and hardware breakpoints. */ ARM_DBG_READ(c1, 0, dscr); @@ -758,11 +762,15 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, watchpoint_handler(addr, regs); break; default: - goto out; + ret = 1; /* Unhandled fault. */ } - ret = 0; -out: + /* + * Re-enable preemption after it was disabled in the + * low-level exception handling code. + */ + preempt_enable(); + return ret; }