History

KVM: x86: Add KVM_RUN_X86_GUEST_MODE kvm_run flag

When a vCPU is interrupted by a signal while running a nested guest, KVM will exit to userspace with L2 state. However, userspace has no way to know whether it sees L1 or L2 state (besides calling KVM_GET_STATS_FD, which does not have a stable ABI). This causes multiple problems: The simplest one is L2 state corruption when userspace marks the sregs as dirty. See this mailing list thread [1] for a complete discussion. Another problem is that if userspace decides to continue by emulating instructions, it will unknowingly emulate with L2 state as if L1 doesn't exist, which can be considered a weird guest escape. Introduce a new flag, KVM_RUN_X86_GUEST_MODE, in the kvm_run data structure, which is set when the vCPU exited while running a nested guest. Also introduce a new capability, KVM_CAP_X86_GUEST_MODE, to advertise the functionality to userspace. [1] https://lore.kernel.org/kvm/20240416123558.212040-1-julian.stecklina@cyberus-technology.de/T/#m280aadcb2e10ae02c191a7dc4ed4b711a74b1f55

Thomas Prescher committed 2 years ago

Commit 85542ad1 parent 508f0c74 files · +22 −0Browse files

Unified · Split

4 files
  1. Documentation/virt/kvm/api.rst +17 −0
  2. arch/x86/include/uapi/asm/kvm.h +1 −0
  3. arch/x86/kvm/x86.c +3 −0
  4. include/uapi/linux/kvm.h +1 −0
Documentation/virt/kvm/api.rst+17−0
@@ -6419,6 +6419,9 @@ affect the device's behavior. Current defined flags:: · 6418 unmodified lines
6419 #define KVM_RUN_X86_SMM (1 << 0)6419 #define KVM_RUN_X86_SMM (1 << 0)
6420 /* x86, set if bus lock detected in VM */6420 /* x86, set if bus lock detected in VM */
6421 #define KVM_RUN_X86_BUS_LOCK (1 << 1)6421 #define KVM_RUN_X86_BUS_LOCK (1 << 1)
6422 /* x86, set if the VCPU is executing a nested (L2) guest */
6423 #define KVM_RUN_X86_GUEST_MODE (1 << 2)
6424
6422 /* arm64, set for KVM_EXIT_DEBUG */6425 /* arm64, set for KVM_EXIT_DEBUG */
6423 #define KVM_DEBUG_ARCH_HSR_HIGH_VALID (1 << 0)6426 #define KVM_DEBUG_ARCH_HSR_HIGH_VALID (1 << 0)
6424 6427
@@ -8089,6 +8092,20 @@ by KVM_CHECK_EXTENSION. · 1664 unmodified lines
8089Note: Userspace is responsible for correctly configuring CPUID 0x15, a.k.a. the8092Note: Userspace is responsible for correctly configuring CPUID 0x15, a.k.a. the
8090core crystal clock frequency, if a non-zero CPUID 0x15 is exposed to the guest.8093core crystal clock frequency, if a non-zero CPUID 0x15 is exposed to the guest.
8091 8094
80957.36 KVM_CAP_X86_GUEST_MODE
8096------------------------------
8097
8098:Architectures: x86
8099:Returns: Informational only, -EINVAL on direct KVM_ENABLE_CAP.
8100
8101The presence of this capability indicates that KVM_RUN will update the
8102KVM_RUN_X86_GUEST_MODE bit in kvm_run.flags to indicate whether the
8103vCPU was executing nested guest code when it exited.
8104
8105KVM exits with the register state of either the L1 or L2 guest
8106depending on which executed at the time of an exit. Userspace must
8107take care to differentiate between these cases.
8108
80928. Other capabilities.81098. Other capabilities.
8093======================8110======================
8094 8111
arch/x86/include/uapi/asm/kvm.h+1−0
@@ -106,6 +106,7 @@ struct kvm_ioapic_state { · 105 unmodified lines
106 106
107#define KVM_RUN_X86_SMM (1 << 0)107#define KVM_RUN_X86_SMM (1 << 0)
108#define KVM_RUN_X86_BUS_LOCK (1 << 1)108#define KVM_RUN_X86_BUS_LOCK (1 << 1)
109#define KVM_RUN_X86_GUEST_MODE (1 << 2)
109 110
110/* for KVM_GET_REGS and KVM_SET_REGS */111/* for KVM_GET_REGS and KVM_SET_REGS */
111struct kvm_regs {112struct kvm_regs {
arch/x86/kvm/x86.c+3−0
@@ -4704,6 +4704,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 4703 unmodified lines
4704 case KVM_CAP_VM_DISABLE_NX_HUGE_PAGES:4704 case KVM_CAP_VM_DISABLE_NX_HUGE_PAGES:
4705 case KVM_CAP_IRQFD_RESAMPLE:4705 case KVM_CAP_IRQFD_RESAMPLE:
4706 case KVM_CAP_MEMORY_FAULT_INFO:4706 case KVM_CAP_MEMORY_FAULT_INFO:
4707 case KVM_CAP_X86_GUEST_MODE:
4707 r = 1;4708 r = 1;
4708 break;4709 break;
4709 case KVM_CAP_X86_APIC_BUS_CYCLES_NS:4710 case KVM_CAP_X86_APIC_BUS_CYCLES_NS:
@@ -10277,6 +10278,8 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) · 5567 unmodified lines
10277 10278
10278 if (is_smm(vcpu))10279 if (is_smm(vcpu))
10279 kvm_run->flags |= KVM_RUN_X86_SMM;10280 kvm_run->flags |= KVM_RUN_X86_SMM;
10281 if (is_guest_mode(vcpu))
10282 kvm_run->flags |= KVM_RUN_X86_GUEST_MODE;
10280}10283}
10281 10284
10282static void update_cr8_intercept(struct kvm_vcpu *vcpu)10285static void update_cr8_intercept(struct kvm_vcpu *vcpu)
include/uapi/linux/kvm.h+1−0
@@ -918,6 +918,7 @@ struct kvm_enable_cap { · 917 unmodified lines
918#define KVM_CAP_GUEST_MEMFD 234918#define KVM_CAP_GUEST_MEMFD 234
919#define KVM_CAP_VM_TYPES 235919#define KVM_CAP_VM_TYPES 235
920#define KVM_CAP_X86_APIC_BUS_CYCLES_NS 236920#define KVM_CAP_X86_APIC_BUS_CYCLES_NS 236
921#define KVM_CAP_X86_GUEST_MODE 237
921 922
922struct kvm_irq_routing_irqchip {923struct kvm_irq_routing_irqchip {
923 __u32 irqchip;924 __u32 irqchip;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t