Simplify interface to TZC-400 driver

The TZC-400 driver previously allowed the possibility of multiple
controller instances to be present in the same executable. This
was unnecessary since there will only ever be one instance.

This change simplifies the tzc_init() function to only take the
base address argument needed by implementation, conforming to the
driver initialization model of other drivers. It also hides some
of the implementation details that were previously exposed by the
API.

The FVP port has been updated accordingly.

THIS CHANGE REQUIRES ALL PLATFORM PORTS THAT USE THE TZC-400
DRIVER TO BE UPDATED

Fixes ARM-software/tf-issues#181

Change-Id: I7b721edf947064989958d8f457d6462d92e742c8
This commit is contained in:
Dan Handley 2014-08-04 19:53:05 +01:00
parent 935db69328
commit 3279f6251e
4 changed files with 103 additions and 85 deletions

View File

@ -34,54 +34,88 @@
#include <stddef.h>
#include <tzc400.h>
static uint32_t tzc_read_build_config(uint64_t base)
/*
* Implementation defined values used to validate inputs later.
* Filters : max of 4 ; 0 to 3
* Regions : max of 9 ; 0 to 8
* Address width : Values between 32 to 64
*/
typedef struct tzc_instance {
uint64_t base;
uint8_t addr_width;
uint8_t num_filters;
uint8_t num_regions;
} tzc_instance_t;
tzc_instance_t tzc;
static inline uint32_t tzc_read_build_config(uint64_t base)
{
return mmio_read_32(base + BUILD_CONFIG_OFF);
}
static uint32_t tzc_read_gate_keeper(uint64_t base)
static inline uint32_t tzc_read_gate_keeper(uint64_t base)
{
return mmio_read_32(base + GATE_KEEPER_OFF);
}
static void tzc_write_gate_keeper(uint64_t base, uint32_t val)
static inline void tzc_write_gate_keeper(uint64_t base, uint32_t val)
{
mmio_write_32(base + GATE_KEEPER_OFF, val);
}
static void tzc_write_action(uint64_t base, tzc_action_t action)
static inline void tzc_write_action(uint64_t base, tzc_action_t action)
{
mmio_write_32(base + ACTION_OFF, action);
}
static void tzc_write_region_base_low(uint64_t base, uint32_t region, uint32_t val)
static inline void tzc_write_region_base_low(uint64_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region), val);
mmio_write_32(base + REGION_BASE_LOW_OFF +
REGION_NUM_OFF(region), val);
}
static void tzc_write_region_base_high(uint64_t base, uint32_t region, uint32_t val)
static inline void tzc_write_region_base_high(uint64_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region), val);
mmio_write_32(base + REGION_BASE_HIGH_OFF +
REGION_NUM_OFF(region), val);
}
static void tzc_write_region_top_low(uint64_t base, uint32_t region, uint32_t val)
static inline void tzc_write_region_top_low(uint64_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region), val);
mmio_write_32(base + REGION_TOP_LOW_OFF +
REGION_NUM_OFF(region), val);
}
static void tzc_write_region_top_high(uint64_t base, uint32_t region, uint32_t val)
static inline void tzc_write_region_top_high(uint64_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_TOP_HIGH_OFF + REGION_NUM_OFF(region), val);
mmio_write_32(base + REGION_TOP_HIGH_OFF +
REGION_NUM_OFF(region), val);
}
static void tzc_write_region_attributes(uint64_t base, uint32_t region, uint32_t val)
static inline void tzc_write_region_attributes(uint64_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region), val);
mmio_write_32(base + REGION_ATTRIBUTES_OFF +
REGION_NUM_OFF(region), val);
}
static void tzc_write_region_id_access(uint64_t base, uint32_t region, uint32_t val)
static inline void tzc_write_region_id_access(uint64_t base,
uint32_t region,
uint32_t val)
{
mmio_write_32(base + REGION_ID_ACCESS_OFF + REGION_NUM_OFF(region), val);
mmio_write_32(base + REGION_ID_ACCESS_OFF +
REGION_NUM_OFF(region), val);
}
static uint32_t tzc_read_component_id(uint64_t base)
@ -130,29 +164,30 @@ static void tzc_set_gate_keeper(uint64_t base, uint8_t filter, uint32_t val)
}
void tzc_init(tzc_instance_t *controller)
void tzc_init(uint64_t base)
{
uint32_t tzc_id, tzc_build;
assert(controller != NULL);
assert(base);
tzc.base = base;
/*
* We expect to see a tzc400. Check component ID. The TZC-400 TRM shows
* component ID is expected to be "0xB105F00D".
*/
tzc_id = tzc_read_component_id(controller->base);
tzc_id = tzc_read_component_id(tzc.base);
if (tzc_id != TZC400_COMPONENT_ID) {
ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
panic();
}
/* Save values we will use later. */
tzc_build = tzc_read_build_config(controller->base);
controller->num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
tzc_build = tzc_read_build_config(tzc.base);
tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
BUILD_CONFIG_NF_MASK) + 1;
controller->addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
BUILD_CONFIG_AW_MASK) + 1;
controller->num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
BUILD_CONFIG_NR_MASK) + 1;
}
@ -166,29 +201,25 @@ void tzc_init(tzc_instance_t *controller)
* this cannot be changed. It is, however, possible to change some region 0
* permissions.
*/
void tzc_configure_region(const tzc_instance_t *controller,
uint32_t filters,
void tzc_configure_region(uint32_t filters,
uint8_t region,
uint64_t region_base,
uint64_t region_top,
tzc_region_attributes_t sec_attr,
uint32_t ns_device_access)
{
uint64_t max_addr;
assert(controller != NULL);
assert(tzc.base);
/* Do range checks on filters and regions. */
assert(((filters >> controller->num_filters) == 0) &&
(region < controller->num_regions));
assert(((filters >> tzc.num_filters) == 0) &&
(region < tzc.num_regions));
/*
* Do address range check based on TZC configuration. A 64bit address is
* the max and expected case.
*/
max_addr = UINT64_MAX >> (64 - controller->addr_width);
if ((region_top > max_addr) || (region_base >= region_top))
assert(0);
assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
(region_base < region_top)));
/* region_base and (region_top + 1) must be 4KB aligned */
assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
@ -200,46 +231,50 @@ void tzc_configure_region(const tzc_instance_t *controller,
* All the address registers are 32 bits wide and have a LOW and HIGH
* component used to construct a up to a 64bit address.
*/
tzc_write_region_base_low(controller->base, region, (uint32_t)(region_base));
tzc_write_region_base_high(controller->base, region, (uint32_t)(region_base >> 32));
tzc_write_region_base_low(tzc.base, region,
(uint32_t)(region_base));
tzc_write_region_base_high(tzc.base, region,
(uint32_t)(region_base >> 32));
tzc_write_region_top_low(controller->base, region, (uint32_t)(region_top));
tzc_write_region_top_high(controller->base, region, (uint32_t)(region_top >> 32));
tzc_write_region_top_low(tzc.base, region,
(uint32_t)(region_top));
tzc_write_region_top_high(tzc.base, region,
(uint32_t)(region_top >> 32));
/* Assign the region to a filter and set secure attributes */
tzc_write_region_attributes(controller->base, region,
tzc_write_region_attributes(tzc.base, region,
(sec_attr << REGION_ATTRIBUTES_SEC_SHIFT) | filters);
/*
* Specify which non-secure devices have permission to access this
* region.
*/
tzc_write_region_id_access(controller->base, region, ns_device_access);
tzc_write_region_id_access(tzc.base, region, ns_device_access);
}
void tzc_set_action(const tzc_instance_t *controller, tzc_action_t action)
void tzc_set_action(tzc_action_t action)
{
assert(controller != NULL);
assert(tzc.base);
/*
* - Currently no handler is provided to trap an error via interrupt
* or exception.
* - The interrupt action has not been tested.
*/
tzc_write_action(controller->base, action);
tzc_write_action(tzc.base, action);
}
void tzc_enable_filters(const tzc_instance_t *controller)
void tzc_enable_filters(void)
{
uint32_t state;
uint32_t filter;
assert(controller != NULL);
assert(tzc.base);
for (filter = 0; filter < controller->num_filters; filter++) {
state = tzc_get_gate_keeper(controller->base, filter);
for (filter = 0; filter < tzc.num_filters; filter++) {
state = tzc_get_gate_keeper(tzc.base, filter);
if (state) {
/* The TZC filter is already configured. Changing the
* programmer's view in an active system can cause
@ -252,21 +287,21 @@ void tzc_enable_filters(const tzc_instance_t *controller)
filter);
panic();
}
tzc_set_gate_keeper(controller->base, filter, 1);
tzc_set_gate_keeper(tzc.base, filter, 1);
}
}
void tzc_disable_filters(const tzc_instance_t *controller)
void tzc_disable_filters(void)
{
uint32_t filter;
assert(controller != NULL);
assert(tzc.base);
/*
* We don't do the same state check as above as the Gatekeepers are
* disabled after reset.
*/
for (filter = 0; filter < controller->num_filters; filter++)
tzc_set_gate_keeper(controller->base, filter, 0);
for (filter = 0; filter < tzc.num_filters; filter++)
tzc_set_gate_keeper(tzc.base, filter, 0);
}

View File

@ -182,27 +182,17 @@ typedef enum {
TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
} tzc_region_attributes_t;
/*
* Implementation defined values used to validate inputs later.
* Filters : max of 4 ; 0 to 3
* Regions : max of 9 ; 0 to 8
* Address width : Values between 32 to 64
*/
typedef struct tzc_instance {
uint64_t base;
uint32_t aid_width;
uint8_t addr_width;
uint8_t num_filters;
uint8_t num_regions;
} tzc_instance_t ;
void tzc_init(tzc_instance_t *controller);
void tzc_configure_region(const tzc_instance_t *controller, uint32_t filters,
uint8_t region, uint64_t region_base, uint64_t region_top,
tzc_region_attributes_t sec_attr, uint32_t ns_device_access);
void tzc_enable_filters(const tzc_instance_t *controller);
void tzc_disable_filters(const tzc_instance_t *controller);
void tzc_set_action(const tzc_instance_t *controller, tzc_action_t action);
void tzc_init(uint64_t base);
void tzc_configure_region(uint32_t filters,
uint8_t region,
uint64_t region_base,
uint64_t region_top,
tzc_region_attributes_t sec_attr,
uint32_t ns_device_access);
void tzc_enable_filters(void);
void tzc_disable_filters(void);
void tzc_set_action(tzc_action_t action);
#endif /* __TZC400__ */

View File

@ -239,9 +239,6 @@
* The NSAIDs for this platform as used to program the TZC400.
*/
/* The FVP has 4 bits of NSAIDs. Used with TZC FAIL_ID (ACE Lite ID width) */
#define FVP_AID_WIDTH 4
/* NSAIDs used by devices in TZC filter 0 on FVP */
#define FVP_NSAID_DEFAULT 0
#define FVP_NSAID_PCI 1

View File

@ -46,8 +46,6 @@
*/
void fvp_security_setup(void)
{
tzc_instance_t controller;
/*
* The Base FVP has a TrustZone address space controller, the Foundation
* FVP does not. Trying to program the device on the foundation FVP will
@ -71,9 +69,7 @@ void fvp_security_setup(void)
* - Provide base address of device on platform.
* - Provide width of ACE-Lite IDs on platform.
*/
controller.base = TZC400_BASE;
controller.aid_width = FVP_AID_WIDTH;
tzc_init(&controller);
tzc_init(TZC400_BASE);
/*
* Currently only filters 0 and 2 are connected on Base FVP.
@ -87,7 +83,7 @@ void fvp_security_setup(void)
*/
/* Disable all filters before programming. */
tzc_disable_filters(&controller);
tzc_disable_filters();
/*
* Allow only non-secure access to all DRAM to supported devices.
@ -101,7 +97,7 @@ void fvp_security_setup(void)
*/
/* Set to cover the first block of DRAM */
tzc_configure_region(&controller, FILTER_SHIFT(0), 1,
tzc_configure_region(FILTER_SHIFT(0), 1,
DRAM1_BASE, DRAM1_END - DRAM1_SEC_SIZE,
TZC_REGION_S_NONE,
TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) |
@ -111,13 +107,13 @@ void fvp_security_setup(void)
TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD));
/* Set to cover the secure reserved region */
tzc_configure_region(&controller, FILTER_SHIFT(0), 3,
tzc_configure_region(FILTER_SHIFT(0), 3,
(DRAM1_END - DRAM1_SEC_SIZE) + 1 , DRAM1_END,
TZC_REGION_S_RDWR,
0x0);
/* Set to cover the second block of DRAM */
tzc_configure_region(&controller, FILTER_SHIFT(0), 2,
tzc_configure_region(FILTER_SHIFT(0), 2,
DRAM2_BASE, DRAM2_END, TZC_REGION_S_NONE,
TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) |
TZC_REGION_ACCESS_RDWR(FVP_NSAID_PCI) |
@ -130,8 +126,8 @@ void fvp_security_setup(void)
* options we have are for access errors to occur quietly or to
* cause an exception. We choose to cause an exception.
*/
tzc_set_action(&controller, TZC_ACTION_ERR);
tzc_set_action(TZC_ACTION_ERR);
/* Enable filters. */
tzc_enable_filters(&controller);
tzc_enable_filters();
}