2018-12-04 05:53:08 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
#ifndef __KVM_X86_VMX_H
|
|
|
|
#define __KVM_X86_VMX_H
|
|
|
|
|
|
|
|
#include <linux/kvm_host.h>
|
|
|
|
|
|
|
|
#include <asm/kvm.h>
|
2018-10-24 16:05:10 +08:00
|
|
|
#include <asm/intel_pt.h>
|
2018-12-04 05:53:08 +08:00
|
|
|
|
|
|
|
#include "capabilities.h"
|
KVM: nVMX: Reset register cache (available and dirty masks) on VMCS switch
Reset the per-vCPU available and dirty register masks when switching
between vmcs01 and vmcs02, as the masks track state relative to the
current VMCS. The stale masks don't cause problems in the current code
base because the registers are either unconditionally written on nested
transitions or, in the case of segment registers, have an additional
tracker that is manually reset.
Note, by dropping (previously implicitly, now explicitly) the dirty mask
when switching the active VMCS, KVM is technically losing writes to the
associated fields. But, the only regs that can be dirtied (RIP, RSP and
PDPTRs) are unconditionally written on nested transitions, e.g. explicit
writeback is a waste of cycles, and a WARN_ON would be rather pointless.
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Message-Id: <20200415203454.8296-3-sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2020-04-16 04:34:51 +08:00
|
|
|
#include "kvm_cache_regs.h"
|
2020-09-24 02:31:11 +08:00
|
|
|
#include "posted_intr.h"
|
2018-12-04 05:53:08 +08:00
|
|
|
#include "vmcs.h"
|
2020-09-24 02:31:12 +08:00
|
|
|
#include "vmx_ops.h"
|
KVM: VMX: Add guest physical address check in EPT violation and misconfig
Check guest physical address against its maximum, which depends on the
guest MAXPHYADDR. If the guest's physical address exceeds the
maximum (i.e. has reserved bits set), inject a guest page fault with
PFERR_RSVD_MASK set.
This has to be done both in the EPT violation and page fault paths, as
there are complications in both cases with respect to the computation
of the correct error code.
For EPT violations, unfortunately the only possibility is to emulate,
because the access type in the exit qualification might refer to an
access to a paging structure, rather than to the access performed by
the program.
Trapping page faults instead is needed in order to correct the error code,
but the access type can be obtained from the original error code and
passed to gva_to_gpa. The corrections required in the error code are
subtle. For example, imagine that a PTE for a supervisor page has a reserved
bit set. On a supervisor-mode access, the EPT violation path would trigger.
However, on a user-mode access, the processor will not notice the reserved
bit and not include PFERR_RSVD_MASK in the error code.
Co-developed-by: Mohammed Gamal <mgamal@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200710154811.418214-8-mgamal@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2020-07-10 23:48:09 +08:00
|
|
|
#include "cpuid.h"
|
2018-12-04 05:53:08 +08:00
|
|
|
|
|
|
|
#define MSR_TYPE_R 1
|
|
|
|
#define MSR_TYPE_W 2
|
|
|
|
#define MSR_TYPE_RW 3
|
|
|
|
|
|
|
|
#define X2APIC_MSR(r) (APIC_BASE_MSR + ((r) >> 4))
|
|
|
|
|
2019-12-04 08:24:42 +08:00
|
|
|
#ifdef CONFIG_X86_64
|
2020-09-24 02:03:58 +08:00
|
|
|
#define MAX_NR_USER_RETURN_MSRS 7
|
2019-12-04 08:24:42 +08:00
|
|
|
#else
|
2020-09-24 02:03:58 +08:00
|
|
|
#define MAX_NR_USER_RETURN_MSRS 4
|
2019-12-04 08:24:42 +08:00
|
|
|
#endif
|
|
|
|
|
2020-09-24 02:03:56 +08:00
|
|
|
#define MAX_NR_LOADSTORE_MSRS 8
|
2018-12-04 05:53:08 +08:00
|
|
|
|
|
|
|
struct vmx_msrs {
|
|
|
|
unsigned int nr;
|
2020-09-24 02:03:56 +08:00
|
|
|
struct vmx_msr_entry val[MAX_NR_LOADSTORE_MSRS];
|
2018-12-04 05:53:08 +08:00
|
|
|
};
|
|
|
|
|
2020-09-24 02:03:58 +08:00
|
|
|
struct vmx_uret_msr {
|
2021-05-05 01:17:28 +08:00
|
|
|
bool load_into_hardware;
|
2018-12-04 05:53:08 +08:00
|
|
|
u64 data;
|
|
|
|
u64 mask;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum segment_cache_field {
|
|
|
|
SEG_FIELD_SEL = 0,
|
|
|
|
SEG_FIELD_BASE = 1,
|
|
|
|
SEG_FIELD_LIMIT = 2,
|
|
|
|
SEG_FIELD_AR = 3,
|
|
|
|
|
|
|
|
SEG_FIELD_NR = 4
|
|
|
|
};
|
|
|
|
|
2018-10-24 16:05:12 +08:00
|
|
|
#define RTIT_ADDR_RANGE 4
|
|
|
|
|
|
|
|
struct pt_ctx {
|
|
|
|
u64 ctl;
|
|
|
|
u64 status;
|
|
|
|
u64 output_base;
|
|
|
|
u64 output_mask;
|
|
|
|
u64 cr3_match;
|
|
|
|
u64 addr_a[RTIT_ADDR_RANGE];
|
|
|
|
u64 addr_b[RTIT_ADDR_RANGE];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct pt_desc {
|
|
|
|
u64 ctl_bitmask;
|
|
|
|
u32 addr_range;
|
|
|
|
u32 caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];
|
|
|
|
struct pt_ctx host;
|
|
|
|
struct pt_ctx guest;
|
|
|
|
};
|
2018-12-04 05:53:08 +08:00
|
|
|
|
2020-11-06 17:03:12 +08:00
|
|
|
union vmx_exit_reason {
|
|
|
|
struct {
|
|
|
|
u32 basic : 16;
|
|
|
|
u32 reserved16 : 1;
|
|
|
|
u32 reserved17 : 1;
|
|
|
|
u32 reserved18 : 1;
|
|
|
|
u32 reserved19 : 1;
|
|
|
|
u32 reserved20 : 1;
|
|
|
|
u32 reserved21 : 1;
|
|
|
|
u32 reserved22 : 1;
|
|
|
|
u32 reserved23 : 1;
|
|
|
|
u32 reserved24 : 1;
|
|
|
|
u32 reserved25 : 1;
|
2020-11-06 17:03:14 +08:00
|
|
|
u32 bus_lock_detected : 1;
|
2020-11-06 17:03:12 +08:00
|
|
|
u32 enclave_mode : 1;
|
|
|
|
u32 smi_pending_mtf : 1;
|
|
|
|
u32 smi_from_vmx_root : 1;
|
|
|
|
u32 reserved30 : 1;
|
|
|
|
u32 failed_vmentry : 1;
|
|
|
|
};
|
|
|
|
u32 full;
|
|
|
|
};
|
|
|
|
|
2021-02-02 22:36:08 +08:00
|
|
|
#define vcpu_to_lbr_desc(vcpu) (&to_vmx(vcpu)->lbr_desc)
|
|
|
|
#define vcpu_to_lbr_records(vcpu) (&to_vmx(vcpu)->lbr_desc.records)
|
|
|
|
|
|
|
|
bool intel_pmu_lbr_is_compatible(struct kvm_vcpu *vcpu);
|
2021-02-01 13:10:31 +08:00
|
|
|
bool intel_pmu_lbr_is_enabled(struct kvm_vcpu *vcpu);
|
2021-02-02 22:36:08 +08:00
|
|
|
|
2021-02-01 13:10:33 +08:00
|
|
|
int intel_pmu_create_guest_lbr_event(struct kvm_vcpu *vcpu);
|
2021-02-01 13:10:34 +08:00
|
|
|
void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu);
|
2021-02-01 13:10:33 +08:00
|
|
|
|
2021-02-02 22:36:08 +08:00
|
|
|
struct lbr_desc {
|
|
|
|
/* Basic info about guest LBR records. */
|
|
|
|
struct x86_pmu_lbr records;
|
2021-02-01 13:10:33 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Emulate LBR feature via passthrough LBR registers when the
|
|
|
|
* per-vcpu guest LBR event is scheduled on the current pcpu.
|
|
|
|
*
|
|
|
|
* The records may be inaccurate if the host reclaims the LBR.
|
|
|
|
*/
|
|
|
|
struct perf_event *event;
|
2021-02-01 13:10:35 +08:00
|
|
|
|
|
|
|
/* True if LBRs are marked as not intercepted in the MSR bitmap */
|
|
|
|
bool msr_passthrough;
|
2021-02-02 22:36:08 +08:00
|
|
|
};
|
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
/*
|
|
|
|
* The nested_vmx structure is part of vcpu_vmx, and holds information we need
|
|
|
|
* for correct emulation of VMX (i.e., nested VMX) on this vcpu.
|
|
|
|
*/
|
|
|
|
struct nested_vmx {
|
|
|
|
/* Has the level1 guest done vmxon? */
|
|
|
|
bool vmxon;
|
|
|
|
gpa_t vmxon_ptr;
|
|
|
|
bool pml_full;
|
|
|
|
|
|
|
|
/* The guest-physical address of the current VMCS L1 keeps for L2 */
|
|
|
|
gpa_t current_vmptr;
|
|
|
|
/*
|
|
|
|
* Cache of the guest's VMCS, existing outside of guest memory.
|
|
|
|
* Loaded from guest memory during VMPTRLD. Flushed to guest
|
|
|
|
* memory during VMCLEAR and VMPTRLD.
|
|
|
|
*/
|
|
|
|
struct vmcs12 *cached_vmcs12;
|
|
|
|
/*
|
|
|
|
* Cache of the guest's shadow VMCS, existing outside of guest
|
|
|
|
* memory. Loaded from guest memory during VM entry. Flushed
|
|
|
|
* to guest memory during VM exit.
|
|
|
|
*/
|
|
|
|
struct vmcs12 *cached_shadow_vmcs12;
|
2019-05-07 23:36:29 +08:00
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
/*
|
|
|
|
* Indicates if the shadow vmcs or enlightened vmcs must be updated
|
|
|
|
* with the data held by struct vmcs12.
|
|
|
|
*/
|
2019-05-07 23:36:27 +08:00
|
|
|
bool need_vmcs12_to_shadow_sync;
|
2018-12-04 05:53:08 +08:00
|
|
|
bool dirty_vmcs12;
|
|
|
|
|
2019-05-07 23:36:29 +08:00
|
|
|
/*
|
|
|
|
* Indicates lazily loaded guest state has not yet been decached from
|
|
|
|
* vmcs02.
|
|
|
|
*/
|
|
|
|
bool need_sync_vmcs02_to_vmcs12_rare;
|
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
/*
|
|
|
|
* vmcs02 has been initialized, i.e. state that is constant for
|
|
|
|
* vmcs02 has been written to the backing VMCS. Initialization
|
|
|
|
* is delayed until L1 actually attempts to run a nested VM.
|
|
|
|
*/
|
|
|
|
bool vmcs02_initialized;
|
|
|
|
|
|
|
|
bool change_vmcs01_virtual_apic_mode;
|
2020-03-21 05:28:23 +08:00
|
|
|
bool reload_vmcs01_apic_access_page;
|
2021-02-13 08:50:12 +08:00
|
|
|
bool update_vmcs01_cpu_dirty_logging;
|
2018-12-04 05:53:08 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Enlightened VMCS has been enabled. It does not mean that L1 has to
|
|
|
|
* use it. However, VMX features available to L1 will be limited based
|
|
|
|
* on what the enlightened VMCS supports.
|
|
|
|
*/
|
|
|
|
bool enlightened_vmcs_enabled;
|
|
|
|
|
|
|
|
/* L2 must run next, and mustn't decide to exit to L1. */
|
|
|
|
bool nested_run_pending;
|
|
|
|
|
2020-02-07 18:36:07 +08:00
|
|
|
/* Pending MTF VM-exit into L1. */
|
|
|
|
bool mtf_pending;
|
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
struct loaded_vmcs vmcs02;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Guest pages referred to in the vmcs02 with host-physical
|
|
|
|
* pointers, so we must keep them pinned while L2 runs.
|
|
|
|
*/
|
|
|
|
struct page *apic_access_page;
|
2019-02-01 04:24:37 +08:00
|
|
|
struct kvm_host_map virtual_apic_map;
|
2019-02-01 04:24:38 +08:00
|
|
|
struct kvm_host_map pi_desc_map;
|
2019-02-01 04:24:36 +08:00
|
|
|
|
|
|
|
struct kvm_host_map msr_bitmap_map;
|
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
struct pi_desc *pi_desc;
|
|
|
|
bool pi_pending;
|
|
|
|
u16 posted_intr_nv;
|
|
|
|
|
|
|
|
struct hrtimer preemption_timer;
|
2020-05-27 05:51:06 +08:00
|
|
|
u64 preemption_timer_deadline;
|
|
|
|
bool has_preemption_timer_deadline;
|
2018-12-04 05:53:08 +08:00
|
|
|
bool preemption_timer_expired;
|
|
|
|
|
|
|
|
/* to migrate it to L2 if VM_ENTRY_LOAD_DEBUG_CONTROLS is off */
|
|
|
|
u64 vmcs01_debugctl;
|
|
|
|
u64 vmcs01_guest_bndcfgs;
|
|
|
|
|
2019-11-11 20:30:55 +08:00
|
|
|
/* to migrate it to L1 if L2 writes to L1's CR8 directly */
|
|
|
|
int l1_tpr_threshold;
|
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
u16 vpid02;
|
|
|
|
u16 last_vpid;
|
|
|
|
|
|
|
|
struct nested_vmx_msrs msrs;
|
|
|
|
|
|
|
|
/* SMM related state */
|
|
|
|
struct {
|
|
|
|
/* in VMX operation on SMM entry? */
|
|
|
|
bool vmxon;
|
|
|
|
/* in guest mode on SMM entry? */
|
|
|
|
bool guest_mode;
|
|
|
|
} smm;
|
|
|
|
|
|
|
|
gpa_t hv_evmcs_vmptr;
|
2019-02-01 04:24:42 +08:00
|
|
|
struct kvm_host_map hv_evmcs_map;
|
2018-12-04 05:53:08 +08:00
|
|
|
struct hv_enlightened_vmcs *hv_evmcs;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct vcpu_vmx {
|
|
|
|
struct kvm_vcpu vcpu;
|
|
|
|
u8 fail;
|
2021-07-14 00:33:19 +08:00
|
|
|
u8 x2apic_msr_bitmap_mode;
|
2019-06-08 01:00:14 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If true, host state has been stored in vmx->loaded_vmcs for
|
|
|
|
* the CPU registers that only need to be switched when transitioning
|
|
|
|
* to/from the kernel, and the registers have been loaded with guest
|
|
|
|
* values. If false, host state is loaded in the CPU registers
|
|
|
|
* and vmx->loaded_vmcs->host_state is invalid.
|
|
|
|
*/
|
|
|
|
bool guest_state_loaded;
|
|
|
|
|
2020-04-16 04:34:53 +08:00
|
|
|
unsigned long exit_qualification;
|
2018-12-04 05:53:08 +08:00
|
|
|
u32 exit_intr_info;
|
|
|
|
u32 idt_vectoring_info;
|
|
|
|
ulong rflags;
|
2019-05-08 03:17:54 +08:00
|
|
|
|
2021-05-05 01:17:27 +08:00
|
|
|
/*
|
|
|
|
* User return MSRs are always emulated when enabled in the guest, but
|
|
|
|
* only loaded into hardware when necessary, e.g. SYSCALL #UDs outside
|
|
|
|
* of 64-bit mode or if EFER.SCE=1, thus the SYSCALL MSRs don't need to
|
|
|
|
* be loaded into hardware if those conditions aren't met.
|
|
|
|
*/
|
2020-09-24 02:03:58 +08:00
|
|
|
struct vmx_uret_msr guest_uret_msrs[MAX_NR_USER_RETURN_MSRS];
|
2020-09-24 02:04:01 +08:00
|
|
|
bool guest_uret_msrs_loaded;
|
2018-12-04 05:53:08 +08:00
|
|
|
#ifdef CONFIG_X86_64
|
|
|
|
u64 msr_host_kernel_gs_base;
|
|
|
|
u64 msr_guest_kernel_gs_base;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
u64 spec_ctrl;
|
2019-07-16 14:55:50 +08:00
|
|
|
u32 msr_ia32_umwait_control;
|
2018-12-04 05:53:08 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* loaded_vmcs points to the VMCS currently used in this vcpu. For a
|
|
|
|
* non-nested (L1) guest, it always points to vmcs01. For a nested
|
2019-06-08 01:00:14 +08:00
|
|
|
* guest (L2), it points to a different VMCS.
|
2018-12-04 05:53:08 +08:00
|
|
|
*/
|
|
|
|
struct loaded_vmcs vmcs01;
|
|
|
|
struct loaded_vmcs *loaded_vmcs;
|
2019-01-25 23:41:05 +08:00
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
struct msr_autoload {
|
|
|
|
struct vmx_msrs guest;
|
|
|
|
struct vmx_msrs host;
|
|
|
|
} msr_autoload;
|
|
|
|
|
2019-11-08 13:14:39 +08:00
|
|
|
struct msr_autostore {
|
|
|
|
struct vmx_msrs guest;
|
|
|
|
} msr_autostore;
|
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
struct {
|
|
|
|
int vm86_active;
|
|
|
|
ulong save_rflags;
|
|
|
|
struct kvm_segment segs[8];
|
|
|
|
} rmode;
|
|
|
|
struct {
|
|
|
|
u32 bitmask; /* 4 bits per segment (1 bit per field) */
|
|
|
|
struct kvm_save_segment {
|
|
|
|
u16 selector;
|
|
|
|
unsigned long base;
|
|
|
|
u32 limit;
|
|
|
|
u32 ar;
|
|
|
|
} seg[8];
|
|
|
|
} segment_cache;
|
|
|
|
int vpid;
|
|
|
|
bool emulation_required;
|
|
|
|
|
2020-11-06 17:03:12 +08:00
|
|
|
union vmx_exit_reason exit_reason;
|
2018-12-04 05:53:08 +08:00
|
|
|
|
|
|
|
/* Posted interrupt descriptor */
|
|
|
|
struct pi_desc pi_desc;
|
|
|
|
|
|
|
|
/* Support for a guest hypervisor (nested VMX) */
|
|
|
|
struct nested_vmx nested;
|
|
|
|
|
|
|
|
/* Dynamic PLE window. */
|
2019-09-06 10:17:21 +08:00
|
|
|
unsigned int ple_window;
|
2018-12-04 05:53:08 +08:00
|
|
|
bool ple_window_dirty;
|
|
|
|
|
|
|
|
bool req_immediate_exit;
|
|
|
|
|
|
|
|
/* Support for PML */
|
|
|
|
#define PML_ENTITY_NUM 512
|
|
|
|
struct page *pml_pg;
|
|
|
|
|
|
|
|
/* apic deadline value in host tsc */
|
|
|
|
u64 hv_deadline_tsc;
|
|
|
|
|
|
|
|
unsigned long host_debugctlmsr;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Only bits masked by msr_ia32_feature_control_valid_bits can be set in
|
x86/msr-index: Clean up bit defines for IA32_FEATURE_CONTROL MSR
As pointed out by Boris, the defines for bits in IA32_FEATURE_CONTROL
are quite a mouthful, especially the VMX bits which must differentiate
between enabling VMX inside and outside SMX (TXT) operation. Rename the
MSR and its bit defines to abbreviate FEATURE_CONTROL as FEAT_CTL to
make them a little friendlier on the eyes.
Arguably, the MSR itself should keep the full IA32_FEATURE_CONTROL name
to match Intel's SDM, but a future patch will add a dedicated Kconfig,
file and functions for the MSR. Using the full name for those assets is
rather unwieldy, so bite the bullet and use IA32_FEAT_CTL so that its
nomenclature is consistent throughout the kernel.
Opportunistically, fix a few other annoyances with the defines:
- Relocate the bit defines so that they immediately follow the MSR
define, e.g. aren't mistaken as belonging to MISC_FEATURE_CONTROL.
- Add whitespace around the block of feature control defines to make
it clear they're all related.
- Use BIT() instead of manually encoding the bit shift.
- Use "VMX" instead of "VMXON" to match the SDM.
- Append "_ENABLED" to the LMCE (Local Machine Check Exception) bit to
be consistent with the kernel's verbiage used for all other feature
control bits. Note, the SDM refers to the LMCE bit as LMCE_ON,
likely to differentiate it from IA32_MCG_EXT_CTL.LMCE_EN. Ignore
the (literal) one-off usage of _ON, the SDM is simply "wrong".
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20191221044513.21680-2-sean.j.christopherson@intel.com
2019-12-21 12:44:55 +08:00
|
|
|
* msr_ia32_feature_control. FEAT_CTL_LOCKED is always included
|
2018-12-04 05:53:08 +08:00
|
|
|
* in msr_ia32_feature_control_valid_bits.
|
|
|
|
*/
|
|
|
|
u64 msr_ia32_feature_control;
|
|
|
|
u64 msr_ia32_feature_control_valid_bits;
|
2021-04-12 12:21:40 +08:00
|
|
|
/* SGX Launch Control public key hash */
|
|
|
|
u64 msr_ia32_sgxlepubkeyhash[4];
|
|
|
|
|
2018-10-24 16:05:12 +08:00
|
|
|
struct pt_desc pt_desc;
|
2021-02-02 22:36:08 +08:00
|
|
|
struct lbr_desc lbr_desc;
|
2020-09-25 22:34:20 +08:00
|
|
|
|
|
|
|
/* Save desired MSR intercept (read: pass-through) state */
|
|
|
|
#define MAX_POSSIBLE_PASSTHROUGH_MSRS 13
|
|
|
|
struct {
|
|
|
|
DECLARE_BITMAP(read, MAX_POSSIBLE_PASSTHROUGH_MSRS);
|
|
|
|
DECLARE_BITMAP(write, MAX_POSSIBLE_PASSTHROUGH_MSRS);
|
|
|
|
} shadow_msr_intercept;
|
2018-12-04 05:53:08 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct kvm_vmx {
|
|
|
|
struct kvm kvm;
|
|
|
|
|
|
|
|
unsigned int tss_addr;
|
|
|
|
bool ept_identity_pagetable_done;
|
|
|
|
gpa_t ept_identity_map_addr;
|
|
|
|
};
|
|
|
|
|
2018-12-04 05:53:17 +08:00
|
|
|
bool nested_vmx_allowed(struct kvm_vcpu *vcpu);
|
2020-05-02 00:31:17 +08:00
|
|
|
void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu,
|
|
|
|
struct loaded_vmcs *buddy);
|
2018-12-04 05:53:16 +08:00
|
|
|
int allocate_vpid(void);
|
|
|
|
void free_vpid(int vpid);
|
|
|
|
void vmx_set_constant_host_state(struct vcpu_vmx *vmx);
|
|
|
|
void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu);
|
2019-05-08 00:06:31 +08:00
|
|
|
void vmx_set_host_fs_gs(struct vmcs_host_state *host, u16 fs_sel, u16 gs_sel,
|
|
|
|
unsigned long fs_base, unsigned long gs_base);
|
2018-12-04 05:53:16 +08:00
|
|
|
int vmx_get_cpl(struct kvm_vcpu *vcpu);
|
2021-09-13 22:09:54 +08:00
|
|
|
bool vmx_emulation_required(struct kvm_vcpu *vcpu);
|
2018-12-04 05:53:16 +08:00
|
|
|
unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu);
|
|
|
|
void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
|
|
|
|
u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu);
|
|
|
|
void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask);
|
2020-10-01 19:29:53 +08:00
|
|
|
int vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer);
|
2018-12-04 05:53:16 +08:00
|
|
|
void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
|
2020-10-07 09:44:15 +08:00
|
|
|
void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
|
2018-12-04 05:53:16 +08:00
|
|
|
void set_cr4_guest_host_mask(struct vcpu_vmx *vmx);
|
|
|
|
void ept_save_pdptrs(struct kvm_vcpu *vcpu);
|
|
|
|
void vmx_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
|
2021-07-14 00:33:07 +08:00
|
|
|
void __vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
|
KVM: x86: Get active PCID only when writing a CR3 value
Retrieve the active PCID only when writing a guest CR3 value, i.e. don't
get the PCID when using EPT or NPT. The PCID is especially problematic
for EPT as the bits have different meaning, and so the PCID and must be
manually stripped, which is annoying and unnecessary. And on VMX,
getting the active PCID also involves reading the guest's CR3 and
CR4.PCIDE, i.e. may add pointless VMREADs.
Opportunistically rename the pgd/pgd_level params to root_hpa and
root_level to better reflect their new roles. Keep the function names,
as "load the guest PGD" is still accurate/correct.
Last, and probably least, pass root_hpa as a hpa_t/u64 instead of an
unsigned long. The EPTP holds a 64-bit value, even in 32-bit mode, so
in theory EPT could support HIGHMEM for 32-bit KVM. Never mind that
doing so would require changing the MMU page allocators and reworking
the MMU to use kmap().
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20210305183123.3978098-2-seanjc@google.com>
Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2021-03-06 02:31:13 +08:00
|
|
|
u64 construct_eptp(struct kvm_vcpu *vcpu, hpa_t root_hpa, int root_level);
|
2020-09-24 02:44:48 +08:00
|
|
|
|
2021-06-23 01:22:44 +08:00
|
|
|
bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu);
|
2021-01-15 11:27:54 +08:00
|
|
|
void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu);
|
2020-04-23 10:25:44 +08:00
|
|
|
bool vmx_nmi_blocked(struct kvm_vcpu *vcpu);
|
|
|
|
bool vmx_interrupt_blocked(struct kvm_vcpu *vcpu);
|
2018-12-04 05:53:16 +08:00
|
|
|
bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu);
|
|
|
|
void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked);
|
|
|
|
void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu);
|
2020-09-24 02:04:06 +08:00
|
|
|
struct vmx_uret_msr *vmx_find_uret_msr(struct vcpu_vmx *vmx, u32 msr);
|
2020-09-25 22:34:18 +08:00
|
|
|
void pt_update_intercept_for_msr(struct kvm_vcpu *vcpu);
|
2019-05-20 12:27:47 +08:00
|
|
|
void vmx_update_host_rsp(struct vcpu_vmx *vmx, unsigned long host_rsp);
|
2020-12-31 08:26:57 +08:00
|
|
|
bool __vmx_vcpu_run(struct vcpu_vmx *vmx, unsigned long *regs, bool launched);
|
2020-09-24 02:03:57 +08:00
|
|
|
int vmx_find_loadstore_msr_slot(struct vmx_msrs *m, u32 msr);
|
2020-08-21 07:05:45 +08:00
|
|
|
void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu);
|
KVM: VMX: Invert the inlining of MSR interception helpers
Invert the inline declarations of the MSR interception helpers between
the wrapper, vmx_set_intercept_for_msr(), and the core implementations,
vmx_{dis,en}able_intercept_for_msr(). Letting the compiler _not_
inline the implementation reduces KVM's code footprint by ~3k bytes.
Back when the helpers were added in commit 904e14fb7cb9 ("KVM: VMX: make
MSR bitmaps per-VCPU"), both the wrapper and the implementations were
__always_inline because the end code distilled down to a few conditionals
and a bit operation. Today, the implementations involve a variety of
checks and bit ops in order to support userspace MSR filtering.
Furthermore, the vast majority of calls to manipulate MSR interception
are not performance sensitive, e.g. vCPU creation and x2APIC toggling.
On the other hand, the one path that is performance sensitive, dynamic
LBR passthrough, uses the wrappers, i.e. is largely untouched by
inverting the inlining.
In short, forcing the low level MSR interception code to be inlined no
longer makes sense.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20210423221912.3857243-1-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2021-04-24 06:19:12 +08:00
|
|
|
|
|
|
|
void vmx_disable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type);
|
|
|
|
void vmx_enable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type);
|
|
|
|
|
2021-05-27 02:44:13 +08:00
|
|
|
u64 vmx_get_l2_tsc_offset(struct kvm_vcpu *vcpu);
|
|
|
|
u64 vmx_get_l2_tsc_multiplier(struct kvm_vcpu *vcpu);
|
|
|
|
|
KVM: VMX: Invert the inlining of MSR interception helpers
Invert the inline declarations of the MSR interception helpers between
the wrapper, vmx_set_intercept_for_msr(), and the core implementations,
vmx_{dis,en}able_intercept_for_msr(). Letting the compiler _not_
inline the implementation reduces KVM's code footprint by ~3k bytes.
Back when the helpers were added in commit 904e14fb7cb9 ("KVM: VMX: make
MSR bitmaps per-VCPU"), both the wrapper and the implementations were
__always_inline because the end code distilled down to a few conditionals
and a bit operation. Today, the implementations involve a variety of
checks and bit ops in order to support userspace MSR filtering.
Furthermore, the vast majority of calls to manipulate MSR interception
are not performance sensitive, e.g. vCPU creation and x2APIC toggling.
On the other hand, the one path that is performance sensitive, dynamic
LBR passthrough, uses the wrappers, i.e. is largely untouched by
inverting the inlining.
In short, forcing the low level MSR interception code to be inlined no
longer makes sense.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20210423221912.3857243-1-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2021-04-24 06:19:12 +08:00
|
|
|
static inline void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr,
|
|
|
|
int type, bool value)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
vmx_enable_intercept_for_msr(vcpu, msr, type);
|
|
|
|
else
|
|
|
|
vmx_disable_intercept_for_msr(vcpu, msr, type);
|
|
|
|
}
|
|
|
|
|
2021-02-13 08:50:12 +08:00
|
|
|
void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu);
|
2018-12-04 05:53:16 +08:00
|
|
|
|
2018-12-04 05:53:07 +08:00
|
|
|
static inline u8 vmx_get_rvi(void)
|
|
|
|
{
|
|
|
|
return vmcs_read16(GUEST_INTR_STATUS) & 0xff;
|
|
|
|
}
|
|
|
|
|
2019-05-08 03:17:54 +08:00
|
|
|
#define BUILD_CONTROLS_SHADOW(lname, uname) \
|
|
|
|
static inline void lname##_controls_set(struct vcpu_vmx *vmx, u32 val) \
|
|
|
|
{ \
|
2019-05-08 03:17:58 +08:00
|
|
|
if (vmx->loaded_vmcs->controls_shadow.lname != val) { \
|
|
|
|
vmcs_write32(uname, val); \
|
|
|
|
vmx->loaded_vmcs->controls_shadow.lname = val; \
|
|
|
|
} \
|
2019-05-08 03:17:54 +08:00
|
|
|
} \
|
KVM: nVMX: Pull KVM L0's desired controls directly from vmcs01
When preparing controls for vmcs02, grab KVM's desired controls from
vmcs01's shadow state instead of recalculating the controls from scratch,
or in the secondary execution controls, instead of using the dedicated
cache. Calculating secondary exec controls is eye-poppingly expensive
due to the guest CPUID checks, hence the dedicated cache, but the other
calculations aren't exactly free either.
Explicitly clear several bits (x2APIC, DESC exiting, and load EFER on
exit) as appropriate as they may be set in vmcs01, whereas the previous
implementation relied on dynamic bits being cleared in the calculator.
Intentionally propagate VM_{ENTRY,EXIT}_LOAD_IA32_PERF_GLOBAL_CTRL from
vmcs01 to vmcs02. Whether or not PERF_GLOBAL_CTRL is loaded depends on
whether or not perf itself is active, so unless perf stops between the
exit from L1 and entry to L2, vmcs01 will hold the desired value. This
is purely an optimization as atomic_switch_perf_msrs() will set/clear
the control as needed at VM-Enter, i.e. it avoids two extra VMWRITEs in
the case where perf is active (versus starting with the bits clear in
vmcs02, which was the previous behavior).
Cc: Zeng Guang <guang.zeng@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20210810171952.2758100-3-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2021-08-11 01:19:50 +08:00
|
|
|
static inline u32 __##lname##_controls_get(struct loaded_vmcs *vmcs) \
|
|
|
|
{ \
|
|
|
|
return vmcs->controls_shadow.lname; \
|
|
|
|
} \
|
2019-05-08 03:17:54 +08:00
|
|
|
static inline u32 lname##_controls_get(struct vcpu_vmx *vmx) \
|
|
|
|
{ \
|
KVM: nVMX: Pull KVM L0's desired controls directly from vmcs01
When preparing controls for vmcs02, grab KVM's desired controls from
vmcs01's shadow state instead of recalculating the controls from scratch,
or in the secondary execution controls, instead of using the dedicated
cache. Calculating secondary exec controls is eye-poppingly expensive
due to the guest CPUID checks, hence the dedicated cache, but the other
calculations aren't exactly free either.
Explicitly clear several bits (x2APIC, DESC exiting, and load EFER on
exit) as appropriate as they may be set in vmcs01, whereas the previous
implementation relied on dynamic bits being cleared in the calculator.
Intentionally propagate VM_{ENTRY,EXIT}_LOAD_IA32_PERF_GLOBAL_CTRL from
vmcs01 to vmcs02. Whether or not PERF_GLOBAL_CTRL is loaded depends on
whether or not perf itself is active, so unless perf stops between the
exit from L1 and entry to L2, vmcs01 will hold the desired value. This
is purely an optimization as atomic_switch_perf_msrs() will set/clear
the control as needed at VM-Enter, i.e. it avoids two extra VMWRITEs in
the case where perf is active (versus starting with the bits clear in
vmcs02, which was the previous behavior).
Cc: Zeng Guang <guang.zeng@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20210810171952.2758100-3-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2021-08-11 01:19:50 +08:00
|
|
|
return __##lname##_controls_get(vmx->loaded_vmcs); \
|
2019-05-08 03:17:54 +08:00
|
|
|
} \
|
|
|
|
static inline void lname##_controls_setbit(struct vcpu_vmx *vmx, u32 val) \
|
|
|
|
{ \
|
|
|
|
lname##_controls_set(vmx, lname##_controls_get(vmx) | val); \
|
|
|
|
} \
|
|
|
|
static inline void lname##_controls_clearbit(struct vcpu_vmx *vmx, u32 val) \
|
|
|
|
{ \
|
|
|
|
lname##_controls_set(vmx, lname##_controls_get(vmx) & ~val); \
|
2018-12-04 05:53:07 +08:00
|
|
|
}
|
2019-05-08 03:17:54 +08:00
|
|
|
BUILD_CONTROLS_SHADOW(vm_entry, VM_ENTRY_CONTROLS)
|
|
|
|
BUILD_CONTROLS_SHADOW(vm_exit, VM_EXIT_CONTROLS)
|
2019-05-08 03:17:55 +08:00
|
|
|
BUILD_CONTROLS_SHADOW(pin, PIN_BASED_VM_EXEC_CONTROL)
|
2019-05-08 03:17:56 +08:00
|
|
|
BUILD_CONTROLS_SHADOW(exec, CPU_BASED_VM_EXEC_CONTROL)
|
2019-05-08 03:17:57 +08:00
|
|
|
BUILD_CONTROLS_SHADOW(secondary_exec, SECONDARY_VM_EXEC_CONTROL)
|
2018-12-04 05:53:07 +08:00
|
|
|
|
KVM: nVMX: Reset register cache (available and dirty masks) on VMCS switch
Reset the per-vCPU available and dirty register masks when switching
between vmcs01 and vmcs02, as the masks track state relative to the
current VMCS. The stale masks don't cause problems in the current code
base because the registers are either unconditionally written on nested
transitions or, in the case of segment registers, have an additional
tracker that is manually reset.
Note, by dropping (previously implicitly, now explicitly) the dirty mask
when switching the active VMCS, KVM is technically losing writes to the
associated fields. But, the only regs that can be dirtied (RIP, RSP and
PDPTRs) are unconditionally written on nested transitions, e.g. explicit
writeback is a waste of cycles, and a WARN_ON would be rather pointless.
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Message-Id: <20200415203454.8296-3-sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2020-04-16 04:34:51 +08:00
|
|
|
static inline void vmx_register_cache_reset(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)
|
|
|
|
| (1 << VCPU_EXREG_RFLAGS)
|
|
|
|
| (1 << VCPU_EXREG_PDPTR)
|
|
|
|
| (1 << VCPU_EXREG_SEGMENTS)
|
2020-05-02 12:32:31 +08:00
|
|
|
| (1 << VCPU_EXREG_CR0)
|
2020-04-16 04:34:53 +08:00
|
|
|
| (1 << VCPU_EXREG_CR3)
|
2020-05-02 12:32:30 +08:00
|
|
|
| (1 << VCPU_EXREG_CR4)
|
2020-04-16 04:34:54 +08:00
|
|
|
| (1 << VCPU_EXREG_EXIT_INFO_1)
|
|
|
|
| (1 << VCPU_EXREG_EXIT_INFO_2));
|
KVM: nVMX: Reset register cache (available and dirty masks) on VMCS switch
Reset the per-vCPU available and dirty register masks when switching
between vmcs01 and vmcs02, as the masks track state relative to the
current VMCS. The stale masks don't cause problems in the current code
base because the registers are either unconditionally written on nested
transitions or, in the case of segment registers, have an additional
tracker that is manually reset.
Note, by dropping (previously implicitly, now explicitly) the dirty mask
when switching the active VMCS, KVM is technically losing writes to the
associated fields. But, the only regs that can be dirtied (RIP, RSP and
PDPTRs) are unconditionally written on nested transitions, e.g. explicit
writeback is a waste of cycles, and a WARN_ON would be rather pointless.
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Message-Id: <20200415203454.8296-3-sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2020-04-16 04:34:51 +08:00
|
|
|
vcpu->arch.regs_dirty = 0;
|
|
|
|
}
|
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
static inline struct kvm_vmx *to_kvm_vmx(struct kvm *kvm)
|
|
|
|
{
|
|
|
|
return container_of(kvm, struct kvm_vmx, kvm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
return container_of(vcpu, struct vcpu_vmx, vcpu);
|
|
|
|
}
|
|
|
|
|
2020-04-16 04:34:53 +08:00
|
|
|
static inline unsigned long vmx_get_exit_qual(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
|
|
|
|
|
|
if (!kvm_register_is_available(vcpu, VCPU_EXREG_EXIT_INFO_1)) {
|
|
|
|
kvm_register_mark_available(vcpu, VCPU_EXREG_EXIT_INFO_1);
|
|
|
|
vmx->exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
|
|
|
|
}
|
|
|
|
return vmx->exit_qualification;
|
|
|
|
}
|
|
|
|
|
2020-04-16 04:34:54 +08:00
|
|
|
static inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
|
|
|
|
|
|
if (!kvm_register_is_available(vcpu, VCPU_EXREG_EXIT_INFO_2)) {
|
|
|
|
kvm_register_mark_available(vcpu, VCPU_EXREG_EXIT_INFO_2);
|
|
|
|
vmx->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
|
|
|
|
}
|
|
|
|
return vmx->exit_intr_info;
|
|
|
|
}
|
|
|
|
|
2019-02-12 03:02:52 +08:00
|
|
|
struct vmcs *alloc_vmcs_cpu(bool shadow, int cpu, gfp_t flags);
|
2018-12-04 05:53:07 +08:00
|
|
|
void free_vmcs(struct vmcs *vmcs);
|
|
|
|
int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs);
|
|
|
|
void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs);
|
|
|
|
void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs);
|
|
|
|
|
|
|
|
static inline struct vmcs *alloc_vmcs(bool shadow)
|
|
|
|
{
|
2019-02-12 03:02:52 +08:00
|
|
|
return alloc_vmcs_cpu(shadow, raw_smp_processor_id(),
|
|
|
|
GFP_KERNEL_ACCOUNT);
|
2018-12-04 05:53:07 +08:00
|
|
|
}
|
|
|
|
|
2019-07-16 14:55:50 +08:00
|
|
|
static inline bool vmx_has_waitpkg(struct vcpu_vmx *vmx)
|
|
|
|
{
|
2021-08-11 01:19:49 +08:00
|
|
|
return secondary_exec_controls_get(vmx) &
|
2019-07-16 14:55:50 +08:00
|
|
|
SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
|
|
|
|
}
|
|
|
|
|
2020-07-10 23:48:08 +08:00
|
|
|
static inline bool vmx_need_pf_intercept(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
2020-09-03 22:11:22 +08:00
|
|
|
if (!enable_ept)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return allow_smaller_maxphyaddr && cpuid_maxphyaddr(vcpu) < boot_cpu_data.x86_phys_bits;
|
2020-07-10 23:48:08 +08:00
|
|
|
}
|
|
|
|
|
2020-09-21 16:10:25 +08:00
|
|
|
static inline bool is_unrestricted_guest(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
return enable_unrestricted_guest && (!is_guest_mode(vcpu) ||
|
|
|
|
(secondary_exec_controls_get(to_vmx(vcpu)) &
|
|
|
|
SECONDARY_EXEC_UNRESTRICTED_GUEST));
|
|
|
|
}
|
|
|
|
|
2020-09-24 02:44:48 +08:00
|
|
|
bool __vmx_guest_state_valid(struct kvm_vcpu *vcpu);
|
|
|
|
static inline bool vmx_guest_state_valid(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
return is_unrestricted_guest(vcpu) || __vmx_guest_state_valid(vcpu);
|
|
|
|
}
|
|
|
|
|
2021-03-18 20:08:40 +08:00
|
|
|
void dump_vmcs(struct kvm_vcpu *vcpu);
|
2019-04-15 21:16:17 +08:00
|
|
|
|
2018-12-04 05:53:08 +08:00
|
|
|
#endif /* __KVM_X86_VMX_H */
|