|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v1 2/2] xen/efi: optionally call SetVirtualAddressMap()
Some UEFI implementations are not happy about running in 1:1 addressing,
but really virtual address space. Specifically, some access
EfiBootServices{Code,Data}, or even totally unmapped areas. Example
crash of GetVariable() call on Thinkpad W540:
Xen call trace:
[<0000000000000080>] 0000000000000080
[<8c2b0398e0000daa>] 8c2b0398e0000daa
Pagetable walk from ffffffff858483a1:
L4[0x1ff] = 0000000000000000 ffffffffffffffff
****************************************
Panic on CPU 0:
FATAL PAGE FAULT
[error_code=0002]
Faulting linear address: ffffffff858483a1
****************************************
Fix this by calling SetVirtualAddressMap() runtime service, giving it
1:1 map for areas marked as needed during runtime. The address space in
which EFI runtime services are called is unchanged, but UEFI view of it
may be.
SetVirtualAddressMap() can be called only once, hence it's incompatible
with kexec. For this reason, make it an optional feature, depending on
!KEXEC. And to not inflate number of supported configurations, hide it
behind EXPERT.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
---
xen/common/Kconfig | 13 +++++++++++++
xen/common/efi/boot.c | 28 ++++++++++++++++++++++++++--
2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 16829f6..fe98f8a 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -88,6 +88,19 @@ config KEXEC
If unsure, say Y.
+config SET_VIRTUAL_ADDRESS_MAP
+ bool "EFI: call SetVirtualAddressMap()" if EXPERT = "y"
+ default n
+ depends on !KEXEC
+ ---help---
+ Call EFI SetVirtualAddressMap() runtime service to setup memory map for
+ further runtime services. According to UEFI spec, it isn't strictly
+ necessary, but many UEFI implementations misbehave when this call is
+ missing. On the other hand, this call can be made only once, which makes
+ it incompatible with kexec (kexec-ing this Xen from other Xen or Linux).
+
+ If unsuser, say N.
+
config XENOPROF
def_bool y
prompt "Xen Oprofile Support" if EXPERT = "y"
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index cddf3de..5c187db 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -1056,11 +1056,17 @@ static void __init
efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop
efi_arch_video_init(gop, info_size, mode_info);
}
+#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
+ (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
+
static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE
*SystemTable)
{
EFI_STATUS status;
UINTN info_size = 0, map_key;
bool retry;
+#ifdef CONFIG_SET_VIRTUAL_ADDRESS_MAP
+ unsigned int i;
+#endif
efi_bs->GetMemoryMap(&info_size, NULL, &map_key,
&efi_mdesc_size, &mdesc_ver);
@@ -1098,6 +1104,26 @@ static void __init efi_exit_boot(EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE *Syste
efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
+
+#ifdef CONFIG_SET_VIRTUAL_ADDRESS_MAP
+ for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+ {
+ EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+
+ if ( desc->Attribute & EFI_MEMORY_RUNTIME )
+ desc->VirtualStart = desc->PhysicalStart;
+ else
+ desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
+ }
+ status = efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
+ mdesc_ver, efi_memmap);
+ if ( status != EFI_SUCCESS )
+ {
+ printk(XENLOG_ERR "EFI: SetVirtualAddressMap() failed (%#lx),
disabling runtime services\n",
+ status);
+ __clear_bit(EFI_RS, &efi_flags);
+ }
+#endif
}
static int __init __maybe_unused set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
@@ -1460,8 +1486,6 @@ static bool __init rt_range_valid(unsigned long smfn,
unsigned long emfn)
return true;
}
-#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
- (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
void __init efi_init_memory(void)
{
--
git-series 0.9.1
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |