Skip to content

Commit

Permalink
KVM: x86/PVM: Explicitly request the GPC refresh if activation fails
Browse files Browse the repository at this point in the history
The commit eb49d06 ("KVM: x86/PVM: Store the valid value for
MSR_PVM_VCPU_STRUCT unconditionally") aimed to address the failure to
restore a snapshot due to the MSR_PVM_VCPU_STRUCT restoration failure by
storing the value before kvm_gpc_activate(). However, this fix worked
accidentally as the GPC is refreshed by timer IRQ handling instead of
adding memslot. If there is no timer IRQ injecting before the first VM
entry, it will cause the host to panic due to the NULL pointer access of
'pvcs_gpc.khva'. Therefore, refer to the PVM specification, a GPC
refresh request is made if the GPC fails to activate during the MSR
setting by the host.  For the guest, setting an invalid MSR value will
trigger a triple fault. Additionally, a WARN_ON_ONCE() is added in
pvm_vcpu_run() to capture unexpected bugs if 'pvcs_gpc.khva' is NULL and
MSR value is not NULL.

Fixes: eb49d06 ("KVM: x86/PVM: Store the valid value for MSR_PVM_VCPU_STRUCT unconditionally")
Signed-off-by: Hou Wenlong <[email protected]>
Link: #7
  • Loading branch information
bysui committed Apr 29, 2024
1 parent 312df69 commit 1a43f74
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions arch/x86/kvm/pvm/pvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1188,15 +1188,17 @@ static int pvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
* failure in kvm_gpc_activate() because no memslot has been
* added yet. As a consequence, the VM will panic after the VM
* restore since the GPC is not active. However, if we store
* the value even if kvm_gpc_activate() fails later when the
* GPC is active, it can be refreshed by the addition of the
* user memory region before the VM entry.
* the value and make a 'KVM_REQ_GPC_REFRESH' request when
* kvm_gpc_activate() fails later, the GPC can be refreshed by
* the request serving before the VM entry. If the guest writes
* an invalid value, the request will trigger a triple fault in
* request serving.
*/
pvm->msr_vcpu_struct = data;
if (!data)
kvm_gpc_deactivate(&pvm->pvcs_gpc);
else if (kvm_gpc_activate(&pvm->pvcs_gpc, data, PAGE_SIZE))
return 1;
kvm_make_request(KVM_REQ_GPC_REFRESH, vcpu);
break;
case MSR_PVM_SUPERVISOR_RSP:
pvm->msr_supervisor_rsp = msr_info->data;
Expand Down Expand Up @@ -2732,6 +2734,16 @@ static fastpath_t pvm_vcpu_run(struct kvm_vcpu *vcpu)
if (pvm->non_pvm_mode)
return EXIT_FASTPATH_NONE;

/*
* Per to PVM specification, if the GPC of PVCS is invalid, meaning
* 'pvcs_gpc.khva' is NULL, then 'pvm->msr_vcpu_struct' must also be
* NULL.
*/
if (WARN_ON_ONCE(!pvm->pvcs_gpc.khva && pvm->msr_vcpu_struct)) {
kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
return EXIT_FASTPATH_NONE;
}

trace_kvm_entry(vcpu);

pvm_load_guest_xsave_state(vcpu);
Expand Down

0 comments on commit 1a43f74

Please sign in to comment.