|
7 | 7 | #include <zephyr/kernel.h>
|
8 | 8 | #include <kernel_internal.h>
|
9 | 9 | #include <zephyr/toolchain.h>
|
| 10 | +#include <zephyr/arch/xtensa/cache.h> |
10 | 11 | #include <zephyr/debug/gdbstub.h>
|
11 | 12 |
|
12 | 13 | #include <xtensa_asm2_context.h>
|
@@ -987,3 +988,35 @@ void arch_gdb_init(void)
|
987 | 988 | */
|
988 | 989 | __asm__ volatile ("_break.n 0");
|
989 | 990 | }
|
| 991 | + |
| 992 | +void arch_gdb_post_memory_write(uintptr_t addr, size_t len, uint8_t align) |
| 993 | +{ |
| 994 | + ARG_UNUSED(addr); |
| 995 | + ARG_UNUSED(len); |
| 996 | + ARG_UNUSED(align); |
| 997 | + |
| 998 | +#if defined(CONFIG_ICACHE) && defined(CONFIG_DCACHE) |
| 999 | + /* |
| 1000 | + * Note that a GDB memory write can write to code memory to |
| 1001 | + * insert breakpoints. We need to deal with this here so |
| 1002 | + * that the instruction cache can actually see the modified |
| 1003 | + * instructions. |
| 1004 | + * |
| 1005 | + * According to the ISA manual, after writing the instructions: |
| 1006 | + * 1. Flush the data cache so the modified instructions are |
| 1007 | + * in the main memory. |
| 1008 | + * 2. Do ISYNC or MEMW or both (depending on which part of |
| 1009 | + * manual you are reading). |
| 1010 | + * 3. Invalidate the instruction cache corresponding to |
| 1011 | + * the modified memory. |
| 1012 | + * 4. Do another ISYNC. |
| 1013 | + */ |
| 1014 | + arch_dcache_flush_range(addr, len); |
| 1015 | + |
| 1016 | + __asm__ volatile("isync; memw"); |
| 1017 | + |
| 1018 | + arch_icache_invd_range(addr, len); |
| 1019 | + |
| 1020 | + __asm__ volatile("isync"); |
| 1021 | +#endif /* CONFIG_ICACHE && CONFIG_DCACHE */ |
| 1022 | +} |
0 commit comments