x86: rename two e820 related functions
[linux-3.10.git] / arch / x86 / kernel / efi.c
index 5d492f9..473c89f 100644 (file)
@@ -40,6 +40,8 @@
 #include <asm/setup.h>
 #include <asm/efi.h>
 #include <asm/time.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
 
 #define EFI_DEBUG      1
 #define PFX            "EFI: "
@@ -52,7 +54,7 @@ EXPORT_SYMBOL(efi);
 
 struct efi_memory_map memmap;
 
-struct efi efi_phys __initdata;
+static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
 static int __init setup_noefi(char *arg)
@@ -211,6 +213,48 @@ unsigned long efi_get_time(void)
                      eft.minute, eft.second);
 }
 
+/*
+ * Tell the kernel about the EFI memory map.  This might include
+ * more than the max 128 entries that can fit in the e820 legacy
+ * (zeropage) memory map.
+ */
+
+static void __init add_efi_memmap(void)
+{
+       void *p;
+
+       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+               efi_memory_desc_t *md = p;
+               unsigned long long start = md->phys_addr;
+               unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
+               int e820_type;
+
+               if (md->attribute & EFI_MEMORY_WB)
+                       e820_type = E820_RAM;
+               else
+                       e820_type = E820_RESERVED;
+               e820_add_region(start, size, e820_type);
+       }
+       sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
+}
+
+void __init efi_reserve_early(void)
+{
+       unsigned long pmap;
+
+       pmap = boot_params.efi_info.efi_memmap;
+#ifdef CONFIG_X86_64
+       pmap += (__u64)boot_params.efi_info.efi_memmap_hi << 32;
+#endif
+       memmap.phys_map = (void *)pmap;
+       memmap.nr_map = boot_params.efi_info.efi_memmap_size /
+               boot_params.efi_info.efi_memdesc_size;
+       memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
+       memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
+       reserve_early(pmap, pmap + memmap.nr_map * memmap.desc_size,
+                     "EFI memmap");
+}
+
 #if EFI_DEBUG
 static void __init print_efi_memmap(void)
 {
@@ -240,21 +284,11 @@ void __init efi_init(void)
        int i = 0;
        void *tmp;
 
-#ifdef CONFIG_X86_32
        efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
-       memmap.phys_map = (void *)boot_params.efi_info.efi_memmap;
-#else
-       efi_phys.systab = (efi_system_table_t *)
-               (boot_params.efi_info.efi_systab |
-                ((__u64)boot_params.efi_info.efi_systab_hi<<32));
-       memmap.phys_map = (void *)
-               (boot_params.efi_info.efi_memmap |
-                ((__u64)boot_params.efi_info.efi_memmap_hi<<32));
+#ifdef CONFIG_X86_64
+       efi_phys.systab = (void *)efi_phys.systab +
+               ((__u64)boot_params.efi_info.efi_systab_hi<<32);
 #endif
-       memmap.nr_map = boot_params.efi_info.efi_memmap_size /
-               boot_params.efi_info.efi_memdesc_size;
-       memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
-       memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
 
        efi.systab = early_ioremap((unsigned long)efi_phys.systab,
                                   sizeof(efi_system_table_t));
@@ -368,17 +402,36 @@ void __init efi_init(void)
        if (memmap.desc_size != sizeof(efi_memory_desc_t))
                printk(KERN_WARNING "Kernel-defined memdesc"
                       "doesn't match the one from EFI!\n");
+       add_efi_memmap();
 
-#ifdef CONFIG_X86_64
        /* Setup for EFI runtime service */
        reboot_type = BOOT_EFI;
 
-#endif
 #if EFI_DEBUG
        print_efi_memmap();
 #endif
 }
 
+static void __init runtime_code_page_mkexec(void)
+{
+       efi_memory_desc_t *md;
+       void *p;
+       u64 addr, npages;
+
+       /* Make EFI runtime service code area executable */
+       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+               md = p;
+
+               if (md->type != EFI_RUNTIME_SERVICES_CODE)
+                       continue;
+
+               addr = md->virt_addr;
+               npages = md->num_pages;
+               memrange_efi_to_native(&addr, &npages);
+               set_memory_x(addr, npages);
+       }
+}
+
 /*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
@@ -391,31 +444,44 @@ void __init efi_enter_virtual_mode(void)
 {
        efi_memory_desc_t *md;
        efi_status_t status;
-       unsigned long end;
-       void *p;
+       unsigned long size;
+       u64 end, systab, addr, npages;
+       void *p, *va;
 
        efi.systab = NULL;
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                md = p;
                if (!(md->attribute & EFI_MEMORY_RUNTIME))
                        continue;
-               if ((md->attribute & EFI_MEMORY_WB) &&
-                   (((md->phys_addr + (md->num_pages<<EFI_PAGE_SHIFT)) >>
-                     PAGE_SHIFT) < end_pfn_map))
-                       md->virt_addr = (unsigned long)__va(md->phys_addr);
+
+               size = md->num_pages << EFI_PAGE_SHIFT;
+               end = md->phys_addr + size;
+
+               if (PFN_UP(end) <= max_pfn_mapped)
+                       va = __va(md->phys_addr);
                else
-                       md->virt_addr = (unsigned long)
-                               efi_ioremap(md->phys_addr,
-                                           md->num_pages << EFI_PAGE_SHIFT);
-               if (!md->virt_addr)
+                       va = efi_ioremap(md->phys_addr, size);
+
+               md->virt_addr = (u64) (unsigned long) va;
+
+               if (!va) {
                        printk(KERN_ERR PFX "ioremap of 0x%llX failed!\n",
                               (unsigned long long)md->phys_addr);
-               end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
-               if ((md->phys_addr <= (unsigned long)efi_phys.systab) &&
-                   ((unsigned long)efi_phys.systab < end))
-                       efi.systab = (efi_system_table_t *)(unsigned long)
-                               (md->virt_addr - md->phys_addr +
-                                (unsigned long)efi_phys.systab);
+                       continue;
+               }
+
+               if (!(md->attribute & EFI_MEMORY_WB)) {
+                       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;
+               if (md->phys_addr <= systab && systab < end) {
+                       systab += md->virt_addr - md->phys_addr;
+                       efi.systab = (efi_system_table_t *) (unsigned long) systab;
+               }
        }
 
        BUG_ON(!efi.systab);
@@ -448,9 +514,10 @@ 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;
-#ifdef CONFIG_X86_64
-       runtime_code_page_mkexec();
-#endif
+       if (__supported_pte_mask & _PAGE_NX)
+               runtime_code_page_mkexec();
+       early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+       memmap.map = NULL;
 }
 
 /*