|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3 25/39] xen/riscv: add guest store emulation for trapped MMIO accesses
Extend the guest page fault handler with store emulation to support MMIO
write accesses.
Like emulate_load(), emulate_store() obtains the trapped instruction with
insn_fetch_faulted(), which also deals with a fault taken while re-reading
it, and decodes it with decode_ldst_insn(). As with the load path, the
access is completed synchronously through do_mmio().
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>
---
Changes in v3:
- Update the commit message.
- Zero-initialize di, as decode_ldst_insn() expects it to start out zeroed.
- Adjust to guest_gpr() taking the decoded instruction rather than a bare
register number.
- Don't change the prototype of emulate_store(): the stub takes a pointer
to const already.
---
Changes in v2:
- Move the emulation code to the new arch/riscv/emulate.c, leaving traps.c
with trap dispatch only.
- Split the patch up: the instruction fetch and the mask/match chain now
live in "xen/riscv: add helpers for decoding a trapped load or store"
(struct decoded_insn, insn_fetch_faulted(), decode_ldst_insn(),
guest_gpr(), advance_pc()), so only emulate_store() itself is left here.
- Since the decoder is now shared with the load path, reject an encoding
which is not a store (!di.is_write) explicitly; in v2 the mask/match
chain was store-only and could not match a load.
- Recognize the XLEN=64-only encodings by the guest's effective XLEN
(guest_xlen()) rather than by Xen's own (CONFIG_RISCV_32). Besides those
encodings simply being reserved on RV32, the compressed ones are ambiguous
there: C.SD and C.FSW share an encoding, and likewise C.SDSP and C.FSWSP.
- Read the source register through guest_gpr() instead of the
GET_RS2()/GET_RS2S()/GET_RS2C() macros; which of the three register
fields an encoding names is now decided by decode_ldst_insn().
- Take the faulting address from struct guest_fault, filled in by
resolve_faulting_gpa(), rather than from the fault_addr parameter.
- Drop the description of a fault taken while re-reading the trapped
instruction: that code is now in the patch adding the decoding helpers,
where a G-stage fault is reported to the guest as CAUSE_FETCH_ACCESS.
- Update the commit message accordingly.
---
---
xen/arch/riscv/emulate.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/xen/arch/riscv/emulate.c b/xen/arch/riscv/emulate.c
index ff8cba7d5116..7ae3f438a726 100644
--- a/xen/arch/riscv/emulate.c
+++ b/xen/arch/riscv/emulate.c
@@ -454,7 +454,26 @@ static int emulate_load(const struct guest_fault *gf)
static int emulate_store(const struct guest_fault *gf)
{
- return -EOPNOTSUPP;
+ struct cpu_user_regs *regs = gf->regs;
+ mmio_info_t info = { .is_write = true };
+ struct decoded_insn di = {};
+ int rc;
+
+ if ( insn_fetch_faulted(gf, &di) )
+ return 0;
+
+ if ( !decode_ldst_insn(&di, guest_xlen(regs)) || !di.is_write )
+ return -EOPNOTSUPP;
+
+ info.data = *guest_gpr(regs, &di);
+
+ rc = do_mmio(&info, gf->gpa, di.len);
+ if ( rc )
+ return rc;
+
+ advance_pc(regs, di.insn_len);
+
+ return 0;
}
static void inject_access_fault(const struct guest_fault *gf)
--
2.55.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |