x86/hyperv: Load/save the Isolation Configuration leaf
authorAndrea Parri (Microsoft) <parri.andrea@gmail.com>
Mon, 1 Feb 2021 14:48:11 +0000 (15:48 +0100)
committerWei Liu <wei.liu@kernel.org>
Thu, 11 Feb 2021 08:47:05 +0000 (08:47 +0000)
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@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: x86@kernel.org
Cc: linux-arch@vger.kernel.org
Link: https://lore.kernel.org/r/20210201144814.2701-2-parri.andrea@gmail.com
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
arch/x86/hyperv/hv_init.c
arch/x86/include/asm/hyperv-tlfs.h
arch/x86/kernel/cpu/mshyperv.c
include/asm-generic/hyperv-tlfs.h
include/asm-generic/mshyperv.h

index 6375967a8244dc4e6777d8ff95de1be33ea77e06..6608d50d7aaa4b5008abbe4ce109b85f5ae2d987 100644 (file)
@@ -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>
@@ -555,3 +556,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.features_b & 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);
index 6bf42aed387e3663c4f5081f4ba2532a9d988f51..6aed936e5e96206a85fafef941ef93bf9a8cdd44 100644 (file)
@@ -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" */
 #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. */
index 43b54bef5448fa360c9ff21444b62fc678e80fd7..fc6cb84c9fe57b994df4a30c45b0fe8124b5f033 100644 (file)
@@ -243,6 +243,7 @@ static void __init ms_hyperv_init_platform(void)
         * Extract the features and hints
         */
        ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
+       ms_hyperv.features_b = cpuid_ebx(HYPERV_CPUID_FEATURES);
        ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
        ms_hyperv.hints    = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
 
@@ -277,6 +278,14 @@ static void __init ms_hyperv_init_platform(void)
                x86_platform.calibrate_cpu = hv_get_tsc_khz;
        }
 
+       if (ms_hyperv.features_b & 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: 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);
index e73a11850055c4de93b69c7e1d5559d779243232..20d3cd950204387759a5a503fb652dff320833cf 100644 (file)
@@ -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)
 
 
 /*
index c57799684170c3ab27e1c108d7afa0c2ab964788..dff58a3db5d5c9f3e5a6b20337ea826c3759f7aa 100644 (file)
 
 struct ms_hyperv_info {
        u32 features;
+       u32 features_b;
        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; }