[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen master] xen/riscv: look up the exception table for any trap taken in Xen context



commit 73b802624afab7a8c0a8c1d447af6d57cbe3c70d
Author:     Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
AuthorDate: Tue Oct 27 08:59:41 2026 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Oct 27 08:59:41 2026 +0100

    xen/riscv: look up the exception table for any trap taken in Xen context
    
    do_trap() consulted the exception table only for CAUSE_ILLEGAL_INSTRUCTION,
    which covers csr_read_safe() but not a probing access faulting with a page
    fault cause: it would reach do_unexpected_trap() instead of its fixup.
    There is no such access yet, the A/D update scheme probe will be the first.
    
    Move the lookup ahead of the cause switch, and only do it for exceptions
    taken in Xen context. Both other cases must skip it:
    
    - Traps taken from the guest: sepc is then a guest address, which the
      guest can point at an address listed in the exception table, making Xen
      act on an entry fully under guest control. Entries are matched by exact
      address, so this needs no more than a numerical collision.
    
    - Interrupts: an interrupt taken at an address listed in the table would
      otherwise be "fixed up" as if the access itself had faulted, silently
      skipping it.
    
    Returning early skips check_for_pcpu_work(), which is correct: that only
    runs for traps taken from the guest.
    
    Cache the "trap came from the guest" test in a local as it is now used
    three times.
    
    Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
    [Baptiste: drop the parts depending on the vAPLIC/vIMSIC series, adapt
     the commit message]
    Assisted-by: Claude:claude-opus-5-5
    Signed-off-by: Baptiste Le Duc <baptiste.le-duc@xxxxxxxxxx>
    Reviewed-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
    Acked-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/riscv/traps.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c
index 10d6855d91..dd53454f23 100644
--- a/xen/arch/riscv/traps.c
+++ b/xen/arch/riscv/traps.c
@@ -195,12 +195,33 @@ void do_trap(struct cpu_user_regs *cpu_regs)
 {
     register_t pc = cpu_regs->sepc;
     unsigned long cause = csr_read(CSR_SCAUSE);
+    bool from_guest = cpu_regs->hstatus & HSTATUS_SPV;
+
+    /*
+     * A synchronous trap taken in Xen context may come from a probing access
+     * like csr_read_safe(), covered by an exception table entry which resumes
+     * execution past the faulting instruction.
+     *
+     * Traps taken from the guest must never be fixed up: sepc is then a guest
+     * address, which the guest could point at an address listed in the
+     * exception table, making Xen act on an entry fully under guest control.
+     *
+     * Interrupts must be excluded too: one taken at an address which happens
+     * to be listed in the exception table would otherwise be "fixed up" as if
+     * the access itself had faulted, silently skipping it.
+     *
+     * Returning early skips check_for_pcpu_work() below, which is correct:
+     * that only runs for traps taken from the guest.
+     */
+    if ( !from_guest && !(cause & CAUSE_IRQ_FLAG) &&
+         fixup_exception(cpu_regs) )
+        return;
 
     switch ( cause )
     {
     case CAUSE_VIRTUAL_SUPERVISOR_ECALL:
         /* CAUSE_VIRTUAL_SUPERVISOR_ECALL should come from VS-mode */
-        BUG_ON(!(cpu_regs->hstatus & HSTATUS_SPV));
+        BUG_ON(!from_guest);
 
         vsbi_handle_ecall(cpu_regs);
         break;
@@ -219,9 +240,6 @@ void do_trap(struct cpu_user_regs *cpu_regs)
             break;
         }
 
-        if ( fixup_exception(cpu_regs) )
-            break;
-
         fallthrough;
     default:
         if ( cause & CAUSE_IRQ_FLAG )
@@ -253,7 +271,7 @@ void do_trap(struct cpu_user_regs *cpu_regs)
         break;
     }
 
-    if ( cpu_regs->hstatus & HSTATUS_SPV )
+    if ( from_guest )
         check_for_pcpu_work();
 }
 
--
generated by git-patchbot for /home/xen/git/xen.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.