Set bit 0 of the Hyper-V private OsLoaderIndications EFI variable during exit_boot() so the bootloader/firmware knows the OS intends to enable VTL1. Without this, VTL1 cannot be brought up from the Linux kernel.
The support bit is first checked in OsLoaderIndicationsSupported, and the variable is only written when the VSM bit is not already set. Signed-off-by: Thara Gopinath <[email protected]> --- drivers/firmware/efi/libstub/x86-stub.c | 57 +++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c index cef32e2c82d8f..ab3cd4fe36599 100644 --- a/drivers/firmware/efi/libstub/x86-stub.c +++ b/drivers/firmware/efi/libstub/x86-stub.c @@ -21,6 +21,17 @@ #include "efistub.h" #include "x86-stub.h" +#ifdef CONFIG_HYPERV_VSM +#define HYPERV_PRIVATE_EFI_NAMESPACE_GUID \ + EFI_GUID(0x610b9e98, 0xc6f6, 0x47f8, 0x8b, 0x47, 0x2d, 0x2d, 0xa0, 0xd5, 0x2a, 0x91) + +static const efi_char16_t efi_HvPrivOsloaderIndications_name[] = L"OsLoaderIndications"; +static const efi_char16_t efi_HvPrivOsloaderIndicationsSupported_name[] = + L"OsLoaderIndicationsSupported"; +#define HV_OSLOADER_INDICATION_VSM BIT(0) + +#endif + extern char _bss[], _ebss[]; const efi_system_table_t *efi_system_table; @@ -754,6 +765,47 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, return EFI_SUCCESS; } +#ifdef CONFIG_HYPERV_VSM +static void efi_set_hv_os_indications(void) +{ + efi_guid_t guid = HYPERV_PRIVATE_EFI_NAMESPACE_GUID; + efi_status_t status; + unsigned long size; + u32 attr, val; + + size = sizeof(val); + status = get_efi_var(efi_HvPrivOsloaderIndicationsSupported_name, + &guid, &attr, &size, &val); + if (status != EFI_SUCCESS) { + efi_err("Could not read Hyper-V OsloaderIndicationsSupported\n"); + return; + } + + if (!(val & HV_OSLOADER_INDICATION_VSM)) { + efi_info("Hyper-V does not support VSM in OsloaderIndicationsSupported\n"); + return; + } + + size = sizeof(val); + status = get_efi_var(efi_HvPrivOsloaderIndications_name, &guid, &attr, &size, &val); + if (status != EFI_SUCCESS) { + efi_err("Could not read Hyper-V OsLoaderIndications\n"); + return; + } + + if (val & HV_OSLOADER_INDICATION_VSM) { + efi_info("VSM is already supported in OsLoaderIndications."); + return; + } + + val |= HV_OSLOADER_INDICATION_VSM; + size = sizeof(val); + status = set_efi_var(efi_HvPrivOsloaderIndications_name, &guid, attr, size, &val); + if (status != EFI_SUCCESS) + efi_err("Could not set Hyper-V OsLoaderIndications to indicate VSM support\n"); +} +#endif + static efi_status_t exit_boot(struct boot_params *boot_params, void *handle) { struct setup_data *e820ext = NULL; @@ -768,6 +820,11 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle) if (status != EFI_SUCCESS) return status; +#ifdef CONFIG_HYPERV_VSM + /* Indicate to bootloader that we will be enabling VTL1 before exiting boot services */ + efi_set_hv_os_indications(); +#endif + /* Might as well exit boot services now */ status = efi_exit_boot_services(handle, &priv, exit_boot_func); if (status != EFI_SUCCESS) -- 2.34.1

