x86, mirror: x86 enabling - find mirrored memory ranges
authorTony Luck <tony.luck@intel.com>
Wed, 24 Jun 2015 23:58:15 +0000 (16:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 25 Jun 2015 00:49:45 +0000 (17:49 -0700)
UEFI GetMemoryMap() uses a new attribute bit to mark mirrored memory
address ranges.  See UEFI 2.5 spec pages 157-158:

  http://www.uefi.org/sites/default/files/resources/UEFI%202_5.pdf

On EFI enabled systems scan the memory map and tell memblock about any
mirrored ranges.

Signed-off-by: Tony Luck <tony.luck@intel.com>
Cc: Xishi Qiu <qiuxishi@huawei.com>
Cc: Hanjun Guo <guohanjun@huawei.com>
Cc: Xiexiuqi <xiexiuqi@huawei.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/x86/kernel/setup.c
arch/x86/platform/efi/efi.c
include/linux/efi.h

index 39ca113676fe54a73ffe3d01276e89cbc2252b62..d3b95b89e9b2974401b48b534bf71604d7db57cc 100644 (file)
@@ -1105,6 +1105,9 @@ void __init setup_arch(char **cmdline_p)
        memblock_set_current_limit(ISA_END_ADDRESS);
        memblock_x86_fill();
 
+       if (efi_enabled(EFI_BOOT))
+               efi_find_mirror();
+
        /*
         * The EFI specification says that boot service code won't be called
         * after ExitBootServices(). This is, in fact, a lie.
index 3b984c3aa1b0b5ba6e7b5e5321edb4fbc7013e5d..c1c382c58c60d58c3ea7a93e09b5f2e04112c6d8 100644 (file)
@@ -117,6 +117,27 @@ void efi_get_time(struct timespec *now)
        now->tv_nsec = 0;
 }
 
+void __init efi_find_mirror(void)
+{
+       void *p;
+       u64 mirror_size = 0, total_size = 0;
+
+       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;
+
+               total_size += size;
+               if (md->attribute & EFI_MEMORY_MORE_RELIABLE) {
+                       memblock_mark_mirror(start, size);
+                       mirror_size += size;
+               }
+       }
+       if (mirror_size)
+               pr_info("Memory: %lldM/%lldM mirrored memory\n",
+                       mirror_size>>20, total_size>>20);
+}
+
 /*
  * Tell the kernel about the EFI memory map.  This might include
  * more than the max 128 entries that can fit in the e820 legacy
index 2092965afca3994606ee8a255a97929a38df8095..5f19efe4eb3f0cb52d43e777be43dc65c9a41bc3 100644 (file)
@@ -96,6 +96,8 @@ typedef       struct {
 #define EFI_MEMORY_WP          ((u64)0x0000000000001000ULL)    /* write-protect */
 #define EFI_MEMORY_RP          ((u64)0x0000000000002000ULL)    /* read-protect */
 #define EFI_MEMORY_XP          ((u64)0x0000000000004000ULL)    /* execute-protect */
+#define EFI_MEMORY_MORE_RELIABLE \
+                               ((u64)0x0000000000010000ULL)    /* higher reliability */
 #define EFI_MEMORY_RUNTIME     ((u64)0x8000000000000000ULL)    /* range requires runtime mapping */
 #define EFI_MEMORY_DESCRIPTOR_VERSION  1
 
@@ -868,6 +870,7 @@ extern void efi_enter_virtual_mode (void);  /* switch EFI to virtual mode, if pos
 extern void efi_late_init(void);
 extern void efi_free_boot_services(void);
 extern efi_status_t efi_query_variable_store(u32 attributes, unsigned long size);
+extern void efi_find_mirror(void);
 #else
 static inline void efi_late_init(void) {}
 static inline void efi_free_boot_services(void) {}