x86: EFI memory mapping changes according to changes to ioremap and c_p_a
PATCH 5/5 x86: EFI memory mapping changes according to changes to ioremap and c_p_a
The patch fixes EFI runtime memory mapping code according to the changes to ioremap() and change_page_attr().
--- arch/x86/kernel/efi.c | 53 ++++++++++++++++---------------------------- arch/x86/kernel/efi_64.c | 56 ++++++++++++++++++++++++++++++++++------------- arch/x86/mm/ioremap.c | 6 ++--- include/asm-x86/efi.h | 12 ++++++++-- include/asm-x86/io_32.h | 8 ++++++ include/asm-x86/io_64.h | 8 ++++++ 6 files changed, 90 insertions(+), 53 deletions(-)
arch/x86/kernel/efi.c +20 -33
@@ -56,6 +56,7 @@ struct efi_memory_map memmap;struct efi efi_phys__initdata ;static efi_system_table_t efi_systab__initdata ; +int efi_rt_mapping_ready__initdata ;static int __init setup_noefi (char *arg) {
@@ -379,32 +380,6 @@ void __init efi_init(void)#endif } -#if defined(CONFIG_X86_64 ) || defined(CONFIG_X86_PAE ) -static void __init runtime_code_page_mkexec (void ) -{ -efi_memory_desc_t *md; -unsigned long end; -void *p; - -if (!(__supported_pte_mask & _PAGE_NX)) -return ; - -/* Make EFI runtime service code area executable */ -for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { - md = p; - end = md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ); -if (md->type ==EFI_RUNTIME_SERVICES_CODE && - (end >>PAGE_SHIFT ) <= max_pfn_mapped) { -set_memory_x (md->virt_addr, md->num_pages); -set_memory_uc (md->virt_addr, md->num_pages); - } - } -__flush_tlb_all (); -} -#else -static inline void __init runtime_code_page_mkexec (void ) { } -#endif -/* * This function will switch the EFI runtime services to virtual mode. * Essentially, look through the EFI memmap and map every region that
@@ -419,6 +394,8 @@ void __init efi_enter_virtual_mode(void)efi_status_t status;unsigned long end;void *p; +enum ioremap_mode mode; +enum ioremap_xmode xmode; efi.systab =NULL ;for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -426,13 +403,23 @@ void __init efi_enter_virtual_mode(void)if (!(md->attribute &EFI_MEMORY_RUNTIME ))continue ; end = md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ); -if ((md->attribute &EFI_MEMORY_WB ) && - ((end >>PAGE_SHIFT ) <= max_pfn_mapped)) + mode = (md->attribute &EFI_MEMORY_WB ) ? +IOR_MODE_CACHED :IOR_MODE_UNCACHED ; + xmode = md->type ==EFI_RUNTIME_SERVICES_CODE ? +IOR_XMODE_EXEC :IOR_XMODE_UNEXEC ; +if ((end >>PAGE_SHIFT ) <= max_pfn_mapped) { md->virt_addr = (unsigned long )__va (md->phys_addr); -else - md->virt_addr = (unsigned long ) -efi_ioremap (md->phys_addr, - md->num_pages <<EFI_PAGE_SHIFT ); +/* Assume pages are mapped as WB */ +if (mode ==IOR_MODE_UNCACHED ) +set_memory_uc (md->virt_addr, md->num_pages); +/* Assume pages are mapped as unexecutable */ +if ((__supported_pte_mask & _PAGE_NX) && + xmode ==IOR_XMODE_EXEC ) +set_memory_x (md->virt_addr, md->num_pages); + }else + md->virt_addr = (unsigned long )__efi_ioremap ( + md->phys_addr, md->num_pages <<EFI_PAGE_SHIFT , + mode, xmode);if (!md->virt_addr) printk(KERN_ERR PFX "ioremap of 0x%llX failed!\n", (unsigned long long )md->phys_addr);
@@ -442,6 +429,7 @@ void __init efi_enter_virtual_mode(void) (md->virt_addr - md->phys_addr + (unsigned long )efi_phys.systab); } + efi_rt_mapping_ready =1 ;BUG_ON (!efi.systab);
@@ -473,7 +461,6 @@ void __init efi_enter_virtual_mode(void) efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; efi.reset_system = virt_efi_reset_system; efi.set_virtual_address_map = virt_efi_set_virtual_address_map; -runtime_code_page_mkexec ();early_iounmap (memmap.map, memmap.nr_map * memmap.desc_size); memmap.map =NULL ; }
arch/x86/kernel/efi_64.c +41 -15
93 lines not on this page · raw message
include/asm-x86/efi.h +10 -2
@@ -33,7 +33,8 @@ extern unsigned long asmlinkage efi_call#define efi_call_virt6 (f, a1, a2, a3, a4, a5, a6) \ efi_call_virt(f, a1, a2, a3, a4, a5, a6) -#define efi_ioremap (addr, size) ioremap(addr, size) +#define __efi_ioremap (addr, size, mode, xmode) \ + __ioremap(addr, size, mode, xmode)#else /* !CONFIG_X86_32 */
@@ -86,7 +87,12 @@ extern u64 efi_call6(void *fp, u64 arg1,efi_call6 ((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) -extern void *efi_ioremap (unsigned long offset,unsigned long size); +enum ioremap_mode ; +enum ioremap_xmode ; +extern void __iomem *__efi_ioremap (unsigned long phys_addr, +unsigned long size, +enum ioremap_mode mode, +enum ioremap_xmode xmode);#endif /* CONFIG_X86_32 */
@@ -94,4 +100,6 @@ extern void efi_reserve_bootmem(void);extern void efi_call_phys_prelog (void );extern void efi_call_phys_epilog (void ); +extern int efi_rt_mapping_ready; +#endif
arch/x86/mm/ioremap.c +3 -3
@@ -65,9 +65,9 @@ int page_is_ram(unsigned long pagenr)* Fix up the linear direct mapping of the kernel to avoid cache attribute * conflicts. */ -static int ioremap_change_attr (unsigned long paddr,unsigned long size, -enum ioremap_mode mode, -enum ioremap_xmode xmode) +int ioremap_change_attr (unsigned long paddr,unsigned long size, +enum ioremap_mode mode, +enum ioremap_xmode xmode) {unsigned long vaddr = (unsigned long )__va (paddr);unsigned long nrpages = size >>PAGE_SHIFT ;
include/asm-x86/io_32.h +8 -0
@@ -110,6 +110,14 @@ enum ioremap_xmode { IOR_XMODE_UNEXEC, }; +/* +* Fix up the linear direct mapping of the kernel to avoid cache attribute +* conflicts. +*/ +extern int ioremap_change_attr (unsigned long paddr,unsigned long size, +enum ioremap_mode mode, +enum ioremap_xmode xmode); +extern void __iomem *__ioremap (unsigned long phys_addr,unsigned long size,enum ioremap_mode mode,enum ioremap_xmode xmode);
include/asm-x86/io_64.h +8 -0
@@ -163,6 +163,14 @@ enum ioremap_xmode { IOR_XMODE_UNEXEC, }; +/* +* Fix up the linear direct mapping of the kernel to avoid cache attribute +* conflicts. +*/ +extern int ioremap_change_attr (unsigned long paddr,unsigned long size, +enum ioremap_mode mode, +enum ioremap_xmode xmode); +extern void __iomem *__ioremap (unsigned long phys_addr,unsigned long size,enum ioremap_mode mode,enum ioremap_xmode xmode);
arch/x86/kernel/efi.c void __init efi_enter_virtual_mode(void) · line 418
Quoted 7 lines · Huang, Ying
arch/x86/kernel/efi.c +7
-0+/* Assume pages are mapped as WB */ +if (mode ==IOR_MODE_UNCACHED ) +set_memory_uc (md->virt_addr, md->num_pages); +/* Assume pages are mapped as unexecutable */ +if ((__supported_pte_mask & _PAGE_NX) && + xmode ==IOR_XMODE_EXEC ) +set_memory_x (md->virt_addr, md->num_pages);
hm, why is the check for __supported_pte_mask needed? That is already listened to in set_memory_x(). [if not then it's an ioremap bug that we want to fix.]
arch/x86/mm/ioremap.c int page_is_ram(unsigned long pagenr) · line 70
Quoted 6 lines
arch/x86/mm/ioremap.c +3
-3-static int ioremap_change_attr (unsigned long paddr,unsigned long size, -enum ioremap_mode mode, -enum ioremap_xmode xmode) +int ioremap_change_attr (unsigned long paddr,unsigned long size, +enum ioremap_mode mode, +enum ioremap_xmode xmode)
hm, there should be no need to use this raw API.
Ingo
Quoted 11 lines · Ingo Molnar
arch/x86/kernel/efi.c void __init efi_enter_virtual_mode(void) · line 418
Quoted 7 lines · Huang, Ying
arch/x86/kernel/efi.c +7
-0+/* Assume pages are mapped as WB */ +if (mode ==IOR_MODE_UNCACHED ) +set_memory_uc (md->virt_addr, md->num_pages); +/* Assume pages are mapped as unexecutable */ +if ((__supported_pte_mask & _PAGE_NX) && + xmode ==IOR_XMODE_EXEC ) +set_memory_x (md->virt_addr, md->num_pages);
Quoted 3 lines
hm, why is the check for
__supported_pte_maskneeded? That is already listened to inset_memory_x(). [if not then it's an ioremap bug that we want to fix.]
OK, I will check it.
Quoted 8 lines
arch/x86/mm/ioremap.c int page_is_ram(unsigned long pagenr) · line 70
Quoted 6 lines
arch/x86/mm/ioremap.c +3
-3-static int ioremap_change_attr (unsigned long paddr,unsigned long size, -enum ioremap_mode mode, -enum ioremap_xmode xmode) +int ioremap_change_attr (unsigned long paddr,unsigned long size, +enum ioremap_mode mode, +enum ioremap_xmode xmode)hm, there should be no need to use this raw API.
Oh, you are right. __efi_ioremap() is only used when there is no identity map. So ioremap_change_attr() need not to be called in __efi_ioremap().
Best Regards,
Huang Ying
Quoted 2 lines · Ying
The patch fixes EFI runtime memory mapping code according to the changes to
ioremap()andchange_page_attr().
this is way overkill. really.
Just call set_memory_x() after your ioremap call, and call set_memory_nx() before the iounmap. THere is no need to hack up ioremap for any of this stuff. At all.
Signature · 3 lines
If you want to reach me at my work email, use [email protected] For development, discussion and tips for power savings, visit http://www.lesswatts.org