aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Welwarsky <matthias.welwarsky@sysgo.com>2016-09-20 11:29:39 +0200
committerMatthias Welwarsky <matthias.welwarsky@sysgo.com>2017-02-10 14:01:39 +0100
commitc6ed75fb0e61cb710c91c935449330ac7b441799 (patch)
tree08707a9f685a0324ba9ae32f7f36cb1a98a45959
parente17d1d4dc870155010422095272d8a6c16435451 (diff)
aarch64: add cache handling when setting/deleting soft breakpoints
Flush D-Cache before, flush D-Cache and invalidate I-Cache after modifying the breakpoint location. Change-Id: Id2e2f4f2545c062de7e27275f66857357496d4ae Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com>
-rw-r--r--src/target/aarch64.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/target/aarch64.c b/src/target/aarch64.c
index 88f9b5a..1eb4d82 100644
--- a/src/target/aarch64.c
+++ b/src/target/aarch64.c
@@ -27,6 +27,7 @@
#include "target_request.h"
#include "target_type.h"
#include "armv8_opcodes.h"
+#include "armv8_cache.h"
#include <helper/time_support.h>
static int aarch64_poll(struct target *target);
@@ -1401,6 +1402,7 @@ static int aarch64_set_breakpoint(struct target *target,
} else if (breakpoint->type == BKPT_SOFT) {
uint8_t code[4];
+
buf_set_u32(code, 0, 32, ARMV8_HLT(0x11));
retval = target_read_memory(target,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
@@ -1408,11 +1410,25 @@ static int aarch64_set_breakpoint(struct target *target,
breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
+
+ armv8_cache_d_inner_flush_virt(armv8,
+ breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+ breakpoint->length);
+
retval = target_write_memory(target,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->length, 1, code);
if (retval != ERROR_OK)
return retval;
+
+ armv8_cache_d_inner_flush_virt(armv8,
+ breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+ breakpoint->length);
+
+ armv8_cache_i_inner_inval_virt(armv8,
+ breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+ breakpoint->length);
+
breakpoint->set = 0x11; /* Any nice value but 0 */
}
@@ -1668,6 +1684,11 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br
}
} else {
/* restore original instruction (kept in target endianness) */
+
+ armv8_cache_d_inner_flush_virt(armv8,
+ breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+ breakpoint->length);
+
if (breakpoint->length == 4) {
retval = target_write_memory(target,
breakpoint->address & 0xFFFFFFFFFFFFFFFE,
@@ -1681,6 +1702,14 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br
if (retval != ERROR_OK)
return retval;
}
+
+ armv8_cache_d_inner_flush_virt(armv8,
+ breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+ breakpoint->length);
+
+ armv8_cache_i_inner_inval_virt(armv8,
+ breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+ breakpoint->length);
}
breakpoint->set = 0;