Message ID | 20250315001931.631210-3-romank@linux.microsoft.com (mailing list archive) |
---|---|
State | Handled Elsewhere, archived |
Headers | show |
Series | arm64: hyperv: Support Virtual Trust Level Boot | expand |
On Fri, Mar 14, 2025 at 05:19:22PM -0700, Roman Kisel wrote: > The arm64 Hyper-V startup path relies on ACPI to detect > running under a Hyper-V compatible hypervisor. That > doesn't work on non-ACPI systems. > > Hoist the ACPI detection logic into a separate function. Then > use the vendor-specific hypervisor service call (implemented > recently in Hyper-V) via SMCCC in the non-ACPI case. > > Signed-off-by: Roman Kisel <romank@linux.microsoft.com> > Reviewed-by: Michael Kelley <mhklinux@outlook.com> > --- > arch/arm64/hyperv/mshyperv.c | 43 +++++++++++++++++++++++++++++++----- > 1 file changed, 38 insertions(+), 5 deletions(-) > > diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c > index 2265ea5ce5ad..c5b03d3af7c5 100644 > --- a/arch/arm64/hyperv/mshyperv.c > +++ b/arch/arm64/hyperv/mshyperv.c > @@ -27,6 +27,41 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) > return 0; > } > > +static bool __init hyperv_detect_via_acpi(void) > +{ > + if (acpi_disabled) > + return false; > +#if IS_ENABLED(CONFIG_ACPI) > + /* > + * Hypervisor ID is only available in ACPI v6+, and the > + * structure layout was extended in v6 to accommodate that > + * new field. > + * > + * At the very minimum, this check makes sure not to read > + * past the FADT structure. > + * > + * It is also needed to catch running in some unknown > + * non-Hyper-V environment that has ACPI 5.x or less. > + * In such a case, it can't be Hyper-V. > + */ > + if (acpi_gbl_FADT.header.revision < 6) > + return false; > + return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0; > +#else > + return false; > +#endif > +} > + The 'acpi_disabled' variable doesn't exist for !CONFIG_ACPI, so its use prior to the ifdeffery looks misplaced. Usual codestyle is to avoid ifdeffery if possible, using IS_ENABLED(). Otherwise, use a stub, e.g. | #ifdef CONFIG_ACPI | static bool __init hyperv_detect_via_acpi(void) | { | if (acpi_disabled) | return false; | | if (acpi_gbl_FADT.header.revision < 6) | return false; | | return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0; | } | #else | static inline bool hyperv_detect_via_acpi(void) { return false; } | #endif Mark. > +static bool __init hyperv_detect_via_smccc(void) > +{ > + uuid_t hyperv_uuid = UUID_INIT( > + 0x4d32ba58, 0x4764, 0xcd24, > + 0x75, 0x6c, 0xef, 0x8e, > + 0x24, 0x70, 0x59, 0x16); > + > + return arm_smccc_hyp_present(&hyperv_uuid); > +} > + > static int __init hyperv_init(void) > { > struct hv_get_vp_registers_output result; > @@ -35,13 +70,11 @@ static int __init hyperv_init(void) > > /* > * Allow for a kernel built with CONFIG_HYPERV to be running in > - * a non-Hyper-V environment, including on DT instead of ACPI. > + * a non-Hyper-V environment. > + * > * In such cases, do nothing and return success. > */ > - if (acpi_disabled) > - return 0; > - > - if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8)) > + if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc()) > return 0; > > /* Setup the guest ID */ > -- > 2.43.0 >
On 3/17/2025 4:37 AM, Mark Rutland wrote: > On Fri, Mar 14, 2025 at 05:19:22PM -0700, Roman Kisel wrote: [...] > The 'acpi_disabled' variable doesn't exist for !CONFIG_ACPI, so its use > prior to the ifdeffery looks misplaced. > > Usual codestyle is to avoid ifdeffery if possible, using IS_ENABLED(). > Otherwise, use a stub, e.g. > That looks much better, thanks for the review! Will implement in the next version. > | #ifdef CONFIG_ACPI > | static bool __init hyperv_detect_via_acpi(void) > | { > | if (acpi_disabled) > | return false; > | > | if (acpi_gbl_FADT.header.revision < 6) > | return false; > | > | return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0; > | } > | #else > | static inline bool hyperv_detect_via_acpi(void) { return false; } > | #endif > > Mark. > >> +static bool __init hyperv_detect_via_smccc(void) >> +{ >> + uuid_t hyperv_uuid = UUID_INIT( >> + 0x4d32ba58, 0x4764, 0xcd24, >> + 0x75, 0x6c, 0xef, 0x8e, >> + 0x24, 0x70, 0x59, 0x16); >> + >> + return arm_smccc_hyp_present(&hyperv_uuid); >> +} >> + >> static int __init hyperv_init(void) >> { >> struct hv_get_vp_registers_output result; >> @@ -35,13 +70,11 @@ static int __init hyperv_init(void) >> >> /* >> * Allow for a kernel built with CONFIG_HYPERV to be running in >> - * a non-Hyper-V environment, including on DT instead of ACPI. >> + * a non-Hyper-V environment. >> + * >> * In such cases, do nothing and return success. >> */ >> - if (acpi_disabled) >> - return 0; >> - >> - if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8)) >> + if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc()) >> return 0; >> >> /* Setup the guest ID */ >> -- >> 2.43.0 >>
From: Mark Rutland <mark.rutland@arm.com> Sent: Monday, March 17, 2025 4:38 AM > > On Fri, Mar 14, 2025 at 05:19:22PM -0700, Roman Kisel wrote: > > The arm64 Hyper-V startup path relies on ACPI to detect > > running under a Hyper-V compatible hypervisor. That > > doesn't work on non-ACPI systems. > > > > Hoist the ACPI detection logic into a separate function. Then > > use the vendor-specific hypervisor service call (implemented > > recently in Hyper-V) via SMCCC in the non-ACPI case. > > > > Signed-off-by: Roman Kisel <romank@linux.microsoft.com> > > Reviewed-by: Michael Kelley <mhklinux@outlook.com> > > --- > > arch/arm64/hyperv/mshyperv.c | 43 +++++++++++++++++++++++++++++++----- > > 1 file changed, 38 insertions(+), 5 deletions(-) > > > > diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c > > index 2265ea5ce5ad..c5b03d3af7c5 100644 > > --- a/arch/arm64/hyperv/mshyperv.c > > +++ b/arch/arm64/hyperv/mshyperv.c > > @@ -27,6 +27,41 @@ int hv_get_hypervisor_version(union > hv_hypervisor_version_info *info) > > return 0; > > } > > > > +static bool __init hyperv_detect_via_acpi(void) > > +{ > > + if (acpi_disabled) > > + return false; > > +#if IS_ENABLED(CONFIG_ACPI) > > + /* > > + * Hypervisor ID is only available in ACPI v6+, and the > > + * structure layout was extended in v6 to accommodate that > > + * new field. > > + * > > + * At the very minimum, this check makes sure not to read > > + * past the FADT structure. > > + * > > + * It is also needed to catch running in some unknown > > + * non-Hyper-V environment that has ACPI 5.x or less. > > + * In such a case, it can't be Hyper-V. > > + */ > > + if (acpi_gbl_FADT.header.revision < 6) > > + return false; > > + return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0; > > +#else > > + return false; > > +#endif > > +} > > + > > The 'acpi_disabled' variable doesn't exist for !CONFIG_ACPI, so its use > prior to the ifdeffery looks misplaced. FWIW, include/linux/acpi.h has #define acpi_disabled 1 when !CONFIG_ACPI. But I agree that using a stub is better. Michael > > Usual codestyle is to avoid ifdeffery if possible, using IS_ENABLED(). > Otherwise, use a stub, e.g. > > | #ifdef CONFIG_ACPI > | static bool __init hyperv_detect_via_acpi(void) > | { > | if (acpi_disabled) > | return false; > | > | if (acpi_gbl_FADT.header.revision < 6) > | return false; > | > | return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0; > | } > | #else > | static inline bool hyperv_detect_via_acpi(void) { return false; } > | #endif > > Mark. > > > +static bool __init hyperv_detect_via_smccc(void) > > +{ > > + uuid_t hyperv_uuid = UUID_INIT( > > + 0x4d32ba58, 0x4764, 0xcd24, > > + 0x75, 0x6c, 0xef, 0x8e, > > + 0x24, 0x70, 0x59, 0x16); > > + > > + return arm_smccc_hyp_present(&hyperv_uuid); > > +} > > + > > static int __init hyperv_init(void) > > { > > struct hv_get_vp_registers_output result; > > @@ -35,13 +70,11 @@ static int __init hyperv_init(void) > > > > /* > > * Allow for a kernel built with CONFIG_HYPERV to be running in > > - * a non-Hyper-V environment, including on DT instead of ACPI. > > + * a non-Hyper-V environment. > > + * > > * In such cases, do nothing and return success. > > */ > > - if (acpi_disabled) > > - return 0; > > - > > - if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8)) > > + if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc()) > > return 0; > > > > /* Setup the guest ID */ > > -- > > 2.43.0 > >
On 3/19/2025 3:11 PM, Michael Kelley wrote: > From: Mark Rutland <mark.rutland@arm.com> Sent: Monday, March 17, 2025 4:38 AM >> >> The 'acpi_disabled' variable doesn't exist for !CONFIG_ACPI, so its use >> prior to the ifdeffery looks misplaced. > > FWIW, include/linux/acpi.h has > > #define acpi_disabled 1 > > when !CONFIG_ACPI. But I agree that using a stub is better. Thanks, Michael! I didn't "fact-checked" what was suggested indeed. Agreed that the stub makes the code look better. > > Michael > >> >> Usual codestyle is to avoid ifdeffery if possible, using IS_ENABLED(). >> Otherwise, use a stub, e.g. >> >> | #ifdef CONFIG_ACPI >> | static bool __init hyperv_detect_via_acpi(void) >> | { >> | if (acpi_disabled) >> | return false; >> | >> | if (acpi_gbl_FADT.header.revision < 6) >> | return false; >> | >> | return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0; >> | } >> | #else >> | static inline bool hyperv_detect_via_acpi(void) { return false; } >> | #endif >> >> Mark. >> >>> +static bool __init hyperv_detect_via_smccc(void) >>> +{ >>> + uuid_t hyperv_uuid = UUID_INIT( >>> + 0x4d32ba58, 0x4764, 0xcd24, >>> + 0x75, 0x6c, 0xef, 0x8e, >>> + 0x24, 0x70, 0x59, 0x16); >>> + >>> + return arm_smccc_hyp_present(&hyperv_uuid); >>> +} >>> + >>> static int __init hyperv_init(void) >>> { >>> struct hv_get_vp_registers_output result; >>> @@ -35,13 +70,11 @@ static int __init hyperv_init(void) >>> >>> /* >>> * Allow for a kernel built with CONFIG_HYPERV to be running in >>> - * a non-Hyper-V environment, including on DT instead of ACPI. >>> + * a non-Hyper-V environment. >>> + * >>> * In such cases, do nothing and return success. >>> */ >>> - if (acpi_disabled) >>> - return 0; >>> - >>> - if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8)) >>> + if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc()) >>> return 0; >>> >>> /* Setup the guest ID */ >>> -- >>> 2.43.0 >>> >
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index 2265ea5ce5ad..c5b03d3af7c5 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -27,6 +27,41 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) return 0; } +static bool __init hyperv_detect_via_acpi(void) +{ + if (acpi_disabled) + return false; +#if IS_ENABLED(CONFIG_ACPI) + /* + * Hypervisor ID is only available in ACPI v6+, and the + * structure layout was extended in v6 to accommodate that + * new field. + * + * At the very minimum, this check makes sure not to read + * past the FADT structure. + * + * It is also needed to catch running in some unknown + * non-Hyper-V environment that has ACPI 5.x or less. + * In such a case, it can't be Hyper-V. + */ + if (acpi_gbl_FADT.header.revision < 6) + return false; + return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0; +#else + return false; +#endif +} + +static bool __init hyperv_detect_via_smccc(void) +{ + uuid_t hyperv_uuid = UUID_INIT( + 0x4d32ba58, 0x4764, 0xcd24, + 0x75, 0x6c, 0xef, 0x8e, + 0x24, 0x70, 0x59, 0x16); + + return arm_smccc_hyp_present(&hyperv_uuid); +} + static int __init hyperv_init(void) { struct hv_get_vp_registers_output result; @@ -35,13 +70,11 @@ static int __init hyperv_init(void) /* * Allow for a kernel built with CONFIG_HYPERV to be running in - * a non-Hyper-V environment, including on DT instead of ACPI. + * a non-Hyper-V environment. + * * In such cases, do nothing and return success. */ - if (acpi_disabled) - return 0; - - if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8)) + if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc()) return 0; /* Setup the guest ID */