tests: arch: arm: verify Armv8.1-M MPU PXN
Adds a test to verify Armv8.1-M MPU architecture's PXN attribute. Verify PXN via static mpu config by utilizing existing __ramfunc MPU region Since previous commit changes the behaviour of __ramfunc region, executing userspace code in this region in privileged mode will result in an MPU fault while execution in unprivileged mode should work fine. Verify PXN via DT by creating a custom section in the unused SRAM region. Since the overlay sets the PXN attribute for the SRAM, executing code in this region in privileged mode will result in an MPU fault while, execution in unprivileged mode should work fine. Also, instead of testing DT config for each board, do it only for MPS3 boards that which can be tested with simulation. Signed-off-by: Sudan Landge <sudan.landge@arm.com>
This commit is contained in:
parent
637bd8f587
commit
0161118913
9 changed files with 226 additions and 0 deletions
10
tests/arch/arm/arm_mpu_pxn/CMakeLists.txt
Normal file
10
tests/arch/arm/arm_mpu_pxn/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(arm_mpu_pxn)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
zephyr_linker_sources_ifdef(CONFIG_SOC_MPS3_CORSTONE300 RAM_SECTIONS mps3_corstone300.ld)
|
||||
zephyr_linker_sources_ifdef(CONFIG_SOC_MPS3_CORSTONE310 RAM_SECTIONS mps3_corstone310.ld)
|
11
tests/arch/arm/arm_mpu_pxn/mps3_corstone300.ld
Normal file
11
tests/arch/arm/arm_mpu_pxn/mps3_corstone300.ld
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
SECTION_DATA_PROLOGUE(.customramfunc, , )
|
||||
{
|
||||
*(.customramfunc) * (".customramfunc.*")
|
||||
}
|
||||
GROUP_DATA_LINK_IN(SRAM, SRAM)
|
18
tests/arch/arm/arm_mpu_pxn/mps3_corstone300_an547.overlay
Normal file
18
tests/arch/arm/arm_mpu_pxn/mps3_corstone300_an547.overlay
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/memory-attr/memory-attr.h>
|
||||
#include <zephyr/dt-bindings/memory-attr/memory-attr-arm.h>
|
||||
|
||||
|
||||
/ {
|
||||
sram: sram@11000000 {
|
||||
compatible = "zephyr,memory-region", "mmio-sram";
|
||||
reg = <0x11000000 DT_SIZE_M(1)>;
|
||||
zephyr,memory-region = "SRAM";
|
||||
zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_PXN) )>;
|
||||
};
|
||||
};
|
18
tests/arch/arm/arm_mpu_pxn/mps3_corstone300_fvp.overlay
Normal file
18
tests/arch/arm/arm_mpu_pxn/mps3_corstone300_fvp.overlay
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/memory-attr/memory-attr.h>
|
||||
#include <zephyr/dt-bindings/memory-attr/memory-attr-arm.h>
|
||||
|
||||
|
||||
/ {
|
||||
sram: sram@11000000 {
|
||||
compatible = "zephyr,memory-region", "mmio-sram";
|
||||
reg = <0x11000000 DT_SIZE_M(1)>;
|
||||
zephyr,memory-region = "SRAM";
|
||||
zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_PXN) )>;
|
||||
};
|
||||
};
|
11
tests/arch/arm/arm_mpu_pxn/mps3_corstone310.ld
Normal file
11
tests/arch/arm/arm_mpu_pxn/mps3_corstone310.ld
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
SECTION_DATA_PROLOGUE(.customramfunc, , )
|
||||
{
|
||||
*(.customramfunc) * (".customramfunc.*")
|
||||
}
|
||||
GROUP_DATA_LINK_IN(DTCM, DTCM)
|
18
tests/arch/arm/arm_mpu_pxn/mps3_corstone310_fvp.overlay
Normal file
18
tests/arch/arm/arm_mpu_pxn/mps3_corstone310_fvp.overlay
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/memory-attr/memory-attr.h>
|
||||
#include <zephyr/dt-bindings/memory-attr/memory-attr-arm.h>
|
||||
|
||||
|
||||
/ {
|
||||
dtcm: dtcm@30000000 {
|
||||
compatible = "zephyr,memory-region";
|
||||
reg = <0x30000000 DT_SIZE_K(32)>;
|
||||
zephyr,memory-region = "DTCM";
|
||||
zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_PXN) )>;
|
||||
};
|
||||
};
|
2
tests/arch/arm/arm_mpu_pxn/prj.conf
Normal file
2
tests/arch/arm/arm_mpu_pxn/prj.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
CONFIG_ZTEST=y
|
||||
CONFIG_ZTEST_FATAL_HOOK=y
|
118
tests/arch/arm/arm_mpu_pxn/src/main.c
Normal file
118
tests/arch/arm/arm_mpu_pxn/src/main.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
#include <zephyr/ztest.h>
|
||||
#include <zephyr/ztest_error_hook.h>
|
||||
|
||||
#define __customramfunc \
|
||||
__attribute__((noinline)) __attribute__((long_call, section(".customramfunc")))
|
||||
|
||||
/**
|
||||
* @brief Simple func to verify PXN via DT config since code with
|
||||
* __customramfunc falls in an MPU region with PXN set
|
||||
*
|
||||
*/
|
||||
__customramfunc bool custom_ram_func(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This is a simple solution to execute a code with and without PXN set
|
||||
* because code that falls in `__ramfunc` section has PXN attr set if
|
||||
* built with CONFIG_USERSPACE and unset otherwise.
|
||||
*/
|
||||
__ramfunc bool ram_function(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
/**
|
||||
* @brief Verify that MPU region with PXN attribute set can be executed from
|
||||
* unprivileged mode.
|
||||
*/
|
||||
ZTEST_USER(arm_mpu_pxn, test_arm_mpu_pxn_static_config_user)
|
||||
{
|
||||
volatile bool ramfunc_called = false;
|
||||
/*
|
||||
* With CONFIG_USERSPACE
|
||||
* - this func is called in unprivileged mode
|
||||
* - and __ramfunc falls in an MPU region which has PXN attribute set
|
||||
*
|
||||
* Calling ram_function shouldn't result in an exception.
|
||||
* This confirms that ram_function though part of a region with PXN attribute set,
|
||||
* can be called from an unprivileged code.
|
||||
*/
|
||||
ramfunc_called = ram_function();
|
||||
zassert_true(true == ramfunc_called,
|
||||
"Executing code in __ramfunc failed in unprivileged mode.");
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Verify that region marked with PXN attribute via DT can be executed
|
||||
* from unprivileged mode but cannot be executed from privileged mode.
|
||||
*/
|
||||
ZTEST_USER(arm_mpu_pxn, test_arm_mpu_pxn_dt)
|
||||
{
|
||||
volatile bool ramfunc_called = false;
|
||||
#ifndef CONFIG_USERSPACE
|
||||
/*
|
||||
* It is expected that calling ram_function() should result in an exception
|
||||
* because with CONFIG_USERSPACE, ram_function falls in region with
|
||||
* PXN attribute set.
|
||||
*/
|
||||
ztest_set_fault_valid(true);
|
||||
#endif
|
||||
|
||||
ramfunc_called = custom_ram_func();
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
zassert_true(1 == ramfunc_called,
|
||||
"Executing code in __customramfunc failed in unprivileged mode.");
|
||||
#else
|
||||
/*
|
||||
* If calling ram_function didn't result in an MPU fault then,
|
||||
* PXN isn't working as expected so, fail the test.
|
||||
*/
|
||||
ztest_test_fail();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This func is always called in privileged mode so, verify that:
|
||||
* - region marked with PXN attribute
|
||||
* cannot be executed from privileged mode
|
||||
* - and same region when marked without PXN attribute
|
||||
* can be executed from privileged mode
|
||||
*/
|
||||
ZTEST(arm_mpu_pxn, test_arm_mpu_pxn_static_config)
|
||||
{
|
||||
volatile bool ramfunc_called = false;
|
||||
#ifdef CONFIG_USERSPACE
|
||||
/*
|
||||
* It is expected that calling ram_function() should result in an exception
|
||||
* because with CONFIG_USERSPACE, ram_function falls in region with
|
||||
* PXN attribute set.
|
||||
*/
|
||||
ztest_set_fault_valid(true);
|
||||
#endif
|
||||
ramfunc_called = ram_function();
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
/*
|
||||
* If calling ram_function didn't result in an MPU fault then,
|
||||
* PXN isn't working as expected so, fail the test.
|
||||
*/
|
||||
ztest_test_fail();
|
||||
#else
|
||||
zassert_true(1 == ramfunc_called, "Executing code in __ramfunc failed in privileged mode.");
|
||||
#endif
|
||||
}
|
||||
|
||||
ZTEST_SUITE(arm_mpu_pxn, NULL, NULL, NULL, NULL, NULL);
|
20
tests/arch/arm/arm_mpu_pxn/testcase.yaml
Normal file
20
tests/arch/arm/arm_mpu_pxn/testcase.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
common:
|
||||
filter: CONFIG_ARM_MPU_PXN
|
||||
tags:
|
||||
- arm
|
||||
- mpu
|
||||
platform_allow:
|
||||
- mps3/corstone300/an547
|
||||
- mps3/corstone300/fvp
|
||||
# TODO: enable this after CONFIG_USERSPACE is supported for mps3/corstone310
|
||||
# - mps3/corstone310/fvp
|
||||
tests:
|
||||
# To verify that region marked with PXN attribute can be executed from unprivileged code
|
||||
# and cannot be executed from privileged code
|
||||
arch.arm.pxn_with_userspace:
|
||||
extra_configs:
|
||||
- CONFIG_USERSPACE=y
|
||||
# To verify that region marked *without* PXN attribute can be executed from privileged code
|
||||
arch.arm.pxn_without_userspace:
|
||||
extra_configs:
|
||||
- CONFIG_USERSPACE=n
|
Loading…
Add table
Add a link
Reference in a new issue