Skip to content

Commit 8ce7ef8

Browse files
committed
KVM: x86/PVM: Handle #VE events
The #VE events that occur during the running of a PVM guest would exit to PVM, so PVM needs to handle it. The handling needs to be split into two steps. The first step is to obtain the #VE information in pvm_vcpu_run_noinstr() after the VM exits, as early as possible before any further operations that may trigger a nested #VE. Then, the cached information can be used in handling #VE in handle_exit_exception(). And only EXIT_REASON_CPUID is allowed for now. Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
1 parent ff988cc commit 8ce7ef8

1 file changed

Lines changed: 38 additions & 12 deletions

File tree

arch/x86/kvm/pvm/pvm.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,6 +2212,19 @@ static int handle_exit_breakpoint(struct kvm_vcpu *vcpu)
22122212
return 1;
22132213
}
22142214

2215+
static void handle_cpuid(struct kvm_vcpu *vcpu)
2216+
{
2217+
u32 eax, ebx, ecx, edx;
2218+
2219+
eax = kvm_rax_read(vcpu);
2220+
ecx = kvm_rcx_read(vcpu);
2221+
kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx, false);
2222+
kvm_rax_write(vcpu, eax);
2223+
kvm_rbx_write(vcpu, ebx);
2224+
kvm_rcx_write(vcpu, ecx);
2225+
kvm_rdx_write(vcpu, edx);
2226+
}
2227+
22152228
static bool handle_synthetic_instruction_pvm_cpuid(struct kvm_vcpu *vcpu)
22162229
{
22172230
/* invlpg 0xffffffffff4d5650; cpuid; */
@@ -2222,26 +2235,39 @@ static bool handle_synthetic_instruction_pvm_cpuid(struct kvm_vcpu *vcpu)
22222235
if (kvm_read_guest_virt(vcpu, kvm_get_linear_rip(vcpu),
22232236
insns, sizeof(insns), &e) == 0 &&
22242237
memcmp(insns, pvm_synthetic_cpuid_insns, sizeof(insns)) == 0) {
2225-
u32 eax, ebx, ecx, edx;
2226-
22272238
if (unlikely(pvm_guest_allowed_va(vcpu, PVM_SYNTHETIC_CPUID_ADDRESS)))
22282239
kvm_mmu_invlpg(vcpu, PVM_SYNTHETIC_CPUID_ADDRESS);
22292240

2230-
eax = kvm_rax_read(vcpu);
2231-
ecx = kvm_rcx_read(vcpu);
2232-
kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx, false);
2233-
kvm_rax_write(vcpu, eax);
2234-
kvm_rbx_write(vcpu, ebx);
2235-
kvm_rcx_write(vcpu, ecx);
2236-
kvm_rdx_write(vcpu, edx);
2237-
2241+
handle_cpuid(vcpu);
22382242
kvm_rip_write(vcpu, kvm_rip_read(vcpu) + sizeof(insns));
22392243
return true;
22402244
}
22412245

22422246
return false;
22432247
}
22442248

2249+
/*
2250+
* Handle the guest initiated #VE.
2251+
*
2252+
* Only EXIT_REASON_CPUID is allowed for now, see virt_exception_user()
2253+
* in arch/x86/coco/tdx/tdx.c.
2254+
*/
2255+
static void handle_exit_virtual_exception(struct kvm_vcpu *vcpu)
2256+
{
2257+
struct vcpu_pvm *pvm = to_pvm(vcpu);
2258+
2259+
switch (pvm->exit_ve.exit_reason) {
2260+
case EXIT_REASON_CPUID:
2261+
handle_cpuid(vcpu);
2262+
kvm_rip_write(vcpu, kvm_rip_read(vcpu) + pvm->exit_ve.instr_len);
2263+
break;
2264+
default:
2265+
pr_warn("Unexpected #VE: %lld\n", pvm->exit_ve.exit_reason);
2266+
kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
2267+
break;
2268+
}
2269+
}
2270+
22452271
static int handle_exit_exception(struct kvm_vcpu *vcpu)
22462272
{
22472273
struct vcpu_pvm *pvm = to_pvm(vcpu);
@@ -2315,8 +2341,8 @@ static int handle_exit_exception(struct kvm_vcpu *vcpu)
23152341
// NMI is handled by pvm_vcpu_run_noinstr().
23162342
return 1;
23172343
case VE_VECTOR:
2318-
// TODO: tdx_handle_virt_exception(regs, &pvm->exit_ve); break;
2319-
goto unknown_exit_reason;
2344+
handle_exit_virtual_exception(vcpu);
2345+
return 1;
23202346
case X86_TRAP_VC:
23212347
// TODO: handle the second part for #VC.
23222348
goto unknown_exit_reason;

0 commit comments

Comments
 (0)