Skip to content

Commit aca1d27

Browse files
DemiMarieardbiesheuvel
authored andcommitted
efi: xen: Implement memory descriptor lookup based on hypercall
Xen on x86 boots dom0 in EFI mode but without providing a memory map. This means that some consistency checks we would like to perform on configuration tables or other data structures in memory are not currently possible. Xen does, however, expose EFI memory descriptor info via a Xen hypercall, so let's wire that up instead. It turns out that the returned information is not identical to what Linux's efi_mem_desc_lookup would return: the address returned is the address passed to the hypercall, and the size returned is the number of bytes remaining in the configuration table. However, none of the callers of efi_mem_desc_lookup() currently care about this. In the future, Xen may gain a hypercall that returns the actual start address, which can be used instead. Co-developed-by: Ard Biesheuvel <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]> Signed-off-by: Demi Marie Obenour <[email protected]> Tested-by: Marek Marczykowski-Górecki <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent ab03e91 commit aca1d27

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

drivers/firmware/efi/efi.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ void __init efi_find_mirror(void)
478478
* and if so, populate the supplied memory descriptor with the appropriate
479479
* data.
480480
*/
481-
int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
481+
int __efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
482482
{
483483
efi_memory_desc_t *md;
484484

@@ -512,6 +512,9 @@ int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
512512
return -ENOENT;
513513
}
514514

515+
extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
516+
__weak __alias(__efi_mem_desc_lookup);
517+
515518
/*
516519
* Calculate the highest address of an efi memory descriptor.
517520
*/

drivers/xen/efi.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <xen/interface/xen.h>
2828
#include <xen/interface/platform.h>
29+
#include <xen/page.h>
2930
#include <xen/xen.h>
3031
#include <xen/xen-ops.h>
3132

@@ -292,3 +293,38 @@ void __init xen_efi_runtime_setup(void)
292293
efi.get_next_high_mono_count = xen_efi_get_next_high_mono_count;
293294
efi.reset_system = xen_efi_reset_system;
294295
}
296+
297+
int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
298+
{
299+
static_assert(XEN_PAGE_SHIFT == EFI_PAGE_SHIFT,
300+
"Mismatch between EFI_PAGE_SHIFT and XEN_PAGE_SHIFT");
301+
struct xen_platform_op op;
302+
union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
303+
int rc;
304+
305+
if (!efi_enabled(EFI_PARAVIRT) || efi_enabled(EFI_MEMMAP))
306+
return __efi_mem_desc_lookup(phys_addr, out_md);
307+
phys_addr &= ~(u64)(EFI_PAGE_SIZE - 1);
308+
op = (struct xen_platform_op) {
309+
.cmd = XENPF_firmware_info,
310+
.u.firmware_info = {
311+
.type = XEN_FW_EFI_INFO,
312+
.index = XEN_FW_EFI_MEM_INFO,
313+
.u.efi_info.mem.addr = phys_addr,
314+
.u.efi_info.mem.size = U64_MAX - phys_addr,
315+
},
316+
};
317+
318+
rc = HYPERVISOR_platform_op(&op);
319+
if (rc) {
320+
pr_warn("Failed to lookup header 0x%llx in Xen memory map: error %d\n",
321+
phys_addr, rc);
322+
}
323+
324+
out_md->phys_addr = info->mem.addr;
325+
out_md->num_pages = info->mem.size >> EFI_PAGE_SHIFT;
326+
out_md->type = info->mem.type;
327+
out_md->attribute = info->mem.attr;
328+
329+
return 0;
330+
}

include/linux/efi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size);
731731
extern int __init efi_uart_console_only (void);
732732
extern u64 efi_mem_desc_end(efi_memory_desc_t *md);
733733
extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md);
734+
extern int __efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md);
734735
extern void efi_mem_reserve(phys_addr_t addr, u64 size);
735736
extern int efi_mem_reserve_persistent(phys_addr_t addr, u64 size);
736737
extern void efi_initialize_iomem_resources(struct resource *code_resource,

0 commit comments

Comments
 (0)