Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mshv: Add support for a new parent partition configuration

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>

authored by

Nuno Das Neves and committed by
Wei Liu
f26c9306 47691ced

+37 -22
+13 -9
drivers/hv/hv_common.c
··· 257 257 258 258 static inline bool hv_output_page_exists(void) 259 259 { 260 - return hv_root_partition() || IS_ENABLED(CONFIG_HYPERV_VTL_MODE); 260 + return hv_parent_partition() || IS_ENABLED(CONFIG_HYPERV_VTL_MODE); 261 261 } 262 262 263 263 void __init hv_get_partition_id(void) ··· 377 377 BUG_ON(!hyperv_pcpu_output_arg); 378 378 } 379 379 380 - if (hv_root_partition()) { 380 + if (hv_parent_partition()) { 381 381 hv_synic_eventring_tail = alloc_percpu(u8 *); 382 382 BUG_ON(!hv_synic_eventring_tail); 383 383 } ··· 531 531 if (msr_vp_index > hv_max_vp_index) 532 532 hv_max_vp_index = msr_vp_index; 533 533 534 - if (hv_root_partition()) { 534 + if (hv_parent_partition()) { 535 535 synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); 536 536 *synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT, 537 537 sizeof(u8), flags); ··· 558 558 * originally allocated memory is reused in hv_common_cpu_init(). 559 559 */ 560 560 561 - if (hv_root_partition()) { 561 + if (hv_parent_partition()) { 562 562 synic_eventring_tail = this_cpu_ptr(hv_synic_eventring_tail); 563 563 kfree(*synic_eventring_tail); 564 564 *synic_eventring_tail = NULL; ··· 729 729 * the root partition setting if also a Confidential VM. 730 730 */ 731 731 if ((ms_hyperv.priv_high & HV_CREATE_PARTITIONS) && 732 - (ms_hyperv.priv_high & HV_CPU_MANAGEMENT) && 733 732 !(ms_hyperv.priv_high & HV_ISOLATION)) { 734 - pr_info("Hyper-V: running as root partition\n"); 735 - if (IS_ENABLED(CONFIG_MSHV_ROOT)) 736 - hv_curr_partition_type = HV_PARTITION_TYPE_ROOT; 737 - else 733 + 734 + if (!IS_ENABLED(CONFIG_MSHV_ROOT)) { 738 735 pr_crit("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n"); 736 + } else if (ms_hyperv.priv_high & HV_CPU_MANAGEMENT) { 737 + pr_info("Hyper-V: running as root partition\n"); 738 + hv_curr_partition_type = HV_PARTITION_TYPE_ROOT; 739 + } else { 740 + pr_info("Hyper-V: running as L1VH partition\n"); 741 + hv_curr_partition_type = HV_PARTITION_TYPE_L1VH; 742 + } 739 743 } 740 744 } 741 745
+13 -13
drivers/hv/mshv_root_main.c
··· 37 37 MODULE_LICENSE("GPL"); 38 38 MODULE_DESCRIPTION("Microsoft Hyper-V root partition VMM interface /dev/mshv"); 39 39 40 - /* TODO move this to mshyperv.h when needed outside driver */ 41 - static inline bool hv_parent_partition(void) 42 - { 43 - return hv_root_partition(); 44 - } 45 - 46 40 /* TODO move this to another file when debugfs code is added */ 47 41 enum hv_stats_vp_counters { /* HV_THREAD_COUNTER */ 48 42 #if defined(CONFIG_X86) ··· 2068 2074 /* Retrieve and stash the supported scheduler type */ 2069 2075 static int __init mshv_retrieve_scheduler_type(struct device *dev) 2070 2076 { 2071 - int ret; 2077 + int ret = 0; 2072 2078 2073 - ret = hv_retrieve_scheduler_type(&hv_scheduler_type); 2079 + if (hv_l1vh_partition()) 2080 + hv_scheduler_type = HV_SCHEDULER_TYPE_CORE_SMT; 2081 + else 2082 + ret = hv_retrieve_scheduler_type(&hv_scheduler_type); 2083 + 2074 2084 if (ret) 2075 2085 return ret; 2076 2086 ··· 2201 2203 { 2202 2204 int err; 2203 2205 2204 - if (mshv_retrieve_scheduler_type(dev)) 2205 - return -ENODEV; 2206 - 2207 2206 err = root_scheduler_init(dev); 2208 2207 if (err) 2209 2208 return err; ··· 2222 2227 struct device *dev; 2223 2228 union hv_hypervisor_version_info version_info; 2224 2229 2225 - if (!hv_root_partition() || is_kdump_kernel()) 2230 + if (!hv_parent_partition() || is_kdump_kernel()) 2226 2231 return -ENODEV; 2227 2232 2228 2233 if (hv_get_hypervisor_version(&version_info)) ··· 2259 2264 2260 2265 mshv_cpuhp_online = ret; 2261 2266 2262 - ret = mshv_root_partition_init(dev); 2267 + ret = mshv_retrieve_scheduler_type(dev); 2268 + if (ret) 2269 + goto remove_cpu_state; 2270 + 2271 + if (hv_root_partition()) 2272 + ret = mshv_root_partition_init(dev); 2263 2273 if (ret) 2264 2274 goto remove_cpu_state; 2265 2275
+11
include/asm-generic/mshyperv.h
··· 31 31 enum hv_partition_type { 32 32 HV_PARTITION_TYPE_GUEST, 33 33 HV_PARTITION_TYPE_ROOT, 34 + HV_PARTITION_TYPE_L1VH, 34 35 }; 35 36 36 37 struct ms_hyperv_info { ··· 355 354 { 356 355 return hv_curr_partition_type == HV_PARTITION_TYPE_ROOT; 357 356 } 357 + static inline bool hv_l1vh_partition(void) 358 + { 359 + return hv_curr_partition_type == HV_PARTITION_TYPE_L1VH; 360 + } 361 + static inline bool hv_parent_partition(void) 362 + { 363 + return hv_root_partition() || hv_l1vh_partition(); 364 + } 358 365 int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages); 359 366 int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id); 360 367 int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags); 361 368 362 369 #else /* CONFIG_MSHV_ROOT */ 363 370 static inline bool hv_root_partition(void) { return false; } 371 + static inline bool hv_l1vh_partition(void) { return false; } 372 + static inline bool hv_parent_partition(void) { return false; } 364 373 static inline int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) 365 374 { 366 375 return -EOPNOTSUPP;