History

efi: Common enable/disable infrastructure for EFI soft reservation

UEFI 2.8 defines an EFI_MEMORY_SP attribute bit to augment the interpretation of the EFI Memory Types as "reserved for a specific purpose". The proposed Linux behavior for specific purpose memory is that it is reserved for direct-access (device-dax) by default and not available for any kernel usage, not even as an OOM fallback. Later, through udev scripts or another init mechanism, these device-dax claimed ranges can be reconfigured and hot-added to the available System-RAM with a unique node identifier. This device-dax management scheme implements "soft" in the "soft reserved" designation by allowing some or all of the reservation to be recovered as typical memory. This policy can be disabled at compile-time with CONFIG_EFI_SOFT_RESERVE=n, or runtime with efi=nosoftreserve. As for this patch, define the common helpers to determine if the EFI_MEMORY_SP attribute should be honored. The determination needs to be made early to prevent the kernel from being loaded into soft-reserved memory, or otherwise allowing early allocations to land there. Follow-on changes are needed per architecture to leverage these helpers in their respective mem-init paths.

Dan Williams committed 7 years ago

Commit b617c521 parent 6950e315 files · +70 −1Browse files

Unified · Split

5 files
  1. Documentation/admin-guide/kernel-parameters.txt +8 −1
  2. drivers/firmware/efi/Kconfig +21 −0
  3. drivers/firmware/efi/efi.c +8 −0
  4. drivers/firmware/efi/libstub/efi-stub-helper.c +19 −0
  5. include/linux/efi.h +14 −0
Documentation/admin-guide/kernel-parameters.txt+8−1
@@ -1168,7 +1168,8 @@ · 1167 unmodified lines
11681168 Format: {"off" | "on" | "skip[mbr]"}
11691169
11701170 efi= [EFI]
1171− Format: { "old_map", "nochunk", "noruntime", "debug" }
1171+ Format: { "old_map", "nochunk", "noruntime", "debug",
1172+ "nosoftreserve" }
11721173 old_map [X86-64]: switch to the old ioremap-based EFI
11731174 runtime services mapping. 32-bit still uses this one by
11741175 default.
@@ -1177,6 +1178,12 @@ · 2 unmodified lines
11771178 firmware implementations.
11781179 noruntime : disable EFI runtime services support
11791180 debug: enable misc debug output
1181+ nosoftreserve: The EFI_MEMORY_SP (Specific Purpose)
1182+ attribute may cause the kernel to reserve the
1183+ memory range for a memory mapping driver to
1184+ claim. Specify efi=nosoftreserve to disable this
1185+ reservation and treat the memory by its base type
1186+ (i.e. EFI_CONVENTIONAL_MEMORY / "System RAM").
11801187
11811188 efi_no_storage_paranoia [EFI; X86]
11821189 Using this parameter you can use more than 50% of
drivers/firmware/efi/Kconfig+21−0
@@ -75,6 +75,27 @@ config EFI_MAX_FAKE_MEM · 74 unmodified lines
7575 Ranges can be set up to this value using comma-separated list.
7676 The default value is 8.
7777
78+config EFI_SOFT_RESERVE
79+ bool "Reserve EFI Specific Purpose Memory"
80+ depends on EFI && EFI_STUB && ACPI_HMAT
81+ default ACPI_HMAT
82+ help
83+ On systems that have mixed performance classes of memory EFI
84+ may indicate specific purpose memory with an attribute (See
85+ EFI_MEMORY_SP in UEFI 2.8). A memory range tagged with this
86+ attribute may have unique performance characteristics compared
87+ to the system's general purpose "System RAM" pool. On the
88+ expectation that such memory has application specific usage,
89+ and its base EFI memory type is "conventional" answer Y to
90+ arrange for the kernel to reserve it as a "Soft Reserved"
91+ resource, and set aside for direct-access (device-dax) by
92+ default. The memory range can later be optionally assigned to
93+ the page allocator by system administrator policy via the
94+ device-dax kmem facility. Say N to have the kernel treat this
95+ memory as "System RAM" by default.
96+
97+ If unsure, say Y.
98+
7899 config EFI_PARAMS_FROM_FDT
79100 bool
80101 help
drivers/firmware/efi/efi.c+8−0
@@ -81,6 +81,11 @@ bool efi_runtime_disabled(void) · 80 unmodified lines
8181 return disable_runtime;
8282 }
8383
84+bool __pure __efi_soft_reserve_enabled(void)
85+{
86+ return !efi_enabled(EFI_MEM_NO_SOFT_RESERVE);
87+}
88+
8489 static int __init parse_efi_cmdline(char *str)
8590 {
8691 if (!str) {
@@ -94,6 +99,9 @@ static int __init parse_efi_cmdline(char *str) · 7 unmodified lines
9499 if (parse_option_str(str, "noruntime"))
95100 disable_runtime = true;
96101
102+ if (parse_option_str(str, "nosoftreserve"))
103+ set_bit(EFI_MEM_NO_SOFT_RESERVE, &efi.flags);
104+
97105 return 0;
98106 }
99107 early_param("efi", parse_efi_cmdline);
drivers/firmware/efi/libstub/efi-stub-helper.c+19−0
@@ -32,6 +32,7 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; · 31 unmodified lines
3232 static int __section(.data) __nokaslr;
3333 static int __section(.data) __quiet;
3434 static int __section(.data) __novamap;
35+static bool __section(.data) efi_nosoftreserve;
3536
3637 int __pure nokaslr(void)
3738 {
@@ -45,6 +46,10 @@ int __pure novamap(void) · 7 unmodified lines
4546 {
4647 return __novamap;
4748 }
49+bool __pure __efi_soft_reserve_enabled(void)
50+{
51+ return !efi_nosoftreserve;
52+}
4853
4954 #define EFI_MMAP_NR_SLACK_SLOTS 8
5055
@@ -211,6 +216,10 @@ again: · 160 unmodified lines
211216 if (desc->type != EFI_CONVENTIONAL_MEMORY)
212217 continue;
213218
219+ if (efi_soft_reserve_enabled() &&
220+ (desc->attribute & EFI_MEMORY_SP))
221+ continue;
222+
214223 if (desc->num_pages < nr_pages)
215224 continue;
216225
@@ -305,6 +314,10 @@ efi_status_t efi_low_alloc_above(efi_system_table_t *sys_table_arg, · 88 unmodified lines
305314 if (desc->type != EFI_CONVENTIONAL_MEMORY)
306315 continue;
307316
317+ if (efi_soft_reserve_enabled() &&
318+ (desc->attribute & EFI_MEMORY_SP))
319+ continue;
320+
308321 if (desc->num_pages < nr_pages)
309322 continue;
310323
@@ -484,6 +497,12 @@ efi_status_t efi_parse_options(char const *cmdline) · 173 unmodified lines
484497 __novamap = 1;
485498 }
486499
500+ if (IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) &&
501+ !strncmp(str, "nosoftreserve", 7)) {
502+ str += strlen("nosoftreserve");
503+ efi_nosoftreserve = 1;
504+ }
505+
487506 /* Group words together, delimited by "," */
488507 while (*str && *str != ' ' && *str != ',')
489508 str++;
include/linux/efi.h+14−0
@@ -1202,6 +1202,7 @@ extern int __init efi_setup_pcdp_console(char *); · 1201 unmodified lines
12021202 #define EFI_DBG 8 /* Print additional debug info at runtime */
12031203 #define EFI_NX_PE_DATA 9 /* Can runtime data regions be mapped non-executable? */
12041204 #define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */
1205+#define EFI_MEM_NO_SOFT_RESERVE 11 /* Is the kernel configured to ignore soft reservations? */
12051206
12061207 #ifdef CONFIG_EFI
12071208 /*
@@ -1212,6 +1213,14 @@ static inline bool efi_enabled(int feature) · 4 unmodified lines
12121213 return test_bit(feature, &efi.flags) != 0;
12131214 }
12141215 extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
1216+
1217+bool __pure __efi_soft_reserve_enabled(void);
1218+
1219+static inline bool __pure efi_soft_reserve_enabled(void)
1220+{
1221+ return IS_ENABLED(CONFIG_EFI_SOFT_RESERVE)
1222+ && __efi_soft_reserve_enabled();
1223+}
12151224 #else
12161225 static inline bool efi_enabled(int feature)
12171226 {
@@ -1225,6 +1234,11 @@ efi_capsule_pending(int *reset_type) · 7 unmodified lines
12251234 {
12261235 return false;
12271236 }
1237+
1238+static inline bool efi_soft_reserve_enabled(void)
1239+{
1240+ return false;
1241+}
12281242 #endif
12291243
12301244 extern int efi_status_to_err(efi_status_t status);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t