mirror of
https://github.com/torvalds/linux.git
synced 2024-11-08 21:21:47 +00:00
x86, efi: Merge contiguous memory regions of the same type and attribute
Some firmware implementations assume that physically contiguous regions will be contiguous in virtual address space. This assumption is, obviously, entirely unjustifiable. Said firmware implementations lack the good grace to handle their failings in a measured and reasonable manner, instead tending to shit all over address space and oopsing the kernel. In an ideal universe these firmware implementations would simultaneously catch fire and cease to be a problem, but since some of them are present in attractively thin and shiny metal devices vanity wins out and some poor developer spends an extended period of time surrounded by a growing array of empty bottles until the underlying reason becomes apparent. Said developer presents this patch, which simply merges adjacent regions if they happen to be contiguous and have the same EFI memory type and caching attributes. Signed-off-by: Matthew Garrett <mjg@redhat.com> Link: http://lkml.kernel.org/r/1304623186-18261-3-git-send-email-mjg@redhat.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
9cd2b07c19
commit
202f9d0a41
@ -498,13 +498,41 @@ static void __init runtime_code_page_mkexec(void)
|
||||
*/
|
||||
void __init efi_enter_virtual_mode(void)
|
||||
{
|
||||
efi_memory_desc_t *md;
|
||||
efi_memory_desc_t *md, *prev_md = NULL;
|
||||
efi_status_t status;
|
||||
unsigned long size;
|
||||
u64 end, systab, addr, npages, end_pfn;
|
||||
void *p, *va;
|
||||
|
||||
efi.systab = NULL;
|
||||
|
||||
/* Merge contiguous regions of the same type and attribute */
|
||||
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||
u64 prev_size;
|
||||
md = p;
|
||||
|
||||
if (!prev_md) {
|
||||
prev_md = md;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prev_md->type != md->type ||
|
||||
prev_md->attribute != md->attribute) {
|
||||
prev_md = md;
|
||||
continue;
|
||||
}
|
||||
|
||||
prev_size = prev_md->num_pages << EFI_PAGE_SHIFT;
|
||||
|
||||
if (md->phys_addr == (prev_md->phys_addr + prev_size)) {
|
||||
prev_md->num_pages += md->num_pages;
|
||||
md->type = EFI_RESERVED_TYPE;
|
||||
md->attribute = 0;
|
||||
continue;
|
||||
}
|
||||
prev_md = md;
|
||||
}
|
||||
|
||||
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||
md = p;
|
||||
if (!(md->attribute & EFI_MEMORY_RUNTIME))
|
||||
|
Loading…
Reference in New Issue
Block a user