Skip to content

Commit

Permalink
KVM: VMX: Use common x86's uret MSR list as the one true list
Browse files Browse the repository at this point in the history
Drop VMX's global list of user return MSRs now that VMX doesn't resort said
list to isolate "active" MSRs, i.e. now that VMX's list and x86's list have
the same MSRs in the same order.

In addition to eliminating the redundant list, this will also allow moving
more of the list management into common x86.

Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20210504171734.1434054-11-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
sean-jc authored and bonzini committed May 7, 2021
1 parent ee9d22e commit 8ea8b8d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 57 deletions.
1 change: 1 addition & 0 deletions arch/x86/include/asm/kvm_host.h
Expand Up @@ -1777,6 +1777,7 @@ int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
unsigned long icr, int op_64_bit);

void kvm_define_user_return_msr(unsigned index, u32 msr);
int kvm_find_user_return_msr(u32 msr);
int kvm_probe_user_return_msr(u32 msr);
int kvm_set_user_return_msr(unsigned index, u64 val, u64 mask);

Expand Down
97 changes: 40 additions & 57 deletions arch/x86/kvm/vmx/vmx.c
Expand Up @@ -454,26 +454,7 @@ static inline void vmx_segment_cache_clear(struct vcpu_vmx *vmx)

static unsigned long host_idt_base;

/*
* Though SYSCALL is only supported in 64-bit mode on Intel CPUs, kvm
* will emulate SYSCALL in legacy mode if the vendor string in guest
* CPUID.0:{EBX,ECX,EDX} is "AuthenticAMD" or "AMDisbetter!" To
* support this emulation, MSR_STAR is included in the list for i386,
* but is never loaded into hardware. MSR_CSTAR is also never loaded
* into hardware and is here purely for emulation purposes.
*/
static u32 vmx_uret_msrs_list[] = {
#ifdef CONFIG_X86_64
MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR,
#endif
MSR_EFER, MSR_TSC_AUX, MSR_STAR,
MSR_IA32_TSX_CTRL,
};

/*
* Number of user return MSRs that are actually supported in hardware.
* vmx_uret_msrs_list is modified when KVM is loaded to drop unsupported MSRs.
*/
/* Number of user return MSRs that are actually supported in hardware. */
static int vmx_nr_uret_msrs;

#if IS_ENABLED(CONFIG_HYPERV)
Expand Down Expand Up @@ -703,22 +684,11 @@ static bool is_valid_passthrough_msr(u32 msr)
return r;
}

static inline int __vmx_find_uret_msr(u32 msr)
{
int i;

for (i = 0; i < vmx_nr_uret_msrs; ++i) {
if (vmx_uret_msrs_list[i] == msr)
return i;
}
return -1;
}

struct vmx_uret_msr *vmx_find_uret_msr(struct vcpu_vmx *vmx, u32 msr)
{
int i;

i = __vmx_find_uret_msr(msr);
i = kvm_find_user_return_msr(msr);
if (i >= 0)
return &vmx->guest_uret_msrs[i];
return NULL;
Expand Down Expand Up @@ -1086,7 +1056,7 @@ static bool update_transition_efer(struct vcpu_vmx *vmx)
return false;
}

i = __vmx_find_uret_msr(MSR_EFER);
i = kvm_find_user_return_msr(MSR_EFER);
if (i < 0)
return false;

Expand Down Expand Up @@ -6922,6 +6892,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)

static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
{
struct vmx_uret_msr *tsx_ctrl;
struct vcpu_vmx *vmx;
int i, cpu, err;

Expand All @@ -6946,29 +6917,25 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)

for (i = 0; i < vmx_nr_uret_msrs; ++i) {
vmx->guest_uret_msrs[i].data = 0;

switch (vmx_uret_msrs_list[i]) {
case MSR_IA32_TSX_CTRL:
/*
* TSX_CTRL_CPUID_CLEAR is handled in the CPUID
* interception. Keep the host value unchanged to avoid
* changing CPUID bits under the host kernel's feet.
*
* hle=0, rtm=0, tsx_ctrl=1 can be found with some
* combinations of new kernel and old userspace. If
* those guests run on a tsx=off host, do allow guests
* to use TSX_CTRL, but do not change the value on the
* host so that TSX remains always disabled.
*/
if (boot_cpu_has(X86_FEATURE_RTM))
vmx->guest_uret_msrs[i].mask = ~(u64)TSX_CTRL_CPUID_CLEAR;
else
vmx->guest_uret_msrs[i].mask = 0;
break;
default:
vmx->guest_uret_msrs[i].mask = -1ull;
break;
}
vmx->guest_uret_msrs[i].mask = -1ull;
}
tsx_ctrl = vmx_find_uret_msr(vmx, MSR_IA32_TSX_CTRL);
if (tsx_ctrl) {
/*
* TSX_CTRL_CPUID_CLEAR is handled in the CPUID interception.
* Keep the host value unchanged to avoid changing CPUID bits
* under the host kernel's feet.
*
* hle=0, rtm=0, tsx_ctrl=1 can be found with some combinations
* of new kernel and old userspace. If those guests run on a
* tsx=off host, do allow guests to use TSX_CTRL, but do not
* change the value on the host so that TSX remains always
* disabled.
*/
if (boot_cpu_has(X86_FEATURE_RTM))
vmx->guest_uret_msrs[i].mask = ~(u64)TSX_CTRL_CPUID_CLEAR;
else
vmx->guest_uret_msrs[i].mask = 0;
}

err = alloc_loaded_vmcs(&vmx->vmcs01);
Expand Down Expand Up @@ -7829,6 +7796,22 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {

static __init void vmx_setup_user_return_msrs(void)
{

/*
* Though SYSCALL is only supported in 64-bit mode on Intel CPUs, kvm
* will emulate SYSCALL in legacy mode if the vendor string in guest
* CPUID.0:{EBX,ECX,EDX} is "AuthenticAMD" or "AMDisbetter!" To
* support this emulation, MSR_STAR is included in the list for i386,
* but is never loaded into hardware. MSR_CSTAR is also never loaded
* into hardware and is here purely for emulation purposes.
*/
const u32 vmx_uret_msrs_list[] = {
#ifdef CONFIG_X86_64
MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR,
#endif
MSR_EFER, MSR_TSC_AUX, MSR_STAR,
MSR_IA32_TSX_CTRL,
};
u32 msr;
int i;

Expand All @@ -7841,7 +7824,7 @@ static __init void vmx_setup_user_return_msrs(void)
continue;

kvm_define_user_return_msr(vmx_nr_uret_msrs, msr);
vmx_uret_msrs_list[vmx_nr_uret_msrs++] = msr;
vmx_nr_uret_msrs++;
}
}

Expand Down
12 changes: 12 additions & 0 deletions arch/x86/kvm/x86.c
Expand Up @@ -364,6 +364,18 @@ void kvm_define_user_return_msr(unsigned slot, u32 msr)
}
EXPORT_SYMBOL_GPL(kvm_define_user_return_msr);

int kvm_find_user_return_msr(u32 msr)
{
int i;

for (i = 0; i < user_return_msrs_global.nr; ++i) {
if (user_return_msrs_global.msrs[i] == msr)
return i;
}
return -1;
}
EXPORT_SYMBOL_GPL(kvm_find_user_return_msr);

static void kvm_user_return_msr_cpu_online(void)
{
unsigned int cpu = smp_processor_id();
Expand Down

0 comments on commit 8ea8b8d

Please sign in to comment.