2017-03-08 14:40:23 +00:00
|
|
|
/*
|
xlat_tables_v2: use get_current_el_maybe_constant() in is_dcache_enabled()
Using get_current_el_maybe_constant() produces more optimized code
because in most cases, we know the exception level at build-time.
For example, BL31 runs at EL3, so unneeded code will be trimmed.
[before]
0000000000000000 <is_dcache_enabled>:
0: d5384240 mrs x0, currentel
4: 53020c00 ubfx w0, w0, #2, #2
8: 7100041f cmp w0, #0x1
c: 54000081 b.ne 1c <is_dcache_enabled+0x1c> // b.any
10: d5381000 mrs x0, sctlr_el1
14: 53020800 ubfx w0, w0, #2, #1
18: d65f03c0 ret
1c: 7100081f cmp w0, #0x2
20: 54000061 b.ne 2c <is_dcache_enabled+0x2c> // b.any
24: d53c1000 mrs x0, sctlr_el2
28: 17fffffb b 14 <is_dcache_enabled+0x14>
2c: d53e1000 mrs x0, sctlr_el3
30: 17fffff9 b 14 <is_dcache_enabled+0x14>
[after]
0000000000000000 <is_dcache_enabled>:
0: d53e1000 mrs x0, sctlr_el3
4: 53020800 ubfx w0, w0, #2, #1
8: d65f03c0 ret
Change-Id: I3698fae9b517022ff9fbfd4cad3a320c6e137e10
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2020-04-02 08:20:21 +01:00
|
|
|
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
|
2017-03-08 14:40:23 +00:00
|
|
|
*
|
2017-05-03 09:38:09 +01:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2017-03-08 14:40:23 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
2018-08-02 09:57:29 +01:00
|
|
|
#include <stdbool.h>
|
2018-08-16 16:52:57 +01:00
|
|
|
#include <stdint.h>
|
2018-12-14 00:18:21 +00:00
|
|
|
|
|
|
|
#include <arch.h>
|
2019-01-11 11:20:10 +00:00
|
|
|
#include <arch_features.h>
|
2018-12-14 00:18:21 +00:00
|
|
|
#include <arch_helpers.h>
|
|
|
|
#include <lib/cassert.h>
|
|
|
|
#include <lib/utils_def.h>
|
|
|
|
#include <lib/xlat_tables/xlat_tables_v2.h>
|
|
|
|
|
2017-03-08 14:40:23 +00:00
|
|
|
#include "../xlat_tables_private.h"
|
|
|
|
|
2018-06-11 13:40:32 +01:00
|
|
|
/*
|
2018-08-02 09:57:29 +01:00
|
|
|
* Returns true if the provided granule size is supported, false otherwise.
|
2018-06-11 13:40:32 +01:00
|
|
|
*/
|
2018-08-02 09:57:29 +01:00
|
|
|
bool xlat_arch_is_granule_size_supported(size_t size)
|
2018-06-11 13:40:32 +01:00
|
|
|
{
|
|
|
|
u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
|
|
|
|
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
if (size == PAGE_SIZE_4KB) {
|
2018-08-02 09:57:29 +01:00
|
|
|
return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) &
|
2018-06-11 13:40:32 +01:00
|
|
|
ID_AA64MMFR0_EL1_TGRAN4_MASK) ==
|
2018-08-02 09:57:29 +01:00
|
|
|
ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED;
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
} else if (size == PAGE_SIZE_16KB) {
|
2018-08-02 09:57:29 +01:00
|
|
|
return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) &
|
2018-06-11 13:40:32 +01:00
|
|
|
ID_AA64MMFR0_EL1_TGRAN16_MASK) ==
|
2018-08-02 09:57:29 +01:00
|
|
|
ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED;
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
} else if (size == PAGE_SIZE_64KB) {
|
2018-08-02 09:57:29 +01:00
|
|
|
return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) &
|
2018-06-11 13:40:32 +01:00
|
|
|
ID_AA64MMFR0_EL1_TGRAN64_MASK) ==
|
2018-08-02 09:57:29 +01:00
|
|
|
ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED;
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
} else {
|
|
|
|
return 0;
|
2018-06-11 13:40:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t xlat_arch_get_max_supported_granule_size(void)
|
|
|
|
{
|
2018-08-02 09:57:29 +01:00
|
|
|
if (xlat_arch_is_granule_size_supported(PAGE_SIZE_64KB)) {
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
return PAGE_SIZE_64KB;
|
2018-08-02 09:57:29 +01:00
|
|
|
} else if (xlat_arch_is_granule_size_supported(PAGE_SIZE_16KB)) {
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
return PAGE_SIZE_16KB;
|
2018-06-11 13:40:32 +01:00
|
|
|
} else {
|
2018-08-02 09:57:29 +01:00
|
|
|
assert(xlat_arch_is_granule_size_supported(PAGE_SIZE_4KB));
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
return PAGE_SIZE_4KB;
|
2018-06-11 13:40:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-25 11:53:25 +01:00
|
|
|
unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr)
|
2017-03-08 14:40:23 +00:00
|
|
|
{
|
|
|
|
/* Physical address can't exceed 48 bits */
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
assert((max_addr & ADDR_MASK_48_TO_63) == 0U);
|
2017-03-08 14:40:23 +00:00
|
|
|
|
|
|
|
/* 48 bits address */
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
if ((max_addr & ADDR_MASK_44_TO_47) != 0U)
|
2017-03-08 14:40:23 +00:00
|
|
|
return TCR_PS_BITS_256TB;
|
|
|
|
|
|
|
|
/* 44 bits address */
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
if ((max_addr & ADDR_MASK_42_TO_43) != 0U)
|
2017-03-08 14:40:23 +00:00
|
|
|
return TCR_PS_BITS_16TB;
|
|
|
|
|
|
|
|
/* 42 bits address */
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
if ((max_addr & ADDR_MASK_40_TO_41) != 0U)
|
2017-03-08 14:40:23 +00:00
|
|
|
return TCR_PS_BITS_4TB;
|
|
|
|
|
|
|
|
/* 40 bits address */
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
if ((max_addr & ADDR_MASK_36_TO_39) != 0U)
|
2017-03-08 14:40:23 +00:00
|
|
|
return TCR_PS_BITS_1TB;
|
|
|
|
|
|
|
|
/* 36 bits address */
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
if ((max_addr & ADDR_MASK_32_TO_35) != 0U)
|
2017-03-08 14:40:23 +00:00
|
|
|
return TCR_PS_BITS_64GB;
|
|
|
|
|
|
|
|
return TCR_PS_BITS_4GB;
|
|
|
|
}
|
|
|
|
|
2017-03-22 15:48:51 +00:00
|
|
|
#if ENABLE_ASSERTIONS
|
2018-05-02 11:23:56 +01:00
|
|
|
/*
|
|
|
|
* Physical Address ranges supported in the AArch64 Memory Model. Value 0b110 is
|
|
|
|
* supported in ARMv8.2 onwards.
|
|
|
|
*/
|
2017-03-08 14:40:23 +00:00
|
|
|
static const unsigned int pa_range_bits_arr[] = {
|
|
|
|
PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100,
|
2018-05-02 11:23:56 +01:00
|
|
|
PARANGE_0101, PARANGE_0110
|
2017-03-08 14:40:23 +00:00
|
|
|
};
|
|
|
|
|
2017-05-31 13:31:48 +01:00
|
|
|
unsigned long long xlat_arch_get_max_supported_pa(void)
|
2017-03-08 14:40:23 +00:00
|
|
|
{
|
|
|
|
u_register_t pa_range = read_id_aa64mmfr0_el1() &
|
|
|
|
ID_AA64MMFR0_EL1_PARANGE_MASK;
|
|
|
|
|
|
|
|
/* All other values are reserved */
|
|
|
|
assert(pa_range < ARRAY_SIZE(pa_range_bits_arr));
|
|
|
|
|
2018-02-16 21:12:58 +00:00
|
|
|
return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL;
|
2017-03-08 14:40:23 +00:00
|
|
|
}
|
2019-01-25 11:36:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return minimum virtual address space size supported by the architecture
|
|
|
|
*/
|
|
|
|
uintptr_t xlat_get_min_virt_addr_space_size(void)
|
|
|
|
{
|
|
|
|
uintptr_t ret;
|
|
|
|
|
|
|
|
if (is_armv8_4_ttst_present())
|
|
|
|
ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
|
|
|
|
else
|
|
|
|
ret = MIN_VIRT_ADDR_SPACE_SIZE;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2017-03-22 15:48:51 +00:00
|
|
|
#endif /* ENABLE_ASSERTIONS*/
|
2017-03-08 14:40:23 +00:00
|
|
|
|
2018-08-02 09:57:29 +01:00
|
|
|
bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx)
|
2017-03-08 14:40:23 +00:00
|
|
|
{
|
2017-10-04 16:52:15 +01:00
|
|
|
if (ctx->xlat_regime == EL1_EL0_REGIME) {
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
assert(xlat_arch_current_el() >= 1U);
|
2018-08-02 09:57:29 +01:00
|
|
|
return (read_sctlr_el1() & SCTLR_M_BIT) != 0U;
|
2018-08-07 19:59:49 +01:00
|
|
|
} else if (ctx->xlat_regime == EL2_REGIME) {
|
|
|
|
assert(xlat_arch_current_el() >= 2U);
|
|
|
|
return (read_sctlr_el2() & SCTLR_M_BIT) != 0U;
|
2017-10-04 16:52:15 +01:00
|
|
|
} else {
|
|
|
|
assert(ctx->xlat_regime == EL3_REGIME);
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
assert(xlat_arch_current_el() >= 3U);
|
2018-08-02 09:57:29 +01:00
|
|
|
return (read_sctlr_el3() & SCTLR_M_BIT) != 0U;
|
2017-10-04 16:52:15 +01:00
|
|
|
}
|
2017-03-08 14:40:23 +00:00
|
|
|
}
|
|
|
|
|
xlat v2: Flush xlat tables after being modified
During cold boot, the initial translation tables are created with data
caches disabled, so all modifications go to memory directly. After the
MMU is enabled and data cache is enabled, any modification to the tables
goes to data cache, and eventually may get flushed to memory.
If CPU0 modifies the tables while CPU1 is off, CPU0 will have the
modified tables in its data cache. When CPU1 is powered on, the MMU is
enabled, then it enables coherency, and then it enables the data cache.
Until this is done, CPU1 isn't in coherency, and the translation tables
it sees can be outdated if CPU0 still has some modified entries in its
data cache.
This can be a problem in some cases. For example, the warm boot code
uses only the tables mapped during cold boot, which don't normally
change. However, if they are modified (and a RO page is made RW, or a XN
page is made executable) the CPU will see the old attributes and crash
when it tries to access it.
This doesn't happen in systems with HW_ASSISTED_COHERENCY or
WARMBOOT_ENABLE_DCACHE_EARLY. In these systems, the data cache is
enabled at the same time as the MMU. As soon as this happens, the CPU is
in coherency.
There was an attempt of a fix in psci_helpers.S, but it didn't solve the
problem. That code has been deleted. The code was introduced in commit
<264410306381> ("Invalidate TLB entries during warm boot").
Now, during a map or unmap operation, the memory associated to each
modified table is flushed. Traversing a table will also flush it's
memory, as there is no way to tell in the current implementation if the
table that has been traversed has also been modified.
Change-Id: I4b520bca27502f1018878061bc5fb82af740bb92
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-08-07 12:47:12 +01:00
|
|
|
bool is_dcache_enabled(void)
|
|
|
|
{
|
xlat_tables_v2: use get_current_el_maybe_constant() in is_dcache_enabled()
Using get_current_el_maybe_constant() produces more optimized code
because in most cases, we know the exception level at build-time.
For example, BL31 runs at EL3, so unneeded code will be trimmed.
[before]
0000000000000000 <is_dcache_enabled>:
0: d5384240 mrs x0, currentel
4: 53020c00 ubfx w0, w0, #2, #2
8: 7100041f cmp w0, #0x1
c: 54000081 b.ne 1c <is_dcache_enabled+0x1c> // b.any
10: d5381000 mrs x0, sctlr_el1
14: 53020800 ubfx w0, w0, #2, #1
18: d65f03c0 ret
1c: 7100081f cmp w0, #0x2
20: 54000061 b.ne 2c <is_dcache_enabled+0x2c> // b.any
24: d53c1000 mrs x0, sctlr_el2
28: 17fffffb b 14 <is_dcache_enabled+0x14>
2c: d53e1000 mrs x0, sctlr_el3
30: 17fffff9 b 14 <is_dcache_enabled+0x14>
[after]
0000000000000000 <is_dcache_enabled>:
0: d53e1000 mrs x0, sctlr_el3
4: 53020800 ubfx w0, w0, #2, #1
8: d65f03c0 ret
Change-Id: I3698fae9b517022ff9fbfd4cad3a320c6e137e10
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2020-04-02 08:20:21 +01:00
|
|
|
unsigned int el = get_current_el_maybe_constant();
|
xlat v2: Flush xlat tables after being modified
During cold boot, the initial translation tables are created with data
caches disabled, so all modifications go to memory directly. After the
MMU is enabled and data cache is enabled, any modification to the tables
goes to data cache, and eventually may get flushed to memory.
If CPU0 modifies the tables while CPU1 is off, CPU0 will have the
modified tables in its data cache. When CPU1 is powered on, the MMU is
enabled, then it enables coherency, and then it enables the data cache.
Until this is done, CPU1 isn't in coherency, and the translation tables
it sees can be outdated if CPU0 still has some modified entries in its
data cache.
This can be a problem in some cases. For example, the warm boot code
uses only the tables mapped during cold boot, which don't normally
change. However, if they are modified (and a RO page is made RW, or a XN
page is made executable) the CPU will see the old attributes and crash
when it tries to access it.
This doesn't happen in systems with HW_ASSISTED_COHERENCY or
WARMBOOT_ENABLE_DCACHE_EARLY. In these systems, the data cache is
enabled at the same time as the MMU. As soon as this happens, the CPU is
in coherency.
There was an attempt of a fix in psci_helpers.S, but it didn't solve the
problem. That code has been deleted. The code was introduced in commit
<264410306381> ("Invalidate TLB entries during warm boot").
Now, during a map or unmap operation, the memory associated to each
modified table is flushed. Traversing a table will also flush it's
memory, as there is no way to tell in the current implementation if the
table that has been traversed has also been modified.
Change-Id: I4b520bca27502f1018878061bc5fb82af740bb92
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-08-07 12:47:12 +01:00
|
|
|
|
|
|
|
if (el == 1U) {
|
|
|
|
return (read_sctlr_el1() & SCTLR_C_BIT) != 0U;
|
2018-08-07 19:59:49 +01:00
|
|
|
} else if (el == 2U) {
|
|
|
|
return (read_sctlr_el2() & SCTLR_C_BIT) != 0U;
|
xlat v2: Flush xlat tables after being modified
During cold boot, the initial translation tables are created with data
caches disabled, so all modifications go to memory directly. After the
MMU is enabled and data cache is enabled, any modification to the tables
goes to data cache, and eventually may get flushed to memory.
If CPU0 modifies the tables while CPU1 is off, CPU0 will have the
modified tables in its data cache. When CPU1 is powered on, the MMU is
enabled, then it enables coherency, and then it enables the data cache.
Until this is done, CPU1 isn't in coherency, and the translation tables
it sees can be outdated if CPU0 still has some modified entries in its
data cache.
This can be a problem in some cases. For example, the warm boot code
uses only the tables mapped during cold boot, which don't normally
change. However, if they are modified (and a RO page is made RW, or a XN
page is made executable) the CPU will see the old attributes and crash
when it tries to access it.
This doesn't happen in systems with HW_ASSISTED_COHERENCY or
WARMBOOT_ENABLE_DCACHE_EARLY. In these systems, the data cache is
enabled at the same time as the MMU. As soon as this happens, the CPU is
in coherency.
There was an attempt of a fix in psci_helpers.S, but it didn't solve the
problem. That code has been deleted. The code was introduced in commit
<264410306381> ("Invalidate TLB entries during warm boot").
Now, during a map or unmap operation, the memory associated to each
modified table is flushed. Traversing a table will also flush it's
memory, as there is no way to tell in the current implementation if the
table that has been traversed has also been modified.
Change-Id: I4b520bca27502f1018878061bc5fb82af740bb92
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-08-07 12:47:12 +01:00
|
|
|
} else {
|
|
|
|
return (read_sctlr_el3() & SCTLR_C_BIT) != 0U;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-05 08:11:48 +01:00
|
|
|
uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime)
|
|
|
|
{
|
|
|
|
if (xlat_regime == EL1_EL0_REGIME) {
|
|
|
|
return UPPER_ATTRS(UXN) | UPPER_ATTRS(PXN);
|
|
|
|
} else {
|
2018-08-07 19:59:49 +01:00
|
|
|
assert((xlat_regime == EL2_REGIME) ||
|
|
|
|
(xlat_regime == EL3_REGIME));
|
2018-07-05 08:11:48 +01:00
|
|
|
return UPPER_ATTRS(XN);
|
|
|
|
}
|
|
|
|
}
|
2017-10-04 16:52:15 +01:00
|
|
|
|
2018-07-11 09:46:45 +01:00
|
|
|
void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime)
|
2017-02-27 17:23:54 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Ensure the translation table write has drained into memory before
|
|
|
|
* invalidating the TLB entry.
|
|
|
|
*/
|
|
|
|
dsbishst();
|
|
|
|
|
2017-09-25 15:23:22 +01:00
|
|
|
/*
|
|
|
|
* This function only supports invalidation of TLB entries for the EL3
|
|
|
|
* and EL1&0 translation regimes.
|
|
|
|
*
|
|
|
|
* Also, it is architecturally UNDEFINED to invalidate TLBs of a higher
|
|
|
|
* exception level (see section D4.9.2 of the ARM ARM rev B.a).
|
|
|
|
*/
|
|
|
|
if (xlat_regime == EL1_EL0_REGIME) {
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
assert(xlat_arch_current_el() >= 1U);
|
2017-09-25 15:23:22 +01:00
|
|
|
tlbivaae1is(TLBI_ADDR(va));
|
2018-08-07 19:59:49 +01:00
|
|
|
} else if (xlat_regime == EL2_REGIME) {
|
|
|
|
assert(xlat_arch_current_el() >= 2U);
|
|
|
|
tlbivae2is(TLBI_ADDR(va));
|
2017-09-25 15:23:22 +01:00
|
|
|
} else {
|
|
|
|
assert(xlat_regime == EL3_REGIME);
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
assert(xlat_arch_current_el() >= 3U);
|
2017-09-25 15:23:22 +01:00
|
|
|
tlbivae3is(TLBI_ADDR(va));
|
|
|
|
}
|
2017-02-27 17:23:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void xlat_arch_tlbi_va_sync(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* A TLB maintenance instruction can complete at any time after
|
|
|
|
* it is issued, but is only guaranteed to be complete after the
|
|
|
|
* execution of DSB by the PE that executed the TLB maintenance
|
|
|
|
* instruction. After the TLB invalidate instruction is
|
|
|
|
* complete, no new memory accesses using the invalidated TLB
|
|
|
|
* entries will be observed by any observer of the system
|
|
|
|
* domain. See section D4.8.2 of the ARMv8 (issue k), paragraph
|
|
|
|
* "Ordering and completion of TLB maintenance instructions".
|
|
|
|
*/
|
|
|
|
dsbish();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The effects of a completed TLB maintenance instruction are
|
|
|
|
* only guaranteed to be visible on the PE that executed the
|
|
|
|
* instruction after the execution of an ISB instruction by the
|
|
|
|
* PE that executed the TLB maintenance instruction.
|
|
|
|
*/
|
|
|
|
isb();
|
|
|
|
}
|
|
|
|
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
unsigned int xlat_arch_current_el(void)
|
Fix execute-never permissions in xlat tables libs
Translation regimes that only support one virtual address space (such as
the ones for EL2 and EL3) can flag memory regions as execute-never by
setting to 1 the XN bit in the Upper Attributes field in the translation
tables descriptors. Translation regimes that support two different
virtual address spaces (such as the one shared by EL1 and EL0) use bits
PXN and UXN instead.
The Trusted Firmware runs at EL3 and EL1, it has to handle translation
tables of both translation regimes, but the previous code handled both
regimes the same way, as if both had only 1 VA range.
When trying to set a descriptor as execute-never it would set the XN
bit correctly in EL3, but it would set the XN bit in EL1 as well. XN is
at the same bit position as UXN, which means that EL0 was being
prevented from executing code at this region, not EL1 as the code
intended. Therefore, the PXN bit was unset to 0 all the time. The result
is that, in AArch64 mode, read-only data sections of BL2 weren't
protected from being executed.
This patch adds support of translation regimes with two virtual address
spaces to both versions of the translation tables library, fixing the
execute-never permissions for translation tables in EL1.
The library currently does not support initializing translation tables
for EL0 software, therefore it does not set/unset the UXN bit. If EL1
software needs to initialize translation tables for EL0 software, it
should use a different library instead.
Change-Id: If27588f9820ff42988851d90dc92801c8ecbe0c9
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2017-04-27 13:30:22 +01:00
|
|
|
{
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
unsigned int el = (unsigned int)GET_EL(read_CurrentEl());
|
Fix execute-never permissions in xlat tables libs
Translation regimes that only support one virtual address space (such as
the ones for EL2 and EL3) can flag memory regions as execute-never by
setting to 1 the XN bit in the Upper Attributes field in the translation
tables descriptors. Translation regimes that support two different
virtual address spaces (such as the one shared by EL1 and EL0) use bits
PXN and UXN instead.
The Trusted Firmware runs at EL3 and EL1, it has to handle translation
tables of both translation regimes, but the previous code handled both
regimes the same way, as if both had only 1 VA range.
When trying to set a descriptor as execute-never it would set the XN
bit correctly in EL3, but it would set the XN bit in EL1 as well. XN is
at the same bit position as UXN, which means that EL0 was being
prevented from executing code at this region, not EL1 as the code
intended. Therefore, the PXN bit was unset to 0 all the time. The result
is that, in AArch64 mode, read-only data sections of BL2 weren't
protected from being executed.
This patch adds support of translation regimes with two virtual address
spaces to both versions of the translation tables library, fixing the
execute-never permissions for translation tables in EL1.
The library currently does not support initializing translation tables
for EL0 software, therefore it does not set/unset the UXN bit. If EL1
software needs to initialize translation tables for EL0 software, it
should use a different library instead.
Change-Id: If27588f9820ff42988851d90dc92801c8ecbe0c9
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2017-04-27 13:30:22 +01:00
|
|
|
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
assert(el > 0U);
|
Fix execute-never permissions in xlat tables libs
Translation regimes that only support one virtual address space (such as
the ones for EL2 and EL3) can flag memory regions as execute-never by
setting to 1 the XN bit in the Upper Attributes field in the translation
tables descriptors. Translation regimes that support two different
virtual address spaces (such as the one shared by EL1 and EL0) use bits
PXN and UXN instead.
The Trusted Firmware runs at EL3 and EL1, it has to handle translation
tables of both translation regimes, but the previous code handled both
regimes the same way, as if both had only 1 VA range.
When trying to set a descriptor as execute-never it would set the XN
bit correctly in EL3, but it would set the XN bit in EL1 as well. XN is
at the same bit position as UXN, which means that EL0 was being
prevented from executing code at this region, not EL1 as the code
intended. Therefore, the PXN bit was unset to 0 all the time. The result
is that, in AArch64 mode, read-only data sections of BL2 weren't
protected from being executed.
This patch adds support of translation regimes with two virtual address
spaces to both versions of the translation tables library, fixing the
execute-never permissions for translation tables in EL1.
The library currently does not support initializing translation tables
for EL0 software, therefore it does not set/unset the UXN bit. If EL1
software needs to initialize translation tables for EL0 software, it
should use a different library instead.
Change-Id: If27588f9820ff42988851d90dc92801c8ecbe0c9
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2017-04-27 13:30:22 +01:00
|
|
|
|
|
|
|
return el;
|
|
|
|
}
|
|
|
|
|
2018-07-15 16:42:01 +01:00
|
|
|
void setup_mmu_cfg(uint64_t *params, unsigned int flags,
|
|
|
|
const uint64_t *base_table, unsigned long long max_pa,
|
|
|
|
uintptr_t max_va, int xlat_regime)
|
2017-03-08 14:40:23 +00:00
|
|
|
{
|
2018-07-12 15:44:42 +01:00
|
|
|
uint64_t mair, ttbr0, tcr;
|
xlat v2: Split MMU setup and enable
At present, the function provided by the translation library to enable
MMU constructs appropriate values for translation library, and programs
them to the right registers. The construction of initial values,
however, is only required once as both the primary and secondaries
program the same values.
Additionally, the MMU-enabling function is written in C, which means
there's an active stack at the time of enabling MMU. On some systems,
like Arm DynamIQ, having active stack while enabling MMU during warm
boot might lead to coherency problems.
This patch addresses both the above problems by:
- Splitting the MMU-enabling function into two: one that sets up
values to be programmed into the registers, and another one that
takes the pre-computed values and writes to the appropriate
registers. With this, the primary effectively calls both functions
to have the MMU enabled, but secondaries only need to call the
latter.
- Rewriting the function that enables MMU in assembly so that it
doesn't use stack.
This patch fixes a bunch of MISRA issues on the way.
Change-Id: I0faca97263a970ffe765f0e731a1417e43fbfc45
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2018-04-27 15:06:57 +01:00
|
|
|
uintptr_t virtual_addr_space_size;
|
2017-05-31 13:38:51 +01:00
|
|
|
|
|
|
|
/* Set attributes in the right indices of the MAIR. */
|
|
|
|
mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
|
|
|
|
mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX);
|
|
|
|
mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Limit the input address ranges and memory region sizes translated
|
|
|
|
* using TTBR0 to the given virtual address space size.
|
|
|
|
*/
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
assert(max_va < ((uint64_t)UINTPTR_MAX));
|
xlat v2: Split MMU setup and enable
At present, the function provided by the translation library to enable
MMU constructs appropriate values for translation library, and programs
them to the right registers. The construction of initial values,
however, is only required once as both the primary and secondaries
program the same values.
Additionally, the MMU-enabling function is written in C, which means
there's an active stack at the time of enabling MMU. On some systems,
like Arm DynamIQ, having active stack while enabling MMU during warm
boot might lead to coherency problems.
This patch addresses both the above problems by:
- Splitting the MMU-enabling function into two: one that sets up
values to be programmed into the registers, and another one that
takes the pre-computed values and writes to the appropriate
registers. With this, the primary effectively calls both functions
to have the MMU enabled, but secondaries only need to call the
latter.
- Rewriting the function that enables MMU in assembly so that it
doesn't use stack.
This patch fixes a bunch of MISRA issues on the way.
Change-Id: I0faca97263a970ffe765f0e731a1417e43fbfc45
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2018-04-27 15:06:57 +01:00
|
|
|
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
virtual_addr_space_size = (uintptr_t)max_va + 1U;
|
2019-01-25 11:36:01 +00:00
|
|
|
|
|
|
|
assert(virtual_addr_space_size >=
|
|
|
|
xlat_get_min_virt_addr_space_size());
|
|
|
|
assert(virtual_addr_space_size <= MAX_VIRT_ADDR_SPACE_SIZE);
|
|
|
|
assert(IS_POWER_OF_TWO(virtual_addr_space_size));
|
xlat v2: Split MMU setup and enable
At present, the function provided by the translation library to enable
MMU constructs appropriate values for translation library, and programs
them to the right registers. The construction of initial values,
however, is only required once as both the primary and secondaries
program the same values.
Additionally, the MMU-enabling function is written in C, which means
there's an active stack at the time of enabling MMU. On some systems,
like Arm DynamIQ, having active stack while enabling MMU during warm
boot might lead to coherency problems.
This patch addresses both the above problems by:
- Splitting the MMU-enabling function into two: one that sets up
values to be programmed into the registers, and another one that
takes the pre-computed values and writes to the appropriate
registers. With this, the primary effectively calls both functions
to have the MMU enabled, but secondaries only need to call the
latter.
- Rewriting the function that enables MMU in assembly so that it
doesn't use stack.
This patch fixes a bunch of MISRA issues on the way.
Change-Id: I0faca97263a970ffe765f0e731a1417e43fbfc45
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2018-04-27 15:06:57 +01:00
|
|
|
|
2017-07-11 15:11:10 +01:00
|
|
|
/*
|
2017-07-19 10:11:13 +01:00
|
|
|
* __builtin_ctzll(0) is undefined but here we are guaranteed that
|
2017-07-11 15:11:10 +01:00
|
|
|
* virtual_addr_space_size is in the range [1,UINTPTR_MAX].
|
|
|
|
*/
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
int t0sz = 64 - __builtin_ctzll(virtual_addr_space_size);
|
|
|
|
|
2019-03-27 11:10:31 +00:00
|
|
|
tcr = (uint64_t)t0sz << TCR_T0SZ_SHIFT;
|
2017-05-31 13:38:51 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the cacheability and shareability attributes for memory
|
|
|
|
* associated with translation table walks.
|
|
|
|
*/
|
xlat: Fix MISRA defects
Fix defects of MISRA C-2012 rules 8.13, 10.1, 10.3, 10.4, 10.8, 11.6,
14.4, 15.7, 17.8, 20.10, 20.12, 21.1 and Directive 4.9.
Change-Id: I7ff61e71733908596dbafe2e99d99b4fce9765bd
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2018-07-24 10:20:53 +01:00
|
|
|
if ((flags & XLAT_TABLE_NC) != 0U) {
|
2017-05-31 13:38:51 +01:00
|
|
|
/* Inner & outer non-cacheable non-shareable. */
|
|
|
|
tcr |= TCR_SH_NON_SHAREABLE |
|
|
|
|
TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC;
|
|
|
|
} else {
|
|
|
|
/* Inner & outer WBWA & shareable. */
|
|
|
|
tcr |= TCR_SH_INNER_SHAREABLE |
|
|
|
|
TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA;
|
|
|
|
}
|
|
|
|
|
2017-05-31 13:31:48 +01:00
|
|
|
/*
|
|
|
|
* It is safer to restrict the max physical address accessible by the
|
|
|
|
* hardware as much as possible.
|
|
|
|
*/
|
2017-10-25 11:53:25 +01:00
|
|
|
unsigned long long tcr_ps_bits = tcr_physical_addr_size_bits(max_pa);
|
2017-05-31 13:31:48 +01:00
|
|
|
|
2018-07-12 15:43:07 +01:00
|
|
|
if (xlat_regime == EL1_EL0_REGIME) {
|
|
|
|
/*
|
|
|
|
* TCR_EL1.EPD1: Disable translation table walk for addresses
|
|
|
|
* that are translated using TTBR1_EL1.
|
|
|
|
*/
|
|
|
|
tcr |= TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT);
|
2018-08-07 19:59:49 +01:00
|
|
|
} else if (xlat_regime == EL2_REGIME) {
|
|
|
|
tcr |= TCR_EL2_RES1 | (tcr_ps_bits << TCR_EL2_PS_SHIFT);
|
2018-07-12 15:43:07 +01:00
|
|
|
} else {
|
|
|
|
assert(xlat_regime == EL3_REGIME);
|
|
|
|
tcr |= TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT);
|
|
|
|
}
|
xlat v2: Split MMU setup and enable
At present, the function provided by the translation library to enable
MMU constructs appropriate values for translation library, and programs
them to the right registers. The construction of initial values,
however, is only required once as both the primary and secondaries
program the same values.
Additionally, the MMU-enabling function is written in C, which means
there's an active stack at the time of enabling MMU. On some systems,
like Arm DynamIQ, having active stack while enabling MMU during warm
boot might lead to coherency problems.
This patch addresses both the above problems by:
- Splitting the MMU-enabling function into two: one that sets up
values to be programmed into the registers, and another one that
takes the pre-computed values and writes to the appropriate
registers. With this, the primary effectively calls both functions
to have the MMU enabled, but secondaries only need to call the
latter.
- Rewriting the function that enables MMU in assembly so that it
doesn't use stack.
This patch fixes a bunch of MISRA issues on the way.
Change-Id: I0faca97263a970ffe765f0e731a1417e43fbfc45
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2018-04-27 15:06:57 +01:00
|
|
|
|
|
|
|
/* Set TTBR bits as well */
|
2018-07-12 15:44:42 +01:00
|
|
|
ttbr0 = (uint64_t) base_table;
|
|
|
|
|
2019-01-11 11:20:10 +00:00
|
|
|
if (is_armv8_2_ttcnp_present()) {
|
|
|
|
/* Enable CnP bit so as to share page tables with all PEs. */
|
|
|
|
ttbr0 |= TTBR_CNP_BIT;
|
|
|
|
}
|
xlat v2: Split MMU setup and enable
At present, the function provided by the translation library to enable
MMU constructs appropriate values for translation library, and programs
them to the right registers. The construction of initial values,
however, is only required once as both the primary and secondaries
program the same values.
Additionally, the MMU-enabling function is written in C, which means
there's an active stack at the time of enabling MMU. On some systems,
like Arm DynamIQ, having active stack while enabling MMU during warm
boot might lead to coherency problems.
This patch addresses both the above problems by:
- Splitting the MMU-enabling function into two: one that sets up
values to be programmed into the registers, and another one that
takes the pre-computed values and writes to the appropriate
registers. With this, the primary effectively calls both functions
to have the MMU enabled, but secondaries only need to call the
latter.
- Rewriting the function that enables MMU in assembly so that it
doesn't use stack.
This patch fixes a bunch of MISRA issues on the way.
Change-Id: I0faca97263a970ffe765f0e731a1417e43fbfc45
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2018-04-27 15:06:57 +01:00
|
|
|
|
2018-07-15 16:42:01 +01:00
|
|
|
params[MMU_CFG_MAIR] = mair;
|
|
|
|
params[MMU_CFG_TCR] = tcr;
|
|
|
|
params[MMU_CFG_TTBR0] = ttbr0;
|
2017-03-08 14:40:23 +00:00
|
|
|
}
|