x86: make 64bit efi to use ioremap_cache for efi_ioremap
RFC PATCH 1/1 x86: make 64bit efi to use ioremap_cache for efi_ioremap
--- arch/x86/kernel/efi.c | 5 +---- arch/x86/kernel/efi_64.c | 27 ++------------------------- include/asm-x86/efi.h | 8 ++------ include/asm-x86/fixmap_64.h | 3 --- 4 files changed, 5 insertions(+), 38 deletions(-)
arch/x86/kernel/efi.c +1 -4
@@ -475,10 +475,7 @@ void __init efi_enter_virtual_mode(void) size = md->num_pages <<EFI_PAGE_SHIFT ; end = md->phys_addr + size; -if (PFN_UP (end) <= max_low_pfn_mapped) - va =__va (md->phys_addr); -else - va =efi_ioremap (md->phys_addr, size); + va =efi_ioremap (md->phys_addr, size); md->virt_addr = (u64 ) (unsigned long ) va;
arch/x86/kernel/efi_64.c +2 -25
@@ -46,8 +46,8 @@ static void __init early_mapping_set_exe {unsigned long num_pages; - start &=PMD_MASK ; - end = (end +PMD_SIZE -1 ) &PMD_MASK ; + start &=PAGE_MASK ; + end = (end +PAGE_SIZE -1 ) &PAGE_MASK ; num_pages = (end - start) >>PAGE_SHIFT ;if (executable)set_memory_x ((unsigned long )__va (start), num_pages);
@@ -97,26 +97,3 @@ void __init efi_call_phys_epilog(void)early_runtime_code_mapping_set_exec (0 ); } -void __iomem *__init efi_ioremap (unsigned long phys_addr,unsigned long size) -{ -static unsigned pages_mapped__initdata ; -unsigned i, pages; -unsigned long offset; - - pages =PFN_UP (phys_addr + size) -PFN_DOWN (phys_addr); - offset = phys_addr & ~PAGE_MASK ; - phys_addr &=PAGE_MASK ; - -if (pages_mapped + pages >MAX_EFI_IO_PAGES ) -return NULL ; - -for (i =0 ; i < pages; i++) { -__set_fixmap (FIX_EFI_IO_MAP_FIRST_PAGE - pages_mapped, - phys_addr,PAGE_KERNEL ); - phys_addr +=PAGE_SIZE ; - pages_mapped++; - } - - return (void __iomem *)__fix_to_virt(FIX_EFI_IO_MAP_FIRST_PAGE - \ - (pages_mapped - pages)) + offset; -}
include/asm-x86/efi.h +2 -6
@@ -33,12 +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_cache(addr, size) -#else /* !CONFIG_X86_32 */ -#define MAX_EFI_IO_PAGES 100 -extern u64 efi_call0 (void *fp);extern u64 efi_call1 (void *fp,u64 arg1);extern u64 efi_call2 (void *fp,u64 arg1,u64 arg2);
@@ -86,10 +82,10 @@ 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 __iomem *efi_ioremap (unsigned long addr,unsigned long size); -#endif /* CONFIG_X86_32 */ +#define efi_ioremap (addr, size) ioremap_cache(addr, size) +extern void efi_reserve_early (void );extern void efi_call_phys_prelog (void );extern void efi_call_phys_epilog (void );
include/asm-x86/fixmap_64.h +0 -3
@@ -43,9 +43,6 @@ enum fixed_addresses {FIX_APIC_BASE ,/* local (CPU) APIC) -- required for SMP or not */ FIX_IO_APIC_BASE_0 ,FIX_IO_APIC_BASE_END =FIX_IO_APIC_BASE_0 +MAX_IO_APICS -1 , -FIX_EFI_IO_MAP_LAST_PAGE , -FIX_EFI_IO_MAP_FIRST_PAGE =FIX_EFI_IO_MAP_LAST_PAGE - +MAX_EFI_IO_PAGES -1 , #ifdef CONFIG_PARAVIRT FIX_PARAVIRT_BOOTMAP, #endif
Quoted 8 lines · Yinghai Lu
Signed-off-by Yinghai Lu <[email protected]>--- arch/x86/kernel/efi.c | 5 +---- arch/x86/kernel/efi_64.c | 27 ++------------------------- include/asm-x86/efi.h | 8 ++------ include/asm-x86/fixmap_64.h | 3 --- 4 files changed, 5 insertions(+), 38 deletions(-)
ok, that looks like a very nice cleanup and should make the EFI mapping code more generic and more robust as well.
Huang, any chance you could test this against latest tip/master on a real EFI system?
Ingo
Hi, Yinghai,
On Sat, Oct 4, 2008 at 2:23 PM, Yinghai Lu <[email protected]> wrote:
[...]
arch/x86/kernel/efi.c void __init efi_enter_virtual_mode(void) · line 478
Quoted 11 lines
arch/x86/kernel/efi.c +1
-4@@ -475,10 +475,7 @@ void __init efi_enter_virtual_mode(void) size = md->num_pages <<EFI_PAGE_SHIFT ; end = md->phys_addr + size; -if (PFN_UP (end) <= max_low_pfn_mapped) - va =__va (md->phys_addr); -else - va =efi_ioremap (md->phys_addr, size); + va =efi_ioremap (md->phys_addr, size);
Using __va and efi_ioremap() here is to make EFI support compatible with kexec. Because EFI provide only efi_enter_virtual_mode(), no efi_leave_virtual_mode(), we should make EFI runtime memory area mapped to same virtual memory area in original kernel and kexeced kernel, so that the EFI runtime services can be used in kexeced kernel.
[...]
arch/x86/kernel/efi_64.c static void __init early_mapping_set_exe · line 53
Quoted 13 lines
arch/x86/kernel/efi_64.c +2
-2@@ -46,8 +46,8 @@ static void __init early_mapping_set_exe {unsigned long num_pages; - start &=PMD_MASK ; - end = (end +PMD_SIZE -1 ) &PMD_MASK ; + start &=PAGE_MASK ; + end = (end +PAGE_SIZE -1 ) &PAGE_MASK ; num_pages = (end - start) >>PAGE_SHIFT ;if (executable)set_memory_x ((unsigned long )__va (start), num_pages);
early_mapping_set_exe() may be called before page allocator is available. Using PAGE_MASK may make set_memory_x() allocate new page, while using PMD_MASK will not.
Best Regards,
Huang Ying
Quoted 10 lines · huang ying
Hi, Yinghai,
On Sat, Oct 4, 2008 at 2:23 PM, Yinghai Lu <[email protected]> wrote:
[...]Quoted 6 lines
arch/x86/kernel/efi.c +0
-0@@ -475,10 +475,7 @@ void __init efi_enter_virtual_mode(void) size = md->num_pages <<EFI_PAGE_SHIFT ; end = md->phys_addr + size;
Quoted 12 lines
arch/x86/kernel/efi.c void __init efi_enter_virtual_mode(void) · line 478
Quoted 5 lines
arch/x86/kernel/efi.c +1
-4-if (PFN_UP (end) <= max_low_pfn_mapped) - va =__va (md->phys_addr); -else - va =efi_ioremap (md->phys_addr, size); + va =efi_ioremap (md->phys_addr, size);Using
__vaandefi_ioremap()here is to make EFI support compatible with kexec. Because EFI provide onlyefi_enter_virtual_mode(), noefi_leave_virtual_mode(), we should make EFI runtime memory area mapped to same virtual memory area in original kernel and kexeced kernel, so that the EFI runtime services can be used in kexeced kernel.
so need to make efi range all under direct-mapping like E820-RAM?
if so we need to updatee820_end_of_low_ram_pfn to return correct max_low_pfn, and then max_low_pfn_mapped...
YH
Quoted 1 line · Yinghai Lu
On Sat, Oct 4, 2008 at 2:35 AM, huang ying <[email protected]> wrote:
[...]
Quoted 8 lines
Quoted 6 lines
Using
__vaandefi_ioremap()here is to make EFI support compatible with kexec. Because EFI provide onlyefi_enter_virtual_mode(), noefi_leave_virtual_mode(), we should make EFI runtime memory area mapped to same virtual memory area in original kernel and kexeced kernel, so that the EFI runtime services can be used in kexeced kernel.so need to make efi range all under direct-mapping like E820-RAM?
Some EFI runtime range is just some RAM area used by EFI runtime services, they can be direct-mapped. Some EFI runtime range may be IO MEM range used by EFI runtime services, it is possible that these IO MEM range can not be direct-mapped. So I implement efi_ioremap() to deal with them.
Best Regards,
Huang Ying
Quoted 10 lines · huang ying
Quoted 1 line · Yinghai Lu
On Sat, Oct 4, 2008 at 2:35 AM, huang ying <[email protected]> wrote:
[...]
Quoted 7 lines
Quoted 6 lines
Using
__vaandefi_ioremap()here is to make EFI support compatible with kexec. Because EFI provide onlyefi_enter_virtual_mode(), noefi_leave_virtual_mode(), we should make EFI runtime memory area mapped to same virtual memory area in original kernel and kexeced kernel, so that the EFI runtime services can be used in kexeced kernel.
Quoted 7 lines
Quoted 1 line
so need to make efi range all under direct-mapping like E820-RAM?
Some EFI runtime range is just some RAM area used by EFI runtime services, they can be direct-mapped. Some EFI runtime range may be IO MEM range used by EFI runtime services, it is possible that these IO MEM range can not be direct-mapped. So I implement
efi_ioremap()to deal with them.
hm, but in the "some RAM area" case, that area should not be listed in the e820 map (or any EFI memory map), and hence it should never be mapped directly. I.e. you should be able to just standardize on ioremap() and have no parallel facility for this.
Ingo
Quoted 1 line · Ingo Molnar
* huang ying <[email protected]> wrote:
[...]
Quoted 10 lines
Quoted 5 lines
Some EFI runtime range is just some RAM area used by EFI runtime services, they can be direct-mapped. Some EFI runtime range may be IO MEM range used by EFI runtime services, it is possible that these IO MEM range can not be direct-mapped. So I implement
efi_ioremap()to deal with them.hm, but in the "some RAM area" case, that area should not be listed in the e820 map (or any EFI memory map), and hence it should never be mapped directly. I.e. you should be able to just standardize on
ioremap()and have no parallel facility for this.
EFI runtime memory area will be E820_RESERVED in e820 map and EFI_RUNTIME_SERVICES_CODE/DATA in EFI memory map. In general they will be mapped directly.
ioremap() should not used here, because for kexec to work, EFI runtime memory area should be mapped to same virtual address across reboot.
Best Regards,
Huang Ying
Quoted 10 lines · huang ying
Quoted 1 line · Yinghai Lu
On Sat, Oct 4, 2008 at 2:35 AM, huang ying <[email protected]> wrote:
[...]
Quoted 7 lines
Quoted 6 lines
Using
__vaandefi_ioremap()here is to make EFI support compatible with kexec. Because EFI provide onlyefi_enter_virtual_mode(), noefi_leave_virtual_mode(), we should make EFI runtime memory area mapped to same virtual memory area in original kernel and kexeced kernel, so that the EFI runtime services can be used in kexeced kernel.
Quoted 8 lines
Quoted 1 line
so need to make efi range all under direct-mapping like E820-RAM?
Some EFI runtime range is just some RAM area used by EFI runtime services, they can be direct-mapped. Some EFI runtime range may be IO MEM range used by EFI runtime services, it is possible that these IO MEM range can not be direct-mapped. So I implement
efi_ioremap()to deal with them.
i'm confused.
so
arch/x86/kernel/efi.c +1 -4
@@ -475,10 +475,7 @@ void __init efi_enter_virtual_mode(void) size = md->num_pages <<EFI_PAGE_SHIFT ; end = md->phys_addr + size; -if (PFN_UP (end) <= max_low_pfn_mapped) - va =__va (md->phys_addr); -else - va =efi_ioremap (md->phys_addr, size); + va =efi_ioremap (md->phys_addr, size); md->virt_addr = (u64 ) (unsigned long ) va;
should be ok.
then how about use ioremap directly to replace fixed mapping in 64bit with efi_ioremap?
YH
Quoted 36 lines · Yinghai Lu
Quoted 10 lines · huang ying
Quoted 1 line · Yinghai Lu
On Sat, Oct 4, 2008 at 2:35 AM, huang ying <[email protected]> wrote:
[...]
Quoted 7 lines
Quoted 6 lines
Using
__vaandefi_ioremap()here is to make EFI support compatible with kexec. Because EFI provide onlyefi_enter_virtual_mode(), noefi_leave_virtual_mode(), we should make EFI runtime memory area mapped to same virtual memory area in original kernel and kexeced kernel, so that the EFI runtime services can be used in kexeced kernel.Quoted 8 lines
Quoted 1 line
so need to make efi range all under direct-mapping like E820-RAM?
Some EFI runtime range is just some RAM area used by EFI runtime services, they can be direct-mapped. Some EFI runtime range may be IO MEM range used by EFI runtime services, it is possible that these IO MEM range can not be direct-mapped. So I implement
efi_ioremap()to deal with them.i'm confused.
so
arch/x86/kernel/efi.c +1
-4@@ -475,10 +475,7 @@ void __init efi_enter_virtual_mode(void) size = md->num_pages <<EFI_PAGE_SHIFT ; end = md->phys_addr + size; -if (PFN_UP (end) <= max_low_pfn_mapped) - va =__va (md->phys_addr); -else - va =efi_ioremap (md->phys_addr, size); + va =efi_ioremap (md->phys_addr, size); md->virt_addr = (u64 ) (unsigned long ) va;
Quoted 1 line
should be ok.
I think __va() and efi_ioremap() should be used.
Quoted 2 lines
then how about use ioremap directly to replace fixed mapping in 64bit with
efi_ioremap?
Because for kexec to work, EFI runtime memory area should be mapped to same virtual address across reboot.
Best Regards,
Huang Ying