lkml.org 
[lkml]   [2012]   [Mar]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectRe: [tip:x86/urgent] x86, efi: Delete efi_ioremap() and fix CONFIG_X86_32 oops
From
Date
On Mon, 2012-02-27 at 18:27 -0800, H. Peter Anvin wrote:
> On 02/23/2012 08:47 PM, H. Peter Anvin wrote:
> >>
> >> please check attach patch for tip/efi branch.
> >
> > That doesn't do anything like what I noted above.
> >
> > We should get rid of dependencies on legacy PC memory layouts, not add
> > more hacks. What is so hard about "when we create the initial mappings,
> > only create for RAM/ACPI/EFI regions" (if we even need to do so for
> > ACPI, I think ACPI might use ioremap() already)?
> >
>
> Hi Yinghai,
>
> Can you please answer my question?

Did you have something like this in mind? Note that it doesn't go all
the way to removing the add_do_memmap boot parameter because I'm not
sure how to do that for GPL exported symbols.

The only testing I've done with this is to ensure that it boots under
qemu (both for EFI and BIOS) on 32/64-bit.

This is on top of tip/x86/efi.

diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index bce688d..4f95f23 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -51,8 +51,9 @@ static inline phys_addr_t get_max_mapped(void)
return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT;
}

-extern unsigned long init_memory_mapping(unsigned long start,
- unsigned long end);
+extern unsigned long init_memory_mapping(void);
+extern unsigned long __init_memory_mapping(unsigned long start,
+ unsigned long end);

extern void initmem_init(void);
extern void free_initmem(void);
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index b1e7c7f..f52ced2 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -769,7 +769,7 @@ int __init gart_iommu_init(void)

if (end_pfn > max_low_pfn_mapped) {
start_pfn = (aper_base>>PAGE_SHIFT);
- init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
+ __init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
}

pr_info("PCI-DMA: using GART IOMMU.\n");
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index e22bb08..b65d287 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -690,8 +690,6 @@ early_param("reservelow", parse_reservelow);

void __init setup_arch(char **cmdline_p)
{
- unsigned long end_pfn;
-
#ifdef CONFIG_X86_32
memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
visws_early_detect();
@@ -927,31 +925,11 @@ void __init setup_arch(char **cmdline_p)

init_gbpages();

- /* max_pfn_mapped is updated here */
- end_pfn = max_low_pfn;
-
-#ifdef CONFIG_X86_64
- /*
- * There may be regions after the last E820_RAM region that we
- * want to include in the kernel direct mapping because their
- * contents are needed at runtime.
- */
- if (efi_enabled) {
- unsigned long efi_end;
-
- efi_end = e820_end_pfn(MAXMEM>>PAGE_SHIFT, E820_RESERVED_EFI);
- if (efi_end > end_pfn)
- end_pfn = efi_end;
- }
-#endif
-
- max_low_pfn_mapped = init_memory_mapping(0, end_pfn << PAGE_SHIFT);
- max_pfn_mapped = max_low_pfn_mapped;
+ /* max_low_pfn_mapped is updated here */
+ max_pfn_mapped = init_memory_mapping();

#ifdef CONFIG_X86_64
if (max_pfn > max_low_pfn) {
- max_pfn_mapped = init_memory_mapping(1UL<<32,
- max_pfn<<PAGE_SHIFT);
/* can we preseve max_low_pfn ?*/
max_low_pfn = max_pfn;
}
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 6cabf65..f1835e9 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -118,8 +118,8 @@ static int __meminit save_mr(struct map_range *mr, int nr_range,
* This runs before bootmem is initialized and gets pages directly from
* the physical memory. To access them they are temporarily mapped.
*/
-unsigned long __init_refok init_memory_mapping(unsigned long start,
- unsigned long end)
+unsigned long __init_refok __init_memory_mapping(unsigned long start,
+ unsigned long end)
{
unsigned long page_size_mask = 0;
unsigned long start_pfn, end_pfn;
@@ -301,6 +301,59 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
return ret >> PAGE_SHIFT;
}

+/*
+ * Traverse the E820 memory map and add RAM/ACPI/EFI regions to the
+ * initial memory mapping.
+ */
+unsigned long __init_refok init_memory_mapping(void)
+{
+ struct e820entry *entry;
+ unsigned long last_pfn_mapped = 0;
+ unsigned long start, end;
+ int i;
+
+ /* Map the legacy region until we fix all drivers */
+ __init_memory_mapping(0, 1 << 20);
+
+ for (i = 0; i < e820.nr_map; i++) {
+ entry = &e820.map[i];
+ start = entry->addr;
+ end = start + entry->size;
+
+ /* We've already mapped below 1MB */
+ if (end < (1 << 20))
+ continue;
+
+ if (start < (1 << 20))
+ start = 1 << 20;
+#ifdef CONFIG_X86_32
+ /*
+ * The map is sorted, so bail once we hit a region
+ * that's above max_low_pfn.
+ */
+ if (start >= max_low_pfn << PAGE_SHIFT)
+ break;
+
+ if (end > max_low_pfn << PAGE_SHIFT)
+ end = max_low_pfn << PAGE_SHIFT;
+#endif
+ switch (entry->type) {
+ case E820_RAM:
+ case E820_RESERVED_EFI:
+ case E820_ACPI:
+ case E820_NVS:
+ last_pfn_mapped = __init_memory_mapping(start, end);
+ break;
+ default:
+ continue;
+ }
+
+ if (end <= max_low_pfn << PAGE_SHIFT)
+ max_low_pfn_mapped = last_pfn_mapped;
+ }
+
+ return last_pfn_mapped;
+}

/*
* devmem_is_allowed() checks to see if /dev/mem access to a certain address
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 436a030..e86e370 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -659,7 +659,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
unsigned long nr_pages = size >> PAGE_SHIFT;
int ret;

- last_mapped_pfn = init_memory_mapping(start, start + size);
+ last_mapped_pfn = __init_memory_mapping(start, start + size);
if (last_mapped_pfn > max_pfn_mapped)
max_pfn_mapped = last_mapped_pfn;

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 264cc6e..ef0a725 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -573,8 +573,7 @@ void __init efi_init(void)
printk(KERN_WARNING
"Kernel-defined memdesc doesn't match the one from EFI!\n");

- if (add_efi_memmap)
- do_add_efi_memmap();
+ do_add_efi_memmap();

#ifdef CONFIG_X86_32
x86_platform.get_wallclock = efi_get_time;



\
 
 \ /
  Last update: 2012-03-07 11:33    [from the cache]
©2003-2011 Jasper Spaans