Commit b05b9f5f authored by Tony Luck's avatar Tony Luck Committed by Linus Torvalds

x86, mirror: x86 enabling - find mirrored memory ranges

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: default avatarTony 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a3f5bafc
...@@ -1105,6 +1105,9 @@ void __init setup_arch(char **cmdline_p) ...@@ -1105,6 +1105,9 @@ void __init setup_arch(char **cmdline_p)
memblock_set_current_limit(ISA_END_ADDRESS); memblock_set_current_limit(ISA_END_ADDRESS);
memblock_x86_fill(); memblock_x86_fill();
if (efi_enabled(EFI_BOOT))
efi_find_mirror();
/* /*
* The EFI specification says that boot service code won't be called * The EFI specification says that boot service code won't be called
* after ExitBootServices(). This is, in fact, a lie. * after ExitBootServices(). This is, in fact, a lie.
......
...@@ -117,6 +117,27 @@ void efi_get_time(struct timespec *now) ...@@ -117,6 +117,27 @@ void efi_get_time(struct timespec *now)
now->tv_nsec = 0; 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 * Tell the kernel about the EFI memory map. This might include
* more than the max 128 entries that can fit in the e820 legacy * more than the max 128 entries that can fit in the e820 legacy
......
...@@ -96,6 +96,8 @@ typedef struct { ...@@ -96,6 +96,8 @@ typedef struct {
#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ #define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */
#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ #define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */
#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-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_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
#define EFI_MEMORY_DESCRIPTOR_VERSION 1 #define EFI_MEMORY_DESCRIPTOR_VERSION 1
...@@ -868,6 +870,7 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos ...@@ -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_late_init(void);
extern void efi_free_boot_services(void); extern void efi_free_boot_services(void);
extern efi_status_t efi_query_variable_store(u32 attributes, unsigned long size); extern efi_status_t efi_query_variable_store(u32 attributes, unsigned long size);
extern void efi_find_mirror(void);
#else #else
static inline void efi_late_init(void) {} static inline void efi_late_init(void) {}
static inline void efi_free_boot_services(void) {} static inline void efi_free_boot_services(void) {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment