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(-)
Index: linux-2.6/arch/x86/kernel/efi.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/efi.c
+++ linux-2.6/arch/x86/kernel/efi.c
@@ -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;
Index: linux-2.6/arch/x86/kernel/efi_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/efi_64.c
+++ linux-2.6/arch/x86/kernel/efi_64.c
@@ -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;
-}
Index: linux-2.6/include/asm-x86/efi.h
===================================================================
--- linux-2.6.orig/include/asm-x86/efi.h
+++ linux-2.6/include/asm-x86/efi.h
@@ -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);
Index: linux-2.6/include/asm-x86/fixmap_64.h
===================================================================
--- linux-2.6.orig/include/asm-x86/fixmap_64.h
+++ linux-2.6/include/asm-x86/fixmap_64.h
@@ -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
* Yinghai Lu <[email protected]> wrote:
> 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:
[...]
> --- linux-2.6.orig/arch/x86/kernel/efi.c
> +++ linux-2.6/arch/x86/kernel/efi.c
> @@ -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.
[...]
> --- linux-2.6.orig/arch/x86/kernel/efi_64.c
> +++ linux-2.6/arch/x86/kernel/efi_64.c
> @@ -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
On Sat, Oct 4, 2008 at 2:35 AM, huang ying <[email protected]> wrote:
> Hi, Yinghai,
>
> On Sat, Oct 4, 2008 at 2:23 PM, Yinghai Lu <[email protected]> wrote:
> [...]
>> --- linux-2.6.orig/arch/x86/kernel/efi.c
>> +++ linux-2.6/arch/x86/kernel/efi.c
>> @@ -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.
so need to make efi range all under direct-mapping like E820-RAM?
if so we need to update
e820_end_of_low_ram_pfn to return correct max_low_pfn, and then
max_low_pfn_mapped...
YH
On Sun, Oct 5, 2008 at 1:44 AM, Yinghai Lu <[email protected]> wrote:
> On Sat, Oct 4, 2008 at 2:35 AM, huang ying <[email protected]> wrote:
[...]
>> 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.
>
> 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
* huang ying <[email protected]> wrote:
> On Sun, Oct 5, 2008 at 1:44 AM, Yinghai Lu <[email protected]> wrote:
> > On Sat, Oct 4, 2008 at 2:35 AM, huang ying <[email protected]> wrote:
> [...]
> >> 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.
> >
> > 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
On Sun, Oct 5, 2008 at 1:56 AM, huang ying <[email protected]> wrote:
> On Sun, Oct 5, 2008 at 1:44 AM, Yinghai Lu <[email protected]> wrote:
>> On Sat, Oct 4, 2008 at 2:35 AM, huang ying <[email protected]> wrote:
> [...]
>>> 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.
>>
>> 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
--- linux-2.6.orig/arch/x86/kernel/efi.c
+++ linux-2.6/arch/x86/kernel/efi.c
@@ -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
On Sun, 2008-10-05 at 12:04 +0200, Ingo Molnar wrote:
> * huang ying <[email protected]> wrote:
[...]
> > 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
On Sun, 2008-10-05 at 11:04 -0700, Yinghai Lu wrote:
> On Sun, Oct 5, 2008 at 1:56 AM, huang ying <[email protected]> wrote:
> > On Sun, Oct 5, 2008 at 1:44 AM, Yinghai Lu <[email protected]> wrote:
> >> On Sat, Oct 4, 2008 at 2:35 AM, huang ying <[email protected]> wrote:
> > [...]
> >>> 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.
> >>
> >> 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
> --- linux-2.6.orig/arch/x86/kernel/efi.c
> +++ linux-2.6/arch/x86/kernel/efi.c
> @@ -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.
I think __va() and efi_ioremap() should be used.
> 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
>> 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.
Why would this require a separate function for 64-bit systems?
Wouldn't the 32-bit function have to take this into consideration as well?
Also, why is the fixed address space so limited? What about EFI runtime services
that are larger than 1MB?
Thanks,
Jonathan Barkelew