[PATCH v11 5/9] x86/efi: Disable LASS while mapping the EFI runtime services
From: Sohil Mehta
Date: Wed Oct 29 2025 - 17:06:15 EST
From: Alexander Shishkin <alexander.shishkin@xxxxxxxxxxxxxxx>
While mapping EFI runtime services, set_virtual_address_map() is called
at its lower mapping, which LASS prohibits. Wrapping the EFI call with
lass_disable()/_enable() is not enough, because the AC flag only
controls data accesses, and not instruction fetches.
Use the big hammer and toggle the CR4.LASS bit to make this work.
Signed-off-by: Alexander Shishkin <alexander.shishkin@xxxxxxxxxxxxxxx>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx>
Signed-off-by: Sohil Mehta <sohil.mehta@xxxxxxxxx>
---
v11:
- No change.
v10:
- Reword code comments
---
arch/x86/platform/efi/efi.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 463b784499a8..ad9f76f90581 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -786,8 +786,8 @@ static void __init __efi_enter_virtual_mode(void)
{
int count = 0, pg_shift = 0;
void *new_memmap = NULL;
+ unsigned long pa, lass;
efi_status_t status;
- unsigned long pa;
if (efi_alloc_page_tables()) {
pr_err("Failed to allocate EFI page tables\n");
@@ -825,11 +825,23 @@ static void __init __efi_enter_virtual_mode(void)
efi_sync_low_kernel_mappings();
+ /*
+ * LASS complains because set_virtual_address_map() is located
+ * at a lower address. To pause enforcement, flipping RFLAGS.AC
+ * is not sufficient, as it only permits data access and not
+ * instruction fetch. Disable the entire LASS mechanism.
+ */
+ lass = cr4_read_shadow() & X86_CR4_LASS;
+ cr4_clear_bits(lass);
+
status = efi_set_virtual_address_map(efi.memmap.desc_size * count,
efi.memmap.desc_size,
efi.memmap.desc_version,
(efi_memory_desc_t *)pa,
efi_systab_phys);
+
+ cr4_set_bits(lass);
+
if (status != EFI_SUCCESS) {
pr_err("Unable to switch EFI into virtual mode (status=%lx)!\n",
status);
--
2.43.0