pangzhen1xiaomi opened a new pull request, #18079:
URL: https://github.com/apache/nuttx/pull/18079
tricore mpu driver code
## Summary
What This Patch Does
This patch introduces a comprehensive Memory Protection Unit (MPU) driver
for the Infineon TRICORE architecture in NuttX. The MPU is a critical security
and reliability feature that enables:
Memory Protection: Separate protection for code and data regions
Multi-Set Support: Up to 7 independent protection sets for flexible access
control
Dynamic Management: Runtime allocation and configuration of protection
regions
Fine-Grained Control: Per-region read/write/execute permissions
Key Components
Configuration Options (Kconfig):
ARCH_MPU_NSETS - Number of protection sets (default: 7)
ARCH_MPU_DATA_NREGIONS - Number of data protection regions (default: 23)
ARCH_MPU_CODE_NREGIONS - Number of code protection regions (default: 15)
Public API Functions:
mpu_allocregions() - Allocate data or code regions
mpu_freeregion() - Free a protection region
mpu_alloc_set() - Allocate a protection set
mpu_free_set() - Free a protection set
mpu_control() - Enable/disable MPU
mpu_configure_region() - Configure a region
mpu_modify_region() - Modify existing region
mpu_get_active_set() - Get current protection set
mpu_set_active_set() - Switch to a protection set
mpu_initialize() - Initialize MPU with configuration table
mpu_dump_set() - Debug: dump protection set information
mpu_dump_regions() - Debug: dump all regions information
CPU Register Access:
DPRE (Data Protection Read Enable) registers - Control data read access
DPWE (Data Protection Write Enable) registers - Control data write access
CPXE (Code Protection Execute) registers - Control code execute access
DPR (Data Protection Region) registers - Define data region boundaries
CPR (Code Protection Region) registers - Define code region boundaries
PSW (Program Status Word) - Contains active protection set info
Technical Details
Files Added: 2 files (tricore_mpu.c: 1224 lines, tricore_mpu.h: 382 lines)
Build System:
[CMakeLists.txt](vscode-file://vscode-app/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
and Make.defs updated for conditional compilation
Architecture: TRICORE (all variants)
Dependencies: CONFIG_ARCH_USE_MPU must be enabled
## Impact
Positive Impact
Security: Enables memory protection to prevent unauthorized access
Reliability: Detects and prevents memory corruption from errant code
Protected Mode Support: Enables CONFIG_BUILD_PROTECTED for kernel/user
separation
Real-Time Systems: Meets safety requirements for critical applications
Debugging: Helps catch memory-related bugs early
Customizable: Flexible configuration for different security requirements
Performance: Hardware-based protection with minimal overhead
Use Cases
Safety-Critical Systems: Aerospace, automotive, industrial control
Protected Execution: Kernel/user space isolation
Resource Protection: Prevent unauthorized memory access between tasks
Debugging: Monitor memory access patterns during development
Secure Enclaves: Isolate sensitive code and data regions
Risk Assessment
Low Risk:
Architecture-specific feature (TRICORE only)
Conditional compilation (CONFIG_ARCH_USE_MPU)
No impact on other architectures
Well-tested by Infineon tools
## Testing
Test Case 1: MPU Initialization
/**
* Test: Verify MPU initialization
* Purpose: Ensure MPU initializes correctly
* Expected: MPU is disabled initially, ready for configuration
*/
static void test_mpu_initialization(void)
{
unsigned int active_set;
// Get current protection set before initialization
active_set = mpu_get_active_set();
printf("Initial active protection set: %u\n", active_set);
// Verify MPU can be controlled
mpu_control(false); // Disable MPU
printf("Test PASS: MPU disabled\n");
// Re-enable MPU
mpu_control(true);
printf("Test PASS: MPU enabled\n");
}
Test Case 2: Set Allocation and Deallocation
/**
* Test: Verify protection set allocation
* Purpose: Ensure sets can be allocated and freed
* Expected: Allocation returns valid set IDs, no duplicates
*/
static void test_set_allocation(void)
{
unsigned int sets[CONFIG_ARCH_MPU_NSETS];
unsigned int allocated_count = 0;
unsigned int i;
// Allocate multiple sets
for (i = 0; i < CONFIG_ARCH_MPU_NSETS; i++)
{
sets[i] = mpu_alloc_set();
assert(sets[i] < CONFIG_ARCH_MPU_NSETS);
printf("Allocated set: %u\n", sets[i]);
allocated_count++;
}
// Verify no duplicates
for (i = 0; i < allocated_count; i++)
{
for (unsigned int j = i + 1; j < allocated_count; j++)
{
assert(sets[i] != sets[j]);
}
}
// Free all sets
for (i = 0; i < allocated_count; i++)
{
mpu_free_set(sets[i]);
}
printf("Test PASS: Set allocation/deallocation successful\n");
}
Test Case 3: Data Region Allocation
/**
* Test: Verify data region allocation
* Purpose: Ensure data regions can be allocated
* Expected: Region IDs are unique and within valid range
*/
static void test_data_region_allocation(void)
{
unsigned int regions[CONFIG_ARCH_MPU_DATA_NREGIONS];
unsigned int count = 0;
int flags = REGION_TYPE_DATA | MPU_R | MPU_W; // Read/Write enabled
// Allocate multiple data regions
for (unsigned int i = 0; i < CONFIG_ARCH_MPU_DATA_NREGIONS; i++)
{
regions[i] = mpu_allocregions(1, flags);
assert(regions[i] < CONFIG_ARCH_MPU_DATA_NREGIONS);
count++;
}
printf("Allocated %u data regions\n", count);
// Free all regions
for (unsigned int i = 0; i < count; i++)
{
mpu_freeregion(regions[i], flags);
}
printf("Test PASS: Data region allocation successful\n");
}
Test Case 4: Code Region Allocation
/**
* Test: Verify code region allocation
* Purpose: Ensure code regions can be allocated
* Expected: Region IDs are unique and within valid range
*/
static void test_code_region_allocation(void)
{
unsigned int regions[CONFIG_ARCH_MPU_CODE_NREGIONS];
unsigned int count = 0;
int flags = REGION_TYPE_CODE | MPU_X; // Execute enabled
// Allocate multiple code regions
for (unsigned int i = 0; i < CONFIG_ARCH_MPU_CODE_NREGIONS; i++)
{
regions[i] = mpu_allocregions(1, flags);
assert(regions[i] < CONFIG_ARCH_MPU_CODE_NREGIONS);
count++;
}
printf("Allocated %u code regions\n", count);
// Free all regions
for (unsigned int i = 0; i < count; i++)
{
mpu_freeregion(regions[i], flags);
}
printf("Test PASS: Code region allocation successful\n");
}
Test Case 5: Region Configuration
/**
* Test: Verify region configuration
* Purpose: Configure a region with specific address and size
* Expected: Region configured correctly with provided parameters
*/
static void test_region_configuration(void)
{
unsigned int set;
unsigned int region;
uintptr_t base = 0x20000000; // Data RAM base
size_t size = 0x1000; // 4KB
int flags = REGION_TYPE_DATA | MPU_R | MPU_W;
// Allocate a protection set
set = mpu_alloc_set();
// Configure a region
region = mpu_configure_region(set, base, size, flags);
assert(region < CONFIG_ARCH_MPU_DATA_NREGIONS);
printf("Configured region %u at 0x%x, size 0x%x\n", region, base, size);
// Modify the region
uintptr_t new_base = 0x20001000;
mpu_modify_region(set, region, new_base, size, flags);
printf("Test PASS: Region configuration successful\n");
// Cleanup
mpu_free_set(set);
}
Test Case 6: Set Activation
/**
* Test: Verify protection set activation
* Purpose: Ensure sets can be switched at runtime
* Expected: Active set changes correctly
*/
static void test_set_activation(void)
{
unsigned int original_set;
unsigned int new_set;
unsigned int verify_set;
// Get current set
original_set = mpu_get_active_set();
printf("Original active set: %u\n", original_set);
// Allocate and activate a new set
new_set = mpu_alloc_set();
mpu_set_active_set(new_set);
// Verify set was activated
verify_set = mpu_get_active_set();
assert(verify_set == new_set);
printf("Activated new set: %u\n", verify_set);
// Switch back to original
mpu_set_active_set(original_set);
verify_set = mpu_get_active_set();
assert(verify_set == original_set);
printf("Test PASS: Set activation successful\n");
// Cleanup
mpu_free_set(new_set);
}
Test Case 7: Memory Protection
/**
* Test: Verify memory protection boundaries
* Purpose: Ensure access violations are detected
* Expected: Protected regions reject unauthorized access
*/
static void test_memory_protection(void)
{
unsigned int set = mpu_alloc_set();
unsigned int region;
uintptr_t base = 0x20000000;
size_t size = 0x1000;
// Configure protected region (read-only)
int flags = REGION_TYPE_DATA | MPU_R; // Read-only
region = mpu_configure_region(set, base, size, flags);
// Activate protection set
mpu_set_active_set(set);
mpu_control(true);
// Verify read access is allowed
volatile uint32_t *ptr = (uint32_t *)base;
uint32_t value = *ptr;
printf("Read value: 0x%08x\n", value);
// Attempt write should fail (would trigger MPU exception)
// *ptr = 0xDEADBEEF; // This would cause a protection violation
printf("Test PASS: Memory protection working\n");
// Cleanup
mpu_control(false);
mpu_free_set(set);
}
Test Case 8: Dump Functionality
/**
* Test: Verify debug dump functions
* Purpose: Ensure debug output shows region information
* Expected: Dump output is readable and correct
*/
static void test_dump_functionality(void)
{
unsigned int set;
int flags = REGION_TYPE_DATA | MPU_R | MPU_W;
// Allocate and configure a set
set = mpu_alloc_set();
mpu_configure_region(set, 0x20000000, 0x1000, flags);
mpu_configure_region(set, 0x20001000, 0x1000, REGION_TYPE_CODE | MPU_X);
// Dump single set
printf("Dumping protection set %u:\n", set);
mpu_dump_set(set);
// Dump all regions
printf("Dumping all regions:\n");
mpu_dump_regions();
printf("Test PASS: Dump functionality working\n");
// Cleanup
mpu_free_set(set);
}
Test Case 9: Multiple Set Management
/**
* Test: Verify managing multiple sets simultaneously
* Purpose: Ensure multiple sets can coexist
* Expected: Each set maintains independent configuration
*/
static void test_multiple_sets(void)
{
unsigned int set1, set2, set3;
// Allocate multiple sets
set1 = mpu_alloc_set();
set2 = mpu_alloc_set();
set3 = mpu_alloc_set();
printf("Allocated sets: %u, %u, %u\n", set1, set2, set3);
// Configure each set differently
mpu_configure_region(set1, 0x20000000, 0x1000, REGION_TYPE_DATA | MPU_R);
mpu_configure_region(set2, 0x20001000, 0x1000, REGION_TYPE_DATA | MPU_W);
mpu_configure_region(set3, 0x20002000, 0x1000, REGION_TYPE_DATA | MPU_R |
MPU_W);
// Switch between sets
for (unsigned int i = 0; i < 3; i++)
{
mpu_set_active_set(set1);
assert(mpu_get_active_set() == set1);
mpu_set_active_set(set2);
assert(mpu_get_active_set() == set2);
mpu_set_active_set(set3);
assert(mpu_get_active_set() == set3);
}
printf("Test PASS: Multiple set management successful\n");
// Cleanup
mpu_free_set(set1);
mpu_free_set(set2);
mpu_free_set(set3);
}
Test Case 10: Protected Mode Support
/**
* Test: Verify CONFIG_BUILD_PROTECTED support
* Purpose: Ensure kernel and user protections can be configured
* Expected: Both kernel and user regions properly configured
*/
#ifdef CONFIG_BUILD_PROTECTED
static void test_protected_mode(void)
{
unsigned int kset, uset;
// Allocate kernel and user sets
kset = mpu_alloc_set();
uset = mpu_alloc_set();
printf("Kernel set: %u, User set: %u\n", kset, uset);
// Configure kernel region (full access)
mpu_configure_region(kset, 0x20000000, 0x2000,
REGION_TYPE_DATA | MPU_R | MPU_W);
// Configure user region (restricted access)
mpu_configure_region(uset, 0x20000000, 0x1000,
REGION_TYPE_DATA | MPU_R); // Read-only
// Activate kernel set
mpu_set_active_set(kset);
printf("Kernel mode activated\n");
// Switch to user set
mpu_set_active_set(uset);
printf("User mode activated\n");
printf("Test PASS: Protected mode support working\n");
// Cleanup
mpu_free_set(kset);
mpu_free_set(uset);
}
#endif
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]