Commit 43d97b2e authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-x86-pat_vmx_msrs-6.12' of https://github.com/kvm-x86/linux into HEAD

KVM VMX and x86 PAT MSR macro cleanup for 6.12:

 - Add common defines for the x86 architectural memory types, i.e. the types
   that are shared across PAT, MTRRs, VMCSes, and EPTPs.

 - Clean up the various VMX MSR macros to make the code self-documenting
   (inasmuch as possible), and to make it less painful to add new macros.
parents 5d55a052 566975f6
Loading
Loading
Loading
Loading
+20 −14
Original line number Diff line number Diff line
@@ -36,6 +36,20 @@
#define EFER_FFXSR		(1<<_EFER_FFXSR)
#define EFER_AUTOIBRS		(1<<_EFER_AUTOIBRS)

/*
 * Architectural memory types that are common to MTRRs, PAT, VMX MSRs, etc.
 * Most MSRs support/allow only a subset of memory types, but the values
 * themselves are common across all relevant MSRs.
 */
#define X86_MEMTYPE_UC		0ull	/* Uncacheable, a.k.a. Strong Uncacheable */
#define X86_MEMTYPE_WC		1ull	/* Write Combining */
/* RESERVED			2 */
/* RESERVED			3 */
#define X86_MEMTYPE_WT		4ull	/* Write Through */
#define X86_MEMTYPE_WP		5ull	/* Write Protected */
#define X86_MEMTYPE_WB		6ull	/* Write Back */
#define X86_MEMTYPE_UC_MINUS	7ull	/* Weak Uncacheabled (PAT only) */

/* FRED MSRs */
#define MSR_IA32_FRED_RSP0	0x1cc			/* Level 0 stack pointer */
#define MSR_IA32_FRED_RSP1	0x1cd			/* Level 1 stack pointer */
@@ -363,6 +377,12 @@

#define MSR_IA32_CR_PAT			0x00000277

#define PAT_VALUE(p0, p1, p2, p3, p4, p5, p6, p7)			\
	((X86_MEMTYPE_ ## p0)      | (X86_MEMTYPE_ ## p1 << 8)  |	\
	(X86_MEMTYPE_ ## p2 << 16) | (X86_MEMTYPE_ ## p3 << 24) |	\
	(X86_MEMTYPE_ ## p4 << 32) | (X86_MEMTYPE_ ## p5 << 40) |	\
	(X86_MEMTYPE_ ## p6 << 48) | (X86_MEMTYPE_ ## p7 << 56))

#define MSR_IA32_DEBUGCTLMSR		0x000001d9
#define MSR_IA32_LASTBRANCHFROMIP	0x000001db
#define MSR_IA32_LASTBRANCHTOIP		0x000001dc
@@ -1157,15 +1177,6 @@
#define MSR_IA32_VMX_VMFUNC             0x00000491
#define MSR_IA32_VMX_PROCBASED_CTLS3	0x00000492

/* VMX_BASIC bits and bitmasks */
#define VMX_BASIC_VMCS_SIZE_SHIFT	32
#define VMX_BASIC_TRUE_CTLS		(1ULL << 55)
#define VMX_BASIC_64		0x0001000000000000LLU
#define VMX_BASIC_MEM_TYPE_SHIFT	50
#define VMX_BASIC_MEM_TYPE_MASK	0x003c000000000000LLU
#define VMX_BASIC_MEM_TYPE_WB	6LLU
#define VMX_BASIC_INOUT		0x0040000000000000LLU

/* Resctrl MSRs: */
/* - Intel: */
#define MSR_IA32_L3_QOS_CFG		0xc81
@@ -1183,11 +1194,6 @@
#define MSR_IA32_SMBA_BW_BASE		0xc0000280
#define MSR_IA32_EVT_CFG_BASE		0xc0000400

/* MSR_IA32_VMX_MISC bits */
#define MSR_IA32_VMX_MISC_INTEL_PT                 (1ULL << 14)
#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29)
#define MSR_IA32_VMX_MISC_PREEMPTION_TIMER_SCALE   0x1F

/* AMD-V MSRs */
#define MSR_VM_CR                       0xc0010114
#define MSR_VM_IGNNE                    0xc0010115
+30 −10
Original line number Diff line number Diff line
@@ -122,19 +122,17 @@

#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR	0x000011ff

#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK	0x0000001f
#define VMX_MISC_SAVE_EFER_LMA			0x00000020
#define VMX_MISC_ACTIVITY_HLT			0x00000040
#define VMX_MISC_ACTIVITY_WAIT_SIPI		0x00000100
#define VMX_MISC_ZERO_LEN_INS			0x40000000
#define VMX_MISC_MSR_LIST_MULTIPLIER		512

/* VMFUNC functions */
#define VMFUNC_CONTROL_BIT(x)	BIT((VMX_FEATURE_##x & 0x1f) - 28)

#define VMX_VMFUNC_EPTP_SWITCHING               VMFUNC_CONTROL_BIT(EPTP_SWITCHING)
#define VMFUNC_EPTP_ENTRIES  512

#define VMX_BASIC_32BIT_PHYS_ADDR_ONLY		BIT_ULL(48)
#define VMX_BASIC_DUAL_MONITOR_TREATMENT	BIT_ULL(49)
#define VMX_BASIC_INOUT				BIT_ULL(54)
#define VMX_BASIC_TRUE_CTLS			BIT_ULL(55)

static inline u32 vmx_basic_vmcs_revision_id(u64 vmx_basic)
{
	return vmx_basic & GENMASK_ULL(30, 0);
@@ -145,9 +143,30 @@ static inline u32 vmx_basic_vmcs_size(u64 vmx_basic)
	return (vmx_basic & GENMASK_ULL(44, 32)) >> 32;
}

static inline u32 vmx_basic_vmcs_mem_type(u64 vmx_basic)
{
	return (vmx_basic & GENMASK_ULL(53, 50)) >> 50;
}

static inline u64 vmx_basic_encode_vmcs_info(u32 revision, u16 size, u8 memtype)
{
	return revision | ((u64)size << 32) | ((u64)memtype << 50);
}

#define VMX_MISC_SAVE_EFER_LMA			BIT_ULL(5)
#define VMX_MISC_ACTIVITY_HLT			BIT_ULL(6)
#define VMX_MISC_ACTIVITY_SHUTDOWN		BIT_ULL(7)
#define VMX_MISC_ACTIVITY_WAIT_SIPI		BIT_ULL(8)
#define VMX_MISC_INTEL_PT			BIT_ULL(14)
#define VMX_MISC_RDMSR_IN_SMM			BIT_ULL(15)
#define VMX_MISC_VMXOFF_BLOCK_SMI		BIT_ULL(28)
#define VMX_MISC_VMWRITE_SHADOW_RO_FIELDS	BIT_ULL(29)
#define VMX_MISC_ZERO_LEN_INS			BIT_ULL(30)
#define VMX_MISC_MSR_LIST_MULTIPLIER		512

static inline int vmx_misc_preemption_timer_rate(u64 vmx_misc)
{
	return vmx_misc & VMX_MISC_PREEMPTION_TIMER_RATE_MASK;
	return vmx_misc & GENMASK_ULL(4, 0);
}

static inline int vmx_misc_cr3_count(u64 vmx_misc)
@@ -508,9 +527,10 @@ enum vmcs_field {
#define VMX_EPTP_PWL_4				0x18ull
#define VMX_EPTP_PWL_5				0x20ull
#define VMX_EPTP_AD_ENABLE_BIT			(1ull << 6)
/* The EPTP memtype is encoded in bits 2:0, i.e. doesn't need to be shifted. */
#define VMX_EPTP_MT_MASK			0x7ull
#define VMX_EPTP_MT_WB				0x6ull
#define VMX_EPTP_MT_UC				0x0ull
#define VMX_EPTP_MT_WB				X86_MEMTYPE_WB
#define VMX_EPTP_MT_UC				X86_MEMTYPE_UC
#define VMX_EPT_READABLE_MASK			0x1ull
#define VMX_EPT_WRITABLE_MASK			0x2ull
#define VMX_EPT_EXECUTABLE_MASK			0x4ull
+6 −0
Original line number Diff line number Diff line
@@ -55,6 +55,12 @@

#include "mtrr.h"

static_assert(X86_MEMTYPE_UC == MTRR_TYPE_UNCACHABLE);
static_assert(X86_MEMTYPE_WC == MTRR_TYPE_WRCOMB);
static_assert(X86_MEMTYPE_WT == MTRR_TYPE_WRTHROUGH);
static_assert(X86_MEMTYPE_WP == MTRR_TYPE_WRPROT);
static_assert(X86_MEMTYPE_WB == MTRR_TYPE_WRBACK);

/* arch_phys_wc_add returns an MTRR register index plus this offset. */
#define MTRR_TO_PHYS_WC_OFFSET 1000

+4 −6
Original line number Diff line number Diff line
@@ -54,9 +54,7 @@ struct nested_vmx_msrs {
};

struct vmcs_config {
	int size;
	u32 basic_cap;
	u32 revision_id;
	u64 basic;
	u32 pin_based_exec_ctrl;
	u32 cpu_based_exec_ctrl;
	u32 cpu_based_2nd_exec_ctrl;
@@ -76,7 +74,7 @@ extern struct vmx_capability vmx_capability __ro_after_init;

static inline bool cpu_has_vmx_basic_inout(void)
{
	return	(((u64)vmcs_config.basic_cap << 32) & VMX_BASIC_INOUT);
	return	vmcs_config.basic & VMX_BASIC_INOUT;
}

static inline bool cpu_has_virtual_nmis(void)
@@ -225,7 +223,7 @@ static inline bool cpu_has_vmx_vmfunc(void)
static inline bool cpu_has_vmx_shadow_vmcs(void)
{
	/* check if the cpu supports writing r/o exit information fields */
	if (!(vmcs_config.misc & MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS))
	if (!(vmcs_config.misc & VMX_MISC_VMWRITE_SHADOW_RO_FIELDS))
		return false;

	return vmcs_config.cpu_based_2nd_exec_ctrl &
@@ -367,7 +365,7 @@ static inline bool cpu_has_vmx_invvpid_global(void)

static inline bool cpu_has_vmx_intel_pt(void)
{
	return (vmcs_config.misc & MSR_IA32_VMX_MISC_INTEL_PT) &&
	return (vmcs_config.misc & VMX_MISC_INTEL_PT) &&
		(vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_PT_USE_GPA) &&
		(vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_RTIT_CTL);
}
+42 −20
Original line number Diff line number Diff line
@@ -1251,21 +1251,32 @@ static bool is_bitwise_subset(u64 superset, u64 subset, u64 mask)

static int vmx_restore_vmx_basic(struct vcpu_vmx *vmx, u64 data)
{
	const u64 feature_and_reserved =
		/* feature (except bit 48; see below) */
		BIT_ULL(49) | BIT_ULL(54) | BIT_ULL(55) |
		/* reserved */
		BIT_ULL(31) | GENMASK_ULL(47, 45) | GENMASK_ULL(63, 56);
	const u64 feature_bits = VMX_BASIC_DUAL_MONITOR_TREATMENT |
				 VMX_BASIC_INOUT |
				 VMX_BASIC_TRUE_CTLS;

	const u64 reserved_bits = GENMASK_ULL(63, 56) |
				  GENMASK_ULL(47, 45) |
				  BIT_ULL(31);

	u64 vmx_basic = vmcs_config.nested.basic;

	if (!is_bitwise_subset(vmx_basic, data, feature_and_reserved))
	BUILD_BUG_ON(feature_bits & reserved_bits);

	/*
	 * Except for 32BIT_PHYS_ADDR_ONLY, which is an anti-feature bit (has
	 * inverted polarity), the incoming value must not set feature bits or
	 * reserved bits that aren't allowed/supported by KVM.  Fields, i.e.
	 * multi-bit values, are explicitly checked below.
	 */
	if (!is_bitwise_subset(vmx_basic, data, feature_bits | reserved_bits))
		return -EINVAL;

	/*
	 * KVM does not emulate a version of VMX that constrains physical
	 * addresses of VMX structures (e.g. VMCS) to 32-bits.
	 */
	if (data & BIT_ULL(48))
	if (data & VMX_BASIC_32BIT_PHYS_ADDR_ONLY)
		return -EINVAL;

	if (vmx_basic_vmcs_revision_id(vmx_basic) !=
@@ -1334,16 +1345,29 @@ vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)

static int vmx_restore_vmx_misc(struct vcpu_vmx *vmx, u64 data)
{
	const u64 feature_and_reserved_bits =
		/* feature */
		BIT_ULL(5) | GENMASK_ULL(8, 6) | BIT_ULL(14) | BIT_ULL(15) |
		BIT_ULL(28) | BIT_ULL(29) | BIT_ULL(30) |
		/* reserved */
		GENMASK_ULL(13, 9) | BIT_ULL(31);
	const u64 feature_bits = VMX_MISC_SAVE_EFER_LMA |
				 VMX_MISC_ACTIVITY_HLT |
				 VMX_MISC_ACTIVITY_SHUTDOWN |
				 VMX_MISC_ACTIVITY_WAIT_SIPI |
				 VMX_MISC_INTEL_PT |
				 VMX_MISC_RDMSR_IN_SMM |
				 VMX_MISC_VMWRITE_SHADOW_RO_FIELDS |
				 VMX_MISC_VMXOFF_BLOCK_SMI |
				 VMX_MISC_ZERO_LEN_INS;

	const u64 reserved_bits = BIT_ULL(31) | GENMASK_ULL(13, 9);

	u64 vmx_misc = vmx_control_msr(vmcs_config.nested.misc_low,
				       vmcs_config.nested.misc_high);

	if (!is_bitwise_subset(vmx_misc, data, feature_and_reserved_bits))
	BUILD_BUG_ON(feature_bits & reserved_bits);

	/*
	 * The incoming value must not set feature bits or reserved bits that
	 * aren't allowed/supported by KVM.  Fields, i.e. multi-bit values, are
	 * explicitly checked below.
	 */
	if (!is_bitwise_subset(vmx_misc, data, feature_bits | reserved_bits))
		return -EINVAL;

	if ((vmx->nested.msrs.pinbased_ctls_high &
@@ -7051,7 +7075,7 @@ static void nested_vmx_setup_misc_data(struct vmcs_config *vmcs_conf,
{
	msrs->misc_low = (u32)vmcs_conf->misc & VMX_MISC_SAVE_EFER_LMA;
	msrs->misc_low |=
		MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS |
		VMX_MISC_VMWRITE_SHADOW_RO_FIELDS |
		VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE |
		VMX_MISC_ACTIVITY_HLT |
		VMX_MISC_ACTIVITY_WAIT_SIPI;
@@ -7066,12 +7090,10 @@ static void nested_vmx_setup_basic(struct nested_vmx_msrs *msrs)
	 * guest, and the VMCS structure we give it - not about the
	 * VMX support of the underlying hardware.
	 */
	msrs->basic =
		VMCS12_REVISION |
		VMX_BASIC_TRUE_CTLS |
		((u64)VMCS12_SIZE << VMX_BASIC_VMCS_SIZE_SHIFT) |
		(VMX_BASIC_MEM_TYPE_WB << VMX_BASIC_MEM_TYPE_SHIFT);
	msrs->basic = vmx_basic_encode_vmcs_info(VMCS12_REVISION, VMCS12_SIZE,
						 X86_MEMTYPE_WB);

	msrs->basic |= VMX_BASIC_TRUE_CTLS;
	if (cpu_has_vmx_basic_inout())
		msrs->basic |= VMX_BASIC_INOUT;
}
Loading