提交 4a3575fd 编写于 作者: H Huang, Ying 提交者: Ingo Molnar

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: NHuang Ying <ying.huang@intel.com>
Signed-off-by: NIngo Molnar <mingo@elte.hu>
Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
上级 f8dfd5ed
...@@ -383,6 +383,7 @@ static void __init runtime_code_page_mkexec(void) ...@@ -383,6 +383,7 @@ static void __init runtime_code_page_mkexec(void)
{ {
efi_memory_desc_t *md; efi_memory_desc_t *md;
void *p; void *p;
u64 addr, npages;
/* Make EFI runtime service code area executable */ /* Make EFI runtime service code area executable */
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
...@@ -391,7 +392,10 @@ static void __init runtime_code_page_mkexec(void) ...@@ -391,7 +392,10 @@ static void __init runtime_code_page_mkexec(void)
if (md->type != EFI_RUNTIME_SERVICES_CODE) if (md->type != EFI_RUNTIME_SERVICES_CODE)
continue; continue;
set_memory_x(md->virt_addr, md->num_pages); addr = md->virt_addr;
npages = md->num_pages;
memrange_efi_to_native(&addr, &npages);
set_memory_x(addr, npages);
} }
} }
...@@ -408,7 +412,7 @@ void __init efi_enter_virtual_mode(void) ...@@ -408,7 +412,7 @@ void __init efi_enter_virtual_mode(void)
efi_memory_desc_t *md; efi_memory_desc_t *md;
efi_status_t status; efi_status_t status;
unsigned long size; unsigned long size;
u64 end, systab; u64 end, systab, addr, npages;
void *p, *va; void *p, *va;
efi.systab = NULL; efi.systab = NULL;
...@@ -420,7 +424,7 @@ void __init efi_enter_virtual_mode(void) ...@@ -420,7 +424,7 @@ void __init efi_enter_virtual_mode(void)
size = md->num_pages << EFI_PAGE_SHIFT; size = md->num_pages << EFI_PAGE_SHIFT;
end = md->phys_addr + size; end = md->phys_addr + size;
if ((end >> PAGE_SHIFT) <= max_pfn_mapped) if (PFN_UP(end) <= max_pfn_mapped)
va = __va(md->phys_addr); va = __va(md->phys_addr);
else else
va = efi_ioremap(md->phys_addr, size); va = efi_ioremap(md->phys_addr, size);
...@@ -433,8 +437,12 @@ void __init efi_enter_virtual_mode(void) ...@@ -433,8 +437,12 @@ void __init efi_enter_virtual_mode(void)
continue; continue;
} }
if (!(md->attribute & EFI_MEMORY_WB)) if (!(md->attribute & EFI_MEMORY_WB)) {
set_memory_uc(md->virt_addr, md->num_pages); addr = md->virt_addr;
npages = md->num_pages;
memrange_efi_to_native(&addr, &npages);
set_memory_uc(addr, npages);
}
systab = (u64) (unsigned long) efi_phys.systab; systab = (u64) (unsigned long) efi_phys.systab;
if (md->phys_addr <= systab && systab < end) { if (md->phys_addr <= systab && systab < end) {
......
...@@ -105,14 +105,14 @@ void __init efi_reserve_bootmem(void) ...@@ -105,14 +105,14 @@ void __init efi_reserve_bootmem(void)
void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size) void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size)
{ {
static unsigned pages_mapped; static unsigned pages_mapped __initdata;
unsigned i, pages; unsigned i, pages;
unsigned long offset;
/* phys_addr and size must be page aligned */ pages = PFN_UP(phys_addr + size) - PFN_DOWN(phys_addr);
if ((phys_addr & ~PAGE_MASK) || (size & ~PAGE_MASK)) offset = phys_addr & ~PAGE_MASK;
return NULL; phys_addr &= PAGE_MASK;
pages = size >> PAGE_SHIFT;
if (pages_mapped + pages > MAX_EFI_IO_PAGES) if (pages_mapped + pages > MAX_EFI_IO_PAGES)
return NULL; return NULL;
...@@ -124,5 +124,5 @@ void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size) ...@@ -124,5 +124,5 @@ void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size)
} }
return (void __iomem *)__fix_to_virt(FIX_EFI_IO_MAP_FIRST_PAGE - \ return (void __iomem *)__fix_to_virt(FIX_EFI_IO_MAP_FIRST_PAGE - \
(pages_mapped - pages)); (pages_mapped - pages)) + offset;
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/pfn.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -394,4 +395,10 @@ struct efi_generic_dev_path { ...@@ -394,4 +395,10 @@ struct efi_generic_dev_path {
u16 length; u16 length;
} __attribute ((packed)); } __attribute ((packed));
static inline void memrange_efi_to_native(u64 *addr, u64 *npages)
{
*npages = PFN_UP(*addr + (*npages<<EFI_PAGE_SHIFT)) - PFN_DOWN(*addr);
*addr &= PAGE_MASK;
}
#endif /* _LINUX_EFI_H */ #endif /* _LINUX_EFI_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册