Skip to content

Commit

Permalink
KVM: x86/PVM: Switch to PVM mode as soon as possible
Browse files Browse the repository at this point in the history
Per to the PVM specification, the 'event_flags' in PVCS is specific to
PVM mode and unrelated to the x86 specification. Therefore, it will not
be changed in non-PVM mode. During VM store, the VMM may inject an event
to invoke the vCPU, and the event is delivered directly before the
vcpu_run() callback. However, the PVM mode switching occurs after
vcpu_run(), so the vCPU delivers the event in non-PVM mode.
Consequently, in pvm_set_rflags(), 'event_flags' is not updated, and the
guest will observe that the X86_EFLAGS_IF is set during event handling,
leading to a BUG_ON() in the guest. Additionally, when the guest exits,
the 'X86_EFLAGS_IF' bit will be updated to the value maintained in the
hypervisor. Therefore, the hypervisor may inject an event during the
event handling of the guest before interrupt is enabled.

To address this issue, switch to PVM mode during the CR0 setting and CS
segment setting, and add a WARN_ON_ONCE() to detect event injection in
non-PVM mode.

Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
  • Loading branch information
bysui committed Apr 10, 2024
1 parent 180111a commit b80d914
Showing 1 changed file with 15 additions and 0 deletions.
15 changes: 15 additions & 0 deletions arch/x86/kvm/pvm/pvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,8 @@ static void pvm_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int
if (cpl == 0 && !pvm->non_pvm_mode)
pvm_standard_msr_star(pvm);
}
if (pvm->non_pvm_mode)
try_to_convert_to_pvm_mode(vcpu);
break;
case VCPU_SREG_LDTR:
// pvm doesn't support LDT
Expand Down Expand Up @@ -1623,6 +1625,19 @@ static int do_pvm_supervisor_interrupt(struct kvm_vcpu *vcpu, int vector,
static int do_pvm_event(struct kvm_vcpu *vcpu, int vector,
bool has_error_code, u64 error_code)
{
/*
* Unlike in VMX, the injected event is delivered by the guest before
* VM entry, so it is not allowed to inject event in non-PVM mode.
* Although, we have attempted to switch to PVM mode before event
* injection, the VMM may still inject event in non-PVM mode, so issue
* a warning for VMM in such cases. Also, try to swith to PVM mode if

This comment has been minimized.

Copy link
@lkml-likexu

lkml-likexu Apr 10, 2024

s/swith/switch/, try to use checkpatch.pl :D

This comment has been minimized.

Copy link
@bysui

bysui Apr 10, 2024

Author Collaborator

Oh, sorry. It was my mistake. I will make sure to do it before pushing the branch next time. Additionally, the commit message is outdated too. :(

* something is broken in the hypervisor.
*/
if (unlikely(to_pvm(vcpu)->non_pvm_mode)) {
pr_warn_ratelimited("Inject event in non-PVM mode");
try_to_convert_to_pvm_mode(vcpu);
}

if (!is_smod(to_pvm(vcpu)))
return do_pvm_user_event(vcpu, vector, has_error_code, error_code);

Expand Down

0 comments on commit b80d914

Please sign in to comment.