• Will Deacon's avatar
    arm64: debug: unmask PSTATE.D earlier · 8ae0073f
    Will Deacon authored
    [ Upstream commit 2ce39ad1 ]
    
    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.
    
    Cc: <stable@vger.kernel.org>
    Acked-by: default avatarMark Rutland <mark.rutland@arm.com>
    Reported-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    Tested-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
    Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
    Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    Tested-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    Signed-off-by: default avatarSasha Levin <alexander.levin@verizon.com>
    8ae0073f
smp.c 14.4 KB