* [PATCH 0/5] riscv: misaligned: fix interruptible context and add tests
@ 2025-04-14 12:34 Clément Léger
2025-04-14 12:34 ` [PATCH 1/5] riscv: misaligned: factorize trap handling Clément Léger
` (4 more replies)
0 siblings, 5 replies; 15+ messages in thread
From: Clément Léger @ 2025-04-14 12:34 UTC (permalink / raw)
To: open list:DOCUMENTATION, open list,
open list:RISC-V ARCHITECTURE,
open list:KERNEL SELFTEST FRAMEWORK
Cc: Clément Léger, Jonathan Corbet, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Shuah Khan,
Andrew Jones, Samuel Holland
This series fixes misaligned access handling when in non interruptible
context by reenabling interrupts when possible. A previous commit
changed raw_copy_from_user() with copy_from_user() which enables page
faulting and thus can sleep. While correct, a warning is now triggered
due to being called in an invalid context (sleeping in
non-interruptible). This series fixes that problem by factorizing
misaligned load/store entry in a single function than reenables
interrupt if the interrupted context had interrupts enabled.
In order for misaligned handling problems to be caught sooner, add a
kselftest for all the currently supported instructions .
Note: these commits were actually part of another larger series for
misaligned request delegation but was split since it isn't directly
required.
Clément Léger (5):
riscv: misaligned: factorize trap handling
riscv: misaligned: enable IRQs while handling misaligned accesses
riscv: misaligned: use get_user() instead of __get_user()
Documentation/sysctl: add riscv to unaligned-trap supported archs
selftests: riscv: add misaligned access testing
Documentation/admin-guide/sysctl/kernel.rst | 4 +-
arch/riscv/kernel/traps.c | 57 ++--
arch/riscv/kernel/traps_misaligned.c | 2 +-
.../selftests/riscv/misaligned/.gitignore | 1 +
.../selftests/riscv/misaligned/Makefile | 12 +
.../selftests/riscv/misaligned/common.S | 33 +++
.../testing/selftests/riscv/misaligned/fpu.S | 180 +++++++++++++
tools/testing/selftests/riscv/misaligned/gp.S | 103 +++++++
.../selftests/riscv/misaligned/misaligned.c | 254 ++++++++++++++++++
9 files changed, 614 insertions(+), 32 deletions(-)
create mode 100644 tools/testing/selftests/riscv/misaligned/.gitignore
create mode 100644 tools/testing/selftests/riscv/misaligned/Makefile
create mode 100644 tools/testing/selftests/riscv/misaligned/common.S
create mode 100644 tools/testing/selftests/riscv/misaligned/fpu.S
create mode 100644 tools/testing/selftests/riscv/misaligned/gp.S
create mode 100644 tools/testing/selftests/riscv/misaligned/misaligned.c
--
2.49.0
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH 1/5] riscv: misaligned: factorize trap handling 2025-04-14 12:34 [PATCH 0/5] riscv: misaligned: fix interruptible context and add tests Clément Léger @ 2025-04-14 12:34 ` Clément Léger 2025-04-21 7:06 ` Alexandre Ghiti 2025-04-14 12:34 ` [PATCH 2/5] riscv: misaligned: enable IRQs while handling misaligned accesses Clément Léger ` (3 subsequent siblings) 4 siblings, 1 reply; 15+ messages in thread From: Clément Léger @ 2025-04-14 12:34 UTC (permalink / raw) To: open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Clément Léger, Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Shuah Khan, Andrew Jones, Samuel Holland misaligned accesses traps are not nmi and should be treated as normal one using irqentry_enter()/exit(). Since both load/store and user/kernel should use almost the same path and that we are going to add some code around that, factorize it. Signed-off-by: Clément Léger <cleger@rivosinc.com> --- arch/riscv/kernel/traps.c | 49 ++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 8ff8e8b36524..55d9f3450398 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -198,47 +198,38 @@ asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *re DO_ERROR_INFO(do_trap_load_fault, SIGSEGV, SEGV_ACCERR, "load access fault"); -asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs) +enum misaligned_access_type { + MISALIGNED_STORE, + MISALIGNED_LOAD, +}; + +static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type type) { - if (user_mode(regs)) { - irqentry_enter_from_user_mode(regs); + irqentry_state_t state = irqentry_enter(regs); + if (type == MISALIGNED_LOAD) { if (handle_misaligned_load(regs)) do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, - "Oops - load address misaligned"); - - irqentry_exit_to_user_mode(regs); + "Oops - load address misaligned"); } else { - irqentry_state_t state = irqentry_nmi_enter(regs); - - if (handle_misaligned_load(regs)) + if (handle_misaligned_store(regs)) do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, - "Oops - load address misaligned"); - - irqentry_nmi_exit(regs, state); + "Oops - store (or AMO) address misaligned"); } + + irqentry_exit(regs, state); } -asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs) +asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs) { - if (user_mode(regs)) { - irqentry_enter_from_user_mode(regs); - - if (handle_misaligned_store(regs)) - do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, - "Oops - store (or AMO) address misaligned"); - - irqentry_exit_to_user_mode(regs); - } else { - irqentry_state_t state = irqentry_nmi_enter(regs); - - if (handle_misaligned_store(regs)) - do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, - "Oops - store (or AMO) address misaligned"); + do_trap_misaligned(regs, MISALIGNED_LOAD); +} - irqentry_nmi_exit(regs, state); - } +asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs) +{ + do_trap_misaligned(regs, MISALIGNED_STORE); } + DO_ERROR_INFO(do_trap_store_fault, SIGSEGV, SEGV_ACCERR, "store (or AMO) access fault"); DO_ERROR_INFO(do_trap_ecall_s, -- 2.49.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/5] riscv: misaligned: factorize trap handling 2025-04-14 12:34 ` [PATCH 1/5] riscv: misaligned: factorize trap handling Clément Léger @ 2025-04-21 7:06 ` Alexandre Ghiti 2025-04-22 7:57 ` Clément Léger 0 siblings, 1 reply; 15+ messages in thread From: Alexandre Ghiti @ 2025-04-21 7:06 UTC (permalink / raw) To: Clément Léger, open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Shuah Khan, Andrew Jones, Samuel Holland, Peter Zijlstra Hi Clément, On 14/04/2025 14:34, Clément Léger wrote: > misaligned accesses traps are not nmi and should be treated as normal > one using irqentry_enter()/exit(). All the traps that come from kernel mode are treated as nmi as it was suggested by Peter here: https://lore.kernel.org/linux-riscv/Yyhv4UUXuSfvMOw+@hirez.programming.kicks-ass.net/ I don't know the differences between irq_nmi_entry/exit() and irq_entry/exit(), so is that still correct to now treat the kernel traps as non-nmi? Thanks, Alex > Since both load/store and user/kernel > should use almost the same path and that we are going to add some code > around that, factorize it. > > Signed-off-by: Clément Léger<cleger@rivosinc.com> > --- > arch/riscv/kernel/traps.c | 49 ++++++++++++++++----------------------- > 1 file changed, 20 insertions(+), 29 deletions(-) > > diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c > index 8ff8e8b36524..55d9f3450398 100644 > --- a/arch/riscv/kernel/traps.c > +++ b/arch/riscv/kernel/traps.c > @@ -198,47 +198,38 @@ asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *re > DO_ERROR_INFO(do_trap_load_fault, > SIGSEGV, SEGV_ACCERR, "load access fault"); > > -asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs) > +enum misaligned_access_type { > + MISALIGNED_STORE, > + MISALIGNED_LOAD, > +}; > + > +static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type type) > { > - if (user_mode(regs)) { > - irqentry_enter_from_user_mode(regs); > + irqentry_state_t state = irqentry_enter(regs); > > + if (type == MISALIGNED_LOAD) { > if (handle_misaligned_load(regs)) > do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, > - "Oops - load address misaligned"); > - > - irqentry_exit_to_user_mode(regs); > + "Oops - load address misaligned"); > } else { > - irqentry_state_t state = irqentry_nmi_enter(regs); > - > - if (handle_misaligned_load(regs)) > + if (handle_misaligned_store(regs)) > do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, > - "Oops - load address misaligned"); > - > - irqentry_nmi_exit(regs, state); > + "Oops - store (or AMO) address misaligned"); > } > + > + irqentry_exit(regs, state); > } > > -asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs) > +asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs) > { > - if (user_mode(regs)) { > - irqentry_enter_from_user_mode(regs); > - > - if (handle_misaligned_store(regs)) > - do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, > - "Oops - store (or AMO) address misaligned"); > - > - irqentry_exit_to_user_mode(regs); > - } else { > - irqentry_state_t state = irqentry_nmi_enter(regs); > - > - if (handle_misaligned_store(regs)) > - do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, > - "Oops - store (or AMO) address misaligned"); > + do_trap_misaligned(regs, MISALIGNED_LOAD); > +} > > - irqentry_nmi_exit(regs, state); > - } > +asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs) > +{ > + do_trap_misaligned(regs, MISALIGNED_STORE); > } > + > DO_ERROR_INFO(do_trap_store_fault, > SIGSEGV, SEGV_ACCERR, "store (or AMO) access fault"); > DO_ERROR_INFO(do_trap_ecall_s, ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/5] riscv: misaligned: factorize trap handling 2025-04-21 7:06 ` Alexandre Ghiti @ 2025-04-22 7:57 ` Clément Léger 2025-04-22 9:44 ` Peter Zijlstra 0 siblings, 1 reply; 15+ messages in thread From: Clément Léger @ 2025-04-22 7:57 UTC (permalink / raw) To: Alexandre Ghiti, open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Shuah Khan, Andrew Jones, Samuel Holland, Peter Zijlstra On 21/04/2025 09:06, Alexandre Ghiti wrote: > Hi Clément, > > > On 14/04/2025 14:34, Clément Léger wrote: >> misaligned accesses traps are not nmi and should be treated as normal >> one using irqentry_enter()/exit(). > > > All the traps that come from kernel mode are treated as nmi as it was > suggested by Peter here: https://lore.kernel.org/linux-riscv/ > Yyhv4UUXuSfvMOw+@hirez.programming.kicks-ass.net/ > > I don't know the differences between irq_nmi_entry/exit() and irq_entry/ > exit(), so is that still correct to now treat the kernel traps as non-nmi? Hi Alex, Actually, this discussion was raised on a previous series [1] by Maciej which replied that we should actually reenable interrupt depending on the state that was interrupted. Looking at other architecture/code, it seems like treating misaligned accesses as NMI is probably not the right way. For instance, loongarch treats them as normal IRQ using a irqentry_enter()/exit() and reenabling IRQS if possible. Moreover, it looks like to me that misaligned access traps are similar (in the way they can be handled) to how the page fault are handled in RISC-V. It uses irqentry_enter()/exit() and reenables interrupts if needed. Additionally, the misaligned access handling does will not take any locks if handling a misaligned access taken while in kernel so even if we interrupt a kernel critical section that does not have interrupts disable, we are good to go. But my understanding might be wrong as well and I might be missing specific cases :) Thanks, Clément https://lore.kernel.org/lkml/alpine.DEB.2.21.2501070143250.18889@angie.orcam.me.uk/ [1] > > Thanks, > > Alex > > >> Since both load/store and user/kernel >> should use almost the same path and that we are going to add some code >> around that, factorize it. >> >> Signed-off-by: Clément Léger<cleger@rivosinc.com> >> --- >> arch/riscv/kernel/traps.c | 49 ++++++++++++++++----------------------- >> 1 file changed, 20 insertions(+), 29 deletions(-) >> >> diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c >> index 8ff8e8b36524..55d9f3450398 100644 >> --- a/arch/riscv/kernel/traps.c >> +++ b/arch/riscv/kernel/traps.c >> @@ -198,47 +198,38 @@ asmlinkage __visible __trap_section void >> do_trap_insn_illegal(struct pt_regs *re >> DO_ERROR_INFO(do_trap_load_fault, >> SIGSEGV, SEGV_ACCERR, "load access fault"); >> -asmlinkage __visible __trap_section void >> do_trap_load_misaligned(struct pt_regs *regs) >> +enum misaligned_access_type { >> + MISALIGNED_STORE, >> + MISALIGNED_LOAD, >> +}; >> + >> +static void do_trap_misaligned(struct pt_regs *regs, enum >> misaligned_access_type type) >> { >> - if (user_mode(regs)) { >> - irqentry_enter_from_user_mode(regs); >> + irqentry_state_t state = irqentry_enter(regs); >> + if (type == MISALIGNED_LOAD) { >> if (handle_misaligned_load(regs)) >> do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, >> - "Oops - load address misaligned"); >> - >> - irqentry_exit_to_user_mode(regs); >> + "Oops - load address misaligned"); >> } else { >> - irqentry_state_t state = irqentry_nmi_enter(regs); >> - >> - if (handle_misaligned_load(regs)) >> + if (handle_misaligned_store(regs)) >> do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, >> - "Oops - load address misaligned"); >> - >> - irqentry_nmi_exit(regs, state); >> + "Oops - store (or AMO) address misaligned"); >> } >> + >> + irqentry_exit(regs, state); >> } >> -asmlinkage __visible __trap_section void >> do_trap_store_misaligned(struct pt_regs *regs) >> +asmlinkage __visible __trap_section void >> do_trap_load_misaligned(struct pt_regs *regs) >> { >> - if (user_mode(regs)) { >> - irqentry_enter_from_user_mode(regs); >> - >> - if (handle_misaligned_store(regs)) >> - do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, >> - "Oops - store (or AMO) address misaligned"); >> - >> - irqentry_exit_to_user_mode(regs); >> - } else { >> - irqentry_state_t state = irqentry_nmi_enter(regs); >> - >> - if (handle_misaligned_store(regs)) >> - do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc, >> - "Oops - store (or AMO) address misaligned"); >> + do_trap_misaligned(regs, MISALIGNED_LOAD); >> +} >> - irqentry_nmi_exit(regs, state); >> - } >> +asmlinkage __visible __trap_section void >> do_trap_store_misaligned(struct pt_regs *regs) >> +{ >> + do_trap_misaligned(regs, MISALIGNED_STORE); >> } >> + >> DO_ERROR_INFO(do_trap_store_fault, >> SIGSEGV, SEGV_ACCERR, "store (or AMO) access fault"); >> DO_ERROR_INFO(do_trap_ecall_s, ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/5] riscv: misaligned: factorize trap handling 2025-04-22 7:57 ` Clément Léger @ 2025-04-22 9:44 ` Peter Zijlstra 2025-04-22 10:17 ` Clément Léger 0 siblings, 1 reply; 15+ messages in thread From: Peter Zijlstra @ 2025-04-22 9:44 UTC (permalink / raw) To: Clément Léger Cc: Alexandre Ghiti, open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK, Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Shuah Khan, Andrew Jones, Samuel Holland On Tue, Apr 22, 2025 at 09:57:12AM +0200, Clément Léger wrote: > > > On 21/04/2025 09:06, Alexandre Ghiti wrote: > > Hi Clément, > > > > > > On 14/04/2025 14:34, Clément Léger wrote: > >> misaligned accesses traps are not nmi and should be treated as normal > >> one using irqentry_enter()/exit(). > > > > > > All the traps that come from kernel mode are treated as nmi as it was > > suggested by Peter here: https://lore.kernel.org/linux-riscv/ > > Yyhv4UUXuSfvMOw+@hirez.programming.kicks-ass.net/ > > > > I don't know the differences between irq_nmi_entry/exit() and irq_entry/ > > exit(), so is that still correct to now treat the kernel traps as non-nmi? > > Hi Alex, > > Actually, this discussion was raised on a previous series [1] by Maciej > which replied that we should actually reenable interrupt depending on > the state that was interrupted. Looking at other architecture/code, it > seems like treating misaligned accesses as NMI is probably not the right > way. For instance, loongarch treats them as normal IRQ using a > irqentry_enter()/exit() and reenabling IRQS if possible. So, a trap that happens in kernel space while IRQs are disabled, SHOULD really be NMI-like. You then have a choice, make all such traps from kernel space NMI-like; this makes it easy on the trap handler, since the context is always the same. Mistakes are 'easy' to find. Or,.. do funny stuff and only make it NMI like if IRQs were disabled. Which gives inconsistent context for the handler and you'll find yourself scratching your head at some point in the future wondering why this one rare occasion goes BOOM. x86 mostly does the first, any trap that can happen with IRQs disabled is treated unconditionally as NMI like. The obvious exception is page-fault, but that already has a from-non-preemptible-context branch that is 'careful'. As to unaligned traps from kernel space, I would imagine they mostly BUG the kernel, except when there's an exception entry for that location, in which case it might do a fixup? Anyway, the reason these exceptions should be NMI like, is because interrupts are not allowed to nest. Notably something like: raw_spin_lock_irqsave(&foo); <IRQ> raw_spin_lock_irqsave(&foo); ... Is an obvious problem. Exceptions that can run while IRQs are disabled, must not use locks -- treating them as NMI-like (they are non-maskable after all), ensures this. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/5] riscv: misaligned: factorize trap handling 2025-04-22 9:44 ` Peter Zijlstra @ 2025-04-22 10:17 ` Clément Léger 2025-05-01 20:41 ` Maciej W. Rozycki 0 siblings, 1 reply; 15+ messages in thread From: Clément Léger @ 2025-04-22 10:17 UTC (permalink / raw) To: Peter Zijlstra Cc: Alexandre Ghiti, open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK, Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Shuah Khan, Andrew Jones, Samuel Holland On 22/04/2025 11:44, Peter Zijlstra wrote: > On Tue, Apr 22, 2025 at 09:57:12AM +0200, Clément Léger wrote: >> >> >> On 21/04/2025 09:06, Alexandre Ghiti wrote: >>> Hi Clément, >>> >>> >>> On 14/04/2025 14:34, Clément Léger wrote: >>>> misaligned accesses traps are not nmi and should be treated as normal >>>> one using irqentry_enter()/exit(). >>> >>> >>> All the traps that come from kernel mode are treated as nmi as it was >>> suggested by Peter here: https://lore.kernel.org/linux-riscv/ >>> Yyhv4UUXuSfvMOw+@hirez.programming.kicks-ass.net/ >>> >>> I don't know the differences between irq_nmi_entry/exit() and irq_entry/ >>> exit(), so is that still correct to now treat the kernel traps as non-nmi? >> >> Hi Alex, >> >> Actually, this discussion was raised on a previous series [1] by Maciej >> which replied that we should actually reenable interrupt depending on >> the state that was interrupted. Looking at other architecture/code, it >> seems like treating misaligned accesses as NMI is probably not the right >> way. For instance, loongarch treats them as normal IRQ using a >> irqentry_enter()/exit() and reenabling IRQS if possible. > > So, a trap that happens in kernel space while IRQs are disabled, SHOULD > really be NMI-like. > > You then have a choice, make all such traps from kernel space NMI-like; > this makes it easy on the trap handler, since the context is always the > same. Mistakes are 'easy' to find. > > Or,.. do funny stuff and only make it NMI like if IRQs were disabled. > Which gives inconsistent context for the handler and you'll find > yourself scratching your head at some point in the future wondering why > this one rare occasion goes BOOM. Hi Peter, Yeah agreed, that might be hazardous. > > x86 mostly does the first, any trap that can happen with IRQs disabled > is treated unconditionally as NMI like. The obvious exception is > page-fault, but that already has a from-non-preemptible-context branch > that is 'careful'. > > As to unaligned traps from kernel space, I would imagine they mostly BUG > the kernel, except when there's an exception entry for that location, in > which case it might do a fixup? The misaligned access exception handling currently handles misaligned access for the kernel as well (except if explicitly disabled). > > > Anyway, the reason these exceptions should be NMI like, is because > interrupts are not allowed to nest. Notably something like: > > > raw_spin_lock_irqsave(&foo); > <IRQ> > raw_spin_lock_irqsave(&foo); > ... > > Is an obvious problem. Exceptions that can run while IRQs are disabled, > must not use locks -- treating them as NMI-like (they are non-maskable > after all), ensures this. As said in my previous reply, the misaligned handling code does not currently access any locks (when handling kernel misaligned accesses) and is self contained. That being said, that assumption might not be true in future so that might be better to take your approach and treat the misaligned access like an NMI. Thanks, Clément ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/5] riscv: misaligned: factorize trap handling 2025-04-22 10:17 ` Clément Léger @ 2025-05-01 20:41 ` Maciej W. Rozycki 2025-05-01 20:51 ` Maciej W. Rozycki 0 siblings, 1 reply; 15+ messages in thread From: Maciej W. Rozycki @ 2025-05-01 20:41 UTC (permalink / raw) To: Clément Léger Cc: Peter Zijlstra, Alexandre Ghiti, open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK, Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Shuah Khan, Andrew Jones, Samuel Holland On Tue, 22 Apr 2025, Clément Léger wrote: > > x86 mostly does the first, any trap that can happen with IRQs disabled > > is treated unconditionally as NMI like. The obvious exception is > > page-fault, but that already has a from-non-preemptible-context branch > > that is 'careful'. > > > > As to unaligned traps from kernel space, I would imagine they mostly BUG > > the kernel, except when there's an exception entry for that location, in > > which case it might do a fixup? > > The misaligned access exception handling currently handles misaligned > access for the kernel as well (except if explicitly disabled). It's currently not clear that a kernel mode unaligned access is indeed a bug, as some network protocol stacks may still rely on unaligned accesses for performance reasons for the regular case where network headers do come out aligned[1][2]. Hopefully not in the hardirq context though, and the usual approach is to keep interrupts disabled in the emulation path if arriving from the kernel mode as we don't expect kernel code to be ever paged out (the same applies to all kinds of machine instruction emulation). References: [1] "TCP SYNs broken in 2.3.41", <https://marc.info/?l=linux-kernel&m=94927689929463> [2] "Alpha: Emulate unaligned LDx_L/STx_C for data consistency", <https://lore.kernel.org/lkml/87v7rd8h99.fsf@email.froward.int.ebiederm.org/> HTH, Maciej ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/5] riscv: misaligned: factorize trap handling 2025-05-01 20:41 ` Maciej W. Rozycki @ 2025-05-01 20:51 ` Maciej W. Rozycki 0 siblings, 0 replies; 15+ messages in thread From: Maciej W. Rozycki @ 2025-05-01 20:51 UTC (permalink / raw) To: Clément Léger Cc: Peter Zijlstra, Alexandre Ghiti, open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK, Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Shuah Khan, Andrew Jones, Samuel Holland On Thu, 1 May 2025, Maciej W. Rozycki wrote: > Hopefully not in the hardirq context though, and the usual approach is to > keep interrupts disabled in the emulation path if arriving from the kernel > mode as we don't expect kernel code to be ever paged out (the same applies > to all kinds of machine instruction emulation). s/code/data/, obviously. Maciej ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/5] riscv: misaligned: enable IRQs while handling misaligned accesses 2025-04-14 12:34 [PATCH 0/5] riscv: misaligned: fix interruptible context and add tests Clément Léger 2025-04-14 12:34 ` [PATCH 1/5] riscv: misaligned: factorize trap handling Clément Léger @ 2025-04-14 12:34 ` Clément Léger 2025-04-21 7:13 ` Alexandre Ghiti 2025-04-14 12:34 ` [PATCH 3/5] riscv: misaligned: use get_user() instead of __get_user() Clément Léger ` (2 subsequent siblings) 4 siblings, 1 reply; 15+ messages in thread From: Clément Léger @ 2025-04-14 12:34 UTC (permalink / raw) To: open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Clément Léger, Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Shuah Khan, Andrew Jones, Samuel Holland We can safely reenable IRQs if they were enabled in the previous context. This allows to access user memory that could potentially trigger a page fault. Fixes: b686ecdeacf6 ("riscv: misaligned: Restrict user access to kernel memory") Signed-off-by: Clément Léger <cleger@rivosinc.com> --- arch/riscv/kernel/traps.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 55d9f3450398..3eecc2addc41 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -206,6 +206,11 @@ enum misaligned_access_type { static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type type) { irqentry_state_t state = irqentry_enter(regs); + bool enable_irqs = !regs_irqs_disabled(regs); + + /* Enable interrupts if they were enabled in the interrupted context. */ + if (enable_irqs) + local_irq_enable(); if (type == MISALIGNED_LOAD) { if (handle_misaligned_load(regs)) @@ -217,6 +222,9 @@ static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type "Oops - store (or AMO) address misaligned"); } + if (enable_irqs) + local_irq_disable(); + irqentry_exit(regs, state); } -- 2.49.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] riscv: misaligned: enable IRQs while handling misaligned accesses 2025-04-14 12:34 ` [PATCH 2/5] riscv: misaligned: enable IRQs while handling misaligned accesses Clément Léger @ 2025-04-21 7:13 ` Alexandre Ghiti 0 siblings, 0 replies; 15+ messages in thread From: Alexandre Ghiti @ 2025-04-21 7:13 UTC (permalink / raw) To: Clément Léger, open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Shuah Khan, Andrew Jones, Samuel Holland On 14/04/2025 14:34, Clément Léger wrote: > We can safely reenable IRQs if they were enabled in the previous > context. This allows to access user memory that could potentially > trigger a page fault. > > Fixes: b686ecdeacf6 ("riscv: misaligned: Restrict user access to kernel memory") > Signed-off-by: Clément Léger <cleger@rivosinc.com> > --- > arch/riscv/kernel/traps.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c > index 55d9f3450398..3eecc2addc41 100644 > --- a/arch/riscv/kernel/traps.c > +++ b/arch/riscv/kernel/traps.c > @@ -206,6 +206,11 @@ enum misaligned_access_type { > static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type type) > { > irqentry_state_t state = irqentry_enter(regs); > + bool enable_irqs = !regs_irqs_disabled(regs); > + > + /* Enable interrupts if they were enabled in the interrupted context. */ > + if (enable_irqs) > + local_irq_enable(); > > if (type == MISALIGNED_LOAD) { > if (handle_misaligned_load(regs)) > @@ -217,6 +222,9 @@ static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type > "Oops - store (or AMO) address misaligned"); > } > > + if (enable_irqs) > + local_irq_disable(); > + > irqentry_exit(regs, state); > } > Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com> Thanks, Alex ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 3/5] riscv: misaligned: use get_user() instead of __get_user() 2025-04-14 12:34 [PATCH 0/5] riscv: misaligned: fix interruptible context and add tests Clément Léger 2025-04-14 12:34 ` [PATCH 1/5] riscv: misaligned: factorize trap handling Clément Léger 2025-04-14 12:34 ` [PATCH 2/5] riscv: misaligned: enable IRQs while handling misaligned accesses Clément Léger @ 2025-04-14 12:34 ` Clément Léger 2025-04-21 7:21 ` Alexandre Ghiti 2025-04-14 12:34 ` [PATCH 4/5] Documentation/sysctl: add riscv to unaligned-trap supported archs Clément Léger 2025-04-14 12:34 ` [PATCH 5/5] selftests: riscv: add misaligned access testing Clément Léger 4 siblings, 1 reply; 15+ messages in thread From: Clément Léger @ 2025-04-14 12:34 UTC (permalink / raw) To: open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Clément Léger, Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Shuah Khan, Andrew Jones, Samuel Holland Now that we can safely handle user memory accesses while in the misaligned access handlers, use get_user() instead of __get_user() to have user memory access checks. Signed-off-by: Clément Léger <cleger@rivosinc.com> --- arch/riscv/kernel/traps_misaligned.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c index 4354c87c0376..97c674d7d34f 100644 --- a/arch/riscv/kernel/traps_misaligned.c +++ b/arch/riscv/kernel/traps_misaligned.c @@ -268,7 +268,7 @@ static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset, int __ret; \ \ if (user_mode(regs)) { \ - __ret = __get_user(insn, (type __user *) insn_addr); \ + __ret = get_user(insn, (type __user *) insn_addr); \ } else { \ insn = *(type *)insn_addr; \ __ret = 0; \ -- 2.49.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/5] riscv: misaligned: use get_user() instead of __get_user() 2025-04-14 12:34 ` [PATCH 3/5] riscv: misaligned: use get_user() instead of __get_user() Clément Léger @ 2025-04-21 7:21 ` Alexandre Ghiti 0 siblings, 0 replies; 15+ messages in thread From: Alexandre Ghiti @ 2025-04-21 7:21 UTC (permalink / raw) To: Clément Léger, open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Shuah Khan, Andrew Jones, Samuel Holland On 14/04/2025 14:34, Clément Léger wrote: > Now that we can safely handle user memory accesses while in the > misaligned access handlers, use get_user() instead of __get_user() to > have user memory access checks. > > Signed-off-by: Clément Léger <cleger@rivosinc.com> > --- > arch/riscv/kernel/traps_misaligned.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c > index 4354c87c0376..97c674d7d34f 100644 > --- a/arch/riscv/kernel/traps_misaligned.c > +++ b/arch/riscv/kernel/traps_misaligned.c > @@ -268,7 +268,7 @@ static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset, > int __ret; \ > \ > if (user_mode(regs)) { \ > - __ret = __get_user(insn, (type __user *) insn_addr); \ > + __ret = get_user(insn, (type __user *) insn_addr); \ > } else { \ > insn = *(type *)insn_addr; \ > __ret = 0; \ Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com> Thanks, Alex ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 4/5] Documentation/sysctl: add riscv to unaligned-trap supported archs 2025-04-14 12:34 [PATCH 0/5] riscv: misaligned: fix interruptible context and add tests Clément Léger ` (2 preceding siblings ...) 2025-04-14 12:34 ` [PATCH 3/5] riscv: misaligned: use get_user() instead of __get_user() Clément Léger @ 2025-04-14 12:34 ` Clément Léger 2025-04-21 7:22 ` Alexandre Ghiti 2025-04-14 12:34 ` [PATCH 5/5] selftests: riscv: add misaligned access testing Clément Léger 4 siblings, 1 reply; 15+ messages in thread From: Clément Léger @ 2025-04-14 12:34 UTC (permalink / raw) To: open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Clément Léger, Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Shuah Khan, Andrew Jones, Samuel Holland riscv supports the "unaligned-trap" sysctl variable, add it to the list of supported architectures. Signed-off-by: Clément Léger <cleger@rivosinc.com> --- Documentation/admin-guide/sysctl/kernel.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst index dd49a89a62d3..a38e91c4d92c 100644 --- a/Documentation/admin-guide/sysctl/kernel.rst +++ b/Documentation/admin-guide/sysctl/kernel.rst @@ -1595,8 +1595,8 @@ unaligned-trap On architectures where unaligned accesses cause traps, and where this feature is supported (``CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW``; currently, -``arc``, ``parisc`` and ``loongarch``), controls whether unaligned traps -are caught and emulated (instead of failing). +``arc``, ``parisc``, ``loongarch`` and ``riscv``), controls whether unaligned +traps are caught and emulated (instead of failing). = ======================================================== 0 Do not emulate unaligned accesses. -- 2.49.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 4/5] Documentation/sysctl: add riscv to unaligned-trap supported archs 2025-04-14 12:34 ` [PATCH 4/5] Documentation/sysctl: add riscv to unaligned-trap supported archs Clément Léger @ 2025-04-21 7:22 ` Alexandre Ghiti 0 siblings, 0 replies; 15+ messages in thread From: Alexandre Ghiti @ 2025-04-21 7:22 UTC (permalink / raw) To: Clément Léger, open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Shuah Khan, Andrew Jones, Samuel Holland On 14/04/2025 14:34, Clément Léger wrote: > riscv supports the "unaligned-trap" sysctl variable, add it to the list > of supported architectures. > > Signed-off-by: Clément Léger <cleger@rivosinc.com> > --- > Documentation/admin-guide/sysctl/kernel.rst | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst > index dd49a89a62d3..a38e91c4d92c 100644 > --- a/Documentation/admin-guide/sysctl/kernel.rst > +++ b/Documentation/admin-guide/sysctl/kernel.rst > @@ -1595,8 +1595,8 @@ unaligned-trap > > On architectures where unaligned accesses cause traps, and where this > feature is supported (``CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW``; currently, > -``arc``, ``parisc`` and ``loongarch``), controls whether unaligned traps > -are caught and emulated (instead of failing). > +``arc``, ``parisc``, ``loongarch`` and ``riscv``), controls whether unaligned > +traps are caught and emulated (instead of failing). > > = ======================================================== > 0 Do not emulate unaligned accesses. Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com> Thanks, Alex ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 5/5] selftests: riscv: add misaligned access testing 2025-04-14 12:34 [PATCH 0/5] riscv: misaligned: fix interruptible context and add tests Clément Léger ` (3 preceding siblings ...) 2025-04-14 12:34 ` [PATCH 4/5] Documentation/sysctl: add riscv to unaligned-trap supported archs Clément Léger @ 2025-04-14 12:34 ` Clément Léger 4 siblings, 0 replies; 15+ messages in thread From: Clément Léger @ 2025-04-14 12:34 UTC (permalink / raw) To: open list:DOCUMENTATION, open list, open list:RISC-V ARCHITECTURE, open list:KERNEL SELFTEST FRAMEWORK Cc: Clément Léger, Jonathan Corbet, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Shuah Khan, Andrew Jones, Samuel Holland This selftest tests (almost) all the currently emulated instruction (except for the RV32 compressed ones which are left as a future exercise for a RV32 user). For the FPU instructions, all the FPU registers are tested. Signed-off-by: Clément Léger <cleger@rivosinc.com> --- .../selftests/riscv/misaligned/.gitignore | 1 + .../selftests/riscv/misaligned/Makefile | 12 + .../selftests/riscv/misaligned/common.S | 33 +++ .../testing/selftests/riscv/misaligned/fpu.S | 180 +++++++++++++ tools/testing/selftests/riscv/misaligned/gp.S | 103 +++++++ .../selftests/riscv/misaligned/misaligned.c | 254 ++++++++++++++++++ 6 files changed, 583 insertions(+) create mode 100644 tools/testing/selftests/riscv/misaligned/.gitignore create mode 100644 tools/testing/selftests/riscv/misaligned/Makefile create mode 100644 tools/testing/selftests/riscv/misaligned/common.S create mode 100644 tools/testing/selftests/riscv/misaligned/fpu.S create mode 100644 tools/testing/selftests/riscv/misaligned/gp.S create mode 100644 tools/testing/selftests/riscv/misaligned/misaligned.c diff --git a/tools/testing/selftests/riscv/misaligned/.gitignore b/tools/testing/selftests/riscv/misaligned/.gitignore new file mode 100644 index 000000000000..5eff15a1f981 --- /dev/null +++ b/tools/testing/selftests/riscv/misaligned/.gitignore @@ -0,0 +1 @@ +misaligned diff --git a/tools/testing/selftests/riscv/misaligned/Makefile b/tools/testing/selftests/riscv/misaligned/Makefile new file mode 100644 index 000000000000..1aa40110c50d --- /dev/null +++ b/tools/testing/selftests/riscv/misaligned/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021 ARM Limited +# Originally tools/testing/arm64/abi/Makefile + +CFLAGS += -I$(top_srcdir)/tools/include + +TEST_GEN_PROGS := misaligned + +include ../../lib.mk + +$(OUTPUT)/misaligned: misaligned.c fpu.S gp.S + $(CC) -g3 -static -o$@ -march=rv64imafdc $(CFLAGS) $(LDFLAGS) $^ diff --git a/tools/testing/selftests/riscv/misaligned/common.S b/tools/testing/selftests/riscv/misaligned/common.S new file mode 100644 index 000000000000..8fa00035bd5d --- /dev/null +++ b/tools/testing/selftests/riscv/misaligned/common.S @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025 Rivos Inc. + * + * Authors: + * Clément Léger <cleger@rivosinc.com> + */ + +.macro lb_sb temp, offset, src, dst + lb \temp, \offset(\src) + sb \temp, \offset(\dst) +.endm + +.macro copy_long_to temp, src, dst + lb_sb \temp, 0, \src, \dst, + lb_sb \temp, 1, \src, \dst, + lb_sb \temp, 2, \src, \dst, + lb_sb \temp, 3, \src, \dst, + lb_sb \temp, 4, \src, \dst, + lb_sb \temp, 5, \src, \dst, + lb_sb \temp, 6, \src, \dst, + lb_sb \temp, 7, \src, \dst, +.endm + +.macro sp_stack_prologue offset + addi sp, sp, -8 + sub sp, sp, \offset +.endm + +.macro sp_stack_epilogue offset + add sp, sp, \offset + addi sp, sp, 8 +.endm diff --git a/tools/testing/selftests/riscv/misaligned/fpu.S b/tools/testing/selftests/riscv/misaligned/fpu.S new file mode 100644 index 000000000000..d008bff58310 --- /dev/null +++ b/tools/testing/selftests/riscv/misaligned/fpu.S @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025 Rivos Inc. + * + * Authors: + * Clément Léger <cleger@rivosinc.com> + */ + +#include "common.S" + +#define CASE_ALIGN 4 + +.macro fpu_load_inst fpreg, inst, precision, load_reg +.align CASE_ALIGN + \inst \fpreg, 0(\load_reg) + fmv.\precision fa0, \fpreg + j 2f +.endm + +#define flw(__fpreg) fpu_load_inst __fpreg, flw, s, s1 +#define fld(__fpreg) fpu_load_inst __fpreg, fld, d, s1 +#define c_flw(__fpreg) fpu_load_inst __fpreg, c.flw, s, s1 +#define c_fld(__fpreg) fpu_load_inst __fpreg, c.fld, d, s1 +#define c_fldsp(__fpreg) fpu_load_inst __fpreg, c.fldsp, d, sp + +.macro fpu_store_inst fpreg, inst, precision, store_reg +.align CASE_ALIGN + fmv.\precision \fpreg, fa0 + \inst \fpreg, 0(\store_reg) + j 2f +.endm + +#define fsw(__fpreg) fpu_store_inst __fpreg, fsw, s, s1 +#define fsd(__fpreg) fpu_store_inst __fpreg, fsd, d, s1 +#define c_fsw(__fpreg) fpu_store_inst __fpreg, c.fsw, s, s1 +#define c_fsd(__fpreg) fpu_store_inst __fpreg, c.fsd, d, s1 +#define c_fsdsp(__fpreg) fpu_store_inst __fpreg, c.fsdsp, d, sp + +.macro fp_test_prologue + move s1, a1 + /* + * Compute jump offset to store the correct FP register since we don't + * have indirect FP register access (or at least we don't use this + * extension so that works on all archs) + */ + sll t0, a0, CASE_ALIGN + la t2, 1f + add t0, t0, t2 + jr t0 +.align CASE_ALIGN +1: +.endm + +.macro fp_test_prologue_compressed + /* FP registers for compressed instructions starts from 8 to 16 */ + addi a0, a0, -8 + fp_test_prologue +.endm + +#define fp_test_body_compressed(__inst_func) \ + __inst_func(f8); \ + __inst_func(f9); \ + __inst_func(f10); \ + __inst_func(f11); \ + __inst_func(f12); \ + __inst_func(f13); \ + __inst_func(f14); \ + __inst_func(f15); \ +2: + +#define fp_test_body(__inst_func) \ + __inst_func(f0); \ + __inst_func(f1); \ + __inst_func(f2); \ + __inst_func(f3); \ + __inst_func(f4); \ + __inst_func(f5); \ + __inst_func(f6); \ + __inst_func(f7); \ + __inst_func(f8); \ + __inst_func(f9); \ + __inst_func(f10); \ + __inst_func(f11); \ + __inst_func(f12); \ + __inst_func(f13); \ + __inst_func(f14); \ + __inst_func(f15); \ + __inst_func(f16); \ + __inst_func(f17); \ + __inst_func(f18); \ + __inst_func(f19); \ + __inst_func(f20); \ + __inst_func(f21); \ + __inst_func(f22); \ + __inst_func(f23); \ + __inst_func(f24); \ + __inst_func(f25); \ + __inst_func(f26); \ + __inst_func(f27); \ + __inst_func(f28); \ + __inst_func(f29); \ + __inst_func(f30); \ + __inst_func(f31); \ +2: +.text + +#define __gen_test_inst(__inst, __suffix) \ +.global test_ ## __inst; \ +test_ ## __inst:; \ + fp_test_prologue ## __suffix; \ + fp_test_body ## __suffix(__inst); \ + ret + +#define gen_test_inst_compressed(__inst) \ + .option arch,+c; \ + __gen_test_inst(c_ ## __inst, _compressed) + +#define gen_test_inst(__inst) \ + .balign 16; \ + .option push; \ + .option arch,-c; \ + __gen_test_inst(__inst, ); \ + .option pop + +.macro fp_test_prologue_load_compressed_sp + copy_long_to t0, a1, sp +.endm + +.macro fp_test_epilogue_load_compressed_sp +.endm + +.macro fp_test_prologue_store_compressed_sp +.endm + +.macro fp_test_epilogue_store_compressed_sp + copy_long_to t0, sp, a1 +.endm + +#define gen_inst_compressed_sp(__inst, __type) \ + .global test_c_ ## __inst ## sp; \ + test_c_ ## __inst ## sp:; \ + sp_stack_prologue a2; \ + fp_test_prologue_## __type ## _compressed_sp; \ + fp_test_prologue_compressed; \ + fp_test_body_compressed(c_ ## __inst ## sp); \ + fp_test_epilogue_## __type ## _compressed_sp; \ + sp_stack_epilogue a2; \ + ret + +#define gen_test_load_compressed_sp(__inst) gen_inst_compressed_sp(__inst, load) +#define gen_test_store_compressed_sp(__inst) gen_inst_compressed_sp(__inst, store) + +/* + * float_fsw_reg - Set a FP register from a register containing the value + * a0 = FP register index to be set + * a1 = addr where to store register value + * a2 = address offset + * a3 = value to be store + */ +gen_test_inst(fsw) + +/* + * float_flw_reg - Get a FP register value and return it + * a0 = FP register index to be retrieved + * a1 = addr to load register from + * a2 = address offset + */ +gen_test_inst(flw) + +gen_test_inst(fsd) +#ifdef __riscv_compressed +gen_test_inst_compressed(fsd) +gen_test_store_compressed_sp(fsd) +#endif + +gen_test_inst(fld) +#ifdef __riscv_compressed +gen_test_inst_compressed(fld) +gen_test_load_compressed_sp(fld) +#endif diff --git a/tools/testing/selftests/riscv/misaligned/gp.S b/tools/testing/selftests/riscv/misaligned/gp.S new file mode 100644 index 000000000000..f53f4c6d81dd --- /dev/null +++ b/tools/testing/selftests/riscv/misaligned/gp.S @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025 Rivos Inc. + * + * Authors: + * Clément Léger <cleger@rivosinc.com> + */ + +#include "common.S" + +.text + +.macro __gen_test_inst inst, src_reg + \inst a2, 0(\src_reg) + move a0, a2 +.endm + +.macro gen_func_header func_name, rvc + .option arch,\rvc + .global test_\func_name + test_\func_name: +.endm + +.macro gen_test_inst inst + .option push + gen_func_header \inst, -c + __gen_test_inst \inst, a0 + .option pop + ret +.endm + +.macro __gen_test_inst_c name, src_reg + .option push + gen_func_header c_\name, +c + __gen_test_inst c.\name, \src_reg + .option pop + ret +.endm + +.macro gen_test_inst_c name + __gen_test_inst_c \name, a0 +.endm + + +.macro gen_test_inst_load_c_sp name + .option push + gen_func_header c_\name\()sp, +c + sp_stack_prologue a1 + copy_long_to t0, a0, sp + c.ldsp a0, 0(sp) + sp_stack_epilogue a1 + .option pop + ret +.endm + +.macro lb_sp_sb_a0 reg, offset + lb_sb \reg, \offset, sp, a0 +.endm + +.macro gen_test_inst_store_c_sp inst_name + .option push + gen_func_header c_\inst_name\()sp, +c + /* Misalign stack pointer */ + sp_stack_prologue a1 + /* Misalign access */ + c.sdsp a2, 0(sp) + copy_long_to t0, sp, a0 + sp_stack_epilogue a1 + .option pop + ret +.endm + + + /* + * a0 = addr to load from + * a1 = address offset + * a2 = value to be loaded + */ +gen_test_inst lh +gen_test_inst lhu +gen_test_inst lw +gen_test_inst lwu +gen_test_inst ld +#ifdef __riscv_compressed +gen_test_inst_c lw +gen_test_inst_c ld +gen_test_inst_load_c_sp ld +#endif + +/* + * a0 = addr where to store value + * a1 = address offset + * a2 = value to be stored + */ +gen_test_inst sh +gen_test_inst sw +gen_test_inst sd +#ifdef __riscv_compressed +gen_test_inst_c sw +gen_test_inst_c sd +gen_test_inst_store_c_sp sd +#endif + diff --git a/tools/testing/selftests/riscv/misaligned/misaligned.c b/tools/testing/selftests/riscv/misaligned/misaligned.c new file mode 100644 index 000000000000..c66aa87ec03e --- /dev/null +++ b/tools/testing/selftests/riscv/misaligned/misaligned.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025 Rivos Inc. + * + * Authors: + * Clément Léger <cleger@rivosinc.com> + */ +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <linux/ptrace.h> +#include "../../kselftest_harness.h" + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <float.h> +#include <errno.h> +#include <math.h> +#include <string.h> +#include <signal.h> +#include <stdbool.h> +#include <unistd.h> +#include <inttypes.h> +#include <ucontext.h> + +#include <sys/prctl.h> + +#define stringify(s) __stringify(s) +#define __stringify(s) #s + +#define VAL16 0x1234 +#define VAL32 0xDEADBEEF +#define VAL64 0x45674321D00DF789 + +#define VAL_float 78951.234375 +#define VAL_double 567890.512396965789589290 + +static bool float_equal(float a, float b) +{ + float scaled_epsilon; + float difference = fabsf(a - b); + + // Scale to the largest value. + a = fabsf(a); + b = fabsf(b); + if (a > b) + scaled_epsilon = FLT_EPSILON * a; + else + scaled_epsilon = FLT_EPSILON * b; + + return difference <= scaled_epsilon; +} + +static bool double_equal(double a, double b) +{ + double scaled_epsilon; + double difference = fabsf(a - b); + + // Scale to the largest value. + a = fabs(a); + b = fabs(b); + if (a > b) + scaled_epsilon = DBL_EPSILON * a; + else + scaled_epsilon = DBL_EPSILON * b; + + return difference <= scaled_epsilon; +} + +#define fpu_load_proto(__inst, __type) \ +extern __type test_ ## __inst(unsigned long fp_reg, void *addr, unsigned long offset, __type value) + +fpu_load_proto(flw, float); +fpu_load_proto(fld, double); +fpu_load_proto(c_flw, float); +fpu_load_proto(c_fld, double); +fpu_load_proto(c_fldsp, double); + +#define fpu_store_proto(__inst, __type) \ +extern void test_ ## __inst(unsigned long fp_reg, void *addr, unsigned long offset, __type value) + +fpu_store_proto(fsw, float); +fpu_store_proto(fsd, double); +fpu_store_proto(c_fsw, float); +fpu_store_proto(c_fsd, double); +fpu_store_proto(c_fsdsp, double); + +#define gp_load_proto(__inst, __type) \ +extern __type test_ ## __inst(void *addr, unsigned long offset, __type value) + +gp_load_proto(lh, uint16_t); +gp_load_proto(lhu, uint16_t); +gp_load_proto(lw, uint32_t); +gp_load_proto(lwu, uint32_t); +gp_load_proto(ld, uint64_t); +gp_load_proto(c_lw, uint32_t); +gp_load_proto(c_ld, uint64_t); +gp_load_proto(c_ldsp, uint64_t); + +#define gp_store_proto(__inst, __type) \ +extern void test_ ## __inst(void *addr, unsigned long offset, __type value) + +gp_store_proto(sh, uint16_t); +gp_store_proto(sw, uint32_t); +gp_store_proto(sd, uint64_t); +gp_store_proto(c_sw, uint32_t); +gp_store_proto(c_sd, uint64_t); +gp_store_proto(c_sdsp, uint64_t); + +#define TEST_GP_LOAD(__inst, __type_size) \ +TEST(gp_load_ ## __inst) \ +{ \ + int offset, ret; \ + uint8_t buf[16] __attribute__((aligned(16))); \ + \ + ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT); \ + ASSERT_EQ(ret, 0); \ + \ + for (offset = 1; offset < __type_size / 8; offset++) { \ + uint ## __type_size ## _t val = VAL ## __type_size; \ + uint ## __type_size ## _t *ptr = (uint ## __type_size ## _t *) (buf + offset); \ + memcpy(ptr, &val, sizeof(val)); \ + val = test_ ## __inst(ptr, offset, val); \ + EXPECT_EQ(VAL ## __type_size, val); \ + } \ +} + +TEST_GP_LOAD(lh, 16); +TEST_GP_LOAD(lhu, 16); +TEST_GP_LOAD(lw, 32); +TEST_GP_LOAD(lwu, 32); +TEST_GP_LOAD(ld, 64); +#ifdef __riscv_compressed +TEST_GP_LOAD(c_lw, 32); +TEST_GP_LOAD(c_ld, 64); +TEST_GP_LOAD(c_ldsp, 64); +#endif + +#define TEST_GP_STORE(__inst, __type_size) \ +TEST(gp_load_ ## __inst) \ +{ \ + int offset, ret; \ + uint8_t buf[16] __attribute__((aligned(16))); \ + \ + ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT); \ + ASSERT_EQ(ret, 0); \ + \ + for (offset = 1; offset < __type_size / 8; offset++) { \ + uint ## __type_size ## _t val = VAL ## __type_size; \ + uint ## __type_size ## _t *ptr = (uint ## __type_size ## _t *) (buf + offset); \ + memset(ptr, 0, sizeof(val)); \ + test_ ## __inst(ptr, offset, val); \ + memcpy(&val, ptr, sizeof(val)); \ + EXPECT_EQ(VAL ## __type_size, val); \ + } \ +} +TEST_GP_STORE(sh, 16); +TEST_GP_STORE(sw, 32); +TEST_GP_STORE(sd, 64); +#ifdef __riscv_compressed +TEST_GP_STORE(c_sw, 32); +TEST_GP_STORE(c_sd, 64); +TEST_GP_STORE(c_sdsp, 64); +#endif + +#define __TEST_FPU_LOAD(__type, __inst, __reg_start, __reg_end) \ +TEST(fpu_load_ ## __inst) \ +{ \ + int i, ret, offset, fp_reg; \ + uint8_t buf[16] __attribute__((aligned(16))); \ + \ + ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT); \ + ASSERT_EQ(ret, 0); \ + \ + for (fp_reg = __reg_start; fp_reg < __reg_end; fp_reg++) { \ + for (offset = 1; offset < 4; offset++) { \ + void *load_addr = (buf + offset); \ + __type val = VAL_ ## __type ; \ + \ + memcpy(load_addr, &val, sizeof(val)); \ + val = test_ ## __inst(fp_reg, load_addr, offset, val); \ + EXPECT_TRUE(__type ##_equal(val, VAL_## __type)); \ + } \ + } \ +} +#define TEST_FPU_LOAD(__type, __inst) \ + __TEST_FPU_LOAD(__type, __inst, 0, 32) +#define TEST_FPU_LOAD_COMPRESSED(__type, __inst) \ + __TEST_FPU_LOAD(__type, __inst, 8, 16) + +TEST_FPU_LOAD(float, flw) +TEST_FPU_LOAD(double, fld) +#ifdef __riscv_compressed +TEST_FPU_LOAD_COMPRESSED(double, c_fld) +TEST_FPU_LOAD_COMPRESSED(double, c_fldsp) +#endif + +#define __TEST_FPU_STORE(__type, __inst, __reg_start, __reg_end) \ +TEST(fpu_store_ ## __inst) \ +{ \ + int i, ret, offset, fp_reg; \ + uint8_t buf[16] __attribute__((aligned(16))); \ + \ + ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT); \ + ASSERT_EQ(ret, 0); \ + \ + for (fp_reg = __reg_start; fp_reg < __reg_end; fp_reg++) { \ + for (offset = 1; offset < 4; offset++) { \ + \ + void *store_addr = (buf + offset); \ + __type val = VAL_ ## __type ; \ + \ + test_ ## __inst(fp_reg, store_addr, offset, val); \ + memcpy(&val, store_addr, sizeof(val)); \ + EXPECT_TRUE(__type ## _equal(val, VAL_## __type)); \ + } \ + } \ +} +#define TEST_FPU_STORE(__type, __inst) \ + __TEST_FPU_STORE(__type, __inst, 0, 32) +#define TEST_FPU_STORE_COMPRESSED(__type, __inst) \ + __TEST_FPU_STORE(__type, __inst, 8, 16) + +TEST_FPU_STORE(float, fsw) +TEST_FPU_STORE(double, fsd) +#ifdef __riscv_compressed +TEST_FPU_STORE_COMPRESSED(double, c_fsd) +TEST_FPU_STORE_COMPRESSED(double, c_fsdsp) +#endif + +TEST_SIGNAL(gen_sigbus, SIGBUS) +{ + uint32_t *ptr; + uint8_t buf[16] __attribute__((aligned(16))); + int ret; + + ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_SIGBUS); + ASSERT_EQ(ret, 0); + + ptr = (uint32_t *)(buf + 1); + *ptr = 0xDEADBEEFULL; +} + +int main(int argc, char **argv) +{ + int ret, val; + + ret = prctl(PR_GET_UNALIGN, &val); + if (ret == -1 && errno == EINVAL) + ksft_exit_skip("SKIP GET_UNALIGN_CTL not supported\n"); + + exit(test_harness_run(argc, argv)); +} -- 2.49.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2025-05-01 20:51 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2025-04-14 12:34 [PATCH 0/5] riscv: misaligned: fix interruptible context and add tests Clément Léger 2025-04-14 12:34 ` [PATCH 1/5] riscv: misaligned: factorize trap handling Clément Léger 2025-04-21 7:06 ` Alexandre Ghiti 2025-04-22 7:57 ` Clément Léger 2025-04-22 9:44 ` Peter Zijlstra 2025-04-22 10:17 ` Clément Léger 2025-05-01 20:41 ` Maciej W. Rozycki 2025-05-01 20:51 ` Maciej W. Rozycki 2025-04-14 12:34 ` [PATCH 2/5] riscv: misaligned: enable IRQs while handling misaligned accesses Clément Léger 2025-04-21 7:13 ` Alexandre Ghiti 2025-04-14 12:34 ` [PATCH 3/5] riscv: misaligned: use get_user() instead of __get_user() Clément Léger 2025-04-21 7:21 ` Alexandre Ghiti 2025-04-14 12:34 ` [PATCH 4/5] Documentation/sysctl: add riscv to unaligned-trap supported archs Clément Léger 2025-04-21 7:22 ` Alexandre Ghiti 2025-04-14 12:34 ` [PATCH 5/5] selftests: riscv: add misaligned access testing Clément Léger
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®