Isolation L3 for AN521 and Musca-B1

- Add Isolation L3 region configuration for AN521 and Musca-B1.
- Add level3-specific linker script/scatter load files for these
  two platforms. The other platforms do not support L3 and do not
  need specific load files at current stage.
- Implement level3-specific dynamic MPU region switching function
  tfm_hal_mpu_update_partition_boundary() while isolation level3
  is chosen.

Change-Id: Icc50683c8a9b32494b29948d1ebeedcb59c0bcaa
Signed-off-by: Kevin Peng <kevin.peng@arm.com>
Co-authored-by: Mingyang Sun <mingyang.sun@arm.com>
diff --git a/platform/ext/common/armclang/tfm_isolation_l3.sct.template b/platform/ext/common/armclang/tfm_isolation_l3.sct.template
new file mode 100644
index 0000000..f3d5f7e
--- /dev/null
+++ b/platform/ext/common/armclang/tfm_isolation_l3.sct.template
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2017-2020 Arm Limited. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{{utilities.donotedit_warning}}
+
+/*
+ * Customized region name prefix abbreviation:
+ *  LR : A Load region.
+ *  ER : A typical execution region.
+ *  PT : An empty execution region used as position-tag/address-alignment.
+ *
+ * No applying customzied prefixes on linker/system reserved/intentional
+ * names, such as 'ARM_LIB_STACK'.
+ */
+
+#include "region_defs.h"
+
+LR_CODE S_CODE_START {
+
+    PT_RO_START S_CODE_START ALIGN 32 EMPTY 0x0 {
+        /* Position tag: code + RO-data */
+    }
+
+    /**** This initial section contains mainly the SPM code and RO-data */
+    ER_TFM_CODE +0 ALIGN 32 {
+        *.o (RESET +First)
+        * (+RO)
+    }
+
+    /**** PSA RoT CODE + RO-data starts here */
+{% for manifest in manifests %}
+    {% if manifest.manifest.type == 'PSA-ROT' %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+    ER_{{manifest.manifest.name}}_RO +0 ALIGN 32 {
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}} (+RO)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}} (+RO)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_FN)
+    }
+    {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+
+    {% endif %}
+{% endfor %}
+    /**** PSA RoT CODE + RO-data ends here */
+
+    /**** APPLICATION RoT CODE + RO-data starts here */
+{% for manifest in manifests %}
+    {% if manifest.manifest.type == 'APPLICATION-ROT' %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+    ER_{{manifest.manifest.name}}_RO +0 ALIGN 32 {
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}} (+RO)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}} (+RO)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_FN)
+    }
+    {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+
+    {% endif %}
+{% endfor %}
+    /**** APPLICATION RoT CODE + RO-data ends here */
+
+    /**** Unprivileged Secure code + RO-data starts here */
+    TFM_UNPRIV_CODE +0 ALIGN 32 {
+        platform_retarget_dev.o (+RO)
+        device_definition.o (+RO)
+        *(SFN)
+        *armlib* (+RO)
+        *libtfmsprt.a (+RO)
+        *psa_client.* (+RO)
+        *psa_service.* (+RO)
+        *psa_lifecycle.* (+RO)
+    }
+
+    PT_RO_END +0 ALIGN 32 EMPTY 0x0 {
+        /* Position tag */
+    }
+
+    /**** Base address of secure data area */
+    PT_SECURE_DATA_START S_DATA_START EMPTY 0x0 {
+        /* Position tag */
+    }
+
+    PT_PRIV_RWZI_START +0 ALIGN 32 EMPTY 0x0 {
+        /* Position tag */
+    }
+
+    /* Shared area between BL2 and runtime to exchange data */
+    TFM_SHARED_DATA +0 ALIGN 32 OVERLAY EMPTY BOOT_TFM_SHARED_DATA_SIZE {
+    }
+
+    /* MSP */
+    ARM_LIB_STACK_MSP +0 ALIGN 32 OVERLAY EMPTY S_MSP_STACK_SIZE {
+    }
+
+    ARM_LIB_HEAP +0 ALIGN 8 EMPTY S_HEAP_SIZE {
+    }
+
+    ER_TFM_DATA +0 {
+        * (+RW +ZI)
+    }
+
+    /**** PSA RoT RWZI starts here */
+{% for manifest in manifests %}
+    {% if manifest.manifest.type == 'PSA-ROT' %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+
+    PT_{{manifest.manifest.name}}_PRIVATE_DATA_START +0 ALIGN 32 {
+        /* Position tag */
+    }
+
+    ER_{{manifest.manifest.name}}_RWZI +0 ALIGN 32 {
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}} (+RW +ZI)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}} (+RW +ZI)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_RW)
+        *({{manifest.manifest.name}}_ATTR_ZI)
+    }
+
+    {% if manifest.attr.tfm_partition_ipc %}
+    {{manifest.manifest.name}}_LINKER_STACK +0 ALIGN 128 EMPTY {{manifest.manifest.stack_size}} {
+    }
+    {% else %}
+    {{manifest.manifest.name}}_LINKER_STACK +0 ALIGN 128 EMPTY 0 {
+    }
+    {% endif %}
+
+    PT_{{manifest.manifest.name}}_PRIVATE_DATA_END +0 ALIGN 32 {
+        /* Position tag */
+    }
+
+    {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+
+    {% endif %}
+{% endfor %}
+
+    /**** PSA RoT RWZI ends here */
+    PT_PRIV_RWZI_END +0 ALIGN 32 EMPTY 0x0 {
+        /* Position tag */
+    }
+
+    /* PSP is unprivileged in single-core topology */
+    ARM_LIB_STACK +0 ALIGN 32 EMPTY S_PSP_STACK_SIZE {
+    }
+
+{% for manifest in manifests %}
+    {% if manifest.manifest.type == 'APPLICATION-ROT' %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+
+    PT_{{manifest.manifest.name}}_PRIVATE_DATA_START +0 ALIGN 32 {
+        /* Position tag */
+    }
+
+    ER_{{manifest.manifest.name}}_RWZI +0 ALIGN 32 {
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}} (+RW +ZI)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}} (+RW +ZI)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_RW)
+        *({{manifest.manifest.name}}_ATTR_ZI)
+    }
+
+    {% if manifest.attr.tfm_partition_ipc %}
+    {{manifest.manifest.name}}_LINKER_STACK +0 ALIGN 128 EMPTY {{manifest.manifest.stack_size}} {
+    }
+    {% else %}
+    {{manifest.manifest.name}}_LINKER_STACK +0 ALIGN 128 EMPTY 0 {
+    }
+    {% endif %}
+
+    PT_{{manifest.manifest.name}}_PRIVATE_DATA_END +0 ALIGN 32 {
+        /* Position tag */
+    }
+
+    {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+
+    {% endif %}
+{% endfor %}
+
+    PT_SRAM_WATERMARK +0 EMPTY 0x0 {
+        /* Position tag */
+    }
+
+    /* Make sure that the sections allocated in the SRAM does not exceed the
+     * size of the SRAM available.
+     */
+    ScatterAssert(ImageLimit(PT_SRAM_WATERMARK) <= S_DATA_START + S_DATA_SIZE)
+
+#if defined(S_CODE_SRAM_ALIAS_BASE)
+    /* eFlash driver code that gets copied from Flash to SRAM */
+    ER_EFLASH_DRIVER_RO S_CODE_SRAM_ALIAS_BASE ALIGN 32 {
+        Driver_GFC100_EFlash.o (+RO)
+        gfc100_eflash_drv.o (+RO)
+        musca_b1_eflash_drv.o (+RO)
+    }
+#endif
+}
+
+LR_VENEER CMSE_VENEER_REGION_START {
+    /*
+     * Place the CMSE Veneers (containing the SG instruction) in a separate
+     * 32 bytes aligned region so that the SAU can be programmed to
+     * just set this region as Non-Secure Callable.
+     */
+    ER_CODE_CMSE_VENEER CMSE_VENEER_REGION_START CMSE_VENEER_REGION_SIZE {
+        *(Veneer$$CMSE)
+    }
+}
+
+LR_NS_PARTITION NS_PARTITION_START {
+    /* Reserved place for NS application.
+     * No code will be placed here, just address of this region is used in the
+     * secure code to configure certain HW components. This generates an empty
+     * execution region description warning during linking.
+     */
+    ER_NS_PARTITION NS_PARTITION_START UNINIT NS_PARTITION_SIZE {
+    }
+}
+
+#ifdef BL2
+LR_SECONDARY_PARTITION SECONDARY_PARTITION_START {
+    /* Reserved place for new image in case of firmware upgrade.
+     * No code will be placed here, just address of this region is used in the
+     * secure code to configure certain HW components. This generates an empty
+     * execution region description warning during linking.
+     */
+    ER_SECONDARY_PARTITION SECONDARY_PARTITION_START \
+        UNINIT SECONDARY_PARTITION_SIZE {
+    }
+}
+#endif /* BL2 */
diff --git a/platform/ext/common/gcc/tfm_isolation_l3.ld.template b/platform/ext/common/gcc/tfm_isolation_l3.ld.template
new file mode 100644
index 0000000..ca918f6
--- /dev/null
+++ b/platform/ext/common/gcc/tfm_isolation_l3.ld.template
@@ -0,0 +1,550 @@
+;/*
+; * Copyright (c) 2009-2020 Arm Limited
+; *
+; * Licensed under the Apache License, Version 2.0 (the "License");
+; * you may not use this file except in compliance with the License.
+; * You may obtain a copy of the License at
+; *
+; *     http://www.apache.org/licenses/LICENSE-2.0
+; *
+; * Unless required by applicable law or agreed to in writing, software
+; * distributed under the License is distributed on an "AS IS" BASIS,
+; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; * See the License for the specific language governing permissions and
+; * limitations under the License.
+; *
+; *
+; * This file is derivative of CMSIS V5.00 gcc_arm.ld
+; */
+
+{{utilities.donotedit_warning}}
+
+/* Linker script to configure memory regions. */
+/* This file will be run trough the pre-processor. */
+
+#include "region_defs.h"
+
+MEMORY
+{
+  FLASH    (rx)  : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE
+  RAM      (rwx) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE
+#if defined(S_CODE_SRAM_ALIAS_BASE)
+  CODE_RAM (rwx) : ORIGIN = S_CODE_SRAM_ALIAS_BASE, LENGTH = TOTAL_CODE_SRAM_SIZE
+#endif
+  VENEERS  (rx)  : ORIGIN = CMSE_VENEER_REGION_START, LENGTH = CMSE_VENEER_REGION_SIZE
+}
+
+__heap_size__  = S_HEAP_SIZE;
+__psp_stack_size__ = S_PSP_STACK_SIZE;
+__msp_init_stack_size__ = S_MSP_STACK_SIZE_INIT;
+
+/* Library configurations */
+GROUP(libgcc.a libc.a libm.a libnosys.a libc_nano.a)
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+    .TFM_VECTORS : ALIGN(4)
+    {
+        __vectors_start__ = .;
+        KEEP(*(.vectors))
+        __vectors_end__ = .;
+        *startup*(.text*)
+        . = ALIGN(4);
+    } > FLASH
+
+    .copy.table : ALIGN(4)
+    {
+        __copy_table_start__ = .;
+        LONG (LOADADDR(.TFM_DATA))
+        LONG (ADDR(.TFM_DATA))
+        LONG (SIZEOF(.TFM_DATA))
+{% for manifest in manifests %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+        LONG (LOADADDR(.ER_{{manifest.manifest.name}}_RWZI))
+        LONG (ADDR(.ER_{{manifest.manifest.name}}_RWZI))
+        LONG (SIZEOF(.ER_{{manifest.manifest.name}}_RWZI))
+    {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+{% endfor %}
+#if defined(S_CODE_SRAM_ALIAS_BASE)
+        LONG (LOADADDR(.ER_EFLASH_DRIVER_RO))
+        LONG (ADDR(.ER_EFLASH_DRIVER_RO))
+        LONG (SIZEOF(.ER_EFLASH_DRIVER_RO))
+#endif
+        __copy_table_end__ = .;
+    } > FLASH
+
+    .zero.table : ALIGN(4)
+    {
+        __zero_table_start__ = .;
+        LONG (ADDR(.TFM_BSS))
+        LONG (SIZEOF(.TFM_BSS))
+{% for manifest in manifests %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+        LONG (ADDR(.{{manifest.manifest.name}}_RWZI_BSS))
+        LONG (SIZEOF(.{{manifest.manifest.name}}_RWZI_BSS))
+    {% if manifest.attr.tfm_partition_ipc %}
+        LONG (ADDR(.{{manifest.manifest.name}}_LINKER_STACK))
+        LONG (SIZEOF(.{{manifest.manifest.name}}_LINKER_STACK))
+    {% endif %}
+        {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+{% endfor %}
+        __zero_table_end__ = .;
+    } > FLASH
+
+    /* Position tag */
+    . = ALIGN(32);
+    Image$$PT_RO_START$$Base = .;
+
+    /**** PSA RoT RO CODE + RO-data starts here */
+{% for manifest in manifests %}
+    {% if manifest.manifest.type == 'PSA-ROT' %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+    .{{manifest.manifest.name}}_RO : ALIGN(32)
+    {
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}}:*(.text*)
+        {{pattern}}:*(.rodata*)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}}(.text*)
+        {{pattern}}:*(.rodata*)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_FN)
+        . = ALIGN(32);
+    } > FLASH
+    Image$${{manifest.manifest.name}}_RO$$Base = ADDR(.{{manifest.manifest.name}}_RO);
+    Image$${{manifest.manifest.name}}_RO$$Limit = ADDR(.{{manifest.manifest.name}}_RO) + SIZEOF(.{{manifest.manifest.name}}_RO);
+    {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+
+    {% endif %}
+{% endfor %}
+    /**** PSA RoT RO CODE + data ends here */
+
+    /**** APPLICATION RoT RO CODE + data starts here */
+{% for manifest in manifests %}
+    {% if manifest.manifest.type == 'APPLICATION-ROT' %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+    .{{manifest.manifest.name}}_RO : ALIGN(32)
+    {
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}}:*(.text*)
+        {{pattern}}:*(.rodata*)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}}(.text*)
+        {{pattern}}:*(.rodata*)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_FN)
+        . = ALIGN(32);
+    } > FLASH
+    Image$${{manifest.manifest.name}}_CODE$$Base = ADDR(.{{manifest.manifest.name}}_RO);
+    Image$${{manifest.manifest.name}}_CODE$$Limit = ADDR(.{{manifest.manifest.name}}_RO) + SIZEOF(.{{manifest.manifest.name}}_RO);
+    {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+
+    {% endif %}
+{% endfor %}
+    /**** APPLICATION RoT RO CODE + data ends here */
+
+    /**** Unprivileged Secure code starts here */
+    .ER_UNPRIV_CODE : ALIGN(32)
+    {
+        *platform_retarget_dev.*(.text*)
+        *platform_retarget_dev.*(.rodata*)
+        *device_definition.*(.text*)
+        *device_definition.*(.rodata*)
+        *(SFN)
+        *armlib*:*(.text*)
+        *armlib*:*(.rodata*)
+        *libtfmsprt*:*(.text*)
+        *libtfmsprt*:*(.rodata*)
+        *psa_client.*(.text*)              /* NXP */
+        *psa_client.*(.rodata*)
+        *psa_service.*(.text*)             /* NXP */
+        *psa_lifecycle.*(.text*)             /* NXP */
+        *psa_lifecycle.*(.rodata*)
+        . = ALIGN(32);
+    } > FLASH
+    Image$$TFM_UNPRIV_CODE$$RO$$Base = ADDR(.ER_UNPRIV_CODE);
+    Image$$TFM_UNPRIV_CODE$$RO$$Limit = ADDR(.ER_UNPRIV_CODE) + SIZEOF(.ER_UNPRIV_CODE);
+
+    .ER_TFM_CODE : ALIGN(4)
+    {
+        *(.text*)
+
+        KEEP(*(.init))
+        KEEP(*(.fini))
+
+
+        /* .ctors */
+        *crtbegin.o(.ctors)
+        *crtbegin?.o(.ctors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+        *(SORT(.ctors.*))
+        *(.ctors)
+
+        /* .dtors */
+         *crtbegin.o(.dtors)
+         *crtbegin?.o(.dtors)
+         *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+         *(SORT(.dtors.*))
+         *(.dtors)
+
+        *(.rodata*)
+
+        KEEP(*(.eh_frame*))
+    } > FLASH
+
+    /* Position tag */
+    . = ALIGN(32);
+    Image$$PT_RO_END$$Base = .;
+
+#if defined(S_CODE_SRAM_ALIAS_BASE)
+    .ER_EFLASH_DRIVER_RO : ALIGN(4)
+    {
+        *Driver_GFC100_EFlash.o(.text*)
+        *Driver_GFC100_EFlash.o(.rodata*)
+        *gfc100_eflash_drv.o(.text*)
+        *gfc100_eflash_drv.o(.rodata*)
+        *musca_b1_eflash_drv.o(.text*)
+        *musca_b1_eflash_drv.o(.rodata*)
+        . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */
+    } > CODE_RAM AT > FLASH
+    Image$$ER_EFLASH_DRIVER_RO$$Base = ADDR(.ER_EFLASH_DRIVER_RO);
+    Image$$ER_EFLASH_DRIVER_RO$$Limit = ADDR(.ER_EFLASH_DRIVER_RO) + SIZEOF(.ER_EFLASH_DRIVER_RO);
+#endif
+
+    .ARM.extab :
+    {
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
+    } > FLASH
+
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+    } > FLASH
+    __exidx_end = .;
+
+    /**** Base address of secure data area */
+    .tfm_secure_data_start :
+    {
+        . = ABSOLUTE(S_DATA_START) ;
+    } > RAM
+
+   /* Position tag */
+    . = ALIGN(32);
+    Image$$PT_PRIV_RWZI_START$$Base = .;
+
+    /* shared_data and msp_stack are overlapping on purpose when
+     * msp_stack is extended until the beginning of RAM, when shared_date
+     * was read out by partitions
+     */
+    .tfm_bl2_shared_data : ALIGN(32)
+    {
+        . += BOOT_TFM_SHARED_DATA_SIZE;
+    } > RAM
+
+    .msp_stack : ALIGN(32)
+    {
+        . += __msp_init_stack_size__;
+    } > RAM
+    Image$$ARM_LIB_STACK_MSP$$ZI$$Base = ADDR(.msp_stack);
+    Image$$ARM_LIB_STACK_MSP$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
+
+    /**** PSA RoT DATA start here */
+{% for manifest in manifests %}
+    {% if manifest.manifest.type == 'PSA-ROT' %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+
+    /* Position tag */
+    . = ALIGN(32);
+    Image$$PT_{{manifest.manifest.name}}_PRIVATE_DATA_START$$Base = .;
+
+    .ER_{{manifest.manifest.name}}_RWZI : ALIGN(32)
+    {
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}}:*(.data*)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}}(.data*)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_RW)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$ER_{{manifest.manifest.name}}_RWZI$$RW$$Base = ADDR(.ER_{{manifest.manifest.name}}_RWZI);
+    Image$$ER_{{manifest.manifest.name}}_RWZI$$RW$$Limit = ADDR(.ER_{{manifest.manifest.name}}_RWZI) + SIZEOF(.ER_{{manifest.manifest.name}}_RWZI);
+
+    .{{manifest.manifest.name}}_RWZI_BSS : ALIGN(32)
+    {
+        start_of_{{manifest.manifest.name}}_RWZI = .;
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}}:*(.bss*)
+        {{pattern}}:*(COMMON)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}}(.bss*)
+        {{pattern}}(COMMON)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_ZI)
+        . += (. - start_of_{{manifest.manifest.name}}_RWZI) ? 0 : 4;
+        . = ALIGN(32);
+    } > RAM AT> RAM
+    Image$$ER_{{manifest.manifest.name}}_RWZI$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_RWZI_BSS);
+    Image$$ER_{{manifest.manifest.name}}_RWZI$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_RWZI_BSS) + SIZEOF(.{{manifest.manifest.name}}_RWZI_BSS);
+
+    {% if manifest.attr.tfm_partition_ipc %}
+
+    .{{manifest.manifest.name}}_LINKER_STACK : ALIGN(128)
+    {
+        . += {{manifest.manifest.stack_size}};
+    } > RAM
+    Image$${{manifest.manifest.name}}_LINKER_STACK$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_LINKER_STACK);
+    Image$${{manifest.manifest.name}}_LINKER_STACK$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_LINKER_STACK) + SIZEOF(.{{manifest.manifest.name}}_LINKER_STACK);
+
+    {% endif %}
+
+    /* Position tag */
+    . = ALIGN(32);
+    Image$$PT_{{manifest.manifest.name}}_PRIVATE_DATA_END$$Base = .;
+
+    {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+
+    {% endif %}
+{% endfor %}
+    /**** PSA RoT DATA end here */
+    . = ALIGN(32);
+
+    /* Position tag */
+    Image$$PT_PRIV_RWZI_END$$Base = .;
+
+    /* PSP is unprivileged in single-core topology */
+    .psp_stack : ALIGN(32)
+    {
+        . += (__psp_stack_size__);
+    } > RAM
+    Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.psp_stack);
+    Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.psp_stack) + SIZEOF(.psp_stack);
+
+    /**** APPLICATION RoT DATA start here */
+{% for manifest in manifests %}
+    {% if manifest.manifest.type == 'APPLICATION-ROT' %}
+    {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+    {% endif %}
+
+    /* Position tag */
+    . = ALIGN(32);
+    Image$$PT_{{manifest.manifest.name}}_PRIVATE_DATA_START$$Base = .;
+
+    .ER_{{manifest.manifest.name}}_RWZI : ALIGN(32)
+    {
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}}:*(.data*)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}}(.data*)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_RW)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$.ER_{{manifest.manifest.name}}_RWZI$$RW$$Base = ADDR(.ER_{{manifest.manifest.name}}_RWZI);
+    Image$$.ER_{{manifest.manifest.name}}_RWZI$$RW$$Limit = ADDR(.ER_{{manifest.manifest.name}}_RWZI) + SIZEOF(.ER_{{manifest.manifest.name}}_RWZI);
+
+    .{{manifest.manifest.name}}_RWZI_BSS : ALIGN(32)
+    {
+        start_of_{{manifest.manifest.name}}_RWZI = .;
+    {% if manifest.attr.linker_pattern.library_list %}
+        {% for pattern in manifest.attr.linker_pattern.library_list %}
+        {{pattern}}:*(.bss*)
+        {{pattern}}:*(COMMON)
+        {% endfor %}
+    {% endif %}
+    {% if manifest.attr.linker_pattern.object_list %}
+        {% for pattern in manifest.attr.linker_pattern.object_list %}
+        {{pattern}}(.bss*)
+        {{pattern}}(COMMON)
+        {% endfor %}
+    {% endif %}
+        *({{manifest.manifest.name}}_ATTR_ZI)
+        . += (. - start_of_{{manifest.manifest.name}}_RWZI) ? 0 : 4;
+        . = ALIGN(32);
+    } > RAM AT> RAM
+    Image$$ER_{{manifest.manifest.name}}_RWZI$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_RWZI_BSS);
+    Image$$ER_{{manifest.manifest.name}}_RWZI$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_RWZI_BSS) + SIZEOF(.{{manifest.manifest.name}}_RWZI_BSS);
+
+    {% if manifest.attr.tfm_partition_ipc %}
+
+    .{{manifest.manifest.name}}_LINKER_STACK : ALIGN(128)
+    {
+        . += {{manifest.manifest.stack_size}};
+    } > RAM
+    Image$${{manifest.manifest.name}}_LINKER_STACK$$ZI$$Base = ADDR(.{{manifest.manifest.name}}_LINKER_STACK);
+    Image$${{manifest.manifest.name}}_LINKER_STACK$$ZI$$Limit = ADDR(.{{manifest.manifest.name}}_LINKER_STACK) + SIZEOF(.{{manifest.manifest.name}}_LINKER_STACK);
+
+    {% endif %}
+
+    /* Position tag */
+    . = ALIGN(32);
+    Image$$PT_{{manifest.manifest.name}}_PRIVATE_DATA_END$$Base = .;
+
+    {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+    {% endif %}
+
+    {% endif %}
+{% endfor %}
+    /**** APPLICATION RoT DATA end here */
+
+    /* Position tag */
+    . = ALIGN(32);
+    Image$$PT_APP_RWZI_END$$Base = .;
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+    .TFM_SP_SECURE_TEST_PARTITION_LINKER_DATA : ALIGN(32)
+    {
+        *libc_nano*:*(.data*)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+
+    .TFM_SP_SECURE_TEST_PARTITION_LINKER_BSS : ALIGN(32)
+    {
+        /* FixMe:
+         * Test framework use printf to print out test result. Implementation of
+         * printf in GCC libc use static data and heap as well. To be able to
+         * execute test suites with TFM_LVL=3 this workaround is needed to
+         * allocate libc static data and heap within the data section of secure
+         * test partition. This can be removed if test service will be executed
+         * in privileged mode.
+         */
+        *libc_nano*:*(.bss*)
+        *libc_nano*:*(COMMON)
+
+        __end__ = .;
+        PROVIDE(end = .);
+        __HeapBase = .;
+        . += __heap_size__;
+        __HeapLimit = .;
+        __heap_limit = .; /* Add for _sbrk */
+
+        . = ALIGN(32);
+    } > RAM AT> RAM
+#else /* TFM_PARTITION_TEST_SECURE_SERVICES */
+    .heap : ALIGN(8)
+    {
+        __end__ = .;
+        PROVIDE(end = .);
+        __HeapBase = .;
+        . += __heap_size__;
+        __HeapLimit = .;
+        __heap_limit = .; /* Add for _sbrk */
+    } > RAM AT> RAM
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+    .TFM_DATA : ALIGN(4)
+    {
+        *(.data*)
+
+        . = ALIGN(4);
+        /* preinit data */
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP(*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+
+        . = ALIGN(4);
+        /* init data */
+        PROVIDE_HIDDEN (__init_array_start = .);
+        KEEP(*(SORT(.init_array.*)))
+        KEEP(*(.init_array))
+        PROVIDE_HIDDEN (__init_array_end = .);
+
+        . = ALIGN(4);
+        /* finit data */
+        PROVIDE_HIDDEN (__fini_array_start = .);
+        KEEP(*(SORT(.fini_array.*)))
+        KEEP(*(.fini_array))
+        PROVIDE_HIDDEN (__fini_array_end = .);
+
+        KEEP(*(.jcr*))
+        . = ALIGN(4);
+
+    } > RAM AT> FLASH
+    Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
+    Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
+
+    .TFM_BSS : ALIGN(4)
+    {
+        __bss_start__ = .;
+        *(.bss*)
+        *(COMMON)
+        . = ALIGN(4);
+        __bss_end__ = .;
+    } > RAM AT> RAM
+    Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
+    Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+
+    Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+    Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
+
+    /*
+     * Place the CMSE Veneers (containing the SG instruction) after the code, in a
+     * separate 32 bytes aligned region so that the SAU can programmed to just set
+     * this region as Non-Secure Callable.
+     */
+    .gnu.sgstubs : ALIGN(32)
+    {
+        *(.gnu.sgstubs*)
+        . = ALIGN(32);
+    } > VENEERS AT> VENEERS
+    Load$$LR$$LR_VENEER$$Base = ADDR(.gnu.sgstubs);
+    Load$$LR$$LR_VENEER$$Limit = ADDR(.gnu.sgstubs) + SIZEOF(.gnu.sgstubs);
+
+    Load$$LR$$LR_NS_PARTITION$$Base = NS_PARTITION_START;
+
+#ifdef BL2
+    Load$$LR$$LR_SECONDARY_PARTITION$$Base = SECONDARY_PARTITION_START;
+#endif /* BL2 */
+
+    PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
+}
diff --git a/platform/ext/target/mps2/an521/CMakeLists.txt b/platform/ext/target/mps2/an521/CMakeLists.txt
index aabdbaf..d1bd199 100644
--- a/platform/ext/target/mps2/an521/CMakeLists.txt
+++ b/platform/ext/target/mps2/an521/CMakeLists.txt
@@ -24,10 +24,15 @@
     $<$<C_COMPILER_ID:GNU>:${CMAKE_CURRENT_SOURCE_DIR}/gcc/startup_cmsdk_mps2_an521_s.S>
     $<$<C_COMPILER_ID:IAR>:${CMAKE_CURRENT_SOURCE_DIR}/iar/startup_cmsdk_mps2_an521_s.s>
 )
+
+# Use a common scatter file for Isolation L1 and L2, a dedicated one for Isolation L3
+# IAR is not supported for L3
 target_add_scatter_file(tfm_s
-    $<$<C_COMPILER_ID:ARMClang>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/armclang/tfm_common_s.sct>
-    $<$<C_COMPILER_ID:GNU>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/gcc/tfm_common_s.ld>
-    $<$<C_COMPILER_ID:IAR>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/iar/tfm_common_s.icf>
+    $<$<AND:$<VERSION_LESS:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:ARMClang>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/armclang/tfm_common_s.sct>
+    $<$<AND:$<VERSION_LESS:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:GNU>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/gcc/tfm_common_s.ld>
+    $<$<AND:$<VERSION_LESS:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:IAR>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/iar/tfm_common_s.icf>
+    $<$<AND:$<VERSION_EQUAL:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:ARMClang>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/armclang/tfm_isolation_l3.sct>
+    $<$<AND:$<VERSION_EQUAL:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:GNU>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/gcc/tfm_isolation_l3.ld>
 )
 
 if(NS)
diff --git a/platform/ext/target/mps2/an521/config.cmake b/platform/ext/target/mps2/an521/config.cmake
index a81c8a1..367749a 100644
--- a/platform/ext/target/mps2/an521/config.cmake
+++ b/platform/ext/target/mps2/an521/config.cmake
@@ -4,3 +4,5 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 #-------------------------------------------------------------------------------
+
+set(TFM_EXTRA_GENERATED_FILE_LIST_PATH  ${CMAKE_CURRENT_SOURCE_DIR}/platform/ext/target/mps2/an521/generated_file_list.yaml  CACHE PATH "Path to extra generated file list. Appended to stardard TFM generated file list." FORCE)
diff --git a/platform/ext/target/mps2/an521/generated_file_list.yaml b/platform/ext/target/mps2/an521/generated_file_list.yaml
new file mode 100644
index 0000000..fc36ea2
--- /dev/null
+++ b/platform/ext/target/mps2/an521/generated_file_list.yaml
@@ -0,0 +1,31 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+# The path of "template" can be relative path to TF-M root or absolute path
+# The path of "output" must be relative path to the root for generated files
+# Both can contain environment variables
+
+{
+  "name": "AN521 generated file list",
+  "type": "generated_file_list",
+  "version_major": 0,
+  "version_minor": 1,
+  "file_list": [
+    {
+        "name": "isolation l3 scatter file",
+        "short_name": "isolation_l3_sct",
+        "template": "platform/ext/common/armclang/tfm_isolation_l3.sct.template",
+        "output": "platform/ext/common/armclang/tfm_isolation_l3.sct"
+    },
+    {
+        "name": "isolation l3 linker script",
+        "short_name": "isolation_l3_ld",
+        "template": "platform/ext/common/gcc/tfm_isolation_l3.ld.template",
+        "output": "platform/ext/common/gcc/tfm_isolation_l3.ld"
+    }
+  ]
+}
diff --git a/platform/ext/target/mps2/an521/tfm_hal_isolation.c b/platform/ext/target/mps2/an521/tfm_hal_isolation.c
index d51ee58..ec8cf10 100644
--- a/platform/ext/target/mps2/an521/tfm_hal_isolation.c
+++ b/platform/ext/target/mps2/an521/tfm_hal_isolation.c
@@ -13,7 +13,49 @@
 #include "tfm_hal_isolation.h"
 
 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
-#if TFM_LVL != 3
+#if TFM_LVL == 3
+REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Base);
+REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Limit);
+REGION_DECLARE(Image$$, PT_RO_START, $$Base);
+REGION_DECLARE(Image$$, PT_RO_END, $$Base);
+REGION_DECLARE(Image$$, PT_PRIV_RWZI_START, $$Base);
+REGION_DECLARE(Image$$, PT_PRIV_RWZI_END, $$Base);
+
+static uint32_t g_static_region_cnt;
+
+static struct mpu_armv8m_region_cfg_t isolation_regions[] = {
+    {
+        0, /* will be updated before using */
+        (uint32_t)&REGION_NAME(Load$$LR$$, LR_VENEER, $$Base),
+        (uint32_t)&REGION_NAME(Load$$LR$$, LR_VENEER, $$Limit),
+        MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
+        MPU_ARMV8M_XN_EXEC_OK,
+        MPU_ARMV8M_AP_RO_PRIV_UNPRIV,
+        MPU_ARMV8M_SH_NONE,
+    },
+    {
+        0, /* will be updated before using */
+        (uint32_t)&REGION_NAME(Image$$, PT_RO_START, $$Base),
+        (uint32_t)&REGION_NAME(Image$$, PT_RO_END, $$Base),
+        MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
+        MPU_ARMV8M_XN_EXEC_OK,
+        MPU_ARMV8M_AP_RO_PRIV_UNPRIV,
+        MPU_ARMV8M_SH_NONE,
+    },
+    /* For isolation Level 3, set up static isolation for privileged data.
+     * Unprivileged data is dynamically set during Partition sheduling.
+     */
+    {
+        0, /* will be updated before using */
+        (uint32_t)&REGION_NAME(Image$$, PT_PRIV_RWZI_START, $$Base),
+        (uint32_t)&REGION_NAME(Image$$, PT_PRIV_RWZI_END, $$Base),
+        MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
+        MPU_ARMV8M_XN_EXEC_NEVER,
+        MPU_ARMV8M_AP_RW_PRIV_ONLY,
+        MPU_ARMV8M_SH_NONE,
+    },
+};
+#else /* TFM_LVL == 3 */
 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
 
 #define MPU_REGION_VENEERS              0
@@ -98,7 +140,7 @@
         MPU_ARMV8M_SH_NONE
     }
 };
-#endif /* TFM_LVL != 3 */
+#endif /* TFM_LVL == 3 */
 #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
 
 enum tfm_hal_status_t tfm_hal_set_up_static_boundaries(void)
@@ -112,12 +154,27 @@
 
     /* Set up static isolation boundaries inside SPE */
 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
-#if TFM_LVL != 3
     int32_t i;
     struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
 
     mpu_armv8m_clean(&dev_mpu_s);
 
+#if TFM_LVL == 3
+    uint32_t cnt;
+
+    /* Update MPU region numbers. The numbers start from 0 and are continuous */
+    cnt = sizeof(isolation_regions) / sizeof(isolation_regions[0]);
+    g_static_region_cnt = cnt;
+    for (i = 0; i < cnt; i++) {
+        /* Update region number */
+        isolation_regions[i].region_nr = i;
+        /* Enable regions */
+        if (mpu_armv8m_region_enable(&dev_mpu_s, &isolation_regions[i])
+                                                             != MPU_ARMV8M_OK) {
+            return TFM_HAL_ERROR_GENERIC;
+        }
+    }
+#else /* TFM_LVL == 3 */
     for (i = 0; i < ARRAY_SIZE(region_cfg); i++) {
         if (mpu_armv8m_region_enable(&dev_mpu_s,
             (struct mpu_armv8m_region_cfg_t *)&region_cfg[i])
@@ -125,11 +182,39 @@
             return TFM_HAL_ERROR_GENERIC;
         }
     }
+#endif /* TFM_LVL == 3 */
 
-    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
-                      HARDFAULT_NMI_ENABLE);
-#endif /* TFM_LVL != 3 */
+    /* Enable MPU */
+    if (mpu_armv8m_enable(&dev_mpu_s,
+                          PRIVILEGED_DEFAULT_ENABLE,
+                          HARDFAULT_NMI_ENABLE) != MPU_ARMV8M_OK) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
 #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
 
     return TFM_HAL_SUCCESS;
 }
+
+#if TFM_LVL == 3
+enum tfm_hal_status_t tfm_hal_mpu_update_partition_boundary(uintptr_t start,
+                                                            uintptr_t end)
+{
+    struct mpu_armv8m_region_cfg_t cfg;
+    enum mpu_armv8m_error_t mpu_err;
+    struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
+
+    /* Partition boundary regions is right after static regions */
+    cfg.region_nr = g_static_region_cnt;
+    cfg.region_base = start;
+    cfg.region_limit = end;
+    cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DATA_IDX;
+    cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
+    cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
+    cfg.attr_sh = MPU_ARMV8M_SH_NONE;
+    mpu_err = mpu_armv8m_region_enable(&dev_mpu_s, &cfg);
+    if (mpu_err != MPU_ARMV8M_OK) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
+    return TFM_HAL_SUCCESS;
+}
+#endif /* TFM_LVL == 3 */
diff --git a/platform/ext/target/musca_b1/CMakeLists.txt b/platform/ext/target/musca_b1/CMakeLists.txt
index a1f9c5a..d2bb26f 100644
--- a/platform/ext/target/musca_b1/CMakeLists.txt
+++ b/platform/ext/target/musca_b1/CMakeLists.txt
@@ -23,9 +23,15 @@
     $<$<C_COMPILER_ID:ARMClang>:${CMAKE_CURRENT_SOURCE_DIR}/Device/Source/armclang/startup_cmsdk_musca_s.s>
     $<$<C_COMPILER_ID:GNU>:${CMAKE_CURRENT_SOURCE_DIR}/Device/Source/gcc/startup_cmsdk_musca_s.S>
 )
+
+# Use a common scatter file for Isolation L1 and L2, a dedicated one for Isolation L3
+# IAR is not supported for L3
 target_add_scatter_file(tfm_s
-    $<$<C_COMPILER_ID:ARMClang>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/armclang/tfm_common_s.sct>
-    $<$<C_COMPILER_ID:GNU>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/gcc/tfm_common_s.ld>
+    $<$<AND:$<VERSION_LESS:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:ARMClang>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/armclang/tfm_common_s.sct>
+    $<$<AND:$<VERSION_LESS:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:GNU>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/gcc/tfm_common_s.ld>
+    $<$<AND:$<VERSION_LESS:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:IAR>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/iar/tfm_common_s.icf>
+    $<$<AND:$<VERSION_EQUAL:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:ARMClang>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/armclang/tfm_isolation_l3.sct>
+    $<$<AND:$<VERSION_EQUAL:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:GNU>>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/gcc/tfm_isolation_l3.ld>
 )
 
 if(NS)
diff --git a/platform/ext/target/musca_b1/config.cmake b/platform/ext/target/musca_b1/config.cmake
index a3bb018..b26e7a3 100644
--- a/platform/ext/target/musca_b1/config.cmake
+++ b/platform/ext/target/musca_b1/config.cmake
@@ -12,3 +12,5 @@
 if(CRYPTO_HW_ACCELERATOR_OTP_STATE STREQUAL "ENABLED")
     set(PLATFORM_DUMMY_CRYPTO_KEYS      FALSE       CACHE BOOL      "Use dummy crypto keys. Should not be used in production.")
 endif()
+
+set(TFM_EXTRA_GENERATED_FILE_LIST_PATH  ${CMAKE_CURRENT_SOURCE_DIR}/platform/ext/target/musca_b1/generated_file_list.yaml  CACHE PATH "Path to extra generated file list. Appended to stardard TFM generated file list." FORCE)
diff --git a/platform/ext/target/musca_b1/generated_file_list.yaml b/platform/ext/target/musca_b1/generated_file_list.yaml
new file mode 100644
index 0000000..ff01824
--- /dev/null
+++ b/platform/ext/target/musca_b1/generated_file_list.yaml
@@ -0,0 +1,31 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+# The path of "template" can be relative path to TF-M root or absolute path
+# The path of "output" must be relative path to the root for generated files
+# Both can contain environment variables
+
+{
+  "name": "musca-b1 generated file list",
+  "type": "generated_file_list",
+  "version_major": 0,
+  "version_minor": 1,
+  "file_list": [
+    {
+        "name": "isolation l3 scatter file",
+        "short_name": "isolation_l3_sct",
+        "template": "platform/ext/common/armclang/tfm_isolation_l3.sct.template",
+        "output": "platform/ext/common/armclang/tfm_isolation_l3.sct"
+    },
+    {
+        "name": "isolation l3 linker script",
+        "short_name": "isolation_l3_ld",
+        "template": "platform/ext/common/gcc/tfm_isolation_l3.ld.template",
+        "output": "platform/ext/common/gcc/tfm_isolation_l3.ld"
+    }
+  ]
+}
diff --git a/platform/ext/target/musca_b1/tfm_hal_isolation.c b/platform/ext/target/musca_b1/tfm_hal_isolation.c
index 67ac95a..d4bc4e1 100644
--- a/platform/ext/target/musca_b1/tfm_hal_isolation.c
+++ b/platform/ext/target/musca_b1/tfm_hal_isolation.c
@@ -13,7 +13,49 @@
 #include "tfm_hal_isolation.h"
 
 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
-#if TFM_LVL != 3
+#if TFM_LVL == 3
+REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Base);
+REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Limit);
+REGION_DECLARE(Image$$, PT_RO_START, $$Base);
+REGION_DECLARE(Image$$, PT_RO_END, $$Base);
+REGION_DECLARE(Image$$, PT_PRIV_RWZI_START, $$Base);
+REGION_DECLARE(Image$$, PT_PRIV_RWZI_END, $$Base);
+
+static uint32_t g_static_region_cnt;
+
+static struct mpu_armv8m_region_cfg_t isolation_regions[] = {
+    {
+        0, /* will be updated before using */
+        (uint32_t)&REGION_NAME(Load$$LR$$, LR_VENEER, $$Base),
+        (uint32_t)&REGION_NAME(Load$$LR$$, LR_VENEER, $$Limit),
+        MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
+        MPU_ARMV8M_XN_EXEC_OK,
+        MPU_ARMV8M_AP_RO_PRIV_UNPRIV,
+        MPU_ARMV8M_SH_NONE,
+    },
+    {
+        0, /* will be updated before using */
+        (uint32_t)&REGION_NAME(Image$$, PT_RO_START, $$Base),
+        (uint32_t)&REGION_NAME(Image$$, PT_RO_END, $$Base),
+        MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
+        MPU_ARMV8M_XN_EXEC_OK,
+        MPU_ARMV8M_AP_RO_PRIV_UNPRIV,
+        MPU_ARMV8M_SH_NONE,
+    },
+    /* For isolation Level 3, set up static isolation for privileged data.
+     * Unprivileged data is dynamically set during Partition sheduling.
+     */
+    {
+        0, /* will be updated before using */
+        (uint32_t)&REGION_NAME(Image$$, PT_PRIV_RWZI_START, $$Base),
+        (uint32_t)&REGION_NAME(Image$$, PT_PRIV_RWZI_END, $$Base),
+        MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
+        MPU_ARMV8M_XN_EXEC_NEVER,
+        MPU_ARMV8M_AP_RW_PRIV_ONLY,
+        MPU_ARMV8M_SH_NONE,
+    },
+};
+#else /* TFM_LVL == 3 */
 #define MPU_REGION_VENEERS              0
 #define MPU_REGION_TFM_UNPRIV_CODE      1
 #define MPU_REGION_TFM_UNPRIV_DATA      2
@@ -33,7 +75,8 @@
 REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Limit);
 
 extern const struct memory_region_limits memory_regions;
-#endif /* TFM_LVL != 3 */
+
+#endif /* TFM_LVL == 3 */
 #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
 
 enum tfm_hal_status_t tfm_hal_set_up_static_boundaries(void)
@@ -51,11 +94,27 @@
 
     /* Set up static isolation boundaries inside SPE */
 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
-#if TFM_LVL != 3
-    struct mpu_armv8m_region_cfg_t region_cfg;
+    int32_t i;
     struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
 
     mpu_armv8m_clean(&dev_mpu_s);
+#if TFM_LVL == 3
+    uint32_t cnt;
+
+    /* Update MPU region numbers. The numbers start from 0 and are continuous */
+    cnt = sizeof(isolation_regions) / sizeof(isolation_regions[0]);
+    g_static_region_cnt = cnt;
+    for (i = 0; i < cnt; i++) {
+        /* Update region number */
+        isolation_regions[i].region_nr = i;
+        /* Enable regions */
+        if (mpu_armv8m_region_enable(&dev_mpu_s, &isolation_regions[i])
+                                                             != MPU_ARMV8M_OK) {
+            return TFM_HAL_ERROR_GENERIC;
+        }
+    }
+#else /* TFM_LVL == 3 */
+    struct mpu_armv8m_region_cfg_t region_cfg;
 
     /* Veneer region */
     region_cfg.region_nr = MPU_REGION_VENEERS;
@@ -138,11 +197,39 @@
     if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
         return TFM_HAL_ERROR_GENERIC;
     }
+#endif /* TFM_LVL == 3 */
 
-    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
-                      HARDFAULT_NMI_ENABLE);
-#endif /* TFM_LVL != 3 */
-#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
+    /* Enable MPU */
+    if (mpu_armv8m_enable(&dev_mpu_s,
+                          PRIVILEGED_DEFAULT_ENABLE,
+                          HARDFAULT_NMI_ENABLE) != MPU_ARMV8M_OK) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
+#endif
 
     return TFM_HAL_SUCCESS;
 }
+
+#if TFM_LVL == 3
+enum tfm_hal_status_t tfm_hal_mpu_update_partition_boundary(uintptr_t start,
+                                                            uintptr_t end)
+{
+    struct mpu_armv8m_region_cfg_t cfg;
+    enum mpu_armv8m_error_t mpu_err;
+    struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
+
+    /* Partition boundary regions is right after static regions */
+    cfg.region_nr = g_static_region_cnt;
+    cfg.region_base = start;
+    cfg.region_limit = end;
+    cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DATA_IDX;
+    cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
+    cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
+    cfg.attr_sh = MPU_ARMV8M_SH_NONE;
+    mpu_err = mpu_armv8m_region_enable(&dev_mpu_s, &cfg);
+    if (mpu_err != MPU_ARMV8M_OK) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
+    return TFM_HAL_SUCCESS;
+}
+#endif /* TFM_LVL == 3 */
diff --git a/platform/include/tfm_spm_hal.h b/platform/include/tfm_spm_hal.h
index fc2246a..0b49340 100644
--- a/platform/include/tfm_spm_hal.h
+++ b/platform/include/tfm_spm_hal.h
@@ -43,8 +43,17 @@
  */
 struct tfm_spm_partition_memory_data_t
 {
-    uint32_t stack_bottom; /*!< The bottom of the stack for the partition. */
-    uint32_t stack_top;    /*!< The top of the stack for the partition. */
+#if TFM_LVL == 3
+    uint32_t data_start;    /* Start of the private data region of current
+                             * partition. Specifically, the private data
+                             * includes RW, ZI and the partition stack below.
+                             */
+    uint32_t data_limit;    /* Address of the byte beyond the end of the data
+                             * region of this partition.
+                             */
+#endif
+    uint32_t stack_bottom;  /* The bottom of the stack for the partition. */
+    uint32_t stack_top;     /* The top of the stack for the partition. */
 };
 #endif