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 <stddef.h>
#include <tzc400.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); 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); 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); 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); 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) 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; 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 * We expect to see a tzc400. Check component ID. The TZC-400 TRM shows
* component ID is expected to be "0xB105F00D". * 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) { if (tzc_id != TZC400_COMPONENT_ID) {
ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id); ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
panic(); panic();
} }
/* Save values we will use later. */ /* Save values we will use later. */
tzc_build = tzc_read_build_config(controller->base); tzc_build = tzc_read_build_config(tzc.base);
controller->num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) & tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
BUILD_CONFIG_NF_MASK) + 1; 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; 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; 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 * this cannot be changed. It is, however, possible to change some region 0
* permissions. * permissions.
*/ */
void tzc_configure_region(const tzc_instance_t *controller, void tzc_configure_region(uint32_t filters,
uint32_t filters,
uint8_t region, uint8_t region,
uint64_t region_base, uint64_t region_base,
uint64_t region_top, uint64_t region_top,
tzc_region_attributes_t sec_attr, tzc_region_attributes_t sec_attr,
uint32_t ns_device_access) uint32_t ns_device_access)
{ {
uint64_t max_addr; assert(tzc.base);
assert(controller != NULL);
/* Do range checks on filters and regions. */ /* Do range checks on filters and regions. */
assert(((filters >> controller->num_filters) == 0) && assert(((filters >> tzc.num_filters) == 0) &&
(region < controller->num_regions)); (region < tzc.num_regions));
/* /*
* Do address range check based on TZC configuration. A 64bit address is * Do address range check based on TZC configuration. A 64bit address is
* the max and expected case. * the max and expected case.
*/ */
max_addr = UINT64_MAX >> (64 - controller->addr_width); assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
if ((region_top > max_addr) || (region_base >= region_top)) (region_base < region_top)));
assert(0);
/* region_base and (region_top + 1) must be 4KB aligned */ /* region_base and (region_top + 1) must be 4KB aligned */
assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0); 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 * All the address registers are 32 bits wide and have a LOW and HIGH
* component used to construct a up to a 64bit address. * 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_low(tzc.base, region,
tzc_write_region_base_high(controller->base, region, (uint32_t)(region_base >> 32)); (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_low(tzc.base, region,
tzc_write_region_top_high(controller->base, region, (uint32_t)(region_top >> 32)); (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 */ /* 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); (sec_attr << REGION_ATTRIBUTES_SEC_SHIFT) | filters);
/* /*
* Specify which non-secure devices have permission to access this * Specify which non-secure devices have permission to access this
* region. * 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 * - Currently no handler is provided to trap an error via interrupt
* or exception. * or exception.
* - The interrupt action has not been tested. * - 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 state;
uint32_t filter; uint32_t filter;
assert(controller != NULL); assert(tzc.base);
for (filter = 0; filter < controller->num_filters; filter++) { for (filter = 0; filter < tzc.num_filters; filter++) {
state = tzc_get_gate_keeper(controller->base, filter); state = tzc_get_gate_keeper(tzc.base, filter);
if (state) { if (state) {
/* The TZC filter is already configured. Changing the /* The TZC filter is already configured. Changing the
* programmer's view in an active system can cause * programmer's view in an active system can cause
@ -252,21 +287,21 @@ void tzc_enable_filters(const tzc_instance_t *controller)
filter); filter);
panic(); 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; uint32_t filter;
assert(controller != NULL); assert(tzc.base);
/* /*
* We don't do the same state check as above as the Gatekeepers are * We don't do the same state check as above as the Gatekeepers are
* disabled after reset. * disabled after reset.
*/ */
for (filter = 0; filter < controller->num_filters; filter++) for (filter = 0; filter < tzc.num_filters; filter++)
tzc_set_gate_keeper(controller->base, filter, 0); 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_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
} tzc_region_attributes_t; } 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_init(uint64_t base);
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, uint8_t region,
tzc_region_attributes_t sec_attr, uint32_t ns_device_access); uint64_t region_base,
void tzc_enable_filters(const tzc_instance_t *controller); uint64_t region_top,
void tzc_disable_filters(const tzc_instance_t *controller); tzc_region_attributes_t sec_attr,
void tzc_set_action(const tzc_instance_t *controller, tzc_action_t action); 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__ */ #endif /* __TZC400__ */

View File

@ -239,9 +239,6 @@
* The NSAIDs for this platform as used to program the TZC400. * 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 */ /* NSAIDs used by devices in TZC filter 0 on FVP */
#define FVP_NSAID_DEFAULT 0 #define FVP_NSAID_DEFAULT 0
#define FVP_NSAID_PCI 1 #define FVP_NSAID_PCI 1

View File

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