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

[PATCH v1 17/17] xen/riscv: add guest store emulation for trapped MMIO accesses



Extend the guest page fault handler with store emulation to support MMIO
write accesses.

The instruction decode mirrors emulate_load() and, like it, is adapted
from Linux's KVM RISC-V implementation. As with the load path, the
completion is synchronous through try_handle_mmio() rather than KVM's
userspace exit/return split, since Xen's MMIO handlers run in the
hypervisor. Faults taken while re-reading the trapped instruction are
handled by decode_trapped_insn(), shared with the load path.

When a guest store instruction faults, the trapped instruction is decoded
using HTINST or, if unavailable, fetched via unprivileged access. At the
moment only virtual interrupt controller (vINTC) traps are expected to
occur, since it is currently the only backend registered with the MMIO
handler dispatch, so in practice the store is emulated via the vINTC
backend.

Together with load emulation, this completes the basic MMIO handling path
needed for virtual interrupt controller support on RISC-V.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
 xen/arch/riscv/traps.c | 55 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c
index 12690ae37aba..18156627d7cd 100644
--- a/xen/arch/riscv/traps.c
+++ b/xen/arch/riscv/traps.c
@@ -377,7 +377,60 @@ static int emulate_load(unsigned long fault_addr, unsigned 
long htinst)
 
 static int emulate_store(unsigned long fault_addr, unsigned long htinst)
 {
-    return -EOPNOTSUPP;
+    struct cpu_user_regs *regs = vcpu_guest_cpu_user_regs(current);
+    mmio_info_t info = { .is_write = true };
+    register_t data;
+    unsigned long insn;
+    unsigned int len, insn_len;
+    int rc;
+
+    if ( decode_trapped_insn(htinst, &insn, &insn_len) )
+        return 0;
+
+    data = GET_RS2(insn, regs);
+
+    if ( (insn & INSN_MASK_SB) == INSN_MATCH_SB )
+        len = 1;
+    else if ( (insn & INSN_MASK_SH) == INSN_MATCH_SH )
+        len = 2;
+    else if ( (insn & INSN_MASK_SW) == INSN_MATCH_SW )
+        len = 4;
+    else if ( (insn & INSN_MASK_C_SW) == INSN_MATCH_C_SW )
+    {
+        len = 4;
+        data = GET_RS2S(insn, regs);
+    }
+    else if ( (insn & INSN_MASK_C_SWSP) == INSN_MATCH_C_SWSP )
+    {
+        len = 4;
+        data = GET_RS2C(insn, regs);
+    }
+#ifndef CONFIG_RISCV_32
+    else if ( (insn & INSN_MASK_SD) == INSN_MATCH_SD )
+        len = 8;
+    else if ( (insn & INSN_MASK_C_SD) == INSN_MATCH_C_SD )
+    {
+        len = 8;
+        data = GET_RS2S(insn, regs);
+    }
+    else if ( (insn & INSN_MASK_C_SDSP) == INSN_MATCH_C_SDSP )
+    {
+        len = 8;
+        data = GET_RS2C(insn, regs);
+    }
+#endif
+    else
+        return -EOPNOTSUPP;
+
+    info.data = data;
+
+    rc = do_mmio(&info, fault_addr, len);
+    if ( rc )
+        return rc;
+
+    advance_pc(regs, insn_len);
+
+    return 0;
 }
 
 static void handle_guest_page_fault(unsigned long cause,
-- 
2.54.0




 


Rackspace

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