diff options
author | Julius Werner <jwerner@chromium.org> | 2015-10-07 18:38:24 -0700 |
---|---|---|
committer | Julius Werner <jwerner@chromium.org> | 2015-11-11 05:07:58 +0100 |
commit | fe4cbf1167fcb27ec332a2efe16297705ca07359 (patch) | |
tree | 31ba9883a29574842f33d9fb073c979437d48cb4 /src/soc | |
parent | 03a0a6517210b4f53082a499df2a7e743ae7452e (diff) | |
download | coreboot-fe4cbf1167fcb27ec332a2efe16297705ca07359.tar.xz |
arm64: mmu: Make page table manipulation work across stages
In order to have a proper runtime-modifyable page table API (e.g. to
remap DRAM after it was intialized), we need to remove any external
bookkeeping kept in global variables (which do not persist across
stages) from the MMU code. This patch implements this in a similar way
as it has recently been done for ARM32 (marking free table slots with a
special sentinel value in the first PTE that cannot occur as part of a
normal page table).
Since this requires the page table buffer to be known at compile-time,
we have to remove the option of passing it to mmu_init() at runtime
(which I already kinda deprecated before). The existing Tegra chipsets
that still used it are switched to instead define it in memlayout in a
minimally invasive change. This might not be the best way to design this
overall (I think we should probably just throw the tables into SRAM like
on all other platforms), but I don't have a Tegra system to test so I'd
rather keep this change low impact and leave the major redesign for
later.
Also inlined some single-use one-liner functions in mmu.c that I felt
confused things more than they cleared up, and fixed an (apparently
harmless?) issue with forgetting to mask out the XN page attribute bit
when casting a table descriptor to a pointer.
BRANCH=None
BUG=None
TEST=Compiled Ryu and Smaug. Booted Oak.
Change-Id: Iad71f97f5ec4b1fc981dbc8ff1dc88d96c8ee55a
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: http://review.coreboot.org/12075
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/nvidia/tegra132/include/soc/addressmap.h | 8 | ||||
-rw-r--r-- | src/soc/nvidia/tegra132/include/soc/memlayout.ld | 1 | ||||
-rw-r--r-- | src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld | 1 | ||||
-rw-r--r-- | src/soc/nvidia/tegra132/include/soc/mmu_operations.h | 3 | ||||
-rw-r--r-- | src/soc/nvidia/tegra132/mmu_operations.c | 43 | ||||
-rw-r--r-- | src/soc/nvidia/tegra210/include/soc/addressmap.h | 7 | ||||
-rw-r--r-- | src/soc/nvidia/tegra210/include/soc/memlayout.ld | 1 | ||||
-rw-r--r-- | src/soc/nvidia/tegra210/include/soc/memlayout_vboot2.ld | 1 | ||||
-rw-r--r-- | src/soc/nvidia/tegra210/mmu_operations.c | 42 |
9 files changed, 34 insertions, 73 deletions
diff --git a/src/soc/nvidia/tegra132/include/soc/addressmap.h b/src/soc/nvidia/tegra132/include/soc/addressmap.h index f51920f24d..fee67fe692 100644 --- a/src/soc/nvidia/tegra132/include/soc/addressmap.h +++ b/src/soc/nvidia/tegra132/include/soc/addressmap.h @@ -114,14 +114,6 @@ enum { /* Provided the careout id, obtain the base and size in 1MiB units. */ void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib); - -/* - * Add any board-specific memory ranges to the address map when executing - * on aarchv8 core. - */ -struct memranges; -void mainboard_add_memory_ranges(struct memranges *map); - /* * There are complications accessing the Trust Zone carveout region. The * AVP cannot access these registers and the CPU can't access this register diff --git a/src/soc/nvidia/tegra132/include/soc/memlayout.ld b/src/soc/nvidia/tegra132/include/soc/memlayout.ld index 0c610422ef..d403c17127 100644 --- a/src/soc/nvidia/tegra132/include/soc/memlayout.ld +++ b/src/soc/nvidia/tegra132/include/soc/memlayout.ld @@ -38,4 +38,5 @@ SECTIONS DRAM_START(0x80000000) POSTRAM_CBFS_CACHE(0x80100000, 1M) RAMSTAGE(0x80200000, 256K) + TTB(0x100000000 - CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB * 1M, 1M) } diff --git a/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld b/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld index a024435a6f..7a6a1688fb 100644 --- a/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld +++ b/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld @@ -40,4 +40,5 @@ SECTIONS DRAM_START(0x80000000) POSTRAM_CBFS_CACHE(0x80100000, 1M) RAMSTAGE(0x80200000, 256K) + TTB(0x100000000 - CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB * 1M, 1M) } diff --git a/src/soc/nvidia/tegra132/include/soc/mmu_operations.h b/src/soc/nvidia/tegra132/include/soc/mmu_operations.h index df5472e86c..f604c40e25 100644 --- a/src/soc/nvidia/tegra132/include/soc/mmu_operations.h +++ b/src/soc/nvidia/tegra132/include/soc/mmu_operations.h @@ -18,7 +18,4 @@ void tegra132_mmu_init(void); -/* Default ttb size of 1MiB */ -#define TTB_SIZE 0x1 - #endif //__SOC_NVIDIA_TEGRA132_MMU_OPERATIONS_H__ diff --git a/src/soc/nvidia/tegra132/mmu_operations.c b/src/soc/nvidia/tegra132/mmu_operations.c index 123f89842e..23531bee79 100644 --- a/src/soc/nvidia/tegra132/mmu_operations.c +++ b/src/soc/nvidia/tegra132/mmu_operations.c @@ -14,16 +14,14 @@ */ #include <arch/mmu.h> -#include <memrange.h> +#include <assert.h> #include <soc/addressmap.h> #include <soc/mmu_operations.h> #include <stdlib.h> #include <stdint.h> +#include <symbols.h> -/* This structure keeps track of all the mmap memory ranges for t132 */ -static struct memranges t132_mmap_ranges; - -static void tegra132_memrange_init(struct memranges *map) +static void tegra132_mmu_config(void) { uint64_t start,end; const unsigned long devmem = MA_DEV | MA_S | MA_RW; @@ -32,46 +30,35 @@ static void tegra132_memrange_init(struct memranges *map) uintptr_t tz_base_mib; size_t tz_size_mib; - memranges_init_empty(map); - memory_in_range_below_4gb(&start,&end); /* Device memory below DRAM */ - memranges_insert(map, 0, start * MiB, devmem); + mmu_config_range((void *)0, start * MiB, devmem); /* DRAM */ - memranges_insert(map, start * MiB, (end-start) * MiB, cachedmem); + mmu_config_range((void *)(start * MiB), (end-start) * MiB, cachedmem); memory_in_range_above_4gb(&start,&end); - memranges_insert(map, start * MiB, (end-start) * MiB, cachedmem); + mmu_config_range((void *)(start * MiB), (end-start) * MiB, cachedmem); /* SRAM */ - memranges_insert(map, TEGRA_SRAM_BASE, TEGRA_SRAM_SIZE, cachedmem); + mmu_config_range(_sram, _sram_size, cachedmem); /* Add TZ carveout. */ carveout_range(CARVEOUT_TZ, &tz_base_mib, &tz_size_mib); - memranges_insert(map, tz_base_mib * MiB, tz_size_mib * MiB, secure_mem); -} -void __attribute__((weak)) mainboard_add_memory_ranges(struct memranges *map) -{ - /* Don't add any ranges by default. */ + mmu_config_range((void *)(tz_base_mib * MiB), + tz_size_mib * MiB, secure_mem); + + /* Ensure page tables are at the base of the trust zone region. */ + assert((uintptr_t)_ttb == tz_base_mib * MiB && + _ttb_size <= tz_size_mib * MiB); } void tegra132_mmu_init(void) { - uintptr_t tz_base_mib; - size_t tz_size_mib; - size_t ttb_size_mib; - struct memranges *map = &t132_mmap_ranges; - - tegra132_memrange_init(map); - mainboard_add_memory_ranges(map); - /* Place page tables at the base of the trust zone region. */ - carveout_range(CARVEOUT_TZ, &tz_base_mib, &tz_size_mib); - tz_base_mib *= MiB; - ttb_size_mib = TTB_SIZE * MiB; - mmu_init(map, (void *)tz_base_mib, ttb_size_mib); + mmu_init(); + tegra132_mmu_config(); mmu_enable(); } diff --git a/src/soc/nvidia/tegra210/include/soc/addressmap.h b/src/soc/nvidia/tegra210/include/soc/addressmap.h index 2151be5f0b..2f6bd8a5f9 100644 --- a/src/soc/nvidia/tegra210/include/soc/addressmap.h +++ b/src/soc/nvidia/tegra210/include/soc/addressmap.h @@ -129,13 +129,6 @@ void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib); void print_carveouts(void); /* - * Add any board-specific memory ranges to the address map when executing - * on aarchv8 core. - */ -struct memranges; -void mainboard_add_memory_ranges(struct memranges *map); - -/* * There are complications accessing the Trust Zone carveout region. The * AVP cannot access these registers and the CPU can't access this register * as a non-secure access. When the page tables live in non-secure memory diff --git a/src/soc/nvidia/tegra210/include/soc/memlayout.ld b/src/soc/nvidia/tegra210/include/soc/memlayout.ld index d24f980207..0338cd9604 100644 --- a/src/soc/nvidia/tegra210/include/soc/memlayout.ld +++ b/src/soc/nvidia/tegra210/include/soc/memlayout.ld @@ -38,4 +38,5 @@ SECTIONS DRAM_START(0x80000000) POSTRAM_CBFS_CACHE(0x80100000, 1M) RAMSTAGE(0x80200000, 256K) + TTB(0x100000000 - CONFIG_TTB_SIZE_MB * 1M, CONFIG_TTB_SIZE_MB * 1M) } diff --git a/src/soc/nvidia/tegra210/include/soc/memlayout_vboot2.ld b/src/soc/nvidia/tegra210/include/soc/memlayout_vboot2.ld index e2e4dd8d24..b4b3dc2822 100644 --- a/src/soc/nvidia/tegra210/include/soc/memlayout_vboot2.ld +++ b/src/soc/nvidia/tegra210/include/soc/memlayout_vboot2.ld @@ -40,4 +40,5 @@ SECTIONS DRAM_START(0x80000000) POSTRAM_CBFS_CACHE(0x80100000, 1M) RAMSTAGE(0x80200000, 256K) + TTB(0x100000000 - CONFIG_TTB_SIZE_MB * 1M, CONFIG_TTB_SIZE_MB * 1M) } diff --git a/src/soc/nvidia/tegra210/mmu_operations.c b/src/soc/nvidia/tegra210/mmu_operations.c index b9cae1419e..de7ae2f487 100644 --- a/src/soc/nvidia/tegra210/mmu_operations.c +++ b/src/soc/nvidia/tegra210/mmu_operations.c @@ -15,16 +15,13 @@ #include <arch/mmu.h> #include <assert.h> -#include <memrange.h> #include <soc/addressmap.h> #include <soc/mmu_operations.h> #include <stdlib.h> #include <stdint.h> +#include <symbols.h> -/* This structure keeps track of all the mmap memory ranges for t210 */ -static struct memranges t210_mmap_ranges; - -static void tegra210_memrange_init(struct memranges *map) +static void tegra210_mmu_config(void) { uint64_t start,end; const unsigned long devmem = MA_DEV | MA_S | MA_RW; @@ -35,45 +32,39 @@ static void tegra210_memrange_init(struct memranges *map) print_carveouts(); - memranges_init_empty(map); - memory_in_range_below_4gb(&start,&end); /* Device memory below DRAM */ - memranges_insert(map, TEGRA_ARM_LOWEST_PERIPH, start * MiB, devmem); + mmu_config_range((void *)TEGRA_ARM_LOWEST_PERIPH, start * MiB, devmem); /* DRAM */ - memranges_insert(map, start * MiB, (end-start) * MiB, cachedmem); + mmu_config_range((void *)(start * MiB), (end-start) * MiB, cachedmem); memory_in_range_above_4gb(&start,&end); - memranges_insert(map, start * MiB, (end-start) * MiB, cachedmem); + mmu_config_range((void *)(start * MiB), (end-start) * MiB, cachedmem); /* SRAM */ - memranges_insert(map, TEGRA_SRAM_BASE, TEGRA_SRAM_SIZE, cachedmem); + mmu_config_range(_sram, _sram_size, cachedmem); /* Add TZ carveout. */ carveout_range(CARVEOUT_TZ, &tz_base_mib, &tz_size_mib); - memranges_insert(map, tz_base_mib * MiB, tz_size_mib * MiB, secure_mem); -} -void __attribute__((weak)) mainboard_add_memory_ranges(struct memranges *map) -{ - /* Don't add any ranges by default. */ + mmu_config_range((void *)(tz_base_mib * MiB), + tz_size_mib * MiB, secure_mem); } void tegra210_mmu_init(void) { uintptr_t tz_base_mib; size_t tz_size_mib; - uintptr_t ttb_base_mib; - size_t ttb_size_mib; - struct memranges *map = &t210_mmap_ranges; - tegra210_memrange_init(map); - mainboard_add_memory_ranges(map); + mmu_init(); + tegra210_mmu_config(); /* - * Place page tables at the end of the trust zone region. + * Page tables are at the end of the trust zone region, but we should + * double-check that memlayout and addressmap.c are in sync. + * * TZDRAM layout is as follows: * * +--------------------------+ <----+DRAM_END @@ -98,11 +89,8 @@ void tegra210_mmu_init(void) * */ carveout_range(CARVEOUT_TZ, &tz_base_mib, &tz_size_mib); + assert((uintptr_t)_ttb + _ttb_size == (tz_base_mib + tz_size_mib) * MiB + && _ttb_size <= tz_size_mib * MiB); - assert(tz_size_mib > CONFIG_TTB_SIZE_MB); - ttb_base_mib = (tz_base_mib + tz_size_mib - CONFIG_TTB_SIZE_MB) * MiB; - - ttb_size_mib = CONFIG_TTB_SIZE_MB * MiB; - mmu_init(map, (void *)ttb_base_mib, ttb_size_mib); mmu_enable(); } |