Skip to content

Commit

Permalink
Armv8.1-m: Add pacbti support (#1147)
Browse files Browse the repository at this point in the history
* copyright-checker: Add FreeRTOS Arm collab copyright

FreeRTOS Arm collab files shall have both Amazon's
and Arm's copyright headers. Hence, the copyright
checker is modified to check for both copyrights.

Signed-off-by: Gaurav Aggarwal <[email protected]>

* armv8-m: Add support for IAR with TFM FREERTOS PORT

As the case for ARMClang, and GCC toolchains, IAR
with TFM FreeRTOS Port support is added.

Signed-off-by: Ahmed Ismail <[email protected]>

* armv8-m: Do not overwrite Control register value

The current ARMv8-M FreeRTOS-Kernel Port code
implementation is modified in a way that allows
the CONTROL register's value to be retained
rather than being overwritten.

This is needed for adding PACBTI support as
the special-purpose CONTROL register `PAC_EN`,
`UPAC_EN`, `BTI_EN`, and `UBTI_EN` PACBTI
enablement bits should be configured before calling
`vRestoreContextOfFirstTask()` function which currently
overwrite the value inside the CONTROL register.

Signed-off-by: Ahmed Ismail <[email protected]>

* armv8.1-m: Add PACBTI support to kernel non-secure implementation

In this commit, Pointer Authentication, and Branch Target
Identification Extension (PACBTI) support is added for
Non-Secure and Non-TrustZone variants of Cortex-M85
FreeRTOS-Kernel Port.

The PACBTI support is added for Arm Compiler For
Embedded, and IAR toolchains only. The support in
the kernel is not yet enabled for GNU toolchain
due to known issues.

Signed-off-by: Ahmed Ismail <[email protected]>

* Fix CI check

Signed-off-by: Gaurav Aggarwal <[email protected]>

---------

Signed-off-by: Gaurav Aggarwal <[email protected]>
Signed-off-by: Ahmed Ismail <[email protected]>
Co-authored-by: Ahmed Ismail <[email protected]>
Co-authored-by: Gaurav Aggarwal <[email protected]>
  • Loading branch information
3 people authored Oct 24, 2024
1 parent e400cc9 commit 7081e76
Show file tree
Hide file tree
Showing 81 changed files with 2,430 additions and 92 deletions.
5 changes: 5 additions & 0 deletions .github/.cSpellWords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ MAINRDY
MAIR
Mang
Mbits
mbranch
mcause
MCFR
MCKA
Expand Down Expand Up @@ -586,6 +587,8 @@ OWATCOM
OWDR
OWER
OWSR
pacbti
PACBTI
PAGEN
PCDR
PCER
Expand Down Expand Up @@ -900,6 +903,7 @@ TXTEN
TXUBR
TXVC
TXVDIS
UBTI
UDCP
UNACKED
uncrustify
Expand All @@ -915,6 +919,7 @@ UNSUB
UNSUBACK
unsubscriptions
unsuspended
UPAC
URAD
URAT
URSTEN
Expand Down
99 changes: 91 additions & 8 deletions .github/scripts/kernel_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
# */

import os
import re
from common.header_checker import HeaderChecker

#--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -106,6 +107,15 @@
r'.*portable/GCC/AVR32_UC3/.*',
]

KERNEL_ARM_COLLAB_FILES_PATTERNS = [
r'.*portable/ARMv8M/*',
r'.*portable/.*/ARM_CM23*',
r'.*portable/.*/ARM_CM33*',
r'.*portable/.*/ARM_CM35*',
r'.*portable/.*/ARM_CM55*',
r'.*portable/.*/ARM_CM85*',
]

KERNEL_HEADER = [
'/*\n',
' * FreeRTOS Kernel <DEVELOPMENT BRANCH>\n',
Expand Down Expand Up @@ -139,19 +149,92 @@

FREERTOS_COPYRIGHT_REGEX = r"^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$"

FREERTOS_ARM_COLLAB_COPYRIGHT_REGEX = r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$)|" + \
r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright 20\d\d Arm Limited and/or its affiliates( \*\/)?$)|" + \
r"(^(;|#)?( *(\/\*|\*|#|\/\/))? <[email protected]>( \*\/)?$)"


class KernelHeaderChecker(HeaderChecker):
def __init__(
self,
header,
padding=1000,
ignored_files=None,
ignored_ext=None,
ignored_patterns=None,
py_ext=None,
asm_ext=None,
third_party_patterns=None,
copyright_regex = None
):
super().__init__(header, padding, ignored_files, ignored_ext, ignored_patterns,
py_ext, asm_ext, third_party_patterns, copyright_regex)

self.armCollabRegex = re.compile(FREERTOS_ARM_COLLAB_COPYRIGHT_REGEX)

self.armCollabFilesPatternList = []
for pattern in KERNEL_ARM_COLLAB_FILES_PATTERNS:
self.armCollabFilesPatternList.append(re.compile(pattern))

def isArmCollabFile(self, path):
for pattern in self.armCollabFilesPatternList:
if pattern.match(path):
return True
return False

def checkArmCollabFile(self, path):
isValid = False
file_ext = os.path.splitext(path)[-1]

with open(path, encoding="utf-8", errors="ignore") as file:
chunk = file.read(len("".join(self.header)) + self.padding)
lines = [("%s\n" % line) for line in chunk.strip().splitlines()][
: len(self.header) + 2
]
if (len(lines) > 0) and (lines[0].find("#!") == 0):
lines.remove(lines[0])

# Split lines in sections.
headers = dict()
headers["text"] = []
headers["copyright"] = []
headers["spdx"] = []
for line in lines:
if self.armCollabRegex.match(line):
headers["copyright"].append(line)
elif "SPDX-License-Identifier:" in line:
headers["spdx"].append(line)
else:
headers["text"].append(line)

text_equal = self.isValidHeaderSection(file_ext, "text", headers["text"])
spdx_equal = self.isValidHeaderSection(file_ext, "spdx", headers["spdx"])

if text_equal and spdx_equal and len(headers["copyright"]) == 3:
isValid = True

return isValid

def customCheck(self, path):
isValid = False
if self.isArmCollabFile(path):
isValid = self.checkArmCollabFile(path)
return isValid


def main():
parser = HeaderChecker.configArgParser()
args = parser.parse_args()

# Configure the checks then run
checker = HeaderChecker(KERNEL_HEADER,
copyright_regex=FREERTOS_COPYRIGHT_REGEX,
ignored_files=KERNEL_IGNORED_FILES,
ignored_ext=KERNEL_IGNORED_EXTENSIONS,
ignored_patterns=KERNEL_IGNORED_PATTERNS,
third_party_patterns=KERNEL_THIRD_PARTY_PATTERNS,
py_ext=KERNEL_PY_EXTENSIONS,
asm_ext=KERNEL_ASM_EXTENSIONS)
checker = KernelHeaderChecker(KERNEL_HEADER,
copyright_regex=FREERTOS_COPYRIGHT_REGEX,
ignored_files=KERNEL_IGNORED_FILES,
ignored_ext=KERNEL_IGNORED_EXTENSIONS,
ignored_patterns=KERNEL_IGNORED_PATTERNS,
third_party_patterns=KERNEL_THIRD_PARTY_PATTERNS,
py_ext=KERNEL_PY_EXTENSIONS,
asm_ext=KERNEL_ASM_EXTENSIONS)
checker.ignoreFile(os.path.split(__file__)[-1])

rc = checker.processArgs(args)
Expand Down
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,18 @@ if(NOT FREERTOS_PORT)
" IAR_ARM_CM33_NONSECURE - Compiler: IAR Target: ARM Cortex-M33 non-secure\n"
" IAR_ARM_CM33_SECURE - Compiler: IAR Target: ARM Cortex-M33 secure\n"
" IAR_ARM_CM33_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M33 non-trustzone non-secure\n"
" IAR_ARM_CM33_TFM - Compiler: IAR Target: ARM Cortex-M33 non-secure for TF-M\n"
" IAR_ARM_CM35P_NONSECURE - Compiler: IAR Target: ARM Cortex-M35P non-secure\n"
" IAR_ARM_CM35P_SECURE - Compiler: IAR Target: ARM Cortex-M35P secure\n"
" IAR_ARM_CM35P_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M35P non-trustzone non-secure\n"
" IAR_ARM_CM55_NONSECURE - Compiler: IAR Target: ARM Cortex-M55 non-secure\n"
" IAR_ARM_CM55_SECURE - Compiler: IAR Target: ARM Cortex-M55 secure\n"
" IAR_ARM_CM55_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M55 non-trustzone non-secure\n"
" IAR_ARM_CM55_TFM - Compiler: IAR Target: ARM Cortex-M55 non-secure for TF-M\n"
" IAR_ARM_CM85_NONSECURE - Compiler: IAR Target: ARM Cortex-M85 non-secure\n"
" IAR_ARM_CM85_SECURE - Compiler: IAR Target: ARM Cortex-M85 secure\n"
" IAR_ARM_CM85_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M85 non-trustzone non-secure\n"
" IAR_ARM_CM85_TFM - Compiler: IAR Target: ARM Cortex-M85 non-secure for TF-M\n"
" IAR_ARM_CRX_NOGIC - Compiler: IAR Target: ARM Cortex-Rx no GIC\n"
" IAR_ATMEGA323 - Compiler: IAR Target: ATMega323\n"
" IAR_ATMEL_SAM7S64 - Compiler: IAR Target: Atmel SAM7S64\n"
Expand Down
2 changes: 1 addition & 1 deletion examples/coverity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ files.

## Getting Started
### Prerequisites
Coverity can be run on any platform mentioned [here](https://sig-docs.synopsys.com/polaris/topics/c_coverity-compatible-platforms.html).
Coverity can be run on any platform mentioned [here](https://documentation.blackduck.com/bundle/coverity-docs/page/deploy-install-guide/topics/supported_platforms_for_coverity_analysis.html).
The following are the prerequisites to generate coverity report:

1. CMake version > 3.13.0 (You can check whether you have this by typing `cmake --version`).
Expand Down
12 changes: 12 additions & 0 deletions include/FreeRTOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -3032,6 +3032,18 @@
#define configCONTROL_INFINITE_LOOP()
#endif

/* Set configENABLE_PAC and/or configENABLE_BTI to 1 to enable PAC and/or BTI
* support and 0 to disable them. These are currently used in ARMv8.1-M ports. */
#if ( portHAS_PACBTI_FEATURE == 1 )
#ifndef configENABLE_PAC
#define configENABLE_PAC 0
#endif

#ifndef configENABLE_BTI
#define configENABLE_BTI 0
#endif
#endif

/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using
* dynamically allocated RAM, in which case when any task is deleted it is known
* that both the task's stack and TCB need to be freed. Sometimes the
Expand Down
97 changes: 95 additions & 2 deletions portable/ARMv8M/non_secure/port.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <[email protected]>
*
* SPDX-License-Identifier: MIT
*
Expand Down Expand Up @@ -110,6 +112,7 @@ typedef void ( * portISR_t )( void );
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
#define portSCB_USG_FAULT_ENABLE_BIT ( 1UL << 18UL )
/*-----------------------------------------------------------*/

/**
Expand Down Expand Up @@ -373,6 +376,20 @@ typedef void ( * portISR_t )( void );
* any secure calls.
*/
#define portNO_SECURE_CONTEXT 0

/**
* @brief Constants required to check and configure PACBTI security feature implementation.
*/
#if ( portHAS_PACBTI_FEATURE == 1 )

#define portID_ISAR5_REG ( *( ( volatile uint32_t * ) 0xe000ed74 ) )

#define portCONTROL_UPAC_EN ( 1UL << 7UL )
#define portCONTROL_PAC_EN ( 1UL << 6UL )
#define portCONTROL_UBTI_EN ( 1UL << 5UL )
#define portCONTROL_BTI_EN ( 1UL << 4UL )

#endif /* portHAS_PACBTI_FEATURE */
/*-----------------------------------------------------------*/

/**
Expand Down Expand Up @@ -410,6 +427,26 @@ static void prvTaskExitError( void );
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
#endif /* configENABLE_FPU */

#if ( portHAS_PACBTI_FEATURE == 1 )

/**
* @brief Configures PACBTI features.
*
* This function configures the Pointer Authentication, and Branch Target
* Identification security features as per the user configuration. It returns
* the value of the special purpose CONTROL register accordingly, and optionally
* updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
* architecture based) target supports PACBTI security feature.
*
* @param xWriteControlRegister Used to control whether the special purpose
* CONTROL register should be updated or not.
*
* @return CONTROL register value according to the configured PACBTI option.
*/
static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );

#endif /* portHAS_PACBTI_FEATURE */

/**
* @brief Setup the timer to generate the tick interrupts.
*
Expand Down Expand Up @@ -1457,6 +1494,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
xMPU_SETTINGS * xMPUSettings ) /* PRIVILEGED_FUNCTION */
{
uint32_t ulIndex = 0;
uint32_t ulControl = 0x0;

xMPUSettings->ulContext[ ulIndex ] = 0x04040404; /* r4. */
ulIndex++;
Expand Down Expand Up @@ -1503,16 +1541,24 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
ulIndex++;

#if ( portHAS_PACBTI_FEATURE == 1 )
{
/* Check PACBTI security feature configuration before pushing the
* CONTROL register's value on task's TCB. */
ulControl = prvConfigurePACBTI( pdFALSE );
}
#endif /* portHAS_PACBTI_FEATURE */

if( xRunPrivileged == pdTRUE )
{
xMPUSettings->ulTaskFlags |= portTASK_IS_PRIVILEGED_FLAG;
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portINITIAL_CONTROL_PRIVILEGED; /* CONTROL. */
xMPUSettings->ulContext[ ulIndex ] = ( ulControl | ( uint32_t ) portINITIAL_CONTROL_PRIVILEGED ); /* CONTROL. */
ulIndex++;
}
else
{
xMPUSettings->ulTaskFlags &= ( ~portTASK_IS_PRIVILEGED_FLAG );
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portINITIAL_CONTROL_UNPRIVILEGED; /* CONTROL. */
xMPUSettings->ulContext[ ulIndex ] = ( ulControl | ( uint32_t ) portINITIAL_CONTROL_UNPRIVILEGED ); /* CONTROL. */
ulIndex++;
}

Expand Down Expand Up @@ -1740,6 +1786,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;

#if ( portHAS_PACBTI_FEATURE == 1 )
{
/* Set the CONTROL register value based on PACBTI security feature
* configuration before starting the first task. */
( void) prvConfigurePACBTI( pdTRUE );
}
#endif /* portHAS_PACBTI_FEATURE */

#if ( configENABLE_MPU == 1 )
{
/* Setup the Memory Protection Unit (MPU). */
Expand Down Expand Up @@ -2158,3 +2212,42 @@ BaseType_t xPortIsInsideInterrupt( void )

#endif /* #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) */
/*-----------------------------------------------------------*/

#if ( portHAS_PACBTI_FEATURE == 1 )

static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
{
uint32_t ulControl = 0x0;

/* Ensure that PACBTI is implemented. */
configASSERT( portID_ISAR5_REG != 0x0 );

/* Enable UsageFault exception if PAC or BTI is enabled. */
#if( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
{
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
}
#endif

#if( configENABLE_PAC == 1 )
{
ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
}
#endif

#if( configENABLE_BTI == 1 )
{
ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
}
#endif

if( xWriteControlRegister == pdTRUE )
{
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
}

return ulControl;
}

#endif /* #if ( portHAS_PACBTI_FEATURE == 1 ) */
/*-----------------------------------------------------------*/
3 changes: 3 additions & 0 deletions portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portmacro.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <[email protected]>
*
* SPDX-License-Identifier: MIT
*
Expand Down Expand Up @@ -51,6 +53,7 @@
#define portARCH_NAME "Cortex-M23"
#define portHAS_ARMV8M_MAIN_EXTENSION 0
#define portARMV8M_MINOR_VERSION 0
#define portHAS_PACBTI_FEATURE 0
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <[email protected]>
*
* SPDX-License-Identifier: MIT
*
Expand Down Expand Up @@ -51,6 +53,7 @@
#define portARCH_NAME "Cortex-M23"
#define portHAS_ARMV8M_MAIN_EXTENSION 0
#define portARMV8M_MINOR_VERSION 0
#define portHAS_PACBTI_FEATURE 0
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/

Expand Down
Loading

0 comments on commit 7081e76

Please sign in to comment.