]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
arm64: debug: unmask PSTATE.D earlier
authorWill Deacon <will.deacon@arm.com>
Tue, 19 Jul 2016 14:07:37 +0000 (15:07 +0100)
committerKamal Mostafa <kamal@canonical.com>
Mon, 22 Aug 2016 14:42:02 +0000 (07:42 -0700)
BugLink: http://bugs.launchpad.net/bugs/1615620
commit 2ce39ad15182604beb6c8fa8bed5e46b59fd1082 upstream.

Clearing PSTATE.D is one of the requirements for generating a debug
exception. The arm64 booting protocol requires that PSTATE.D is set,
since many of the debug registers (for example, the hw_breakpoint
registers) are UNKNOWN out of reset and could potentially generate
spurious, fatal debug exceptions in early boot code if PSTATE.D was
clear. Once the debug registers have been safely initialised, PSTATE.D
is cleared, however this is currently broken for two reasons:

(1) The boot CPU clears PSTATE.D in a postcore_initcall and secondary
    CPUs clear PSTATE.D in secondary_start_kernel. Since the initcall
    runs after SMP (and the scheduler) have been initialised, there is
    no guarantee that it is actually running on the boot CPU. In this
    case, the boot CPU is left with PSTATE.D set and is not capable of
    generating debug exceptions.

(2) In a preemptible kernel, we may explicitly schedule on the IRQ
    return path to EL1. If an IRQ occurs with PSTATE.D set in the idle
    thread, then we may schedule the kthread_init thread, run the
    postcore_initcall to clear PSTATE.D and then context switch back
    to the idle thread before returning from the IRQ. The exception
    return path will then restore PSTATE.D from the stack, and set it
    again.

This patch fixes the problem by moving the clearing of PSTATE.D earlier
to proc.S. This has the desirable effect of clearing it in one place for
all CPUs, long before we have to worry about the scheduler or any
exception handling. We ensure that the previous reset of MDSCR_EL1 has
completed before unmasking the exception, so that any spurious
exceptions resulting from UNKNOWN debug registers are not generated.

Without this patch applied, the kprobes selftests have been seen to fail
under KVM, where we end up attempting to step the OOL instruction buffer
with PSTATE.D set and therefore fail to complete the step.

Acked-by: Mark Rutland <mark.rutland@arm.com>
Reported-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/smp.c
arch/arm64/mm/proc.S

index c1492ba1f6d14e71c263fa26904fab9980439b4f..e51f27ac13fd230b758f8405c8d801d2313b6798 100644 (file)
@@ -152,7 +152,6 @@ static int debug_monitors_init(void)
        /* Clear the OS lock. */
        on_each_cpu(clear_os_lock, NULL, 1);
        isb();
-       local_dbg_enable();
 
        /* Register hotplug handler. */
        __register_cpu_notifier(&os_lock_nb);
index 4a1f6fabb5dc9883570d29338ccab846fb28e9af..3b158f66d62a41bf4ef3ec07671c0888047d275a 100644 (file)
@@ -191,7 +191,6 @@ asmlinkage void secondary_start_kernel(void)
        set_cpu_online(cpu, true);
        complete(&cpu_running);
 
-       local_dbg_enable();
        local_irq_enable();
        local_async_enable();
 
index b278b18d292df2f9036d118688f09b872c69fc34..18201e9e8cc71c22d017a9573cf722bdab63de74 100644 (file)
@@ -168,6 +168,8 @@ ENTRY(__cpu_setup)
        msr     cpacr_el1, x0                   // Enable FP/ASIMD
        mov     x0, #1 << 12                    // Reset mdscr_el1 and disable
        msr     mdscr_el1, x0                   // access to the DCC from EL0
+       isb                                     // Unmask debug exceptions now,
+       enable_dbg                              // since this is per-cpu
        reset_pmuserenr_el0 x0                  // Disable PMU access from EL0
        /*
         * Memory region attributes for LPAE: