RISC-V: KVM: Inject instruction access fault on unmapped guest fetch

When an instruction guest-page-fault targets a GPA that is not backed
by any memslot, KVM has no MMIO emulation path for the fetch. Load and
store guest-page faults can be routed through MMIO emulation, but an
instruction fetch has no data payload or access size for userspace to
complete in the same way.

Treat this case as an architectural access fault in the guest. On bare
metal, fetching from an inaccessible physical address raises an
instruction access fault for the supervisor to handle through its trap
vector. Reflect EXC_INST_ACCESS back to the guest so the guest observes
the same class of exception rather than leaving the fetch as a
host-handled condition.

stval contains the virtual address of the portion of the instruction that
caused the fault, while sepc points to the beginning of the instruction.

Signed-off-by: Qingwei Hu <qingwei.hu@bytedance.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260707122548.281685-1-qingwei.hu@bytedance.com
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Qingwei Hu
2026-07-07 20:25:48 +08:00
committed by Anup Patel
parent 298276da73
commit 4d638dc091

View File

@@ -38,6 +38,25 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
return kvm_riscv_vcpu_mmio_store(vcpu, run,
fault_addr,
trap->htinst);
case EXC_INST_GUEST_PAGE_FAULT: {
/*
* No memslot backs this GPA and an instruction fetch
* cannot be emulated as MMIO. On bare metal a fetch
* from an unbacked physical address raises an
* instruction access fault, so reflect that back to
* the guest.
*/
struct kvm_cpu_trap inst_trap = {
.sepc = trap->sepc,
.scause = EXC_INST_ACCESS,
.stval = trap->stval,
.htval = 0,
.htinst = 0,
};
kvm_riscv_vcpu_trap_redirect(vcpu, &inst_trap);
return 1;
}
default:
return -EOPNOTSUPP;
};