Skip to content

Commit 974555d

Browse files
fangyu0809avpatel
authored andcommitted
RISC-V: KVM: Fix guest page fault within HLV* instructions
When executing HLV* instructions at the HS mode, a guest page fault may occur when a g-stage page table migration between triggering the virtual instruction exception and executing the HLV* instruction. This may be a corner case, and one simpler way to handle this is to re-execute the instruction where the virtual instruction exception occurred, and the guest page fault will be automatically handled. Fixes: b91f0e4 ("RISC-V: KVM: Factor-out instruction emulation into separate sources") Signed-off-by: Fangyu Yu <fangyu.yu@linux.alibaba.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20251121133543.46822-1-fangyu.yu@linux.alibaba.com Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent df60cb2 commit 974555d

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

arch/riscv/kvm/vcpu_insn.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,22 @@ static int system_opcode_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
298298
return (rc <= 0) ? rc : 1;
299299
}
300300

301+
static bool is_load_guest_page_fault(unsigned long scause)
302+
{
303+
/**
304+
* If a g-stage page fault occurs, the direct approach
305+
* is to let the g-stage page fault handler handle it
306+
* naturally, however, calling the g-stage page fault
307+
* handler here seems rather strange.
308+
* Considering this is a corner case, we can directly
309+
* return to the guest and re-execute the same PC, this
310+
* will trigger a g-stage page fault again and then the
311+
* regular g-stage page fault handler will populate
312+
* g-stage page table.
313+
*/
314+
return (scause == EXC_LOAD_GUEST_PAGE_FAULT);
315+
}
316+
301317
/**
302318
* kvm_riscv_vcpu_virtual_insn -- Handle virtual instruction trap
303319
*
@@ -323,6 +339,8 @@ int kvm_riscv_vcpu_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
323339
ct->sepc,
324340
&utrap);
325341
if (utrap.scause) {
342+
if (is_load_guest_page_fault(utrap.scause))
343+
return 1;
326344
utrap.sepc = ct->sepc;
327345
kvm_riscv_vcpu_trap_redirect(vcpu, &utrap);
328346
return 1;
@@ -378,6 +396,8 @@ int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
378396
insn = kvm_riscv_vcpu_unpriv_read(vcpu, true, ct->sepc,
379397
&utrap);
380398
if (utrap.scause) {
399+
if (is_load_guest_page_fault(utrap.scause))
400+
return 1;
381401
/* Redirect trap if we failed to read instruction */
382402
utrap.sepc = ct->sepc;
383403
kvm_riscv_vcpu_trap_redirect(vcpu, &utrap);
@@ -504,6 +524,8 @@ int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
504524
insn = kvm_riscv_vcpu_unpriv_read(vcpu, true, ct->sepc,
505525
&utrap);
506526
if (utrap.scause) {
527+
if (is_load_guest_page_fault(utrap.scause))
528+
return 1;
507529
/* Redirect trap if we failed to read instruction */
508530
utrap.sepc = ct->sepc;
509531
kvm_riscv_vcpu_trap_redirect(vcpu, &utrap);

0 commit comments

Comments
 (0)