Re: [RFC PATCH 09/13] x86/cpufeature: Add detection of KVM XO

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Oct 03, 2019 at 02:23:56PM -0700, Rick Edgecombe wrote:
> Add a new CPUID leaf to hold the contents of CPUID 0x40000030 EAX to
> detect KVM defined generic VMM features.
> 
> The leaf was proposed to allow KVM to communicate features that are
> defined by KVM, but available for any VMM to implement.
> 
> Add cpu_feature_enabled() support for features in this leaf (KVM XO), and
> a pgtable_kvmxo_enabled() helper similar to pgtable_l5_enabled() so that
> pgtable_kvmxo_enabled() can be used in early code that includes
> arch/x86/include/asm/sparsemem.h.
> 
> Lastly, in head64.c detect and this feature and perform necessary
> adjustments to physical_mask.

Can this be exposed to /proc/cpuinfo so a guest userspace can determine
if this feature is enabled?

-Kees

> 
> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@xxxxxxxxx>
> ---
>  arch/x86/include/asm/cpufeature.h             |  6 ++-
>  arch/x86/include/asm/cpufeatures.h            |  2 +-
>  arch/x86/include/asm/disabled-features.h      |  3 +-
>  arch/x86/include/asm/pgtable_32_types.h       |  1 +
>  arch/x86/include/asm/pgtable_64_types.h       | 26 ++++++++++++-
>  arch/x86/include/asm/required-features.h      |  3 +-
>  arch/x86/include/asm/sparsemem.h              |  4 +-
>  arch/x86/kernel/cpu/common.c                  |  5 +++
>  arch/x86/kernel/head64.c                      | 38 ++++++++++++++++++-
>  .../arch/x86/include/asm/disabled-features.h  |  3 +-
>  10 files changed, 80 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
> index 17127ffbc2a2..7d04ea4f1623 100644
> --- a/arch/x86/include/asm/cpufeature.h
> +++ b/arch/x86/include/asm/cpufeature.h
> @@ -82,8 +82,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
>  	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) ||	\
>  	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) ||	\
>  	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) ||	\
> +	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 19, feature_bit) ||	\
>  	   REQUIRED_MASK_CHECK					  ||	\
> -	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
> +	   BUILD_BUG_ON_ZERO(NCAPINTS != 20))
>  
>  #define DISABLED_MASK_BIT_SET(feature_bit)				\
>  	 ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  0, feature_bit) ||	\
> @@ -105,8 +106,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
>  	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) ||	\
>  	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) ||	\
>  	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) ||	\
> +	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 19, feature_bit) ||	\
>  	   DISABLED_MASK_CHECK					  ||	\
> -	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
> +	   BUILD_BUG_ON_ZERO(NCAPINTS != 20))
>  
>  #define cpu_has(c, bit)							\
>  	(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :	\
> diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
> index 7ba217e894ea..9c1b07674401 100644
> --- a/arch/x86/include/asm/cpufeatures.h
> +++ b/arch/x86/include/asm/cpufeatures.h
> @@ -13,7 +13,7 @@
>  /*
>   * Defines x86 CPU feature bits
>   */
> -#define NCAPINTS			19	   /* N 32-bit words worth of info */
> +#define NCAPINTS			20	   /* N 32-bit words worth of info */
>  #define NBUGINTS			1	   /* N 32-bit bug flags */
>  
>  /*
> diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
> index a5ea841cc6d2..f0f935f8d917 100644
> --- a/arch/x86/include/asm/disabled-features.h
> +++ b/arch/x86/include/asm/disabled-features.h
> @@ -84,6 +84,7 @@
>  #define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP)
>  #define DISABLED_MASK17	0
>  #define DISABLED_MASK18	0
> -#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
> +#define DISABLED_MASK19	0
> +#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 20)
>  
>  #endif /* _ASM_X86_DISABLED_FEATURES_H */
> diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h
> index b0bc0fff5f1f..57a11692715e 100644
> --- a/arch/x86/include/asm/pgtable_32_types.h
> +++ b/arch/x86/include/asm/pgtable_32_types.h
> @@ -16,6 +16,7 @@
>  #endif
>  
>  #define pgtable_l5_enabled() 0
> +#define pgtable_kvmxo_enabled() 0
>  
>  #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
>  #define PGDIR_MASK	(~(PGDIR_SIZE - 1))
> diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h
> index 6b55b837ead4..7c7c9d1a199a 100644
> --- a/arch/x86/include/asm/pgtable_64_types.h
> +++ b/arch/x86/include/asm/pgtable_64_types.h
> @@ -43,10 +43,34 @@ static inline bool pgtable_l5_enabled(void)
>  extern unsigned int pgdir_shift;
>  extern unsigned int ptrs_per_p4d;
>  
> +#ifdef CONFIG_KVM_XO
> +extern unsigned int __pgtable_kvmxo_enabled;
> +
> +#ifdef USE_EARLY_PGTABLE
> +/*
> + * cpu_feature_enabled() is not available in early boot code.
> + * Use variable instead.
> + */
> +static inline bool pgtable_kvmxo_enabled(void)
> +{
> +	return __pgtable_kvmxo_enabled;
> +}
> +#else
> +#define pgtable_kvmxo_enabled() cpu_feature_enabled(X86_FEATURE_KVM_XO)
> +#endif /* USE_EARLY_PGTABLE */
> +
> +#else
> +#define pgtable_kvmxo_enabled() 0
> +#endif /* CONFIG_KVM_XO */
> +
>  #endif	/* !__ASSEMBLY__ */
>  
>  #define SHARED_KERNEL_PMD	0
>  
> +#if defined(CONFIG_X86_5LEVEL) || defined(CONFIG_KVM_XO)
> +#define MAX_POSSIBLE_PHYSMEM_BITS	52
> +#endif
> +
>  #ifdef CONFIG_X86_5LEVEL
>  
>  /*
> @@ -64,8 +88,6 @@ extern unsigned int ptrs_per_p4d;
>  #define P4D_SIZE		(_AC(1, UL) << P4D_SHIFT)
>  #define P4D_MASK		(~(P4D_SIZE - 1))
>  
> -#define MAX_POSSIBLE_PHYSMEM_BITS	52
> -
>  #else /* CONFIG_X86_5LEVEL */
>  
>  /*
> diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h
> index 6847d85400a8..fa5700097f64 100644
> --- a/arch/x86/include/asm/required-features.h
> +++ b/arch/x86/include/asm/required-features.h
> @@ -101,6 +101,7 @@
>  #define REQUIRED_MASK16	0
>  #define REQUIRED_MASK17	0
>  #define REQUIRED_MASK18	0
> -#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
> +#define REQUIRED_MASK19	0
> +#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 20)
>  
>  #endif /* _ASM_X86_REQUIRED_FEATURES_H */
> diff --git a/arch/x86/include/asm/sparsemem.h b/arch/x86/include/asm/sparsemem.h
> index 199218719a86..24b305195369 100644
> --- a/arch/x86/include/asm/sparsemem.h
> +++ b/arch/x86/include/asm/sparsemem.h
> @@ -27,8 +27,8 @@
>  # endif
>  #else /* CONFIG_X86_32 */
>  # define SECTION_SIZE_BITS	27 /* matt - 128 is convenient right now */
> -# define MAX_PHYSADDR_BITS	(pgtable_l5_enabled() ? 52 : 44)
> -# define MAX_PHYSMEM_BITS	(pgtable_l5_enabled() ? 52 : 46)
> +# define MAX_PHYSADDR_BITS	((pgtable_l5_enabled() ? 52 : 44) - !!pgtable_kvmxo_enabled())
> +# define MAX_PHYSMEM_BITS	((pgtable_l5_enabled() ? 52 : 46) - !!pgtable_kvmxo_enabled())
>  #endif
>  
>  #endif /* CONFIG_SPARSEMEM */
> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> index 4f08e164c0b1..ee204aefbcfd 100644
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -933,6 +933,11 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
>  		c->x86_capability[CPUID_D_1_EAX] = eax;
>  	}
>  
> +	eax = cpuid_eax(0x40000000);
> +	c->extended_cpuid_level = eax;
> +	if (c->extended_cpuid_level >= 0x40000030)
> +		c->x86_capability[CPUID_4000_0030_EAX] = cpuid_eax(0x40000030);
> +
>  	/* AMD-defined flags: level 0x80000001 */
>  	eax = cpuid_eax(0x80000000);
>  	c->extended_cpuid_level = eax;
> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
> index 55f5294c3cdf..7091702a7bec 100644
> --- a/arch/x86/kernel/head64.c
> +++ b/arch/x86/kernel/head64.c
> @@ -52,6 +52,11 @@ unsigned int ptrs_per_p4d __ro_after_init = 1;
>  EXPORT_SYMBOL(ptrs_per_p4d);
>  #endif
>  
> +#ifdef CONFIG_KVM_XO
> +unsigned int __pgtable_kvmxo_enabled __ro_after_init;
> +unsigned int __pgtable_kvmxo_bit __ro_after_init;
> +#endif /* CONFIG_KVM_XO */
> +
>  #ifdef CONFIG_DYNAMIC_MEMORY_LAYOUT
>  unsigned long page_offset_base __ro_after_init = __PAGE_OFFSET_BASE_L4;
>  EXPORT_SYMBOL(page_offset_base);
> @@ -73,12 +78,14 @@ static unsigned long __head *fixup_long(void *ptr, unsigned long physaddr)
>  	return fixup_pointer(ptr, physaddr);
>  }
>  
> -#ifdef CONFIG_X86_5LEVEL
> +#if defined(CONFIG_X86_5LEVEL) || defined(CONFIG_KVM_XO)
>  static unsigned int __head *fixup_int(void *ptr, unsigned long physaddr)
>  {
>  	return fixup_pointer(ptr, physaddr);
>  }
> +#endif
>  
> +#ifdef CONFIG_X86_5LEVEL
>  static bool __head check_la57_support(unsigned long physaddr)
>  {
>  	/*
> @@ -104,6 +111,33 @@ static bool __head check_la57_support(unsigned long physaddr)
>  }
>  #endif
>  
> +#ifdef CONFIG_KVM_XO
> +static void __head check_kvmxo_support(unsigned long physaddr)
> +{
> +	unsigned long physbits;
> +
> +	if ((native_cpuid_eax(0x40000000) < 0x40000030) ||
> +	    !(native_cpuid_eax(0x40000030) & (1 << (X86_FEATURE_KVM_XO & 31))))
> +		return;
> +
> +	if (native_cpuid_eax(0x80000000) < 0x80000008)
> +		return;
> +
> +	physbits = native_cpuid_eax(0x80000008) & 0xff;
> +
> +	/*
> +	 * If KVM XO is active, the top physical address bit is the permisison
> +	 * bit, so zero it in the mask.
> +	 */
> +	physical_mask &= ~(1UL << physbits);
> +
> +	*fixup_int(&__pgtable_kvmxo_enabled, physaddr) = 1;
> +	*fixup_int(&__pgtable_kvmxo_bit, physaddr) = physbits;
> +}
> +#else /* CONFIG_KVM_XO */
> +static void __head check_kvmxo_support(unsigned long physaddr) { }
> +#endif /* CONFIG_KVM_XO */
> +
>  /* Code in __startup_64() can be relocated during execution, but the compiler
>   * doesn't have to generate PC-relative relocations when accessing globals from
>   * that function. Clang actually does not generate them, which leads to
> @@ -127,6 +161,8 @@ unsigned long __head __startup_64(unsigned long physaddr,
>  
>  	la57 = check_la57_support(physaddr);
>  
> +	check_kvmxo_support(physaddr);
> +
>  	/* Is the address too large? */
>  	if (physaddr >> MAX_PHYSMEM_BITS)
>  		for (;;);
> diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h
> index a5ea841cc6d2..f0f935f8d917 100644
> --- a/tools/arch/x86/include/asm/disabled-features.h
> +++ b/tools/arch/x86/include/asm/disabled-features.h
> @@ -84,6 +84,7 @@
>  #define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP)
>  #define DISABLED_MASK17	0
>  #define DISABLED_MASK18	0
> -#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
> +#define DISABLED_MASK19	0
> +#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 20)
>  
>  #endif /* _ASM_X86_DISABLED_FEATURES_H */
> -- 
> 2.17.1
> 

-- 
Kees Cook




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux