Skip to content

Commit 02a3e3c

Browse files
Vidossuryasaimadhu
authored andcommitted
x86/boot: Parse SRAT table and count immovable memory regions
Parse SRAT for the immovable memory regions and use that information to control which offset KASLR selects so that it doesn't overlap with any movable region. [ bp: - Move struct mem_vector where it is visible so that it builds. - Correct comments. - Rewrite commit message. ] Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com> Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Baoquan He <bhe@redhat.com> Cc: <caoj.fnst@cn.fujitsu.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: <indou.takao@jp.fujitsu.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Juergen Gross <jgross@suse.com> Cc: <kasong@redhat.com> Cc: <keescook@chromium.org> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> Cc: <msys.mizuma@gmail.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: x86-ml <x86@kernel.org> Link: https://lkml.kernel.org/r/20190123110850.12433-7-fanc.fnst@cn.fujitsu.com
1 parent 3a63f70 commit 02a3e3c

File tree

3 files changed

+131
-4
lines changed

3 files changed

+131
-4
lines changed

arch/x86/boot/compressed/acpi.c

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,22 @@
44
#include "error.h"
55
#include "../string.h"
66

7+
#include <linux/numa.h>
78
#include <linux/efi.h>
89
#include <asm/efi.h>
910

11+
/*
12+
* Longest parameter of 'acpi=' is 'copy_dsdt', plus an extra '\0'
13+
* for termination.
14+
*/
15+
#define MAX_ACPI_ARG_LENGTH 10
16+
17+
/*
18+
* Immovable memory regions representation. Max amount of memory regions is
19+
* MAX_NUMNODES*2.
20+
*/
21+
struct mem_vector immovable_mem[MAX_NUMNODES*2];
22+
1023
/*
1124
* Max length of 64-bit hex address string is 19, prefix "0x" + 16 hex
1225
* digits, and '\0' for termination.
@@ -203,3 +216,111 @@ acpi_physical_address get_rsdp_addr(void)
203216

204217
return pa;
205218
}
219+
220+
#if defined(CONFIG_RANDOMIZE_BASE) && defined(CONFIG_MEMORY_HOTREMOVE)
221+
/* Compute SRAT address from RSDP. */
222+
static unsigned long get_acpi_srat_table(void)
223+
{
224+
unsigned long root_table, acpi_table;
225+
struct acpi_table_header *header;
226+
struct acpi_table_rsdp *rsdp;
227+
u32 num_entries, size, len;
228+
char arg[10];
229+
u8 *entry;
230+
231+
rsdp = (struct acpi_table_rsdp *)(long)boot_params->acpi_rsdp_addr;
232+
if (!rsdp)
233+
return 0;
234+
235+
/* Get ACPI root table from RSDP.*/
236+
if (!(cmdline_find_option("acpi", arg, sizeof(arg)) == 4 &&
237+
!strncmp(arg, "rsdt", 4)) &&
238+
rsdp->xsdt_physical_address &&
239+
rsdp->revision > 1) {
240+
root_table = rsdp->xsdt_physical_address;
241+
size = ACPI_XSDT_ENTRY_SIZE;
242+
} else {
243+
root_table = rsdp->rsdt_physical_address;
244+
size = ACPI_RSDT_ENTRY_SIZE;
245+
}
246+
247+
if (!root_table)
248+
return 0;
249+
250+
header = (struct acpi_table_header *)root_table;
251+
len = header->length;
252+
if (len < sizeof(struct acpi_table_header) + size)
253+
return 0;
254+
255+
num_entries = (len - sizeof(struct acpi_table_header)) / size;
256+
entry = (u8 *)(root_table + sizeof(struct acpi_table_header));
257+
258+
while (num_entries--) {
259+
if (size == ACPI_RSDT_ENTRY_SIZE)
260+
acpi_table = *(u32 *)entry;
261+
else
262+
acpi_table = *(u64 *)entry;
263+
264+
if (acpi_table) {
265+
header = (struct acpi_table_header *)acpi_table;
266+
267+
if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_SRAT))
268+
return acpi_table;
269+
}
270+
entry += size;
271+
}
272+
return 0;
273+
}
274+
275+
/**
276+
* count_immovable_mem_regions - Parse SRAT and cache the immovable
277+
* memory regions into the immovable_mem array.
278+
*
279+
* Return the number of immovable memory regions on success, 0 on failure:
280+
*
281+
* - Too many immovable memory regions
282+
* - ACPI off or no SRAT found
283+
* - No immovable memory region found.
284+
*/
285+
int count_immovable_mem_regions(void)
286+
{
287+
unsigned long table_addr, table_end, table;
288+
struct acpi_subtable_header *sub_table;
289+
struct acpi_table_header *table_header;
290+
char arg[MAX_ACPI_ARG_LENGTH];
291+
int num = 0;
292+
293+
if (cmdline_find_option("acpi", arg, sizeof(arg)) == 3 &&
294+
!strncmp(arg, "off", 3))
295+
return 0;
296+
297+
table_addr = get_acpi_srat_table();
298+
if (!table_addr)
299+
return 0;
300+
301+
table_header = (struct acpi_table_header *)table_addr;
302+
table_end = table_addr + table_header->length;
303+
table = table_addr + sizeof(struct acpi_table_srat);
304+
305+
while (table + sizeof(struct acpi_subtable_header) < table_end) {
306+
sub_table = (struct acpi_subtable_header *)table;
307+
if (sub_table->type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) {
308+
struct acpi_srat_mem_affinity *ma;
309+
310+
ma = (struct acpi_srat_mem_affinity *)sub_table;
311+
if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && ma->length) {
312+
immovable_mem[num].start = ma->base_address;
313+
immovable_mem[num].size = ma->length;
314+
num++;
315+
}
316+
317+
if (num >= MAX_NUMNODES*2) {
318+
debug_putstr("Too many immovable memory regions, aborting.\n");
319+
return 0;
320+
}
321+
}
322+
table += sub_table->length;
323+
}
324+
return num;
325+
}
326+
#endif /* CONFIG_RANDOMIZE_BASE && CONFIG_MEMORY_HOTREMOVE */

arch/x86/boot/compressed/kaslr.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,6 @@ static unsigned long get_boot_seed(void)
8787
#define KASLR_COMPRESSED_BOOT
8888
#include "../../lib/kaslr.c"
8989

90-
struct mem_vector {
91-
unsigned long long start;
92-
unsigned long long size;
93-
};
9490

9591
/* Only supporting at most 4 unusable memmap regions with kaslr */
9692
#define MAX_MEMMAP_REGIONS 4

arch/x86/boot/compressed/misc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ int cmdline_find_option(const char *option, char *buffer, int bufsize);
7272
int cmdline_find_option_bool(const char *option);
7373
#endif
7474

75+
struct mem_vector {
76+
unsigned long long start;
77+
unsigned long long size;
78+
};
7579

7680
#if CONFIG_RANDOMIZE_BASE
7781
/* kaslr.c */
@@ -126,3 +130,9 @@ acpi_physical_address get_rsdp_addr(void);
126130
#else
127131
static inline acpi_physical_address get_rsdp_addr(void) { return 0; }
128132
#endif
133+
134+
#if defined(CONFIG_RANDOMIZE_BASE) && defined(CONFIG_MEMORY_HOTREMOVE)
135+
int count_immovable_mem_regions(void);
136+
#else
137+
static inline int count_immovable_mem_regions(void) { return 0; }
138+
#endif

0 commit comments

Comments
 (0)