Commit 4a3575fd436aa98957184afd745e4ada8f1542d8

Authored by Huang, Ying
Committed by Ingo Molnar
1 parent f8dfd5ed14

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 }
... ... @@ -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 */