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]

Reply via email to