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); } --