mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2026-08-26 21:27:15 -05:00
aarch64: fix SMBIOS parsing crash when loaded via shim
map startup-only regions as Normal memory
This commit is contained in:
+14
-8
@@ -8,7 +8,8 @@
|
|||||||
// regions described by the BIOS/EFI memory map, so all mapping functions
|
// regions described by the BIOS/EFI memory map, so all mapping functions
|
||||||
// simply return the physical address unchanged. RAM is mapped as Normal
|
// simply return the physical address unchanged. RAM is mapped as Normal
|
||||||
// write-back cacheable memory, the frame buffer as Normal non-cacheable
|
// write-back cacheable memory, the frame buffer as Normal non-cacheable
|
||||||
// memory, and anything else mapped on demand (MMIO) as Device-nGnRnE.
|
// memory, and anything else mapped on demand either as Normal write-back
|
||||||
|
// (RAM-resident firmware tables) or as Device-nGnRnE (MMIO).
|
||||||
//
|
//
|
||||||
// The tables use the 4KB granule with a 48-bit input address range and
|
// The tables use the 4KB granule with a 48-bit input address range and
|
||||||
// are built from 1GB and 2MB block descriptors only. paging_init() is
|
// are built from 1GB and 2MB block descriptors only. paging_init() is
|
||||||
@@ -66,6 +67,7 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
uint64_t end;
|
uint64_t end;
|
||||||
|
uint64_t attrs;
|
||||||
} device_region_t;
|
} device_region_t;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -287,13 +289,13 @@ void paging_init(void)
|
|||||||
paging_incomplete |= !map_range(cmd_line_start, cmd_line_end, PTE_ATTR_NORMAL);
|
paging_incomplete |= !map_range(cmd_line_start, cmd_line_end, PTE_ATTR_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replay the device mappings made via map_region.
|
// Replay the mappings made via map_region.
|
||||||
for (int i = 0; i < num_device_regions; i++) {
|
for (int i = 0; i < num_device_regions; i++) {
|
||||||
paging_incomplete |= !map_range(device_regions[i].start, device_regions[i].end, PTE_ATTR_DEVICE);
|
paging_incomplete |= !map_range(device_regions[i].start, device_regions[i].end, device_regions[i].attrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t map_region(uintptr_t base_addr, size_t size, bool only_for_startup __attribute__((unused)))
|
uintptr_t map_region(uintptr_t base_addr, size_t size, bool only_for_startup)
|
||||||
{
|
{
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
size = 1;
|
size = 1;
|
||||||
@@ -304,6 +306,12 @@ uintptr_t map_region(uintptr_t base_addr, size_t size, bool only_for_startup __a
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Startup-only regions are RAM-resident firmware tables (ACPI, SMBIOS,
|
||||||
|
// ...) and must be mapped as Normal memory: their parsers do unaligned
|
||||||
|
// accesses, which fault on Device memory. Everything else is assumed
|
||||||
|
// to be MMIO. Regions mapped earlier keep their original attributes.
|
||||||
|
uint64_t attrs = only_for_startup ? (PTE_ATTR_NORMAL | PTE_PXN) : PTE_ATTR_DEVICE;
|
||||||
|
|
||||||
// Record the region (at block granularity) so the mapping can be
|
// Record the region (at block granularity) so the mapping can be
|
||||||
// replayed when the page tables are rebuilt after relocation.
|
// replayed when the page tables are rebuilt after relocation.
|
||||||
uint64_t start = base_addr & ~(BLOCK_2M - 1);
|
uint64_t start = base_addr & ~(BLOCK_2M - 1);
|
||||||
@@ -320,13 +328,11 @@ uintptr_t map_region(uintptr_t base_addr, size_t size, bool only_for_startup __a
|
|||||||
}
|
}
|
||||||
device_regions[num_device_regions].start = start;
|
device_regions[num_device_regions].start = start;
|
||||||
device_regions[num_device_regions].end = end;
|
device_regions[num_device_regions].end = end;
|
||||||
|
device_regions[num_device_regions].attrs = attrs;
|
||||||
num_device_regions++;
|
num_device_regions++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anything not already mapped is assumed to be MMIO and gets a Device
|
if (!map_range(base_addr, base_addr + size, attrs)) {
|
||||||
// mapping. Regions mapped earlier (e.g. RAM, the frame buffer) keep
|
|
||||||
// their original attributes.
|
|
||||||
if (!map_range(base_addr, base_addr + size, PTE_ATTR_DEVICE)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user