Skip to content

Commit db912b8

Browse files
NunoDasNevesliuw
authored andcommitted
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 <[email protected]> Reviewed-by: Easwar Hariharan <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Link: https://lore.kernel.org/r/1740167795-13296-3-git-send-email-nunodasneves@linux.microsoft.com Signed-off-by: Wei Liu <[email protected]> Message-ID: <1740167795-13296-3-git-send-email-nunodasneves@linux.microsoft.com>
1 parent 9d8731a commit db912b8

File tree

9 files changed

+58
-45
lines changed

9 files changed

+58
-45
lines changed

arch/arm64/hyperv/mshyperv.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ static int __init hyperv_init(void)
6161
ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints,
6262
ms_hyperv.misc_features);
6363

64+
hv_identify_partition_type();
65+
6466
ret = hv_common_init();
6567
if (ret)
6668
return ret;

arch/x86/hyperv/hv_init.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static int hv_cpu_init(unsigned int cpu)
9090
return 0;
9191

9292
hvp = &hv_vp_assist_page[cpu];
93-
if (hv_root_partition) {
93+
if (hv_root_partition()) {
9494
/*
9595
* For root partition we get the hypervisor provided VP assist
9696
* page, instead of allocating a new page.
@@ -242,7 +242,7 @@ static int hv_cpu_die(unsigned int cpu)
242242

243243
if (hv_vp_assist_page && hv_vp_assist_page[cpu]) {
244244
union hv_vp_assist_msr_contents msr = { 0 };
245-
if (hv_root_partition) {
245+
if (hv_root_partition()) {
246246
/*
247247
* For root partition the VP assist page is mapped to
248248
* hypervisor provided page, and thus we unmap the
@@ -317,7 +317,7 @@ static int hv_suspend(void)
317317
union hv_x64_msr_hypercall_contents hypercall_msr;
318318
int ret;
319319

320-
if (hv_root_partition)
320+
if (hv_root_partition())
321321
return -EPERM;
322322

323323
/*
@@ -518,7 +518,7 @@ void __init hyperv_init(void)
518518
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
519519
hypercall_msr.enable = 1;
520520

521-
if (hv_root_partition) {
521+
if (hv_root_partition()) {
522522
struct page *pg;
523523
void *src;
524524

@@ -592,7 +592,7 @@ void __init hyperv_init(void)
592592
* If we're running as root, we want to create our own PCI MSI domain.
593593
* We can't set this in hv_pci_init because that would be too late.
594594
*/
595-
if (hv_root_partition)
595+
if (hv_root_partition())
596596
x86_init.irqs.create_pci_msi_domain = hv_create_pci_msi_domain;
597597
#endif
598598

arch/x86/kernel/cpu/mshyperv.c

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
#include <asm/numa.h>
3434
#include <asm/svm.h>
3535

36-
/* Is Linux running as the root partition? */
37-
bool hv_root_partition;
3836
/* Is Linux running on nested Microsoft Hypervisor */
3937
bool hv_nested;
4038
struct ms_hyperv_info ms_hyperv;
@@ -451,25 +449,7 @@ static void __init ms_hyperv_init_platform(void)
451449
pr_debug("Hyper-V: max %u virtual processors, %u logical processors\n",
452450
ms_hyperv.max_vp_index, ms_hyperv.max_lp_index);
453451

454-
/*
455-
* Check CPU management privilege.
456-
*
457-
* To mirror what Windows does we should extract CPU management
458-
* features and use the ReservedIdentityBit to detect if Linux is the
459-
* root partition. But that requires negotiating CPU management
460-
* interface (a process to be finalized). For now, use the privilege
461-
* flag as the indicator for running as root.
462-
*
463-
* Hyper-V should never specify running as root and as a Confidential
464-
* VM. But to protect against a compromised/malicious Hyper-V trying
465-
* to exploit root behavior to expose Confidential VM memory, ignore
466-
* the root partition setting if also a Confidential VM.
467-
*/
468-
if ((ms_hyperv.priv_high & HV_CPU_MANAGEMENT) &&
469-
!(ms_hyperv.priv_high & HV_ISOLATION)) {
470-
hv_root_partition = true;
471-
pr_info("Hyper-V: running as root partition\n");
472-
}
452+
hv_identify_partition_type();
473453

474454
if (ms_hyperv.hints & HV_X64_HYPERV_NESTED) {
475455
hv_nested = true;
@@ -618,7 +598,7 @@ static void __init ms_hyperv_init_platform(void)
618598

619599
# ifdef CONFIG_SMP
620600
smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu;
621-
if (hv_root_partition ||
601+
if (hv_root_partition() ||
622602
(!ms_hyperv.paravisor_present && hv_isolation_type_snp()))
623603
smp_ops.smp_prepare_cpus = hv_smp_prepare_cpus;
624604
# endif

drivers/clocksource/hyperv_timer.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ static void __init hv_init_tsc_clocksource(void)
582582
* mapped.
583583
*/
584584
tsc_msr.as_uint64 = hv_get_msr(HV_MSR_REFERENCE_TSC);
585-
if (hv_root_partition)
585+
if (hv_root_partition())
586586
tsc_pfn = tsc_msr.pfn;
587587
else
588588
tsc_pfn = HVPFN_DOWN(virt_to_phys(tsc_page));
@@ -627,7 +627,7 @@ void __init hv_remap_tsc_clocksource(void)
627627
if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
628628
return;
629629

630-
if (!hv_root_partition) {
630+
if (!hv_root_partition()) {
631631
WARN(1, "%s: attempt to remap TSC page in guest partition\n",
632632
__func__);
633633
return;

drivers/hv/hv.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ int hv_synic_alloc(void)
144144
* Synic message and event pages are allocated by paravisor.
145145
* Skip these pages allocation here.
146146
*/
147-
if (!ms_hyperv.paravisor_present && !hv_root_partition) {
147+
if (!ms_hyperv.paravisor_present && !hv_root_partition()) {
148148
hv_cpu->synic_message_page =
149149
(void *)get_zeroed_page(GFP_ATOMIC);
150150
if (!hv_cpu->synic_message_page) {
@@ -272,7 +272,7 @@ void hv_synic_enable_regs(unsigned int cpu)
272272
simp.as_uint64 = hv_get_msr(HV_MSR_SIMP);
273273
simp.simp_enabled = 1;
274274

275-
if (ms_hyperv.paravisor_present || hv_root_partition) {
275+
if (ms_hyperv.paravisor_present || hv_root_partition()) {
276276
/* Mask out vTOM bit. ioremap_cache() maps decrypted */
277277
u64 base = (simp.base_simp_gpa << HV_HYP_PAGE_SHIFT) &
278278
~ms_hyperv.shared_gpa_boundary;
@@ -291,7 +291,7 @@ void hv_synic_enable_regs(unsigned int cpu)
291291
siefp.as_uint64 = hv_get_msr(HV_MSR_SIEFP);
292292
siefp.siefp_enabled = 1;
293293

294-
if (ms_hyperv.paravisor_present || hv_root_partition) {
294+
if (ms_hyperv.paravisor_present || hv_root_partition()) {
295295
/* Mask out vTOM bit. ioremap_cache() maps decrypted */
296296
u64 base = (siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT) &
297297
~ms_hyperv.shared_gpa_boundary;
@@ -367,7 +367,7 @@ void hv_synic_disable_regs(unsigned int cpu)
367367
* addresses.
368368
*/
369369
simp.simp_enabled = 0;
370-
if (ms_hyperv.paravisor_present || hv_root_partition) {
370+
if (ms_hyperv.paravisor_present || hv_root_partition()) {
371371
iounmap(hv_cpu->synic_message_page);
372372
hv_cpu->synic_message_page = NULL;
373373
} else {
@@ -379,7 +379,7 @@ void hv_synic_disable_regs(unsigned int cpu)
379379
siefp.as_uint64 = hv_get_msr(HV_MSR_SIEFP);
380380
siefp.siefp_enabled = 0;
381381

382-
if (ms_hyperv.paravisor_present || hv_root_partition) {
382+
if (ms_hyperv.paravisor_present || hv_root_partition()) {
383383
iounmap(hv_cpu->synic_event_page);
384384
hv_cpu->synic_event_page = NULL;
385385
} else {

drivers/hv/hv_common.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,18 @@
3434
u64 hv_current_partition_id = HV_PARTITION_ID_SELF;
3535
EXPORT_SYMBOL_GPL(hv_current_partition_id);
3636

37+
enum hv_partition_type hv_curr_partition_type;
38+
EXPORT_SYMBOL_GPL(hv_curr_partition_type);
39+
3740
/*
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
3942
* Hyper-V specific globals so they are shared across all architectures and are
4043
* built only when CONFIG_HYPERV is defined. But on x86,
4144
* ms_hyperv_init_platform() is built even when CONFIG_HYPERV is not
4245
* defined, and it uses these three variables. So mark them as __weak
4346
* here, allowing for an overriding definition in the module containing
4447
* ms_hyperv_init_platform().
4548
*/
46-
bool __weak hv_root_partition;
47-
EXPORT_SYMBOL_GPL(hv_root_partition);
48-
4949
bool __weak hv_nested;
5050
EXPORT_SYMBOL_GPL(hv_nested);
5151

@@ -283,7 +283,7 @@ static void hv_kmsg_dump_register(void)
283283

284284
static inline bool hv_output_page_exists(void)
285285
{
286-
return hv_root_partition || IS_ENABLED(CONFIG_HYPERV_VTL_MODE);
286+
return hv_root_partition() || IS_ENABLED(CONFIG_HYPERV_VTL_MODE);
287287
}
288288

289289
void __init hv_get_partition_id(void)
@@ -594,7 +594,7 @@ EXPORT_SYMBOL_GPL(hv_setup_dma_ops);
594594

595595
bool hv_is_hibernation_supported(void)
596596
{
597-
return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4);
597+
return !hv_root_partition() && acpi_sleep_state_supported(ACPI_STATE_S4);
598598
}
599599
EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);
600600

@@ -717,3 +717,23 @@ int hv_result_to_errno(u64 status)
717717
}
718718
return -EIO;
719719
}
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+
}
739+
}

drivers/hv/vmbus_drv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2656,7 +2656,7 @@ static int __init hv_acpi_init(void)
26562656
if (!hv_is_hyperv_initialized())
26572657
return -ENODEV;
26582658

2659-
if (hv_root_partition && !hv_nested)
2659+
if (hv_root_partition() && !hv_nested)
26602660
return 0;
26612661

26622662
/*

drivers/iommu/hyperv-iommu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ static int __init hyperv_prepare_irq_remapping(void)
130130
x86_init.hyper.msi_ext_dest_id())
131131
return -ENODEV;
132132

133-
if (hv_root_partition) {
133+
if (hv_root_partition()) {
134134
name = "HYPERV-ROOT-IR";
135135
ops = &hyperv_root_ir_domain_ops;
136136
} else {
@@ -151,7 +151,7 @@ static int __init hyperv_prepare_irq_remapping(void)
151151
return -ENOMEM;
152152
}
153153

154-
if (hv_root_partition)
154+
if (hv_root_partition())
155155
return 0; /* The rest is only relevant to guests */
156156

157157
/*

include/asm-generic/mshyperv.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828

2929
#define VTPM_BASE_ADDRESS 0xfed40000
3030

31+
enum hv_partition_type {
32+
HV_PARTITION_TYPE_GUEST,
33+
HV_PARTITION_TYPE_ROOT,
34+
};
35+
3136
struct ms_hyperv_info {
3237
u32 features;
3338
u32 priv_high;
@@ -59,6 +64,7 @@ struct ms_hyperv_info {
5964
extern struct ms_hyperv_info ms_hyperv;
6065
extern bool hv_nested;
6166
extern u64 hv_current_partition_id;
67+
extern enum hv_partition_type hv_curr_partition_type;
6268

6369
extern void * __percpu *hyperv_pcpu_input_arg;
6470
extern void * __percpu *hyperv_pcpu_output_arg;
@@ -190,8 +196,6 @@ void hv_remove_crash_handler(void);
190196
extern int vmbus_interrupt;
191197
extern int vmbus_irq;
192198

193-
extern bool hv_root_partition;
194-
195199
#if IS_ENABLED(CONFIG_HYPERV)
196200
/*
197201
* Hypervisor's notion of virtual processor ID is different from
@@ -213,6 +217,7 @@ void __init hv_common_free(void);
213217
void __init ms_hyperv_late_init(void);
214218
int hv_common_cpu_init(unsigned int cpu);
215219
int hv_common_cpu_die(unsigned int cpu);
220+
void hv_identify_partition_type(void);
216221

217222
void *hv_alloc_hyperv_page(void);
218223
void *hv_alloc_hyperv_zeroed_page(void);
@@ -310,6 +315,7 @@ void hyperv_cleanup(void);
310315
bool hv_query_ext_cap(u64 cap_query);
311316
void hv_setup_dma_ops(struct device *dev, bool coherent);
312317
#else /* CONFIG_HYPERV */
318+
static inline void hv_identify_partition_type(void) {}
313319
static inline bool hv_is_hyperv_initialized(void) { return false; }
314320
static inline bool hv_is_hibernation_supported(void) { return false; }
315321
static inline void hyperv_cleanup(void) {}
@@ -321,4 +327,9 @@ static inline enum hv_isolation_type hv_get_isolation_type(void)
321327
}
322328
#endif /* CONFIG_HYPERV */
323329

330+
static inline bool hv_root_partition(void)
331+
{
332+
return hv_curr_partition_type == HV_PARTITION_TYPE_ROOT;
333+
}
334+
324335
#endif

0 commit comments

Comments
 (0)