Commit 199c8471 authored by Dan Williams's avatar Dan Williams Committed by Rafael J. Wysocki
Browse files

x86/efi: Add efi_fake_mem support for EFI_MEMORY_SP



Given that EFI_MEMORY_SP is platform BIOS policy decision for marking
memory ranges as "reserved for a specific purpose" there will inevitably
be scenarios where the BIOS omits the attribute in situations where it
is desired. Unlike other attributes if the OS wants to reserve this
memory from the kernel the reservation needs to happen early in init. So
early, in fact, that it needs to happen before e820__memblock_setup()
which is a pre-requisite for efi_fake_memmap() that wants to allocate
memory for the updated table.

Introduce an x86 specific efi_fake_memmap_early() that can search for
attempts to set EFI_MEMORY_SP via efi_fake_mem and update the e820 table
accordingly.

The KASLR code that scans the command line looking for user-directed
memory reservations also needs to be updated to consider
"efi_fake_mem=nn@ss:0x40000" requests.

Acked-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 16993c0f
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -1196,15 +1196,21 @@
			updating original EFI memory map.
			Region of memory which aa attribute is added to is
			from ss to ss+nn.

			If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000
			is specified, EFI_MEMORY_MORE_RELIABLE(0x10000)
			attribute is added to range 0x100000000-0x180000000 and
			0x10a0000000-0x1120000000.

			If efi_fake_mem=8G@9G:0x40000 is specified, the
			EFI_MEMORY_SP(0x40000) attribute is added to
			range 0x240000000-0x43fffffff.

			Using this parameter you can do debugging of EFI memmap
			related feature. For example, you can do debugging of
			related features. For example, you can do debugging of
			Address Range Mirroring feature even if your box
			doesn't support it.
			doesn't support it, or mark specific memory as
			"soft reserved".

	efivar_ssdt=	[EFI; X86] Name of an EFI variable that contains an SSDT
			that is to be dynamically loaded by Linux. If there are
+35 −7
Original line number Diff line number Diff line
@@ -132,8 +132,14 @@ char *skip_spaces(const char *str)
#include "../../../../lib/ctype.c"
#include "../../../../lib/cmdline.c"

enum parse_mode {
	PARSE_MEMMAP,
	PARSE_EFI,
};

static int
parse_memmap(char *p, unsigned long long *start, unsigned long long *size)
parse_memmap(char *p, unsigned long long *start, unsigned long long *size,
		enum parse_mode mode)
{
	char *oldp;

@@ -156,8 +162,29 @@ parse_memmap(char *p, unsigned long long *start, unsigned long long *size)
		*start = memparse(p + 1, &p);
		return 0;
	case '@':
		/* memmap=nn@ss specifies usable region, should be skipped */
		if (mode == PARSE_MEMMAP) {
			/*
			 * memmap=nn@ss specifies usable region, should
			 * be skipped
			 */
			*size = 0;
		} else {
			unsigned long long flags;

			/*
			 * efi_fake_mem=nn@ss:attr the attr specifies
			 * flags that might imply a soft-reservation.
			 */
			*start = memparse(p + 1, &p);
			if (p && *p == ':') {
				p++;
				if (kstrtoull(p, 0, &flags) < 0)
					*size = 0;
				else if (flags & EFI_MEMORY_SP)
					return 0;
			}
			*size = 0;
		}
		/* Fall through */
	default:
		/*
@@ -172,7 +199,7 @@ parse_memmap(char *p, unsigned long long *start, unsigned long long *size)
	return -EINVAL;
}

static void mem_avoid_memmap(char *str)
static void mem_avoid_memmap(enum parse_mode mode, char *str)
{
	static int i;

@@ -187,7 +214,7 @@ static void mem_avoid_memmap(char *str)
		if (k)
			*k++ = 0;

		rc = parse_memmap(str, &start, &size);
		rc = parse_memmap(str, &start, &size, mode);
		if (rc < 0)
			break;
		str = k;
@@ -238,7 +265,6 @@ static void parse_gb_huge_pages(char *param, char *val)
	}
}


static void handle_mem_options(void)
{
	char *args = (char *)get_cmd_line_ptr();
@@ -271,7 +297,7 @@ static void handle_mem_options(void)
		}

		if (!strcmp(param, "memmap")) {
			mem_avoid_memmap(val);
			mem_avoid_memmap(PARSE_MEMMAP, val);
		} else if (strstr(param, "hugepages")) {
			parse_gb_huge_pages(param, val);
		} else if (!strcmp(param, "mem")) {
@@ -284,6 +310,8 @@ static void handle_mem_options(void)
				goto out;

			mem_limit = mem_size;
		} else if (!strcmp(param, "efi_fake_mem")) {
			mem_avoid_memmap(PARSE_EFI, val);
		}
	}

+8 −0
Original line number Diff line number Diff line
@@ -263,4 +263,12 @@ static inline void efi_reserve_boot_services(void)
}
#endif /* CONFIG_EFI */

#ifdef CONFIG_EFI_FAKE_MEMMAP
extern void __init efi_fake_memmap_early(void);
#else
static inline void efi_fake_memmap_early(void)
{
}
#endif

#endif /* _ASM_X86_EFI_H */
+2 −0
Original line number Diff line number Diff line
@@ -262,6 +262,8 @@ int __init efi_memblock_x86_reserve_range(void)
	if (add_efi_memmap || do_efi_soft_reserve())
		do_add_efi_memmap();

	efi_fake_memmap_early();

	WARN(efi.memmap.desc_version != 1,
	     "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
	     efi.memmap.desc_version);
+4 −1
Original line number Diff line number Diff line
@@ -20,13 +20,16 @@ obj-$(CONFIG_UEFI_CPER) += cper.o
obj-$(CONFIG_EFI_RUNTIME_MAP)		+= runtime-map.o
obj-$(CONFIG_EFI_RUNTIME_WRAPPERS)	+= runtime-wrappers.o
obj-$(CONFIG_EFI_STUB)			+= libstub/
obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_map.o
obj-$(CONFIG_EFI_BOOTLOADER_CONTROL)	+= efibc.o
obj-$(CONFIG_EFI_TEST)			+= test/
obj-$(CONFIG_EFI_DEV_PATH_PARSER)	+= dev-path-parser.o
obj-$(CONFIG_APPLE_PROPERTIES)		+= apple-properties.o
obj-$(CONFIG_EFI_RCI2_TABLE)		+= rci2-table.o

fake_map-y				+= fake_mem.o
fake_map-$(CONFIG_X86)			+= x86_fake_mem.o

arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
obj-$(CONFIG_ARM)			+= $(arm-obj-y)
obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
Loading