This is an automated email from Gerrit.

"Adrien Charruel <acharr...@nanoxplore.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8656

-- gerrit

commit 917f9ed217000b2d8395037a94c234bb4b537a6d
Author: Adrien Grassein <agrass...@nanoxplore.com>
Date:   Fri Dec 6 10:37:06 2024 +0100

    target/aarch64: Better handle cache flush
    
    - Flush d and i-caches when needed (each time memory is written)
    - Create a function that writes the system_control_register to
      avoid code duplication
    - Decouple MMU and Cache management
    
    Change-Id: Ib9bad31a0b680556d5839d3f221740820237deeb
    Signed-off-by: Adrien Grassein <agrass...@nanoxplore.com>
    Signed-off-by: Adrien Charruel <acharr...@nanoxplore.com>

diff --git a/src/target/aarch64.c b/src/target/aarch64.c
index 4a2b9df8a3..ec317ef410 100644
--- a/src/target/aarch64.c
+++ b/src/target/aarch64.c
@@ -56,103 +56,19 @@ static int aarch64_virt2phys(struct target *target,
 static int aarch64_read_cpu_memory(struct target *target,
        uint64_t address, uint32_t size, uint32_t count, uint8_t *buffer);
 
-static int aarch64_restore_system_control_reg(struct target *target)
+static int aarch64_write_system_control_reg(struct target *target,
+       uint64_t system_control_reg)
 {
        enum arm_mode target_mode = ARM_MODE_ANY;
        int retval = ERROR_OK;
        uint32_t instr;
 
-       struct aarch64_common *aarch64 = target_to_aarch64(target);
        struct armv8_common *armv8 = target_to_armv8(target);
 
-       if (aarch64->system_control_reg != aarch64->system_control_reg_curr) {
-               aarch64->system_control_reg_curr = aarch64->system_control_reg;
-               /* LOG_INFO("cp15_control_reg: %8.8" PRIx32, 
cortex_v8->cp15_control_reg); */
-
-               switch (armv8->arm.core_mode) {
-               case ARMV8_64_EL0T:
-                       target_mode = ARMV8_64_EL1H;
-                       /* fall through */
-               case ARMV8_64_EL1T:
-               case ARMV8_64_EL1H:
-                       instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL1, 0);
-                       break;
-               case ARMV8_64_EL2T:
-               case ARMV8_64_EL2H:
-                       instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL2, 0);
-                       break;
-               case ARMV8_64_EL3H:
-               case ARMV8_64_EL3T:
-                       instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL3, 0);
-                       break;
-
-               case ARM_MODE_SVC:
-               case ARM_MODE_ABT:
-               case ARM_MODE_FIQ:
-               case ARM_MODE_IRQ:
-               case ARM_MODE_HYP:
-               case ARM_MODE_UND:
-               case ARM_MODE_SYS:
-               case ARM_MODE_MON:
-                       instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
-                       break;
-
-               default:
-                       LOG_ERROR("cannot read system control register in this 
mode: (%s : 0x%x)",
-                                       armv8_mode_name(armv8->arm.core_mode), 
armv8->arm.core_mode);
-                       return ERROR_FAIL;
-               }
-
-               if (target_mode != ARM_MODE_ANY)
-                       armv8_dpm_modeswitch(&armv8->dpm, target_mode);
-
-               retval = armv8->dpm.instr_write_data_r0_64(&armv8->dpm, instr, 
aarch64->system_control_reg);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               if (target_mode != ARM_MODE_ANY)
-                       armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY);
-       }
-
-       return retval;
-}
-
-/*  modify system_control_reg in order to enable or disable mmu for :
- *  - virt2phys address conversion
- *  - read or write memory in phys or virt address */
-static int aarch64_mmu_modify(struct target *target, int enable)
-{
-       struct aarch64_common *aarch64 = target_to_aarch64(target);
-       struct armv8_common *armv8 = &aarch64->armv8_common;
-       int retval = ERROR_OK;
-       enum arm_mode target_mode = ARM_MODE_ANY;
-       uint32_t instr = 0;
-
-       if (enable) {
-               /*      if mmu enabled at target stop and mmu not enable */
-               if (!(aarch64->system_control_reg & 0x1U)) {
-                       LOG_ERROR("trying to enable mmu on target stopped with 
mmu disable");
-                       return ERROR_FAIL;
-               }
-               if (!(aarch64->system_control_reg_curr & 0x1U))
-                       aarch64->system_control_reg_curr |= 0x1U;
-       } else {
-               if (aarch64->system_control_reg_curr & 0x4U) {
-                       /*  data cache is active */
-                       aarch64->system_control_reg_curr &= ~0x4U;
-                       /* flush data cache armv8 function to be called */
-                       if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache)
-                               
armv8->armv8_mmu.armv8_cache.flush_all_data_cache(target);
-               }
-               if ((aarch64->system_control_reg_curr & 0x1U)) {
-                       aarch64->system_control_reg_curr &= ~0x1U;
-               }
-       }
-
        switch (armv8->arm.core_mode) {
        case ARMV8_64_EL0T:
                target_mode = ARMV8_64_EL1H;
-               /* fall through */
+       /* fall through */
        case ARMV8_64_EL1T:
        case ARMV8_64_EL1H:
                instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL1, 0);
@@ -178,14 +94,17 @@ static int aarch64_mmu_modify(struct target *target, int 
enable)
                break;
 
        default:
-               LOG_DEBUG("unknown cpu state 0x%x", armv8->arm.core_mode);
-               break;
+               LOG_ERROR("cannot read system control register in this mode: 
(%s : 0x%x)",
+                               armv8_mode_name(armv8->arm.core_mode), 
armv8->arm.core_mode);
+                       return ERROR_FAIL;
        }
+
        if (target_mode != ARM_MODE_ANY)
                armv8_dpm_modeswitch(&armv8->dpm, target_mode);
 
-       retval = armv8->dpm.instr_write_data_r0_64(&armv8->dpm, instr,
-                               aarch64->system_control_reg_curr);
+       retval = armv8->dpm.instr_write_data_r0_64(&armv8->dpm, instr, 
system_control_reg);
+       if (retval != ERROR_OK)
+               return retval;
 
        if (target_mode != ARM_MODE_ANY)
                armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY);
@@ -193,6 +112,82 @@ static int aarch64_mmu_modify(struct target *target, int 
enable)
        return retval;
 }
 
+static int aarch64_restore_system_control_reg(struct target *target)
+{
+       int retval = ERROR_OK;
+
+       struct aarch64_common *aarch64 = target_to_aarch64(target);
+
+       if (aarch64->system_control_reg != aarch64->system_control_reg_curr) {
+               aarch64->system_control_reg_curr = aarch64->system_control_reg;
+               retval = aarch64_write_system_control_reg(target, 
aarch64->system_control_reg_curr);
+       }
+
+       return retval;
+}
+
+static int aarch64_flush_and_deactivate_caches(struct target *target)
+{
+       struct aarch64_common *aarch64 = target_to_aarch64(target);
+       struct armv8_common *armv8 = &aarch64->armv8_common;
+       int retval = ERROR_OK;
+
+       uint64_t system_control_reg_curr_updated = 
aarch64->system_control_reg_curr;
+
+       if (system_control_reg_curr_updated & 0x4U) {
+               /*  data cache is active */
+               system_control_reg_curr_updated &= ~0x4U;
+               /* flush data cache armv8 function to be called */
+               if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache)
+                       
armv8->armv8_mmu.armv8_cache.flush_all_data_cache(target);
+       }
+       if (system_control_reg_curr_updated & 0x1000U) {
+               /*  instruction cache is active */
+               system_control_reg_curr_updated &= ~0x1000U;
+               /* flush instruction cache armv8 function to be called */
+               if (armv8->armv8_mmu.armv8_cache.flush_all_instruction_cache)
+                       
armv8->armv8_mmu.armv8_cache.flush_all_instruction_cache(target);
+       }
+
+       if (system_control_reg_curr_updated != 
aarch64->system_control_reg_curr) {
+               aarch64->system_control_reg_curr = 
system_control_reg_curr_updated;
+               retval = aarch64_write_system_control_reg(target, 
aarch64->system_control_reg_curr);
+       }
+
+       return retval;
+}
+
+/*  modify system_control_reg in order to enable or disable mmu for :
+ *  - virt2phys address conversion
+ *  - read or write memory in phys or virt address */
+static int aarch64_mmu_modify(struct target *target, int enable)
+{
+       struct aarch64_common *aarch64 = target_to_aarch64(target);
+       int retval = ERROR_OK;
+
+       uint64_t system_control_reg_curr_updated = 
aarch64->system_control_reg_curr;
+
+       if (enable) {
+               /*      if mmu enabled at target stop and mmu not enable */
+               if (!(system_control_reg_curr_updated & 0x1U)) {
+                       LOG_ERROR("trying to enable mmu on target stopped with 
mmu disable");
+                       return ERROR_FAIL;
+               }
+               if (!(system_control_reg_curr_updated & 0x1U))
+                       system_control_reg_curr_updated |= 0x1U;
+       } else {
+               if ((system_control_reg_curr_updated & 0x1U))
+                       system_control_reg_curr_updated &= ~0x1U;
+       }
+
+       if (system_control_reg_curr_updated != 
aarch64->system_control_reg_curr) {
+               aarch64->system_control_reg_curr = 
system_control_reg_curr_updated;
+               retval = aarch64_write_system_control_reg(target, 
aarch64->system_control_reg_curr);
+       }
+
+       return retval;
+}
+
 static int aarch64_read_prsr(struct target *target, uint32_t *prsr)
 {
        struct armv8_common *armv8 = target_to_armv8(target);
@@ -2521,6 +2516,10 @@ static int aarch64_read_phys_memory(struct target 
*target,
        int retval = ERROR_COMMAND_SYNTAX_ERROR;
 
        if (count && buffer) {
+               /* Flush any CPU cache */
+               retval = aarch64_flush_and_deactivate_caches(target);
+               if (retval != ERROR_OK)
+                       return retval;
                /* read memory through APB-AP */
                retval = aarch64_mmu_modify(target, 0);
                if (retval != ERROR_OK)
@@ -2547,6 +2546,12 @@ static int aarch64_read_memory(struct target *target, 
target_addr_t address,
                if (retval != ERROR_OK)
                        return retval;
        }
+
+       /* Flush any CPU cache */
+       retval = aarch64_flush_and_deactivate_caches(target);
+       if (retval != ERROR_OK)
+               return retval;
+
        return aarch64_read_cpu_memory(target, address, size, count, buffer);
 }
 
@@ -2557,6 +2562,11 @@ static int aarch64_write_phys_memory(struct target 
*target,
        int retval = ERROR_COMMAND_SYNTAX_ERROR;
 
        if (count && buffer) {
+               /* Flush any CPU cache */
+               retval = aarch64_flush_and_deactivate_caches(target);
+               if (retval != ERROR_OK)
+                       return retval;
+
                /* write memory through APB-AP */
                retval = aarch64_mmu_modify(target, 0);
                if (retval != ERROR_OK)
@@ -2584,6 +2594,12 @@ static int aarch64_write_memory(struct target *target, 
target_addr_t address,
                if (retval != ERROR_OK)
                        return retval;
        }
+
+       /* Flush any CPU cache */
+       retval = aarch64_flush_and_deactivate_caches(target);
+       if (retval != ERROR_OK)
+               return retval;
+
        return aarch64_write_cpu_memory(target, address, size, count, buffer);
 }
 

-- 

Reply via email to