1
0

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:
Linus Torvalds
2025-10-17 13:04:21 -10:00
2 changed files with 15 additions and 4 deletions

View File

@@ -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)
/*

View File

@@ -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);
}