Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -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.
+21 −0
Original line number Original line Diff line number Diff line
@@ -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
+3 −0
Original line number Original line Diff line number Diff line
@@ -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
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) {}