Tegra: smmu: add smmu_verify function
The SMMU configuration can get corrupted or updated by external clients during boot without our knowledge. This patch introduces a "verify" function for the SMMU driver, to check that the boot configuration settings are intact. Usually, this function should be called at the end of the boot cycle. This function only calls panic() on silicon platforms. Change-Id: I2ab45a7f228781e71c73ba1f4ffc49353effe146 Signed-off-by: George Bauernschmidt <georgeb@nvidia.com>
This commit is contained in:
parent
13fed5a7b4
commit
21ec61a904
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <memctrl.h>
|
||||
#include <profiler.h>
|
||||
#include <smmu.h>
|
||||
#include <tegra_def.h>
|
||||
#include <tegra_platform.h>
|
||||
#include <tegra_private.h>
|
||||
|
@ -272,6 +273,13 @@ void bl31_plat_runtime_setup(void)
|
|||
*/
|
||||
tegra_memctrl_disable_ahb_redirection();
|
||||
|
||||
#if defined(TEGRA_SMMU0_BASE)
|
||||
/*
|
||||
* Verify the integrity of the previously configured SMMU(s) settings
|
||||
*/
|
||||
tegra_smmu_verify();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add final timestamp before exiting BL31.
|
||||
*/
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <common/debug.h>
|
||||
|
||||
#include <smmu.h>
|
||||
#include <tegra_platform.h>
|
||||
#include <tegra_private.h>
|
||||
|
||||
extern void memcpy16(void *dest, const void *src, unsigned int length);
|
||||
|
@ -21,15 +22,17 @@ extern void memcpy16(void *dest, const void *src, unsigned int length);
|
|||
#define SMMU_NUM_CONTEXTS 64U
|
||||
#define SMMU_CONTEXT_BANK_MAX_IDX 64U
|
||||
|
||||
#define MISMATCH_DETECTED 0x55AA55AAU
|
||||
|
||||
/*
|
||||
* Init SMMU during boot or "System Suspend" exit
|
||||
*/
|
||||
void tegra_smmu_init(void)
|
||||
{
|
||||
uint32_t val, cb_idx, smmu_id, ctx_base;
|
||||
uint32_t smmu_counter = plat_get_num_smmu_devices();
|
||||
uint32_t num_smmu_devices = plat_get_num_smmu_devices();
|
||||
|
||||
for (smmu_id = 0U; smmu_id < smmu_counter; smmu_id++) {
|
||||
for (smmu_id = 0U; smmu_id < num_smmu_devices; smmu_id++) {
|
||||
/* Program the SMMU pagesize and reset CACHE_LOCK bit */
|
||||
val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
|
||||
val |= SMMU_GSR0_PGSIZE_64K;
|
||||
|
@ -44,7 +47,7 @@ void tegra_smmu_init(void)
|
|||
/* disable TCU prefetch for all contexts */
|
||||
ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS)
|
||||
+ SMMU_CBn_ACTLR;
|
||||
for (cb_idx = 0; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) {
|
||||
for (cb_idx = 0U; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) {
|
||||
val = tegra_smmu_read_32(smmu_id,
|
||||
ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx));
|
||||
val &= (uint32_t)~SMMU_CBn_ACTLR_CPRE_BIT;
|
||||
|
@ -63,3 +66,56 @@ void tegra_smmu_init(void)
|
|||
tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify SMMU settings have not been altered during boot
|
||||
*/
|
||||
void tegra_smmu_verify(void)
|
||||
{
|
||||
uint32_t cb_idx, ctx_base, smmu_id, val;
|
||||
uint32_t num_smmu_devices = plat_get_num_smmu_devices();
|
||||
uint32_t mismatch = 0U;
|
||||
|
||||
for (smmu_id = 0U; smmu_id < num_smmu_devices; smmu_id++) {
|
||||
/* check PGSIZE_64K bit inr S Aux. Config. Register */
|
||||
val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
|
||||
if (0U == (val & SMMU_GSR0_PGSIZE_64K)) {
|
||||
ERROR("%s: PGSIZE_64K Mismatch - smmu_id=%d, GSR0_SECURE_ACR=%x\n",
|
||||
__func__, smmu_id, val);
|
||||
mismatch = MISMATCH_DETECTED;
|
||||
}
|
||||
|
||||
/* check CACHE LOCK bit in S Aux. Config. Register */
|
||||
if (0U == (val & SMMU_ACR_CACHE_LOCK_ENABLE_BIT)) {
|
||||
ERROR("%s: CACHE_LOCK Mismatch - smmu_id=%d, GSR0_SECURE_ACR=%x\n",
|
||||
__func__, smmu_id, val);
|
||||
mismatch = MISMATCH_DETECTED;
|
||||
}
|
||||
|
||||
/* check CACHE LOCK bit in NS Aux. Config. Register */
|
||||
val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
|
||||
if (0U == (val & SMMU_ACR_CACHE_LOCK_ENABLE_BIT)) {
|
||||
ERROR("%s: Mismatch - smmu_id=%d, GNSR_ACR=%x\n",
|
||||
__func__, smmu_id, val);
|
||||
mismatch = MISMATCH_DETECTED;
|
||||
}
|
||||
|
||||
/* verify TCU prefetch for all contexts is disabled */
|
||||
ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS) +
|
||||
SMMU_CBn_ACTLR;
|
||||
for (cb_idx = 0U; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) {
|
||||
val = tegra_smmu_read_32(smmu_id,
|
||||
ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx));
|
||||
if (0U != (val & SMMU_CBn_ACTLR_CPRE_BIT)) {
|
||||
ERROR("%s: Mismatch - smmu_id=%d, cb_idx=%d, GSR0_PGSIZE_64K=%x\n",
|
||||
__func__, smmu_id, cb_idx, val);
|
||||
mismatch = MISMATCH_DETECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Treat configuration mismatch as fatal */
|
||||
if ((mismatch == MISMATCH_DETECTED) && tegra_platform_is_silicon()) {
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,6 +144,7 @@ static inline void tegra_mc_write_32(uint32_t off, uint32_t val)
|
|||
mmio_write_32(TEGRA_MC_BASE + off, val);
|
||||
}
|
||||
|
||||
#if defined(TEGRA_MC_STREAMID_BASE)
|
||||
static inline uint32_t tegra_mc_streamid_read_32(uint32_t off)
|
||||
{
|
||||
return mmio_read_32(TEGRA_MC_STREAMID_BASE + off);
|
||||
|
@ -153,6 +154,7 @@ static inline void tegra_mc_streamid_write_32(uint32_t off, uint32_t val)
|
|||
{
|
||||
mmio_write_32(TEGRA_MC_STREAMID_BASE + off, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define mc_set_pcfifo_unordered_boot_so_mss(id, client) \
|
||||
((uint32_t)~MC_PCFIFO_CLIENT_CONFIG##id##_PCFIFO_##client##_MASK | \
|
||||
|
|
|
@ -86,6 +86,7 @@ static inline void tegra_smmu_write_32(uint32_t smmu_id,
|
|||
}
|
||||
|
||||
void tegra_smmu_init(void);
|
||||
void tegra_smmu_verify(void);
|
||||
uint32_t plat_get_num_smmu_devices(void);
|
||||
|
||||
#endif /* SMMU_H */
|
||||
|
|
Loading…
Reference in New Issue