From: Andrea Parri (Microsoft) <parri.andrea@xxxxxxxxx> Sent: Tuesday, January 26, 2021 3:57 AM > > If bit 22 of Group B Features is set, the guest has access to the > Isolation Configuration CPUID leaf. On x86, the first four bits > of EAX in this leaf provide the isolation type of the partition; > we entail three isolation types: 'SNP' (hardware-based isolation), > 'VBS' (software-based isolation), and 'NONE' (no isolation). > > Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@xxxxxxxxx> > Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > Cc: Ingo Molnar <mingo@xxxxxxxxxx> > Cc: Borislav Petkov <bp@xxxxxxxxx> > Cc: "H. Peter Anvin" <hpa@xxxxxxxxx> > Cc: Arnd Bergmann <arnd@xxxxxxxx> > Cc: x86@xxxxxxxxxx > Cc: linux-arch@xxxxxxxxxxxxxxx > --- > arch/x86/hyperv/hv_init.c | 15 +++++++++++++++ > arch/x86/include/asm/hyperv-tlfs.h | 15 +++++++++++++++ > arch/x86/kernel/cpu/mshyperv.c | 9 +++++++++ > include/asm-generic/hyperv-tlfs.h | 1 + > include/asm-generic/mshyperv.h | 5 +++++ > 5 files changed, 45 insertions(+) > > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c > index e04d90af4c27c..dc94e95c57b98 100644 > --- a/arch/x86/hyperv/hv_init.c > +++ b/arch/x86/hyperv/hv_init.c > @@ -10,6 +10,7 @@ > #include <linux/acpi.h> > #include <linux/efi.h> > #include <linux/types.h> > +#include <linux/bitfield.h> > #include <asm/apic.h> > #include <asm/desc.h> > #include <asm/hypervisor.h> > @@ -528,3 +529,17 @@ bool hv_is_hibernation_supported(void) > return acpi_sleep_state_supported(ACPI_STATE_S4); > } > EXPORT_SYMBOL_GPL(hv_is_hibernation_supported); > + > +enum hv_isolation_type hv_get_isolation_type(void) > +{ > + if (!(ms_hyperv.hypercalls_features & HV_ISOLATION)) > + return HV_ISOLATION_TYPE_NONE; > + return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b); > +} > +EXPORT_SYMBOL_GPL(hv_get_isolation_type); > + > +bool hv_is_isolation_supported(void) > +{ > + return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE; > +} > +EXPORT_SYMBOL_GPL(hv_is_isolation_supported); > diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h > index 6bf42aed387e3..6aed936e5e962 100644 > --- a/arch/x86/include/asm/hyperv-tlfs.h > +++ b/arch/x86/include/asm/hyperv-tlfs.h > @@ -22,6 +22,7 @@ > #define HYPERV_CPUID_ENLIGHTMENT_INFO 0x40000004 > #define HYPERV_CPUID_IMPLEMENT_LIMITS 0x40000005 > #define HYPERV_CPUID_NESTED_FEATURES 0x4000000A > +#define HYPERV_CPUID_ISOLATION_CONFIG 0x4000000C > > #define HYPERV_CPUID_VIRT_STACK_INTERFACE 0x40000081 > #define HYPERV_VS_INTERFACE_EAX_SIGNATURE 0x31235356 /* "VS#1" */ > @@ -122,6 +123,20 @@ > #define HV_X64_NESTED_GUEST_MAPPING_FLUSH BIT(18) > #define HV_X64_NESTED_MSR_BITMAP BIT(19) > > +/* HYPERV_CPUID_ISOLATION_CONFIG.EAX bits. */ > +#define HV_PARAVISOR_PRESENT BIT(0) > + > +/* HYPERV_CPUID_ISOLATION_CONFIG.EBX bits. */ > +#define HV_ISOLATION_TYPE GENMASK(3, 0) > +#define HV_SHARED_GPA_BOUNDARY_ACTIVE BIT(5) > +#define HV_SHARED_GPA_BOUNDARY_BITS GENMASK(11, 6) > + > +enum hv_isolation_type { > + HV_ISOLATION_TYPE_NONE = 0, > + HV_ISOLATION_TYPE_VBS = 1, > + HV_ISOLATION_TYPE_SNP = 2 > +}; > + > /* Hyper-V specific model specific registers (MSRs) */ > > /* MSR used to identify the guest OS. */ > diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c > index f628e3dc150f3..0d4aaf6694d01 100644 > --- a/arch/x86/kernel/cpu/mshyperv.c > +++ b/arch/x86/kernel/cpu/mshyperv.c > @@ -225,6 +225,7 @@ static void __init ms_hyperv_init_platform(void) > * Extract the features and hints > */ > ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES); > + ms_hyperv.hypercalls_features = cpuid_ebx(HYPERV_CPUID_FEATURES); > ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES); > ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO); > > @@ -259,6 +260,14 @@ static void __init ms_hyperv_init_platform(void) > x86_platform.calibrate_cpu = hv_get_tsc_khz; > } > > + if (ms_hyperv.hypercalls_features & HV_ISOLATION) { > + ms_hyperv.isolation_config_a = cpuid_eax(HYPERV_CPUID_ISOLATION_CONFIG); > + ms_hyperv.isolation_config_b = cpuid_ebx(HYPERV_CPUID_ISOLATION_CONFIG); > + > + pr_info("Hyper-V: Isolation Config: GroupA 0x%x, GroupB 0x%x\n", Nit: Let's put a space after the word "Group", so that we have "Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n". > + ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b); > + } > + > if (ms_hyperv.hints & HV_X64_ENLIGHTENED_VMCS_RECOMMENDED) { > ms_hyperv.nested_features = > cpuid_eax(HYPERV_CPUID_NESTED_FEATURES); > diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h > index e73a11850055c..20d3cd9502043 100644 > --- a/include/asm-generic/hyperv-tlfs.h > +++ b/include/asm-generic/hyperv-tlfs.h > @@ -89,6 +89,7 @@ > #define HV_ACCESS_STATS BIT(8) > #define HV_DEBUGGING BIT(11) > #define HV_CPU_POWER_MANAGEMENT BIT(12) > +#define HV_ISOLATION BIT(22) > > > /* > diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h > index c57799684170c..c7f75b36f88ba 100644 > --- a/include/asm-generic/mshyperv.h > +++ b/include/asm-generic/mshyperv.h > @@ -27,11 +27,14 @@ > > struct ms_hyperv_info { > u32 features; > + u32 hypercalls_features; There was an offline conversation about renaming some of these fields so they more obviously map to the Hyper-V TLFS while also being architecture neutral. Toward that end, I'd suggest the "hypercalls_features" field should be named "features_b". This would align with the offline discussion, and matches what you've done with "isolation_config_a" and similar below (which is good). > u32 misc_features; > u32 hints; > u32 nested_features; > u32 max_vp_index; > u32 max_lp_index; > + u32 isolation_config_a; > + u32 isolation_config_b; > }; > extern struct ms_hyperv_info ms_hyperv; > > @@ -169,6 +172,8 @@ void hyperv_report_panic(struct pt_regs *regs, long err, bool > in_die); > void hyperv_report_panic_msg(phys_addr_t pa, size_t size); > bool hv_is_hyperv_initialized(void); > bool hv_is_hibernation_supported(void); > +enum hv_isolation_type hv_get_isolation_type(void); > +bool hv_is_isolation_supported(void); > void hyperv_cleanup(void); > #else /* CONFIG_HYPERV */ > static inline bool hv_is_hyperv_initialized(void) { return false; } > -- > 2.25.1