|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4 22/42] 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 the only MMIO handler registered is the vAPLIC one, so in
practice every trapped guest store ends up in vaplic_mmio_ops' write
handler.
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>
Reviewed-by: Baptiste Le Duc <baptiste.le-duc@xxxxxxxxxx>
---
Changes in v4:
- Update the commit message.
- Add Reviewed-by: Baptiste Le Duc <baptiste.le-duc@xxxxxxxxxx>.
---
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 e95642b7617f..170485ef4c01 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.56.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |