Platform: Move isolation hw code to SPM hal

Moves code related to hardware specific aspects of MPU, PPC, MPC and SAU
to SPM hal. Leaves the code parts that use cmse defined interface to
access these peripherals in secure_sw folder.

Change-Id: I594847686cac51ee0f9fae217152b6e90723bb9e
Signed-off-by: Mate Toth-Pal <mate.toth-pal@arm.com>
diff --git a/platform/ext/Mps2AN519.cmake b/platform/ext/Mps2AN519.cmake
index 74cbb9a..a890294 100755
--- a/platform/ext/Mps2AN519.cmake
+++ b/platform/ext/Mps2AN519.cmake
@@ -96,7 +96,9 @@
   message(FATAL_ERROR "Configuration variable BUILD_TARGET_CFG (true|false) is undefined!")
 elseif(BUILD_TARGET_CFG)
   list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an519/target_cfg.c")
-  list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an519/spm_hal.c")
+  list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/mps2/an519/spm_hal.c")
+  list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/mps2/an519/native_drivers/mpu_armv8m_drv.c")
+  embedded_include_directories(PATH "${PLATFORM_DIR}/common" ABSOLUTE)
 endif()
 
 if (NOT DEFINED BUILD_TARGET_HARDWARE_KEYS)
diff --git a/platform/ext/Mps2AN521.cmake b/platform/ext/Mps2AN521.cmake
index f44db7b..0b388ce 100755
--- a/platform/ext/Mps2AN521.cmake
+++ b/platform/ext/Mps2AN521.cmake
@@ -113,7 +113,9 @@
   message(FATAL_ERROR "Configuration variable BUILD_TARGET_CFG (true|false) is undefined!")
 elseif(BUILD_TARGET_CFG)
   list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an521/target_cfg.c")
-  list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an521/spm_hal.c")
+  list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/mps2/an521/spm_hal.c")
+  list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/mps2/an521/native_drivers/mpu_armv8m_drv.c")
+  embedded_include_directories(PATH "${PLATFORM_DIR}/common" ABSOLUTE)
 endif()
 
 if (NOT DEFINED BUILD_TARGET_HARDWARE_KEYS)
diff --git a/platform/ext/musca_a.cmake b/platform/ext/musca_a.cmake
index 3789170..985c3bc 100755
--- a/platform/ext/musca_a.cmake
+++ b/platform/ext/musca_a.cmake
@@ -96,7 +96,9 @@
   message(FATAL_ERROR "Configuration variable BUILD_TARGET_CFG (true|false) is undefined!")
 elseif(BUILD_TARGET_CFG)
   list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/target_cfg.c")
-  list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/spm_hal.c")
+  list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_a/spm_hal.c")
+  list(APPEND ALL_SRC_C_S "${PLATFORM_DIR}/target/musca_a/Native_Driver/mpu_armv8m_drv.c")
+  embedded_include_directories(PATH "${PLATFORM_DIR}/common" ABSOLUTE)
 endif()
 
 if (NOT DEFINED BUILD_TARGET_HARDWARE_KEYS)
diff --git a/platform/ext/target/mps2/an519/native_drivers/mpu_armv8m_drv.c b/platform/ext/target/mps2/an519/native_drivers/mpu_armv8m_drv.c
new file mode 100644
index 0000000..e540be2
--- /dev/null
+++ b/platform/ext/target/mps2/an519/native_drivers/mpu_armv8m_drv.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "mpu_armv8m_drv.h"
+#include "cmsis_cpu.h"
+
+/*
+ * FixMe:
+ * This is a beta quality driver for MPU in v8M. To be finalized.
+ */
+
+enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
+                                          uint32_t privdef_en,
+                                          uint32_t hfnmi_en)
+{
+    /*No error checking*/
+
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    mpu->CTRL =
+            (privdef_en ? MPU_CTRL_PRIVDEFENA_Msk : 0) |
+            (hfnmi_en   ? MPU_CTRL_HFNMIENA_Msk   : 0);
+
+    /*Ensure all configuration is written before enable*/
+
+    mpu->CTRL |= MPU_CTRL_ENABLE_Msk;
+
+    /* Enable MPU before next instruction */
+    __asm("DSB");
+    __asm("ISB");
+    return MPU_ARMV8M_OK;
+}
+
+enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev)
+{
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    /* Reset all fields as enable does full setup */
+    mpu->CTRL = 0;
+
+    return MPU_ARMV8M_OK;
+}
+
+
+enum mpu_armv8m_error_t mpu_armv8m_region_enable(
+                                struct mpu_armv8m_dev_t *dev,
+                                struct mpu_armv8m_region_cfg_t *region_cfg)
+{
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
+    uint32_t ctrl_before;
+    uint32_t base_cfg;
+    uint32_t limit_cfg;
+
+    /*FIXME : Add complete error checking*/
+    if ((region_cfg->region_base & ~MPU_RBAR_ADDR_Msk) != 0) {
+        return MPU_ARMV8M_ERROR;
+    }
+    /* region_limit doesn't need to be aligned but the scatter
+     * file needs to be setup to ensure that partitions do not overlap.
+     */
+
+    ctrl_before = mpu->CTRL;
+    mpu->CTRL = 0;
+
+    mpu->RNR  = region_cfg->region_nr & MPU_RNR_REGION_Msk;
+
+    /* This 0s the lower bits of the base address */
+    base_cfg = region_cfg->region_base & MPU_RBAR_ADDR_Msk;
+    base_cfg |= (region_cfg->attr_sh << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk;
+    base_cfg |= (region_cfg->attr_access << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk;
+    base_cfg |= (region_cfg->attr_exec << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk;
+
+    mpu->RBAR = base_cfg;
+
+    /*This 0s the lower bits of base address but they are treated as 1 */
+    limit_cfg = (region_cfg->region_limit-1) & MPU_RLAR_LIMIT_Msk;
+
+    /*FIXME: Enable the memory attr setting */
+    limit_cfg |= MPU_RLAR_EN_Msk;
+
+    mpu->RLAR = limit_cfg;
+
+    /*Restore main MPU control*/
+    mpu->CTRL = ctrl_before;
+
+    /* Enable MPU before the next instruction */
+    __asm("DSB");
+    __asm("ISB");
+
+    return ret_val;
+}
+
+
+enum mpu_armv8m_error_t mpu_armv8m_region_disable(
+                                struct mpu_armv8m_dev_t *dev,
+                                uint32_t region_nr)
+{
+
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
+    uint32_t ctrl_before;
+
+    /*FIXME : Add complete error checking*/
+
+    ctrl_before = mpu->CTRL;
+    mpu->CTRL = 0;
+
+    mpu->RNR  = region_nr & MPU_RNR_REGION_Msk;
+
+    mpu->RBAR = 0;
+    mpu->RLAR = 0;
+
+    /*Restore main MPU control*/
+    mpu->CTRL = ctrl_before;
+
+    return ret_val;
+}
+
+enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev)
+{
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+    uint32_t i = (mpu->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
+
+    while (i > 0) {
+        mpu_armv8m_region_disable(dev, i-1);
+        i--;
+    }
+
+    return MPU_ARMV8M_OK;
+
+}
diff --git a/platform/ext/target/mps2/an519/native_drivers/mpu_armv8m_drv.h b/platform/ext/target/mps2/an519/native_drivers/mpu_armv8m_drv.h
new file mode 100644
index 0000000..0abf7fd
--- /dev/null
+++ b/platform/ext/target/mps2/an519/native_drivers/mpu_armv8m_drv.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __MPU_ARMV8M_DRV_H__
+#define __MPU_ARMV8M_DRV_H__
+
+#include <stdint.h>
+
+#include "cmsis.h"
+
+#define PRIVILEGED_DEFAULT_ENABLE 1
+#define HARDFAULT_NMI_ENABLE      1
+
+struct mpu_armv8m_dev_t {
+    const uint32_t base;
+};
+
+enum mpu_armv8m_error_t {
+    MPU_ARMV8M_OK,
+    MPU_ARMV8M_ERROR
+};
+
+enum mpu_armv8m_attr_exec_t {
+    MPU_ARMV8M_XN_EXEC_OK,
+    MPU_ARMV8M_XN_EXEC_NEVER
+};
+
+enum mpu_armv8m_attr_access_t {
+    MPU_ARMV8M_AP_RW_PRIV_ONLY,
+    MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
+    MPU_ARMV8M_AP_RO_PRIV_ONLY,
+    MPU_ARMV8M_AP_RO_PRIV_UNPRIV
+};
+
+enum mpu_armv8m_attr_shared_t {
+    MPU_ARMV8M_SH_NONE,
+    MPU_ARMV8M_SH_UNUSED,
+    MPU_ARMV8M_SH_OUTER,
+    MPU_ARMV8M_SH_INNER
+};
+
+struct mpu_armv8m_region_cfg_t {
+    uint32_t region_nr;
+    uint32_t region_base;
+    uint32_t region_limit;
+    enum mpu_armv8m_attr_exec_t     attr_exec;
+    enum mpu_armv8m_attr_access_t   attr_access;
+    enum mpu_armv8m_attr_shared_t   attr_sh;
+};
+
+struct mpu_armv8m_region_cfg_raw_t {
+    uint32_t region_nr;
+    uint32_t region_base;
+    uint32_t region_limit;
+};
+
+
+/**
+ * \brief Enable MPU
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ * \param[in] privdef_en     privilege default region 1:enable 0:disable
+ * \param[in] hfnmi_en       mpu for hard fault & nmi  1:enable 0:disable
+ *
+ * \return Error code \ref mpu_armv8m_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+
+enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
+                                          uint32_t privdef_en,
+                                          uint32_t hfnmi_en);
+
+/**
+ * \brief Disable MPU
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev);
+
+/**
+ * \brief Disable MPU and clean all regions
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev);
+
+/**
+ * \brief Enable MPU Region
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ * \param[in] region_cfg     MPU region config \ref mpu_armv8m_region_cfg_t
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_region_enable(
+                                struct mpu_armv8m_dev_t *dev,
+                                struct mpu_armv8m_region_cfg_t *region_cfg);
+
+/**
+ * \brief Disable MPU Region
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ * \param[in] region_nr            Region number
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_region_disable(
+                                struct mpu_armv8m_dev_t *dev,
+                                uint32_t region_nr);
+
+#endif /* __MPU_ARMV8M_DRV_H__ */
diff --git a/platform/ext/target/mps2/an519/spm_hal.c b/platform/ext/target/mps2/an519/spm_hal.c
index 6f98696..a520043 100644
--- a/platform/ext/target/mps2/an519/spm_hal.c
+++ b/platform/ext/target/mps2/an519/spm_hal.c
@@ -5,15 +5,301 @@
  *

  */

 

+#include <stdio.h>

 #include "platform/include/tfm_spm_hal.h"

 #include "spm_api.h"

 #include "spm_db.h"

+#include "tfm_platform_api.h"

+#include "target_cfg.h"

+#include "Driver_MPC.h"

+#include "mpu_armv8m_drv.h"

+#include "region_defs.h"

+#include "secure_utilities.h"

 

-void tfm_spm_hal_init_platform_data(uint32_t partition_id,

-        struct tfm_spm_partition_platform_data_t *platform_data)

+/* Import MPC driver */

+extern ARM_DRIVER_MPC Driver_SRAM1_MPC;

+

+struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };

+

+void tfm_spm_hal_init_isolation_hw(void)

 {

-    platform_data->periph_start = 0;

-    platform_data->periph_limit = 0;

-    platform_data->periph_ppc_bank = 0;

-    platform_data->periph_ppc_loc = 0;

+    /* Configures non-secure memory spaces in the target */

+    sau_and_idau_cfg();

+    mpc_init_cfg();

+    ppc_init_cfg();

 }

+

+void tfm_spm_hal_configure_default_isolation(

+        const struct tfm_spm_partition_platform_data_t *platform_data)

+{

+    if (platform_data) {

+        ppc_configure_to_secure(platform_data->periph_ppc_bank,

+                                platform_data->periph_ppc_loc);

+    }

+}

+

+#if TFM_LVL != 1

+

+#define MPU_REGION_VENEERS           0

+#define MPU_REGION_TFM_UNPRIV_CODE   1

+#define MPU_REGION_TFM_UNPRIV_DATA   2

+#define MPU_REGION_NS_DATA           3

+#define PARTITION_REGION_RO          4

+#define PARTITION_REGION_RW_STACK    5

+#define PARTITION_REGION_PERIPH      6

+#define PARTITION_REGION_SHARE       7

+

+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);

+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);

+REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);

+REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);

+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);

+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);

+

+static enum spm_err_t tfm_spm_mpu_init(void)

+{

+    struct mpu_armv8m_region_cfg_t region_cfg;

+

+    mpu_armv8m_clean(&dev_mpu_s);

+

+    /* Veneer region */

+    region_cfg.region_nr = MPU_REGION_VENEERS;

+    region_cfg.region_base = CMSE_VENEER_REGION_START;

+    region_cfg.region_limit = CMSE_VENEER_REGION_LIMIT;

+    region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    /* TFM Core unprivileged code region */

+    region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_CODE;

+    region_cfg.region_base =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);

+    region_cfg.region_limit =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);

+    region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    /* TFM Core unprivileged data region */

+    region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_DATA;

+    region_cfg.region_base =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);

+    region_cfg.region_limit =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);

+    region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    /* TFM Core unprivileged non-secure data region */

+    region_cfg.region_nr = MPU_REGION_NS_DATA;

+    region_cfg.region_base = NS_DATA_START;

+    region_cfg.region_limit = NS_DATA_LIMIT;

+    region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return SPM_ERR_OK;

+}

+

+enum spm_err_t tfm_spm_hal_partition_sandbox_config(

+        const struct tfm_spm_partition_memory_data_t *memory_data,

+        const struct tfm_spm_partition_platform_data_t *platform_data)

+{

+    /* This function takes a partition id and enables the

+     * SPM partition for that partition

+     */

+

+    struct mpu_armv8m_region_cfg_t region_cfg;

+

+    mpu_armv8m_disable(&dev_mpu_s);

+

+    /* Configure Regions */

+    if (memory_data->ro_start) {

+        /* RO region */

+        region_cfg.region_nr = PARTITION_REGION_RO;

+        region_cfg.region_base = memory_data->ro_start;

+        region_cfg.region_limit = memory_data->ro_limit;

+        region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;

+

+        if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)

+            != MPU_ARMV8M_OK) {

+            return SPM_ERR_INVALID_CONFIG;

+        }

+    }

+

+    /* RW, ZI and stack as one region */

+    region_cfg.region_nr = PARTITION_REGION_RW_STACK;

+    region_cfg.region_base = memory_data->rw_start;

+    region_cfg.region_limit = memory_data->stack_top;

+    region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    if (platform_data) {

+        /* Peripheral */

+        region_cfg.region_nr = PARTITION_REGION_PERIPH;

+        region_cfg.region_base = platform_data->periph_start;

+        region_cfg.region_limit = platform_data->periph_limit;

+        region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+        if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)

+            != MPU_ARMV8M_OK) {

+            return SPM_ERR_INVALID_CONFIG;

+        }

+

+        ppc_en_secure_unpriv(platform_data->periph_ppc_bank,

+                             platform_data->periph_ppc_loc);

+    }

+

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return SPM_ERR_OK;

+}

+

+enum spm_err_t tfm_spm_hal_partition_sandbox_deconfig(

+        const struct tfm_spm_partition_memory_data_t *memory_data,

+        const struct tfm_spm_partition_platform_data_t *platform_data)

+{

+    /* This function takes a partition id and disables the

+     * SPM partition for that partition

+     */

+

+    if (platform_data) {

+        /* Peripheral */

+        ppc_clr_secure_unpriv(platform_data->periph_ppc_bank,

+                              platform_data->periph_ppc_loc);

+    }

+

+    mpu_armv8m_disable(&dev_mpu_s);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RO);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RW_STACK);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_PERIPH);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return SPM_ERR_OK;

+}

+

+/**

+ * Set share region to which the partition needs access

+ */

+enum spm_err_t tfm_spm_hal_set_share_region(

+        enum tfm_buffer_share_region_e share)

+{

+    struct mpu_armv8m_region_cfg_t region_cfg;

+    enum spm_err_t res = SPM_ERR_INVALID_CONFIG;

+    uint32_t scratch_base =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);

+    uint32_t scratch_limit =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);

+

+    mpu_armv8m_disable(&dev_mpu_s);

+

+    if (share == TFM_BUFFER_SHARE_DISABLE) {

+        mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);

+    } else {

+

+        region_cfg.region_nr = PARTITION_REGION_SHARE;

+        region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+        switch (share) {

+        case TFM_BUFFER_SHARE_SCRATCH:

+            /* Use scratch area for SP-to-SP data sharing */

+            region_cfg.region_base = scratch_base;

+            region_cfg.region_limit = scratch_limit;

+            res = SPM_ERR_OK;

+            break;

+        case TFM_BUFFER_SHARE_NS_CODE:

+            region_cfg.region_base = NS_CODE_START;

+            region_cfg.region_limit = NS_CODE_LIMIT;

+            /* Only allow read access to NS code region and keep

+             * exec.never attribute

+             */

+            region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+            res = SPM_ERR_OK;

+            break;

+        default:

+            /* Leave res to be set to SPM_ERR_INVALID_CONFIG */

+            break;

+        }

+        if (res == SPM_ERR_OK) {

+            mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg);

+        }

+    }

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return res;

+}

+

+#endif /* TFM_LVL != 1 */

+

+void tfm_spm_hal_setup_isolation_hw(void)

+{

+#if TFM_LVL != 1

+    if (tfm_spm_mpu_init() != SPM_ERR_OK) {

+        ERROR_MSG("Failed to set up initial MPU configuration! Halting.");

+        while (1) {

+            ;

+        }

+    }

+#endif

+}

+

+void MPC_Handler(void)

+{

+    /* Clear MPC interrupt flag and pending MPC IRQ */

+    Driver_SRAM1_MPC.ClearInterrupt();

+    NVIC_ClearPendingIRQ(MPC_IRQn);

+

+    /* Print fault message and block execution */

+    LOG_MSG("Oops... MPC fault!!!");

+

+    /* Inform TF-M core that isolation boundary has been violated */

+    tfm_access_violation_handler();

+}

+

+void PPC_Handler(void)

+{

+    /*

+     * Due to an issue on the FVP, the PPC fault doesn't trigger a

+     * PPC IRQ which is handled by the PPC_handler.

+     * In the FVP execution, this code is not execute.

+     */

+

+    /* Clear PPC interrupt flag and pending PPC IRQ */

+    ppc_clear_irq();

+    NVIC_ClearPendingIRQ(PPC_IRQn);

+

+    /* Print fault message*/

+    LOG_MSG("Oops... PPC fault!!!");

+

+    /* Inform TF-M core that isolation boundary has been violated */

+    tfm_access_violation_handler();

+}

+

diff --git a/platform/ext/target/mps2/an519/target_cfg.c b/platform/ext/target/mps2/an519/target_cfg.c
index e73378b..edc9bb3 100644
--- a/platform/ext/target/mps2/an519/target_cfg.c
+++ b/platform/ext/target/mps2/an519/target_cfg.c
@@ -31,6 +31,20 @@
 #define PERIPHERALS_BASE_NS_START (0x40000000)
 #define PERIPHERALS_BASE_NS_END   (0x4FFFFFFF)
 
+struct tfm_spm_partition_platform_data_t tfm_peripheral_uart1 = {
+        UART1_BASE_S,
+        UART1_BASE_S + 0xFFF,
+        PPC_SP_APB_PPC_EXP1,
+        CMSDK_UART1_APB_PPC_POS
+};
+
+struct tfm_spm_partition_platform_data_t tfm_peripheral_fpga_io = {
+        MPS2_IO_FPGAIO_BASE_S,
+        MPS2_IO_FPGAIO_BASE_S + 0xFFF,
+        PPC_SP_APB_PPC_EXP2,
+        CMSDK_FPGA_IO_PPC_POS
+};
+
 void enable_fault_handlers(void)
 {
     /* Fault handles enable registers are not present in a baseline
diff --git a/platform/ext/target/mps2/an519/target_cfg.h b/platform/ext/target/mps2/an519/target_cfg.h
index 39280c7..e60a866 100644
--- a/platform/ext/target/mps2/an519/target_cfg.h
+++ b/platform/ext/target/mps2/an519/target_cfg.h
@@ -17,6 +17,8 @@
 #ifndef __SSE200_TARGET_CFG_H__
 #define __SSE200_TARGET_CFG_H__
 
+#include "tfm_peripherals_def.h"
+
 /**
  * \brief Defines the word offsets of Slave Peripheral Protection Controller
  *        Registers
@@ -42,24 +44,15 @@
 };
 
 /**
- * \brief BusFault, UsageFault, MemManageFault and SecureFault
- *        are not present on AN519 so the body of this function
- *        is empty
+ * Holds the data necessary to do isolation for a specific peripheral.
  */
-void enable_fault_handlers(void);
-
-/**
- * \brief Configures all external interrupts to target the
- *        NS state, apart for the ones associated to secure
- *        peripherals (plus MPC and PPC)
- */
-void nvic_interrupt_target_state_cfg();
-
-/**
- * \brief This function enable the interrupts associated
- *        to the secure peripherals (plus MPC and PPC)
- */
-void nvic_interrupt_enable();
+struct tfm_spm_partition_platform_data_t
+{
+    uint32_t periph_start;
+    uint32_t periph_limit;
+    uint16_t periph_ppc_bank;
+    uint16_t periph_ppc_loc;
+};
 
 /**
  * \brief Configures the Memory Protection Controller.
diff --git a/platform/ext/target/mps2/an519/tfm_peripherals_def.h b/platform/ext/target/mps2/an519/tfm_peripherals_def.h
new file mode 100644
index 0000000..ca09d67
--- /dev/null
+++ b/platform/ext/target/mps2/an519/tfm_peripherals_def.h
@@ -0,0 +1,19 @@
+/*

+ * Copyright (c) 2018, Arm Limited. All rights reserved.

+ *

+ * SPDX-License-Identifier: BSD-3-Clause

+ *

+ */

+

+#ifndef __TFM_PERIPHERALS_DEF_H__

+#define __TFM_PERIPHERALS_DEF_H__

+

+struct tfm_spm_partition_platform_data_t;

+

+extern struct tfm_spm_partition_platform_data_t tfm_peripheral_uart1;

+extern struct tfm_spm_partition_platform_data_t tfm_peripheral_fpga_io;

+

+#define TFM_PERIPHERAL_FPGA_IO   (&tfm_peripheral_fpga_io)

+#define TFM_PERIPHERAL_UART1     (&tfm_peripheral_uart1)

+

+#endif /* __TFM_PERIPHERALS_DEF_H__ */

diff --git a/platform/ext/target/mps2/an521/native_drivers/mpu_armv8m_drv.c b/platform/ext/target/mps2/an521/native_drivers/mpu_armv8m_drv.c
new file mode 100644
index 0000000..e540be2
--- /dev/null
+++ b/platform/ext/target/mps2/an521/native_drivers/mpu_armv8m_drv.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "mpu_armv8m_drv.h"
+#include "cmsis_cpu.h"
+
+/*
+ * FixMe:
+ * This is a beta quality driver for MPU in v8M. To be finalized.
+ */
+
+enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
+                                          uint32_t privdef_en,
+                                          uint32_t hfnmi_en)
+{
+    /*No error checking*/
+
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    mpu->CTRL =
+            (privdef_en ? MPU_CTRL_PRIVDEFENA_Msk : 0) |
+            (hfnmi_en   ? MPU_CTRL_HFNMIENA_Msk   : 0);
+
+    /*Ensure all configuration is written before enable*/
+
+    mpu->CTRL |= MPU_CTRL_ENABLE_Msk;
+
+    /* Enable MPU before next instruction */
+    __asm("DSB");
+    __asm("ISB");
+    return MPU_ARMV8M_OK;
+}
+
+enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev)
+{
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    /* Reset all fields as enable does full setup */
+    mpu->CTRL = 0;
+
+    return MPU_ARMV8M_OK;
+}
+
+
+enum mpu_armv8m_error_t mpu_armv8m_region_enable(
+                                struct mpu_armv8m_dev_t *dev,
+                                struct mpu_armv8m_region_cfg_t *region_cfg)
+{
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
+    uint32_t ctrl_before;
+    uint32_t base_cfg;
+    uint32_t limit_cfg;
+
+    /*FIXME : Add complete error checking*/
+    if ((region_cfg->region_base & ~MPU_RBAR_ADDR_Msk) != 0) {
+        return MPU_ARMV8M_ERROR;
+    }
+    /* region_limit doesn't need to be aligned but the scatter
+     * file needs to be setup to ensure that partitions do not overlap.
+     */
+
+    ctrl_before = mpu->CTRL;
+    mpu->CTRL = 0;
+
+    mpu->RNR  = region_cfg->region_nr & MPU_RNR_REGION_Msk;
+
+    /* This 0s the lower bits of the base address */
+    base_cfg = region_cfg->region_base & MPU_RBAR_ADDR_Msk;
+    base_cfg |= (region_cfg->attr_sh << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk;
+    base_cfg |= (region_cfg->attr_access << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk;
+    base_cfg |= (region_cfg->attr_exec << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk;
+
+    mpu->RBAR = base_cfg;
+
+    /*This 0s the lower bits of base address but they are treated as 1 */
+    limit_cfg = (region_cfg->region_limit-1) & MPU_RLAR_LIMIT_Msk;
+
+    /*FIXME: Enable the memory attr setting */
+    limit_cfg |= MPU_RLAR_EN_Msk;
+
+    mpu->RLAR = limit_cfg;
+
+    /*Restore main MPU control*/
+    mpu->CTRL = ctrl_before;
+
+    /* Enable MPU before the next instruction */
+    __asm("DSB");
+    __asm("ISB");
+
+    return ret_val;
+}
+
+
+enum mpu_armv8m_error_t mpu_armv8m_region_disable(
+                                struct mpu_armv8m_dev_t *dev,
+                                uint32_t region_nr)
+{
+
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
+    uint32_t ctrl_before;
+
+    /*FIXME : Add complete error checking*/
+
+    ctrl_before = mpu->CTRL;
+    mpu->CTRL = 0;
+
+    mpu->RNR  = region_nr & MPU_RNR_REGION_Msk;
+
+    mpu->RBAR = 0;
+    mpu->RLAR = 0;
+
+    /*Restore main MPU control*/
+    mpu->CTRL = ctrl_before;
+
+    return ret_val;
+}
+
+enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev)
+{
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+    uint32_t i = (mpu->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
+
+    while (i > 0) {
+        mpu_armv8m_region_disable(dev, i-1);
+        i--;
+    }
+
+    return MPU_ARMV8M_OK;
+
+}
diff --git a/platform/ext/target/mps2/an521/native_drivers/mpu_armv8m_drv.h b/platform/ext/target/mps2/an521/native_drivers/mpu_armv8m_drv.h
new file mode 100644
index 0000000..0abf7fd
--- /dev/null
+++ b/platform/ext/target/mps2/an521/native_drivers/mpu_armv8m_drv.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __MPU_ARMV8M_DRV_H__
+#define __MPU_ARMV8M_DRV_H__
+
+#include <stdint.h>
+
+#include "cmsis.h"
+
+#define PRIVILEGED_DEFAULT_ENABLE 1
+#define HARDFAULT_NMI_ENABLE      1
+
+struct mpu_armv8m_dev_t {
+    const uint32_t base;
+};
+
+enum mpu_armv8m_error_t {
+    MPU_ARMV8M_OK,
+    MPU_ARMV8M_ERROR
+};
+
+enum mpu_armv8m_attr_exec_t {
+    MPU_ARMV8M_XN_EXEC_OK,
+    MPU_ARMV8M_XN_EXEC_NEVER
+};
+
+enum mpu_armv8m_attr_access_t {
+    MPU_ARMV8M_AP_RW_PRIV_ONLY,
+    MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
+    MPU_ARMV8M_AP_RO_PRIV_ONLY,
+    MPU_ARMV8M_AP_RO_PRIV_UNPRIV
+};
+
+enum mpu_armv8m_attr_shared_t {
+    MPU_ARMV8M_SH_NONE,
+    MPU_ARMV8M_SH_UNUSED,
+    MPU_ARMV8M_SH_OUTER,
+    MPU_ARMV8M_SH_INNER
+};
+
+struct mpu_armv8m_region_cfg_t {
+    uint32_t region_nr;
+    uint32_t region_base;
+    uint32_t region_limit;
+    enum mpu_armv8m_attr_exec_t     attr_exec;
+    enum mpu_armv8m_attr_access_t   attr_access;
+    enum mpu_armv8m_attr_shared_t   attr_sh;
+};
+
+struct mpu_armv8m_region_cfg_raw_t {
+    uint32_t region_nr;
+    uint32_t region_base;
+    uint32_t region_limit;
+};
+
+
+/**
+ * \brief Enable MPU
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ * \param[in] privdef_en     privilege default region 1:enable 0:disable
+ * \param[in] hfnmi_en       mpu for hard fault & nmi  1:enable 0:disable
+ *
+ * \return Error code \ref mpu_armv8m_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+
+enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
+                                          uint32_t privdef_en,
+                                          uint32_t hfnmi_en);
+
+/**
+ * \brief Disable MPU
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev);
+
+/**
+ * \brief Disable MPU and clean all regions
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev);
+
+/**
+ * \brief Enable MPU Region
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ * \param[in] region_cfg     MPU region config \ref mpu_armv8m_region_cfg_t
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_region_enable(
+                                struct mpu_armv8m_dev_t *dev,
+                                struct mpu_armv8m_region_cfg_t *region_cfg);
+
+/**
+ * \brief Disable MPU Region
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ * \param[in] region_nr            Region number
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_region_disable(
+                                struct mpu_armv8m_dev_t *dev,
+                                uint32_t region_nr);
+
+#endif /* __MPU_ARMV8M_DRV_H__ */
diff --git a/platform/ext/target/mps2/an521/spm_hal.c b/platform/ext/target/mps2/an521/spm_hal.c
index 6f98696..e26496a 100644
--- a/platform/ext/target/mps2/an521/spm_hal.c
+++ b/platform/ext/target/mps2/an521/spm_hal.c
@@ -5,15 +5,301 @@
  *

  */

 

+#include <stdio.h>

 #include "platform/include/tfm_spm_hal.h"

 #include "spm_api.h"

 #include "spm_db.h"

+#include "tfm_platform_api.h"

+#include "target_cfg.h"

+#include "Driver_MPC.h"

+#include "mpu_armv8m_drv.h"

+#include "region_defs.h"

+#include "secure_utilities.h"

 

-void tfm_spm_hal_init_platform_data(uint32_t partition_id,

-        struct tfm_spm_partition_platform_data_t *platform_data)

+/* Import MPC driver */

+extern ARM_DRIVER_MPC Driver_SRAM1_MPC;

+

+struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };

+

+void tfm_spm_hal_init_isolation_hw(void)

 {

-    platform_data->periph_start = 0;

-    platform_data->periph_limit = 0;

-    platform_data->periph_ppc_bank = 0;

-    platform_data->periph_ppc_loc = 0;

+    /* Configures non-secure memory spaces in the target */

+    sau_and_idau_cfg();

+    mpc_init_cfg();

+    ppc_init_cfg();

 }

+

+void tfm_spm_hal_configure_default_isolation(

+                  const struct tfm_spm_partition_platform_data_t *platform_data)

+{

+    if (platform_data) {

+        ppc_configure_to_secure(platform_data->periph_ppc_bank,

+                                platform_data->periph_ppc_loc);

+    }

+}

+

+#if TFM_LVL != 1

+

+#define MPU_REGION_VENEERS           0

+#define MPU_REGION_TFM_UNPRIV_CODE   1

+#define MPU_REGION_TFM_UNPRIV_DATA   2

+#define MPU_REGION_NS_DATA           3

+#define PARTITION_REGION_RO          4

+#define PARTITION_REGION_RW_STACK    5

+#define PARTITION_REGION_PERIPH      6

+#define PARTITION_REGION_SHARE       7

+

+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);

+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);

+REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);

+REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);

+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);

+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);

+

+static enum spm_err_t tfm_spm_mpu_init(void)

+{

+    struct mpu_armv8m_region_cfg_t region_cfg;

+

+    mpu_armv8m_clean(&dev_mpu_s);

+

+    /* Veneer region */

+    region_cfg.region_nr = MPU_REGION_VENEERS;

+    region_cfg.region_base = CMSE_VENEER_REGION_START;

+    region_cfg.region_limit = CMSE_VENEER_REGION_LIMIT;

+    region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    /* TFM Core unprivileged code region */

+    region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_CODE;

+    region_cfg.region_base =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);

+    region_cfg.region_limit =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);

+    region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    /* TFM Core unprivileged data region */

+    region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_DATA;

+    region_cfg.region_base =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);

+    region_cfg.region_limit =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);

+    region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    /* TFM Core unprivileged non-secure data region */

+    region_cfg.region_nr = MPU_REGION_NS_DATA;

+    region_cfg.region_base = NS_DATA_START;

+    region_cfg.region_limit = NS_DATA_LIMIT;

+    region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return SPM_ERR_OK;

+}

+

+enum spm_err_t tfm_spm_hal_partition_sandbox_config(

+                  const struct tfm_spm_partition_memory_data_t *memory_data,

+                  const struct tfm_spm_partition_platform_data_t *platform_data)

+{

+    /* This function takes a partition id and enables the

+     * SPM partition for that partition

+     */

+

+    struct mpu_armv8m_region_cfg_t region_cfg;

+

+    mpu_armv8m_disable(&dev_mpu_s);

+

+    /* Configure Regions */

+    if (memory_data->ro_start) {

+        /* RO region */

+        region_cfg.region_nr = PARTITION_REGION_RO;

+        region_cfg.region_base = memory_data->ro_start;

+        region_cfg.region_limit = memory_data->ro_limit;

+        region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;

+

+        if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)

+            != MPU_ARMV8M_OK) {

+            return SPM_ERR_INVALID_CONFIG;

+        }

+    }

+

+    /* RW, ZI and stack as one region */

+    region_cfg.region_nr = PARTITION_REGION_RW_STACK;

+    region_cfg.region_base = memory_data->rw_start;

+    region_cfg.region_limit = memory_data->stack_top;

+    region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    if (platform_data) {

+        /* Peripheral */

+        region_cfg.region_nr = PARTITION_REGION_PERIPH;

+        region_cfg.region_base = platform_data->periph_start;

+        region_cfg.region_limit = platform_data->periph_limit;

+        region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+        if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)

+            != MPU_ARMV8M_OK) {

+            return SPM_ERR_INVALID_CONFIG;

+        }

+

+        ppc_en_secure_unpriv(platform_data->periph_ppc_bank,

+                             platform_data->periph_ppc_loc);

+    }

+

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return SPM_ERR_OK;

+}

+

+enum spm_err_t tfm_spm_hal_partition_sandbox_deconfig(

+                  const struct tfm_spm_partition_memory_data_t *memory_data,

+                  const struct tfm_spm_partition_platform_data_t *platform_data)

+{

+    /* This function takes a partition id and disables the

+     * SPM partition for that partition

+     */

+

+    if (platform_data) {

+        /* Peripheral */

+        ppc_clr_secure_unpriv(platform_data->periph_ppc_bank,

+                              platform_data->periph_ppc_loc);

+    }

+

+    mpu_armv8m_disable(&dev_mpu_s);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RO);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RW_STACK);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_PERIPH);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return SPM_ERR_OK;

+}

+

+/**

+ * Set share region to which the partition needs access

+ */

+enum spm_err_t tfm_spm_hal_set_share_region(

+                                           enum tfm_buffer_share_region_e share)

+{

+    struct mpu_armv8m_region_cfg_t region_cfg;

+    enum spm_err_t res = SPM_ERR_INVALID_CONFIG;

+    uint32_t scratch_base =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);

+    uint32_t scratch_limit =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);

+

+    mpu_armv8m_disable(&dev_mpu_s);

+

+    if (share == TFM_BUFFER_SHARE_DISABLE) {

+        mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);

+    } else {

+

+        region_cfg.region_nr = PARTITION_REGION_SHARE;

+        region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+        switch (share) {

+        case TFM_BUFFER_SHARE_SCRATCH:

+            /* Use scratch area for SP-to-SP data sharing */

+            region_cfg.region_base = scratch_base;

+            region_cfg.region_limit = scratch_limit;

+            res = SPM_ERR_OK;

+            break;

+        case TFM_BUFFER_SHARE_NS_CODE:

+            region_cfg.region_base = NS_CODE_START;

+            region_cfg.region_limit = NS_CODE_LIMIT;

+            /* Only allow read access to NS code region and keep

+             * exec.never attribute

+             */

+            region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+            res = SPM_ERR_OK;

+            break;

+        default:

+            /* Leave res to be set to SPM_ERR_INVALID_CONFIG */

+            break;

+        }

+        if (res == SPM_ERR_OK) {

+            mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg);

+        }

+    }

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return res;

+}

+

+#endif /* TFM_LVL != 1 */

+

+void tfm_spm_hal_setup_isolation_hw(void)

+{

+#if TFM_LVL != 1

+    if (tfm_spm_mpu_init() != SPM_ERR_OK) {

+        ERROR_MSG("Failed to set up initial MPU configuration! Halting.");

+        while (1) {

+            ;

+        }

+    }

+#endif

+}

+

+void MPC_Handler(void)

+{

+    /* Clear MPC interrupt flag and pending MPC IRQ */

+    Driver_SRAM1_MPC.ClearInterrupt();

+    NVIC_ClearPendingIRQ(MPC_IRQn);

+

+    /* Print fault message and block execution */

+    LOG_MSG("Oops... MPC fault!!!");

+

+    /* Inform TF-M core that isolation boundary has been violated */

+    tfm_access_violation_handler();

+}

+

+void PPC_Handler(void)

+{

+    /*

+     * Due to an issue on the FVP, the PPC fault doesn't trigger a

+     * PPC IRQ which is handled by the PPC_handler.

+     * In the FVP execution, this code is not execute.

+     */

+

+    /* Clear PPC interrupt flag and pending PPC IRQ */

+    ppc_clear_irq();

+    NVIC_ClearPendingIRQ(PPC_IRQn);

+

+    /* Print fault message*/

+    LOG_MSG("Oops... PPC fault!!!");

+

+    /* Inform TF-M core that isolation boundary has been violated */

+    tfm_access_violation_handler();

+}

+

diff --git a/platform/ext/target/mps2/an521/target_cfg.c b/platform/ext/target/mps2/an521/target_cfg.c
index 4d69786..54ea719 100644
--- a/platform/ext/target/mps2/an521/target_cfg.c
+++ b/platform/ext/target/mps2/an521/target_cfg.c
@@ -31,6 +31,20 @@
 #define PERIPHERALS_BASE_NS_START (0x40000000)
 #define PERIPHERALS_BASE_NS_END   (0x4FFFFFFF)
 
+struct tfm_spm_partition_platform_data_t tfm_peripheral_uart1 = {
+        UART1_BASE_S,
+        UART1_BASE_S + 0xFFF,
+        PPC_SP_APB_PPC_EXP1,
+        CMSDK_UART1_APB_PPC_POS
+};
+
+struct tfm_spm_partition_platform_data_t tfm_peripheral_fpga_io = {
+        MPS2_IO_FPGAIO_BASE_S,
+        MPS2_IO_FPGAIO_BASE_S + 0xFFF,
+        PPC_SP_APB_PPC_EXP2,
+        CMSDK_FPGA_IO_PPC_POS
+};
+
 void enable_fault_handlers(void)
 {
     /* Enables BUS, MEM, USG and Secure faults */
diff --git a/platform/ext/target/mps2/an521/target_cfg.h b/platform/ext/target/mps2/an521/target_cfg.h
index 26c5cda..1b9e050 100644
--- a/platform/ext/target/mps2/an521/target_cfg.h
+++ b/platform/ext/target/mps2/an521/target_cfg.h
@@ -17,6 +17,8 @@
 #ifndef __SSE200_TARGET_CFG_H__
 #define __SSE200_TARGET_CFG_H__
 
+#include "tfm_peripherals_def.h"
+
 enum ppc_bank_e
 {
     PPC_SP_AHB_PPC0 = 0,
@@ -38,23 +40,15 @@
 };
 
 /**
- * \brief Enables the fault handlers BusFault, UsageFault,
- *        MemManageFault and SecureFault.
+ * Holds the data necessary to do isolation for a specific peripheral.
  */
-void enable_fault_handlers(void);
-
-/**
- * \brief Configures all external interrupts to target the
- *        NS state, apart for the ones associated to secure
- *        peripherals (plus MPC and PPC)
- */
-void nvic_interrupt_target_state_cfg();
-
-/**
- * \brief This function enable the interrupts associated
- *        to the secure peripherals (plus MPC and PPC)
- */
-void nvic_interrupt_enable();
+struct tfm_spm_partition_platform_data_t
+{
+    uint32_t periph_start;
+    uint32_t periph_limit;
+    uint16_t periph_ppc_bank;
+    uint16_t periph_ppc_loc;
+};
 
 /**
  * \brief Configures the Memory Protection Controller.
diff --git a/platform/ext/target/mps2/an521/tfm_peripherals_def.h b/platform/ext/target/mps2/an521/tfm_peripherals_def.h
new file mode 100644
index 0000000..ca09d67
--- /dev/null
+++ b/platform/ext/target/mps2/an521/tfm_peripherals_def.h
@@ -0,0 +1,19 @@
+/*

+ * Copyright (c) 2018, Arm Limited. All rights reserved.

+ *

+ * SPDX-License-Identifier: BSD-3-Clause

+ *

+ */

+

+#ifndef __TFM_PERIPHERALS_DEF_H__

+#define __TFM_PERIPHERALS_DEF_H__

+

+struct tfm_spm_partition_platform_data_t;

+

+extern struct tfm_spm_partition_platform_data_t tfm_peripheral_uart1;

+extern struct tfm_spm_partition_platform_data_t tfm_peripheral_fpga_io;

+

+#define TFM_PERIPHERAL_FPGA_IO   (&tfm_peripheral_fpga_io)

+#define TFM_PERIPHERAL_UART1     (&tfm_peripheral_uart1)

+

+#endif /* __TFM_PERIPHERALS_DEF_H__ */

diff --git a/platform/ext/target/musca_a/Native_Driver/mpu_armv8m_drv.c b/platform/ext/target/musca_a/Native_Driver/mpu_armv8m_drv.c
new file mode 100644
index 0000000..e540be2
--- /dev/null
+++ b/platform/ext/target/musca_a/Native_Driver/mpu_armv8m_drv.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "mpu_armv8m_drv.h"
+#include "cmsis_cpu.h"
+
+/*
+ * FixMe:
+ * This is a beta quality driver for MPU in v8M. To be finalized.
+ */
+
+enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
+                                          uint32_t privdef_en,
+                                          uint32_t hfnmi_en)
+{
+    /*No error checking*/
+
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    mpu->CTRL =
+            (privdef_en ? MPU_CTRL_PRIVDEFENA_Msk : 0) |
+            (hfnmi_en   ? MPU_CTRL_HFNMIENA_Msk   : 0);
+
+    /*Ensure all configuration is written before enable*/
+
+    mpu->CTRL |= MPU_CTRL_ENABLE_Msk;
+
+    /* Enable MPU before next instruction */
+    __asm("DSB");
+    __asm("ISB");
+    return MPU_ARMV8M_OK;
+}
+
+enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev)
+{
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    /* Reset all fields as enable does full setup */
+    mpu->CTRL = 0;
+
+    return MPU_ARMV8M_OK;
+}
+
+
+enum mpu_armv8m_error_t mpu_armv8m_region_enable(
+                                struct mpu_armv8m_dev_t *dev,
+                                struct mpu_armv8m_region_cfg_t *region_cfg)
+{
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
+    uint32_t ctrl_before;
+    uint32_t base_cfg;
+    uint32_t limit_cfg;
+
+    /*FIXME : Add complete error checking*/
+    if ((region_cfg->region_base & ~MPU_RBAR_ADDR_Msk) != 0) {
+        return MPU_ARMV8M_ERROR;
+    }
+    /* region_limit doesn't need to be aligned but the scatter
+     * file needs to be setup to ensure that partitions do not overlap.
+     */
+
+    ctrl_before = mpu->CTRL;
+    mpu->CTRL = 0;
+
+    mpu->RNR  = region_cfg->region_nr & MPU_RNR_REGION_Msk;
+
+    /* This 0s the lower bits of the base address */
+    base_cfg = region_cfg->region_base & MPU_RBAR_ADDR_Msk;
+    base_cfg |= (region_cfg->attr_sh << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk;
+    base_cfg |= (region_cfg->attr_access << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk;
+    base_cfg |= (region_cfg->attr_exec << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk;
+
+    mpu->RBAR = base_cfg;
+
+    /*This 0s the lower bits of base address but they are treated as 1 */
+    limit_cfg = (region_cfg->region_limit-1) & MPU_RLAR_LIMIT_Msk;
+
+    /*FIXME: Enable the memory attr setting */
+    limit_cfg |= MPU_RLAR_EN_Msk;
+
+    mpu->RLAR = limit_cfg;
+
+    /*Restore main MPU control*/
+    mpu->CTRL = ctrl_before;
+
+    /* Enable MPU before the next instruction */
+    __asm("DSB");
+    __asm("ISB");
+
+    return ret_val;
+}
+
+
+enum mpu_armv8m_error_t mpu_armv8m_region_disable(
+                                struct mpu_armv8m_dev_t *dev,
+                                uint32_t region_nr)
+{
+
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+
+    enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
+    uint32_t ctrl_before;
+
+    /*FIXME : Add complete error checking*/
+
+    ctrl_before = mpu->CTRL;
+    mpu->CTRL = 0;
+
+    mpu->RNR  = region_nr & MPU_RNR_REGION_Msk;
+
+    mpu->RBAR = 0;
+    mpu->RLAR = 0;
+
+    /*Restore main MPU control*/
+    mpu->CTRL = ctrl_before;
+
+    return ret_val;
+}
+
+enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev)
+{
+    MPU_Type *mpu = (MPU_Type *)dev->base;
+    uint32_t i = (mpu->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
+
+    while (i > 0) {
+        mpu_armv8m_region_disable(dev, i-1);
+        i--;
+    }
+
+    return MPU_ARMV8M_OK;
+
+}
diff --git a/platform/ext/target/musca_a/Native_Driver/mpu_armv8m_drv.h b/platform/ext/target/musca_a/Native_Driver/mpu_armv8m_drv.h
new file mode 100644
index 0000000..0abf7fd
--- /dev/null
+++ b/platform/ext/target/musca_a/Native_Driver/mpu_armv8m_drv.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __MPU_ARMV8M_DRV_H__
+#define __MPU_ARMV8M_DRV_H__
+
+#include <stdint.h>
+
+#include "cmsis.h"
+
+#define PRIVILEGED_DEFAULT_ENABLE 1
+#define HARDFAULT_NMI_ENABLE      1
+
+struct mpu_armv8m_dev_t {
+    const uint32_t base;
+};
+
+enum mpu_armv8m_error_t {
+    MPU_ARMV8M_OK,
+    MPU_ARMV8M_ERROR
+};
+
+enum mpu_armv8m_attr_exec_t {
+    MPU_ARMV8M_XN_EXEC_OK,
+    MPU_ARMV8M_XN_EXEC_NEVER
+};
+
+enum mpu_armv8m_attr_access_t {
+    MPU_ARMV8M_AP_RW_PRIV_ONLY,
+    MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
+    MPU_ARMV8M_AP_RO_PRIV_ONLY,
+    MPU_ARMV8M_AP_RO_PRIV_UNPRIV
+};
+
+enum mpu_armv8m_attr_shared_t {
+    MPU_ARMV8M_SH_NONE,
+    MPU_ARMV8M_SH_UNUSED,
+    MPU_ARMV8M_SH_OUTER,
+    MPU_ARMV8M_SH_INNER
+};
+
+struct mpu_armv8m_region_cfg_t {
+    uint32_t region_nr;
+    uint32_t region_base;
+    uint32_t region_limit;
+    enum mpu_armv8m_attr_exec_t     attr_exec;
+    enum mpu_armv8m_attr_access_t   attr_access;
+    enum mpu_armv8m_attr_shared_t   attr_sh;
+};
+
+struct mpu_armv8m_region_cfg_raw_t {
+    uint32_t region_nr;
+    uint32_t region_base;
+    uint32_t region_limit;
+};
+
+
+/**
+ * \brief Enable MPU
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ * \param[in] privdef_en     privilege default region 1:enable 0:disable
+ * \param[in] hfnmi_en       mpu for hard fault & nmi  1:enable 0:disable
+ *
+ * \return Error code \ref mpu_armv8m_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+
+enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
+                                          uint32_t privdef_en,
+                                          uint32_t hfnmi_en);
+
+/**
+ * \brief Disable MPU
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev);
+
+/**
+ * \brief Disable MPU and clean all regions
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev);
+
+/**
+ * \brief Enable MPU Region
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ * \param[in] region_cfg     MPU region config \ref mpu_armv8m_region_cfg_t
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_region_enable(
+                                struct mpu_armv8m_dev_t *dev,
+                                struct mpu_armv8m_region_cfg_t *region_cfg);
+
+/**
+ * \brief Disable MPU Region
+ *
+ * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
+ * \param[in] region_nr            Region number
+ *
+ * \return Error code \ref arm_mpu_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mpu_armv8m_error_t mpu_armv8m_region_disable(
+                                struct mpu_armv8m_dev_t *dev,
+                                uint32_t region_nr);
+
+#endif /* __MPU_ARMV8M_DRV_H__ */
diff --git a/platform/ext/target/musca_a/spm_hal.c b/platform/ext/target/musca_a/spm_hal.c
index 6f98696..a520043 100644
--- a/platform/ext/target/musca_a/spm_hal.c
+++ b/platform/ext/target/musca_a/spm_hal.c
@@ -5,15 +5,301 @@
  *

  */

 

+#include <stdio.h>

 #include "platform/include/tfm_spm_hal.h"

 #include "spm_api.h"

 #include "spm_db.h"

+#include "tfm_platform_api.h"

+#include "target_cfg.h"

+#include "Driver_MPC.h"

+#include "mpu_armv8m_drv.h"

+#include "region_defs.h"

+#include "secure_utilities.h"

 

-void tfm_spm_hal_init_platform_data(uint32_t partition_id,

-        struct tfm_spm_partition_platform_data_t *platform_data)

+/* Import MPC driver */

+extern ARM_DRIVER_MPC Driver_SRAM1_MPC;

+

+struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };

+

+void tfm_spm_hal_init_isolation_hw(void)

 {

-    platform_data->periph_start = 0;

-    platform_data->periph_limit = 0;

-    platform_data->periph_ppc_bank = 0;

-    platform_data->periph_ppc_loc = 0;

+    /* Configures non-secure memory spaces in the target */

+    sau_and_idau_cfg();

+    mpc_init_cfg();

+    ppc_init_cfg();

 }

+

+void tfm_spm_hal_configure_default_isolation(

+        const struct tfm_spm_partition_platform_data_t *platform_data)

+{

+    if (platform_data) {

+        ppc_configure_to_secure(platform_data->periph_ppc_bank,

+                                platform_data->periph_ppc_loc);

+    }

+}

+

+#if TFM_LVL != 1

+

+#define MPU_REGION_VENEERS           0

+#define MPU_REGION_TFM_UNPRIV_CODE   1

+#define MPU_REGION_TFM_UNPRIV_DATA   2

+#define MPU_REGION_NS_DATA           3

+#define PARTITION_REGION_RO          4

+#define PARTITION_REGION_RW_STACK    5

+#define PARTITION_REGION_PERIPH      6

+#define PARTITION_REGION_SHARE       7

+

+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);

+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);

+REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);

+REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);

+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);

+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);

+

+static enum spm_err_t tfm_spm_mpu_init(void)

+{

+    struct mpu_armv8m_region_cfg_t region_cfg;

+

+    mpu_armv8m_clean(&dev_mpu_s);

+

+    /* Veneer region */

+    region_cfg.region_nr = MPU_REGION_VENEERS;

+    region_cfg.region_base = CMSE_VENEER_REGION_START;

+    region_cfg.region_limit = CMSE_VENEER_REGION_LIMIT;

+    region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    /* TFM Core unprivileged code region */

+    region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_CODE;

+    region_cfg.region_base =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);

+    region_cfg.region_limit =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);

+    region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    /* TFM Core unprivileged data region */

+    region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_DATA;

+    region_cfg.region_base =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);

+    region_cfg.region_limit =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);

+    region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    /* TFM Core unprivileged non-secure data region */

+    region_cfg.region_nr = MPU_REGION_NS_DATA;

+    region_cfg.region_base = NS_DATA_START;

+    region_cfg.region_limit = NS_DATA_LIMIT;

+    region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return SPM_ERR_OK;

+}

+

+enum spm_err_t tfm_spm_hal_partition_sandbox_config(

+        const struct tfm_spm_partition_memory_data_t *memory_data,

+        const struct tfm_spm_partition_platform_data_t *platform_data)

+{

+    /* This function takes a partition id and enables the

+     * SPM partition for that partition

+     */

+

+    struct mpu_armv8m_region_cfg_t region_cfg;

+

+    mpu_armv8m_disable(&dev_mpu_s);

+

+    /* Configure Regions */

+    if (memory_data->ro_start) {

+        /* RO region */

+        region_cfg.region_nr = PARTITION_REGION_RO;

+        region_cfg.region_base = memory_data->ro_start;

+        region_cfg.region_limit = memory_data->ro_limit;

+        region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;

+

+        if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)

+            != MPU_ARMV8M_OK) {

+            return SPM_ERR_INVALID_CONFIG;

+        }

+    }

+

+    /* RW, ZI and stack as one region */

+    region_cfg.region_nr = PARTITION_REGION_RW_STACK;

+    region_cfg.region_base = memory_data->rw_start;

+    region_cfg.region_limit = memory_data->stack_top;

+    region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+    region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+    region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+

+    if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {

+        return SPM_ERR_INVALID_CONFIG;

+    }

+

+    if (platform_data) {

+        /* Peripheral */

+        region_cfg.region_nr = PARTITION_REGION_PERIPH;

+        region_cfg.region_base = platform_data->periph_start;

+        region_cfg.region_limit = platform_data->periph_limit;

+        region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+        if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)

+            != MPU_ARMV8M_OK) {

+            return SPM_ERR_INVALID_CONFIG;

+        }

+

+        ppc_en_secure_unpriv(platform_data->periph_ppc_bank,

+                             platform_data->periph_ppc_loc);

+    }

+

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return SPM_ERR_OK;

+}

+

+enum spm_err_t tfm_spm_hal_partition_sandbox_deconfig(

+        const struct tfm_spm_partition_memory_data_t *memory_data,

+        const struct tfm_spm_partition_platform_data_t *platform_data)

+{

+    /* This function takes a partition id and disables the

+     * SPM partition for that partition

+     */

+

+    if (platform_data) {

+        /* Peripheral */

+        ppc_clr_secure_unpriv(platform_data->periph_ppc_bank,

+                              platform_data->periph_ppc_loc);

+    }

+

+    mpu_armv8m_disable(&dev_mpu_s);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RO);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RW_STACK);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_PERIPH);

+    mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return SPM_ERR_OK;

+}

+

+/**

+ * Set share region to which the partition needs access

+ */

+enum spm_err_t tfm_spm_hal_set_share_region(

+        enum tfm_buffer_share_region_e share)

+{

+    struct mpu_armv8m_region_cfg_t region_cfg;

+    enum spm_err_t res = SPM_ERR_INVALID_CONFIG;

+    uint32_t scratch_base =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);

+    uint32_t scratch_limit =

+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);

+

+    mpu_armv8m_disable(&dev_mpu_s);

+

+    if (share == TFM_BUFFER_SHARE_DISABLE) {

+        mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);

+    } else {

+

+        region_cfg.region_nr = PARTITION_REGION_SHARE;

+        region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;

+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;

+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;

+        switch (share) {

+        case TFM_BUFFER_SHARE_SCRATCH:

+            /* Use scratch area for SP-to-SP data sharing */

+            region_cfg.region_base = scratch_base;

+            region_cfg.region_limit = scratch_limit;

+            res = SPM_ERR_OK;

+            break;

+        case TFM_BUFFER_SHARE_NS_CODE:

+            region_cfg.region_base = NS_CODE_START;

+            region_cfg.region_limit = NS_CODE_LIMIT;

+            /* Only allow read access to NS code region and keep

+             * exec.never attribute

+             */

+            region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;

+            res = SPM_ERR_OK;

+            break;

+        default:

+            /* Leave res to be set to SPM_ERR_INVALID_CONFIG */

+            break;

+        }

+        if (res == SPM_ERR_OK) {

+            mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg);

+        }

+    }

+    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,

+                      HARDFAULT_NMI_ENABLE);

+

+    return res;

+}

+

+#endif /* TFM_LVL != 1 */

+

+void tfm_spm_hal_setup_isolation_hw(void)

+{

+#if TFM_LVL != 1

+    if (tfm_spm_mpu_init() != SPM_ERR_OK) {

+        ERROR_MSG("Failed to set up initial MPU configuration! Halting.");

+        while (1) {

+            ;

+        }

+    }

+#endif

+}

+

+void MPC_Handler(void)

+{

+    /* Clear MPC interrupt flag and pending MPC IRQ */

+    Driver_SRAM1_MPC.ClearInterrupt();

+    NVIC_ClearPendingIRQ(MPC_IRQn);

+

+    /* Print fault message and block execution */

+    LOG_MSG("Oops... MPC fault!!!");

+

+    /* Inform TF-M core that isolation boundary has been violated */

+    tfm_access_violation_handler();

+}

+

+void PPC_Handler(void)

+{

+    /*

+     * Due to an issue on the FVP, the PPC fault doesn't trigger a

+     * PPC IRQ which is handled by the PPC_handler.

+     * In the FVP execution, this code is not execute.

+     */

+

+    /* Clear PPC interrupt flag and pending PPC IRQ */

+    ppc_clear_irq();

+    NVIC_ClearPendingIRQ(PPC_IRQn);

+

+    /* Print fault message*/

+    LOG_MSG("Oops... PPC fault!!!");

+

+    /* Inform TF-M core that isolation boundary has been violated */

+    tfm_access_violation_handler();

+}

+

diff --git a/platform/ext/target/musca_a/target_cfg.h b/platform/ext/target/musca_a/target_cfg.h
index 6e93ff5..3d59934 100755
--- a/platform/ext/target/musca_a/target_cfg.h
+++ b/platform/ext/target/musca_a/target_cfg.h
@@ -17,6 +17,8 @@
 #ifndef __TARGET_CFG_H__
 #define __TARGET_CFG_H__
 
+#include "tfm_peripherals_def.h"
+
 enum ppc_bank_e
 {
     PPC_SP_AHB_PPC0 = 0,
@@ -38,23 +40,15 @@
 };
 
 /**
- * \brief Enables the fault handlers BusFault, UsageFault,
- *        MemManageFault and SecureFault.
+ * Holds the data necessary to do isolation for a specific peripheral.
  */
-void enable_fault_handlers(void);
-
-/**
- * \brief Configures all external interrupts to target the
- *        NS state, apart for the ones associated to secure
- *        peripherals (plus MPC and PPC)
- */
-void nvic_interrupt_target_state_cfg();
-
-/**
- * \brief This function enables the interrupts associated
- *        to the secure peripherals (plus MPC and PPC)
- */
-void nvic_interrupt_enable();
+struct tfm_spm_partition_platform_data_t
+{
+    uint32_t periph_start;
+    uint32_t periph_limit;
+    uint16_t periph_ppc_bank;
+    uint16_t periph_ppc_loc;
+};
 
 /**
  * \brief Configures the Memory Protection Controller.
diff --git a/platform/ext/target/musca_a/tfm_peripherals_def.h b/platform/ext/target/musca_a/tfm_peripherals_def.h
new file mode 100644
index 0000000..2bd251e
--- /dev/null
+++ b/platform/ext/target/musca_a/tfm_peripherals_def.h
@@ -0,0 +1,13 @@
+/*

+ * Copyright (c) 2018, Arm Limited. All rights reserved.

+ *

+ * SPDX-License-Identifier: BSD-3-Clause

+ *

+ */

+

+#ifndef __TFM_PERIPHERALS_DEF_H__

+#define __TFM_PERIPHERALS_DEF_H__

+

+struct tfm_spm_partition_platform_data_t;

+

+#endif /* __TFM_PERIPHERALS_DEF_H__ */