Skip to content

Commit 279fa5c

Browse files
arm64b0day robot
authored andcommitted
arm64:acpi fix the acpi alignment exception when 'mem=' specified
When kernel parameter 'mem=x' is specified by the command line, probably the ACPI memory regions from firmware will beyond the scope of the physical memory space after limited, if we don't add back those regions into memblock in this case, then the ACPI core will map it as device memory type. Since the ACPI core will produce non-alignment access when parsing the AML data stream, alignment exception will be generated upon the device memory mapped region. Below is an alignment exception output observed on ARM platform with acpi enabled: ... [ 0.542475] Unable to handle kernel paging request at virtual address ffff0000080521e7 [ 0.550457] pgd = ffff000008aa0000 [ 0.553880] [ffff0000080521e7] *pgd=000000801fffe003, *pud=000000801fffd003, *pmd=000000801fffc003, *pte=00e80083ff1c1707 [ 0.564939] Internal error: Oops: 96000021 [#1] PREEMPT SMP [ 0.570553] Modules linked in: [ 0.573626] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.7.0-rc3-next-20160616+ torvalds#172 [ 0.581344] Hardware name: AMD Overdrive/Supercharger/Default string, BIOS ROD1001A 02/09/2016 [ 0.590025] task: ffff800001ef0000 ti: ffff800001ef8000 task.ti: ffff800001ef8000 [ 0.597571] PC is at acpi_ns_lookup+0x520/0x734 [ 0.602134] LR is at acpi_ns_lookup+0x4a4/0x734 [ 0.606693] pc : [<ffff0000083b8b10>] lr : [<ffff0000083b8a94>] pstate: 60000045 [ 0.614145] sp : ffff800001efb8b0 [ 0.617478] x29: ffff800001efb8c0 x28: 000000000000001b [ 0.622829] x27: 0000000000000001 x26: 0000000000000000 [ 0.628181] x25: ffff800001efb9e8 x24: ffff000008a10000 [ 0.633531] x23: 0000000000000001 x22: 0000000000000001 [ 0.638881] x21: ffff000008724000 x20: 000000000000001b [ 0.644230] x19: ffff0000080521e7 x18: 000000000000000d [ 0.649580] x17: 00000000000038ff x16: 0000000000000002 [ 0.654929] x15: 0000000000000007 x14: 0000000000007fff [ 0.660278] x13: ffffff0000000000 x12: 0000000000000018 [ 0.665627] x11: 000000001fffd200 x10: 00000000ffffff76 [ 0.670978] x9 : 000000000000005f x8 : ffff000008725fa8 [ 0.676328] x7 : ffff000008a8df70 x6 : ffff000008a8df70 [ 0.681679] x5 : ffff000008a8d000 x4 : 0000000000000010 [ 0.687027] x3 : 0000000000000010 x2 : 000000000000000c [ 0.692378] x1 : 0000000000000006 x0 : 0000000000000000 ... [ 1.262235] [<ffff0000083b8b10>] acpi_ns_lookup+0x520/0x734 [ 1.267845] [<ffff0000083a7160>] acpi_ds_load1_begin_op+0x174/0x4fc [ 1.274156] [<ffff0000083c1f4c>] acpi_ps_build_named_op+0xf8/0x220 [ 1.280380] [<ffff0000083c227c>] acpi_ps_create_op+0x208/0x33c [ 1.286254] [<ffff0000083c1820>] acpi_ps_parse_loop+0x204/0x838 [ 1.292215] [<ffff0000083c2fd4>] acpi_ps_parse_aml+0x1bc/0x42c [ 1.298090] [<ffff0000083bc6e8>] acpi_ns_one_complete_parse+0x1e8/0x22c [ 1.304753] [<ffff0000083bc7b8>] acpi_ns_parse_table+0x8c/0x128 [ 1.310716] [<ffff0000083bb8fc>] acpi_ns_load_table+0xc0/0x1e8 [ 1.316591] [<ffff0000083c9068>] acpi_tb_load_namespace+0xf8/0x2e8 [ 1.322818] [<ffff000008984128>] acpi_load_tables+0x7c/0x110 [ 1.328516] [<ffff000008982ea4>] acpi_init+0x90/0x2c0 [ 1.333603] [<ffff0000080819fc>] do_one_initcall+0x38/0x12c [ 1.339215] [<ffff000008960cd4>] kernel_init_freeable+0x148/0x1ec [ 1.345353] [<ffff0000086b7d30>] kernel_init+0x10/0xec [ 1.350529] [<ffff000008084e10>] ret_from_fork+0x10/0x40 [ 1.355878] Code: b9009fbc 2a00037b 36380057 3219037b (b940026) [ 1.362035] ---[ end trace 03381e5eb0a24de4 ]--- [ 1.366691] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b With 'efi=debug', we can see those ACPI regions from firmware as: [ 0.000000] efi: 0x0083ff1b5000-0x0083ff1c2fff [ACPI Reclaim Memory| | | | | | | | |WB|WT|WC|UC]* [ 0.000000] efi: 0x0083ff223000-0x0083ff224fff [ACPI Memory NVS | | | | | | | | |WB|WT|WC|UC]* This patch is trying to add back those regions into memblock, make ACPI core map it as normal memory instead of device memory type. Signed-off-by: Dennis Chen <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Steve Capper <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: Will Deacon <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Rafael J. Wysocki <[email protected]> Cc: Matt Fleming <[email protected]> Cc: [email protected] Cc: [email protected]
1 parent 541ec87 commit 279fa5c

File tree

4 files changed

+57
-2
lines changed

4 files changed

+57
-2
lines changed

arch/arm64/include/asm/memblock.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@
1616
#ifndef __ASM_MEMBLOCK_H
1717
#define __ASM_MEMBLOCK_H
1818

19-
extern void arm64_memblock_init(void);
19+
#ifdef CONFIG_ACPI
20+
typedef struct {
21+
u64 base;
22+
u64 size;
23+
int resv;
24+
} efi_acpi_reg_t;
25+
26+
#define MAX_ACPI_REGS 4
27+
extern unsigned int nr_acpi_regs;
28+
extern efi_acpi_reg_t acpi_regs[MAX_ACPI_REGS];
29+
#endif
2030

31+
extern void arm64_memblock_init(void);
32+
extern phys_addr_t memory_limit;
2133
#endif

arch/arm64/kernel/acpi.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <asm/cputype.h>
2929
#include <asm/cpu_ops.h>
3030
#include <asm/smp_plat.h>
31+
#include <asm/memblock.h>
3132

3233
#ifdef CONFIG_ACPI_APEI
3334
# include <linux/efi.h>
@@ -196,6 +197,8 @@ static int __init acpi_fadt_sanity_check(void)
196197
*/
197198
void __init acpi_boot_table_init(void)
198199
{
200+
int i;
201+
199202
/*
200203
* Enable ACPI instead of device tree unless
201204
* - ACPI has been disabled explicitly (acpi=off), or
@@ -226,6 +229,26 @@ void __init acpi_boot_table_init(void)
226229
if (!param_acpi_force)
227230
disable_acpi();
228231
}
232+
233+
/*
234+
* For the case of 'mem=x' kernel parameter specified by cmdline:
235+
* when ACPI parses raw AML data within the ACPI data region,
236+
* sometimes it will produce non-alignment memory access, in order
237+
* to make kernel avoid generating alignment fault in this case, we
238+
* need to add back the firmware ACPI memory region into memblock,
239+
* thus the ACPI core will map it as normal memory, otherwise ACPI
240+
* will map the region as device memory type which trigers alignment
241+
* exception.
242+
*/
243+
if (!acpi_disabled && memory_limit != (phys_addr_t)ULLONG_MAX) {
244+
for (i = 0; i < nr_acpi_regs; i++) {
245+
memblock_add(acpi_regs[i].base, acpi_regs[i].size);
246+
/* MEMBLOCK_NOMAP maybe cleaned before, re-flag it */
247+
if (acpi_regs[i].resv)
248+
memblock_mark_nomap(acpi_regs[i].base,
249+
acpi_regs[i].size);
250+
}
251+
}
229252
}
230253

231254
#ifdef CONFIG_ACPI_APEI

arch/arm64/mm/init.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include <asm/sizes.h>
4747
#include <asm/tlb.h>
4848
#include <asm/alternative.h>
49+
#include <asm/memblock.h>
4950

5051
#include "mm.h"
5152

@@ -172,7 +173,7 @@ static void __init arm64_memory_present(void)
172173
}
173174
#endif
174175

175-
static phys_addr_t memory_limit = (phys_addr_t)ULLONG_MAX;
176+
phys_addr_t memory_limit = (phys_addr_t)ULLONG_MAX;
176177

177178
/*
178179
* Limit the memory size that was specified via FDT.

drivers/firmware/efi/arm-init.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,15 @@
2323
#include <linux/screen_info.h>
2424

2525
#include <asm/efi.h>
26+
#include <asm/memblock.h>
2627

2728
u64 efi_system_table;
2829

30+
#ifdef CONFIG_ACPI
31+
unsigned int nr_acpi_regs;
32+
efi_acpi_reg_t acpi_regs[MAX_ACPI_REGS];
33+
#endif
34+
2935
static int __init is_normal_ram(efi_memory_desc_t *md)
3036
{
3137
if (md->attribute & EFI_MEMORY_WB)
@@ -210,6 +216,19 @@ static __init void reserve_regions(void)
210216
if (resv)
211217
memblock_mark_nomap(paddr, size);
212218

219+
#ifdef CONFIG_ACPI
220+
if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
221+
md->type == EFI_ACPI_MEMORY_NVS) {
222+
if (nr_acpi_regs >= MAX_ACPI_REGS) {
223+
WARN_ONCE(1, "Too many ACPI mem regions: %d\n", nr_acpi_regs);
224+
continue;
225+
}
226+
acpi_regs[nr_acpi_regs].base = paddr;
227+
acpi_regs[nr_acpi_regs].size = size;
228+
acpi_regs[nr_acpi_regs].resv = resv;
229+
nr_acpi_regs++;
230+
}
231+
#endif
213232
}
214233

215234
set_bit(EFI_MEMMAP, &efi.flags);

0 commit comments

Comments
 (0)