Commit 4a3575fd436aa98957184afd745e4ada8f1542d8
Committed by
Ingo Molnar
1 parent
f8dfd5ed14
Exists in
master
and in
7 other branches
x86: EFI_PAGE_SHIFT fix
Make x86 EFI code works when EFI_PAGE_SHIFT != PAGE_SHIFT. The memrage_efi_to_native() provided in this patch can be used on other EFI platform such as IA64 too. This patch has been tested on Intel x86_64 platform with EFI 64/32 firmware. Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Showing 3 changed files with 26 additions and 11 deletions Side-by-side Diff
arch/x86/kernel/efi.c
... | ... | @@ -383,6 +383,7 @@ |
383 | 383 | { |
384 | 384 | efi_memory_desc_t *md; |
385 | 385 | void *p; |
386 | + u64 addr, npages; | |
386 | 387 | |
387 | 388 | /* Make EFI runtime service code area executable */ |
388 | 389 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
... | ... | @@ -391,7 +392,10 @@ |
391 | 392 | if (md->type != EFI_RUNTIME_SERVICES_CODE) |
392 | 393 | continue; |
393 | 394 | |
394 | - set_memory_x(md->virt_addr, md->num_pages); | |
395 | + addr = md->virt_addr; | |
396 | + npages = md->num_pages; | |
397 | + memrange_efi_to_native(&addr, &npages); | |
398 | + set_memory_x(addr, npages); | |
395 | 399 | } |
396 | 400 | } |
397 | 401 | |
... | ... | @@ -408,7 +412,7 @@ |
408 | 412 | efi_memory_desc_t *md; |
409 | 413 | efi_status_t status; |
410 | 414 | unsigned long size; |
411 | - u64 end, systab; | |
415 | + u64 end, systab, addr, npages; | |
412 | 416 | void *p, *va; |
413 | 417 | |
414 | 418 | efi.systab = NULL; |
... | ... | @@ -420,7 +424,7 @@ |
420 | 424 | size = md->num_pages << EFI_PAGE_SHIFT; |
421 | 425 | end = md->phys_addr + size; |
422 | 426 | |
423 | - if ((end >> PAGE_SHIFT) <= max_pfn_mapped) | |
427 | + if (PFN_UP(end) <= max_pfn_mapped) | |
424 | 428 | va = __va(md->phys_addr); |
425 | 429 | else |
426 | 430 | va = efi_ioremap(md->phys_addr, size); |
... | ... | @@ -433,8 +437,12 @@ |
433 | 437 | continue; |
434 | 438 | } |
435 | 439 | |
436 | - if (!(md->attribute & EFI_MEMORY_WB)) | |
437 | - set_memory_uc(md->virt_addr, md->num_pages); | |
440 | + if (!(md->attribute & EFI_MEMORY_WB)) { | |
441 | + addr = md->virt_addr; | |
442 | + npages = md->num_pages; | |
443 | + memrange_efi_to_native(&addr, &npages); | |
444 | + set_memory_uc(addr, npages); | |
445 | + } | |
438 | 446 | |
439 | 447 | systab = (u64) (unsigned long) efi_phys.systab; |
440 | 448 | if (md->phys_addr <= systab && systab < end) { |
arch/x86/kernel/efi_64.c
... | ... | @@ -105,14 +105,14 @@ |
105 | 105 | |
106 | 106 | void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size) |
107 | 107 | { |
108 | - static unsigned pages_mapped; | |
108 | + static unsigned pages_mapped __initdata; | |
109 | 109 | unsigned i, pages; |
110 | + unsigned long offset; | |
110 | 111 | |
111 | - /* phys_addr and size must be page aligned */ | |
112 | - if ((phys_addr & ~PAGE_MASK) || (size & ~PAGE_MASK)) | |
113 | - return NULL; | |
112 | + pages = PFN_UP(phys_addr + size) - PFN_DOWN(phys_addr); | |
113 | + offset = phys_addr & ~PAGE_MASK; | |
114 | + phys_addr &= PAGE_MASK; | |
114 | 115 | |
115 | - pages = size >> PAGE_SHIFT; | |
116 | 116 | if (pages_mapped + pages > MAX_EFI_IO_PAGES) |
117 | 117 | return NULL; |
118 | 118 | |
... | ... | @@ -124,6 +124,6 @@ |
124 | 124 | } |
125 | 125 | |
126 | 126 | return (void __iomem *)__fix_to_virt(FIX_EFI_IO_MAP_FIRST_PAGE - \ |
127 | - (pages_mapped - pages)); | |
127 | + (pages_mapped - pages)) + offset; | |
128 | 128 | } |
include/linux/efi.h
... | ... | @@ -18,6 +18,7 @@ |
18 | 18 | #include <linux/proc_fs.h> |
19 | 19 | #include <linux/rtc.h> |
20 | 20 | #include <linux/ioport.h> |
21 | +#include <linux/pfn.h> | |
21 | 22 | |
22 | 23 | #include <asm/page.h> |
23 | 24 | #include <asm/system.h> |
... | ... | @@ -393,6 +394,12 @@ |
393 | 394 | u8 sub_type; |
394 | 395 | u16 length; |
395 | 396 | } __attribute ((packed)); |
397 | + | |
398 | +static inline void memrange_efi_to_native(u64 *addr, u64 *npages) | |
399 | +{ | |
400 | + *npages = PFN_UP(*addr + (*npages<<EFI_PAGE_SHIFT)) - PFN_DOWN(*addr); | |
401 | + *addr &= PAGE_MASK; | |
402 | +} | |
396 | 403 | |
397 | 404 | #endif /* _LINUX_EFI_H */ |