fix(gpt_rme): add necessary barriers and remove cache clean

This patch adds necessary barriers after GPT entries are modified
so that the writes are observed correctly by the GPC hardware.
The shareability of GPC fetches are changed from OSH to ISH so
that they align with the shareability of MMU attributes for the
region. Thus by adding a dsbishst() between the GPT L1 entry
write as part of granule migration at runtime, we can now remove
the clean cache maintenance operation (CMO) for that region.

Signed-off-by: Soby Mathew <soby.mathew@arm.com>
Signed-off-by: Robert Wakim <robert.wakim@arm.com>
Change-Id: Ib9e405b106f0db95c7fbdb26773c0ed41663a5b4
This commit is contained in:
Soby Mathew 2021-10-11 14:38:46 +01:00
parent 55eeb7b08f
commit 77612b90ac
1 changed files with 22 additions and 11 deletions

View File

@ -708,8 +708,12 @@ int gpt_enable(void)
/* GPCCR_EL3.PGS */
gpccr_el3 |= SET_GPCCR_PGS(gpt_config.pgs);
/* Set shareability attribute to Outher Shareable */
gpccr_el3 |= SET_GPCCR_SH(GPCCR_SH_OS);
/*
* Since EL3 maps the L1 region as Inner shareable, use the same
* shareability attribute for GPC as well so that
* GPC fetches are visible to PEs
*/
gpccr_el3 |= SET_GPCCR_SH(GPCCR_SH_IS);
/* Outer and Inner cacheability set to Normal memory, WB, RA, WA. */
gpccr_el3 |= SET_GPCCR_ORGN(GPCCR_ORGN_WB_RA_WA);
@ -720,6 +724,7 @@ int gpt_enable(void)
/* TODO: Configure GPCCR_EL3_GPCP for Fault control. */
write_gpccr_el3(gpccr_el3);
isb();
tlbipaallos();
dsb();
isb();
@ -759,7 +764,7 @@ int gpt_init_l0_tables(unsigned int pps, uintptr_t l0_mem_base,
int ret;
uint64_t gpt_desc;
/* Ensure that MMU and caches are enabled. */
/* Ensure that MMU and Data caches are enabled. */
assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
/* Validate other parameters. */
@ -814,7 +819,7 @@ int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, uintptr_t l1_mem_base,
int ret;
int l1_gpt_cnt;
/* Ensure that MMU and caches are enabled. */
/* Ensure that MMU and Data caches are enabled. */
assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
/* PGS is needed for gpt_validate_pas_mappings so check it now. */
@ -888,6 +893,9 @@ int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, uintptr_t l1_mem_base,
/* Make sure that all the entries are written to the memory. */
dsbishst();
tlbipaallos();
dsb();
isb();
return 0;
}
@ -907,7 +915,7 @@ int gpt_runtime_init(void)
{
u_register_t reg;
/* Ensure that MMU and caches are enabled. */
/* Ensure that MMU and Data caches are enabled. */
assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
/* Ensure GPC are already enabled. */
@ -1028,6 +1036,9 @@ int gpt_transition_pas(uint64_t base, size_t size, unsigned int src_sec_state,
/* Ensure that the tables have been set up before taking requests. */
assert(gpt_config.plat_gpt_l0_base != 0U);
/* Ensure that MMU and data caches are enabled. */
assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
/* Check for address range overflow. */
if ((ULONG_MAX - base) < size) {
VERBOSE("[GPT] Transition request address overflow!\n");
@ -1093,18 +1104,18 @@ int gpt_transition_pas(uint64_t base, size_t size, unsigned int src_sec_state,
gpt_l1_desc |= ((uint64_t)target_pas << gpi_shift);
gpt_l1_addr[idx] = gpt_l1_desc;
/* Ensure that the write operation happens before the unlock. */
dmbishst();
/* Ensure that the write operation will be observed by GPC */
dsbishst();
/* Unlock access to the L1 tables. */
spin_unlock(&gpt_lock);
/* Cache maintenance. */
clean_dcache_range((uintptr_t)&gpt_l1_addr[idx],
sizeof(uint64_t));
gpt_tlbi_by_pa(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p));
dsbishst();
/*
* The isb() will be done as part of context
* synchronization when returning to lower EL
*/
VERBOSE("[GPT] Granule 0x%llx, GPI 0x%x->0x%x\n", base, gpi,
target_pas);