Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Catalin Marinas: - Explicitly encode the XZR register if the value passed to write_sysreg_s() is 0. The GIC CDEOI instruction is encoded as a system register write with XZR as the source register. However, clang does not honour the "Z" register constraint, leading to incorrect code generation - Ensure the interrupts (DAIF.IF) are unmasked when completing single-step of a suspended breakpoint before calling exit_to_user_mode(). With pseudo-NMIs, interrupts are (additionally) masked at the PMR_EL1 register, handled by local_irq_*() * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: debug: always unmask interrupts in el0_softstp() arm64/sysreg: Fix GIC CDEOI instruction encoding
This commit is contained in:
@@ -1220,10 +1220,19 @@
|
||||
__val; \
|
||||
})
|
||||
|
||||
/*
|
||||
* The "Z" constraint combined with the "%x0" template should be enough
|
||||
* to force XZR generation if (v) is a constant 0 value but LLVM does not
|
||||
* yet understand that modifier/constraint combo so a conditional is required
|
||||
* to nudge the compiler into using XZR as a source for a 0 constant value.
|
||||
*/
|
||||
#define write_sysreg_s(v, r) do { \
|
||||
u64 __val = (u64)(v); \
|
||||
u32 __maybe_unused __check_r = (u32)(r); \
|
||||
asm volatile(__msr_s(r, "%x0") : : "rZ" (__val)); \
|
||||
if (__builtin_constant_p(__val) && __val == 0) \
|
||||
asm volatile(__msr_s(r, "xzr")); \
|
||||
else \
|
||||
asm volatile(__msr_s(r, "%x0") : : "r" (__val)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
|
||||
@@ -697,6 +697,8 @@ static void noinstr el0_breakpt(struct pt_regs *regs, unsigned long esr)
|
||||
|
||||
static void noinstr el0_softstp(struct pt_regs *regs, unsigned long esr)
|
||||
{
|
||||
bool step_done;
|
||||
|
||||
if (!is_ttbr0_addr(regs->pc))
|
||||
arm64_apply_bp_hardening();
|
||||
|
||||
@@ -707,10 +709,10 @@ static void noinstr el0_softstp(struct pt_regs *regs, unsigned long esr)
|
||||
* If we are stepping a suspended breakpoint there's nothing more to do:
|
||||
* the single-step is complete.
|
||||
*/
|
||||
if (!try_step_suspended_breakpoints(regs)) {
|
||||
local_daif_restore(DAIF_PROCCTX);
|
||||
step_done = try_step_suspended_breakpoints(regs);
|
||||
local_daif_restore(DAIF_PROCCTX);
|
||||
if (!step_done)
|
||||
do_el0_softstep(esr, regs);
|
||||
}
|
||||
arm64_exit_to_user_mode(regs);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user