]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mshv: Add support for a new parent partition configuration
authorNuno Das Neves <nunodasneves@linux.microsoft.com>
Tue, 2 Sep 2025 23:48:33 +0000 (16:48 -0700)
committerWei Liu <wei.liu@kernel.org>
Mon, 8 Sep 2025 22:10:51 +0000 (22:10 +0000)
Detect booting as an "L1VH" partition. This is a new scenario very
similar to root partition where the mshv_root driver can be used to
create and manage guest partitions.

It mostly works the same as root partition, but there are some
differences in how various features are handled. hv_l1vh_partition()
is introduced to handle these cases. Add hv_parent_partition()
which returns true for either case, replacing some hv_root_partition()
checks.

Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Acked-by: Wei Liu <wei.liu@kernel.org>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
drivers/hv/hv_common.c
drivers/hv/mshv_root_main.c
include/asm-generic/mshyperv.h

index 49898d10fafff5ffdb08cf7991af05d724f6a258..e109a620c83fc8ba0f1eb9aff67303e11e860be6 100644 (file)
@@ -257,7 +257,7 @@ static void hv_kmsg_dump_register(void)
 
 static inline bool hv_output_page_exists(void)
 {
-       return hv_root_partition() || IS_ENABLED(CONFIG_HYPERV_VTL_MODE);
+       return hv_parent_partition() || IS_ENABLED(CONFIG_HYPERV_VTL_MODE);
 }
 
 void __init hv_get_partition_id(void)
@@ -377,7 +377,7 @@ int __init hv_common_init(void)
                BUG_ON(!hyperv_pcpu_output_arg);
        }
 
-       if (hv_root_partition()) {
+       if (hv_parent_partition()) {
                hv_synic_eventring_tail = alloc_percpu(u8 *);
                BUG_ON(!hv_synic_eventring_tail);
        }
@@ -531,7 +531,7 @@ int hv_common_cpu_init(unsigned int cpu)
        if (msr_vp_index > hv_max_vp_index)
                hv_max_vp_index = msr_vp_index;
 
-       if (hv_root_partition()) {
+       if (hv_parent_partition()) {
                synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
                *synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
                                                sizeof(u8), flags);
@@ -558,7 +558,7 @@ int hv_common_cpu_die(unsigned int cpu)
         * originally allocated memory is reused in hv_common_cpu_init().
         */
 
-       if (hv_root_partition()) {
+       if (hv_parent_partition()) {
                synic_eventring_tail = this_cpu_ptr(hv_synic_eventring_tail);
                kfree(*synic_eventring_tail);
                *synic_eventring_tail = NULL;
@@ -729,13 +729,17 @@ void hv_identify_partition_type(void)
         * the root partition setting if also a Confidential VM.
         */
        if ((ms_hyperv.priv_high & HV_CREATE_PARTITIONS) &&
-           (ms_hyperv.priv_high & HV_CPU_MANAGEMENT) &&
            !(ms_hyperv.priv_high & HV_ISOLATION)) {
-               pr_info("Hyper-V: running as root partition\n");
-               if (IS_ENABLED(CONFIG_MSHV_ROOT))
-                       hv_curr_partition_type = HV_PARTITION_TYPE_ROOT;
-               else
+
+               if (!IS_ENABLED(CONFIG_MSHV_ROOT)) {
                        pr_crit("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n");
+               } else if (ms_hyperv.priv_high & HV_CPU_MANAGEMENT) {
+                       pr_info("Hyper-V: running as root partition\n");
+                       hv_curr_partition_type = HV_PARTITION_TYPE_ROOT;
+               } else {
+                       pr_info("Hyper-V: running as L1VH partition\n");
+                       hv_curr_partition_type = HV_PARTITION_TYPE_L1VH;
+               }
        }
 }
 
index 72df774e410aba6f5d746666f86012a2d62e2268..aa20a5c96afaf3ba9a5ad6f182bb2bd8911a516a 100644 (file)
@@ -37,12 +37,6 @@ MODULE_AUTHOR("Microsoft");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Microsoft Hyper-V root partition VMM interface /dev/mshv");
 
-/* TODO move this to mshyperv.h when needed outside driver */
-static inline bool hv_parent_partition(void)
-{
-       return hv_root_partition();
-}
-
 /* TODO move this to another file when debugfs code is added */
 enum hv_stats_vp_counters {                    /* HV_THREAD_COUNTER */
 #if defined(CONFIG_X86)
@@ -2074,9 +2068,13 @@ static int __init hv_retrieve_scheduler_type(enum hv_scheduler_type *out)
 /* Retrieve and stash the supported scheduler type */
 static int __init mshv_retrieve_scheduler_type(struct device *dev)
 {
-       int ret;
+       int ret = 0;
+
+       if (hv_l1vh_partition())
+               hv_scheduler_type = HV_SCHEDULER_TYPE_CORE_SMT;
+       else
+               ret = hv_retrieve_scheduler_type(&hv_scheduler_type);
 
-       ret = hv_retrieve_scheduler_type(&hv_scheduler_type);
        if (ret)
                return ret;
 
@@ -2203,9 +2201,6 @@ static int __init mshv_root_partition_init(struct device *dev)
 {
        int err;
 
-       if (mshv_retrieve_scheduler_type(dev))
-               return -ENODEV;
-
        err = root_scheduler_init(dev);
        if (err)
                return err;
@@ -2227,7 +2222,7 @@ static int __init mshv_parent_partition_init(void)
        struct device *dev;
        union hv_hypervisor_version_info version_info;
 
-       if (!hv_root_partition() || is_kdump_kernel())
+       if (!hv_parent_partition() || is_kdump_kernel())
                return -ENODEV;
 
        if (hv_get_hypervisor_version(&version_info))
@@ -2264,7 +2259,12 @@ static int __init mshv_parent_partition_init(void)
 
        mshv_cpuhp_online = ret;
 
-       ret = mshv_root_partition_init(dev);
+       ret = mshv_retrieve_scheduler_type(dev);
+       if (ret)
+               goto remove_cpu_state;
+
+       if (hv_root_partition())
+               ret = mshv_root_partition_init(dev);
        if (ret)
                goto remove_cpu_state;
 
index a729b77983fab0873974de412832dd84df578527..dbd4c2f3aee32f2504ca84ca3e6bf66905afdc57 100644 (file)
@@ -31,6 +31,7 @@
 enum hv_partition_type {
        HV_PARTITION_TYPE_GUEST,
        HV_PARTITION_TYPE_ROOT,
+       HV_PARTITION_TYPE_L1VH,
 };
 
 struct ms_hyperv_info {
@@ -354,12 +355,22 @@ static inline bool hv_root_partition(void)
 {
        return hv_curr_partition_type == HV_PARTITION_TYPE_ROOT;
 }
+static inline bool hv_l1vh_partition(void)
+{
+       return hv_curr_partition_type == HV_PARTITION_TYPE_L1VH;
+}
+static inline bool hv_parent_partition(void)
+{
+       return hv_root_partition() || hv_l1vh_partition();
+}
 int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);
 int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);
 int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);
 
 #else /* CONFIG_MSHV_ROOT */
 static inline bool hv_root_partition(void) { return false; }
+static inline bool hv_l1vh_partition(void) { return false; }
+static inline bool hv_parent_partition(void) { return false; }
 static inline int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
 {
        return -EOPNOTSUPP;