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

Configure Feed

Select the types of activity you want to include in your feed.

hyperv: Change hv_root_partition into a function

Introduce hv_curr_partition_type to store the partition type
as an enum.

Right now this is limited to guest or root partition, but there will
be other kinds in future and the enum is easily extensible.

Set up hv_curr_partition_type early in Hyper-V initialization with
hv_identify_partition_type(). hv_root_partition() just queries this
value, and shouldn't be called before that.

Making this check into a function sets the stage for adding a config
option to gate the compilation of root partition code. In particular,
hv_root_partition() can be stubbed out always be false if root
partition support isn't desired.

Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
Link: https://lore.kernel.org/r/1740167795-13296-3-git-send-email-nunodasneves@linux.microsoft.com
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Message-ID: <1740167795-13296-3-git-send-email-nunodasneves@linux.microsoft.com>

authored by

Nuno Das Neves and committed by
Wei Liu
db912b89 9d8731a1

+58 -45
+2
arch/arm64/hyperv/mshyperv.c
··· 61 61 ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints, 62 62 ms_hyperv.misc_features); 63 63 64 + hv_identify_partition_type(); 65 + 64 66 ret = hv_common_init(); 65 67 if (ret) 66 68 return ret;
+5 -5
arch/x86/hyperv/hv_init.c
··· 90 90 return 0; 91 91 92 92 hvp = &hv_vp_assist_page[cpu]; 93 - if (hv_root_partition) { 93 + if (hv_root_partition()) { 94 94 /* 95 95 * For root partition we get the hypervisor provided VP assist 96 96 * page, instead of allocating a new page. ··· 242 242 243 243 if (hv_vp_assist_page && hv_vp_assist_page[cpu]) { 244 244 union hv_vp_assist_msr_contents msr = { 0 }; 245 - if (hv_root_partition) { 245 + if (hv_root_partition()) { 246 246 /* 247 247 * For root partition the VP assist page is mapped to 248 248 * hypervisor provided page, and thus we unmap the ··· 317 317 union hv_x64_msr_hypercall_contents hypercall_msr; 318 318 int ret; 319 319 320 - if (hv_root_partition) 320 + if (hv_root_partition()) 321 321 return -EPERM; 322 322 323 323 /* ··· 518 518 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 519 519 hypercall_msr.enable = 1; 520 520 521 - if (hv_root_partition) { 521 + if (hv_root_partition()) { 522 522 struct page *pg; 523 523 void *src; 524 524 ··· 592 592 * If we're running as root, we want to create our own PCI MSI domain. 593 593 * We can't set this in hv_pci_init because that would be too late. 594 594 */ 595 - if (hv_root_partition) 595 + if (hv_root_partition()) 596 596 x86_init.irqs.create_pci_msi_domain = hv_create_pci_msi_domain; 597 597 #endif 598 598
+2 -22
arch/x86/kernel/cpu/mshyperv.c
··· 33 33 #include <asm/numa.h> 34 34 #include <asm/svm.h> 35 35 36 - /* Is Linux running as the root partition? */ 37 - bool hv_root_partition; 38 36 /* Is Linux running on nested Microsoft Hypervisor */ 39 37 bool hv_nested; 40 38 struct ms_hyperv_info ms_hyperv; ··· 449 451 pr_debug("Hyper-V: max %u virtual processors, %u logical processors\n", 450 452 ms_hyperv.max_vp_index, ms_hyperv.max_lp_index); 451 453 452 - /* 453 - * Check CPU management privilege. 454 - * 455 - * To mirror what Windows does we should extract CPU management 456 - * features and use the ReservedIdentityBit to detect if Linux is the 457 - * root partition. But that requires negotiating CPU management 458 - * interface (a process to be finalized). For now, use the privilege 459 - * flag as the indicator for running as root. 460 - * 461 - * Hyper-V should never specify running as root and as a Confidential 462 - * VM. But to protect against a compromised/malicious Hyper-V trying 463 - * to exploit root behavior to expose Confidential VM memory, ignore 464 - * the root partition setting if also a Confidential VM. 465 - */ 466 - if ((ms_hyperv.priv_high & HV_CPU_MANAGEMENT) && 467 - !(ms_hyperv.priv_high & HV_ISOLATION)) { 468 - hv_root_partition = true; 469 - pr_info("Hyper-V: running as root partition\n"); 470 - } 454 + hv_identify_partition_type(); 471 455 472 456 if (ms_hyperv.hints & HV_X64_HYPERV_NESTED) { 473 457 hv_nested = true; ··· 598 618 599 619 # ifdef CONFIG_SMP 600 620 smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu; 601 - if (hv_root_partition || 621 + if (hv_root_partition() || 602 622 (!ms_hyperv.paravisor_present && hv_isolation_type_snp())) 603 623 smp_ops.smp_prepare_cpus = hv_smp_prepare_cpus; 604 624 # endif
+2 -2
drivers/clocksource/hyperv_timer.c
··· 582 582 * mapped. 583 583 */ 584 584 tsc_msr.as_uint64 = hv_get_msr(HV_MSR_REFERENCE_TSC); 585 - if (hv_root_partition) 585 + if (hv_root_partition()) 586 586 tsc_pfn = tsc_msr.pfn; 587 587 else 588 588 tsc_pfn = HVPFN_DOWN(virt_to_phys(tsc_page)); ··· 627 627 if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) 628 628 return; 629 629 630 - if (!hv_root_partition) { 630 + if (!hv_root_partition()) { 631 631 WARN(1, "%s: attempt to remap TSC page in guest partition\n", 632 632 __func__); 633 633 return;
+5 -5
drivers/hv/hv.c
··· 144 144 * Synic message and event pages are allocated by paravisor. 145 145 * Skip these pages allocation here. 146 146 */ 147 - if (!ms_hyperv.paravisor_present && !hv_root_partition) { 147 + if (!ms_hyperv.paravisor_present && !hv_root_partition()) { 148 148 hv_cpu->synic_message_page = 149 149 (void *)get_zeroed_page(GFP_ATOMIC); 150 150 if (!hv_cpu->synic_message_page) { ··· 272 272 simp.as_uint64 = hv_get_msr(HV_MSR_SIMP); 273 273 simp.simp_enabled = 1; 274 274 275 - if (ms_hyperv.paravisor_present || hv_root_partition) { 275 + if (ms_hyperv.paravisor_present || hv_root_partition()) { 276 276 /* Mask out vTOM bit. ioremap_cache() maps decrypted */ 277 277 u64 base = (simp.base_simp_gpa << HV_HYP_PAGE_SHIFT) & 278 278 ~ms_hyperv.shared_gpa_boundary; ··· 291 291 siefp.as_uint64 = hv_get_msr(HV_MSR_SIEFP); 292 292 siefp.siefp_enabled = 1; 293 293 294 - if (ms_hyperv.paravisor_present || hv_root_partition) { 294 + if (ms_hyperv.paravisor_present || hv_root_partition()) { 295 295 /* Mask out vTOM bit. ioremap_cache() maps decrypted */ 296 296 u64 base = (siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT) & 297 297 ~ms_hyperv.shared_gpa_boundary; ··· 367 367 * addresses. 368 368 */ 369 369 simp.simp_enabled = 0; 370 - if (ms_hyperv.paravisor_present || hv_root_partition) { 370 + if (ms_hyperv.paravisor_present || hv_root_partition()) { 371 371 iounmap(hv_cpu->synic_message_page); 372 372 hv_cpu->synic_message_page = NULL; 373 373 } else { ··· 379 379 siefp.as_uint64 = hv_get_msr(HV_MSR_SIEFP); 380 380 siefp.siefp_enabled = 0; 381 381 382 - if (ms_hyperv.paravisor_present || hv_root_partition) { 382 + if (ms_hyperv.paravisor_present || hv_root_partition()) { 383 383 iounmap(hv_cpu->synic_event_page); 384 384 hv_cpu->synic_event_page = NULL; 385 385 } else {
+26 -6
drivers/hv/hv_common.c
··· 34 34 u64 hv_current_partition_id = HV_PARTITION_ID_SELF; 35 35 EXPORT_SYMBOL_GPL(hv_current_partition_id); 36 36 37 + enum hv_partition_type hv_curr_partition_type; 38 + EXPORT_SYMBOL_GPL(hv_curr_partition_type); 39 + 37 40 /* 38 - * hv_root_partition, ms_hyperv and hv_nested are defined here with other 41 + * ms_hyperv and hv_nested are defined here with other 39 42 * Hyper-V specific globals so they are shared across all architectures and are 40 43 * built only when CONFIG_HYPERV is defined. But on x86, 41 44 * ms_hyperv_init_platform() is built even when CONFIG_HYPERV is not ··· 46 43 * here, allowing for an overriding definition in the module containing 47 44 * ms_hyperv_init_platform(). 48 45 */ 49 - bool __weak hv_root_partition; 50 - EXPORT_SYMBOL_GPL(hv_root_partition); 51 - 52 46 bool __weak hv_nested; 53 47 EXPORT_SYMBOL_GPL(hv_nested); 54 48 ··· 283 283 284 284 static inline bool hv_output_page_exists(void) 285 285 { 286 - return hv_root_partition || IS_ENABLED(CONFIG_HYPERV_VTL_MODE); 286 + return hv_root_partition() || IS_ENABLED(CONFIG_HYPERV_VTL_MODE); 287 287 } 288 288 289 289 void __init hv_get_partition_id(void) ··· 594 594 595 595 bool hv_is_hibernation_supported(void) 596 596 { 597 - return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4); 597 + return !hv_root_partition() && acpi_sleep_state_supported(ACPI_STATE_S4); 598 598 } 599 599 EXPORT_SYMBOL_GPL(hv_is_hibernation_supported); 600 600 ··· 716 716 break; 717 717 } 718 718 return -EIO; 719 + } 720 + 721 + void hv_identify_partition_type(void) 722 + { 723 + /* Assume guest role */ 724 + hv_curr_partition_type = HV_PARTITION_TYPE_GUEST; 725 + /* 726 + * Check partition creation and cpu management privileges 727 + * 728 + * Hyper-V should never specify running as root and as a Confidential 729 + * VM. But to protect against a compromised/malicious Hyper-V trying 730 + * to exploit root behavior to expose Confidential VM memory, ignore 731 + * the root partition setting if also a Confidential VM. 732 + */ 733 + if ((ms_hyperv.priv_high & HV_CREATE_PARTITIONS) && 734 + (ms_hyperv.priv_high & HV_CPU_MANAGEMENT) && 735 + !(ms_hyperv.priv_high & HV_ISOLATION)) { 736 + pr_info("Hyper-V: running as root partition\n"); 737 + hv_curr_partition_type = HV_PARTITION_TYPE_ROOT; 738 + } 719 739 }
+1 -1
drivers/hv/vmbus_drv.c
··· 2656 2656 if (!hv_is_hyperv_initialized()) 2657 2657 return -ENODEV; 2658 2658 2659 - if (hv_root_partition && !hv_nested) 2659 + if (hv_root_partition() && !hv_nested) 2660 2660 return 0; 2661 2661 2662 2662 /*
+2 -2
drivers/iommu/hyperv-iommu.c
··· 130 130 x86_init.hyper.msi_ext_dest_id()) 131 131 return -ENODEV; 132 132 133 - if (hv_root_partition) { 133 + if (hv_root_partition()) { 134 134 name = "HYPERV-ROOT-IR"; 135 135 ops = &hyperv_root_ir_domain_ops; 136 136 } else { ··· 151 151 return -ENOMEM; 152 152 } 153 153 154 - if (hv_root_partition) 154 + if (hv_root_partition()) 155 155 return 0; /* The rest is only relevant to guests */ 156 156 157 157 /*
+13 -2
include/asm-generic/mshyperv.h
··· 28 28 29 29 #define VTPM_BASE_ADDRESS 0xfed40000 30 30 31 + enum hv_partition_type { 32 + HV_PARTITION_TYPE_GUEST, 33 + HV_PARTITION_TYPE_ROOT, 34 + }; 35 + 31 36 struct ms_hyperv_info { 32 37 u32 features; 33 38 u32 priv_high; ··· 64 59 extern struct ms_hyperv_info ms_hyperv; 65 60 extern bool hv_nested; 66 61 extern u64 hv_current_partition_id; 62 + extern enum hv_partition_type hv_curr_partition_type; 67 63 68 64 extern void * __percpu *hyperv_pcpu_input_arg; 69 65 extern void * __percpu *hyperv_pcpu_output_arg; ··· 196 190 extern int vmbus_interrupt; 197 191 extern int vmbus_irq; 198 192 199 - extern bool hv_root_partition; 200 - 201 193 #if IS_ENABLED(CONFIG_HYPERV) 202 194 /* 203 195 * Hypervisor's notion of virtual processor ID is different from ··· 217 213 void __init ms_hyperv_late_init(void); 218 214 int hv_common_cpu_init(unsigned int cpu); 219 215 int hv_common_cpu_die(unsigned int cpu); 216 + void hv_identify_partition_type(void); 220 217 221 218 void *hv_alloc_hyperv_page(void); 222 219 void *hv_alloc_hyperv_zeroed_page(void); ··· 315 310 bool hv_query_ext_cap(u64 cap_query); 316 311 void hv_setup_dma_ops(struct device *dev, bool coherent); 317 312 #else /* CONFIG_HYPERV */ 313 + static inline void hv_identify_partition_type(void) {} 318 314 static inline bool hv_is_hyperv_initialized(void) { return false; } 319 315 static inline bool hv_is_hibernation_supported(void) { return false; } 320 316 static inline void hyperv_cleanup(void) {} ··· 326 320 return HV_ISOLATION_TYPE_NONE; 327 321 } 328 322 #endif /* CONFIG_HYPERV */ 323 + 324 + static inline bool hv_root_partition(void) 325 + { 326 + return hv_curr_partition_type == HV_PARTITION_TYPE_ROOT; 327 + } 329 328 330 329 #endif