aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Borneo <borneo.antonio@gmail.com>2024-05-14 12:16:13 +0200
committerAntonio Borneo <borneo.antonio@gmail.com>2024-06-23 09:29:22 +0000
commit2a63fabd095044f0a05cf69a34300409809f676b (patch)
treebaa4d930aac37c81297c36fda54bd33245f6f165
parent766a84b79892c1321f3f86d3f1b301519269b4f5 (diff)
downloadriscv-openocd-2a63fabd095044f0a05cf69a34300409809f676b.zip
riscv-openocd-2a63fabd095044f0a05cf69a34300409809f676b.tar.gz
riscv-openocd-2a63fabd095044f0a05cf69a34300409809f676b.tar.bz2
target: aarch64: access reg SPSR_EL2 only in EL2 and EL3
The register SPSR_EL2 is accessible and it's content is relevant only when the target is in EL2 or EL3. Virtualization SW in EL1 can also access it, but this either triggers a trap to EL2 or returns SPSR_EL1. Debugger should not mix the real SPSR_EL2 with the virtual register. Plus, the register is 64 bits wide. Without this patch, an error: Error: Opcode 0xd53c4000, DSCR.ERR=1, DSCR.EL=1 is triggered by GDB register window or through GDB command x/p $SPSR_EL2 or through OpenOCD command reg SPSR_EL2 Detect the EL and return error if the register cannot be accessed. Handle the register as 64 bits. Change-Id: If3792296b36282c08d597dd46cfe044d6b8288ea Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: https://review.openocd.org/c/openocd/+/8273 Tested-by: jenkins
-rw-r--r--src/target/armv8.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/target/armv8.c b/src/target/armv8.c
index 49fcb72..b622dc9 100644
--- a/src/target/armv8.c
+++ b/src/target/armv8.c
@@ -365,9 +365,13 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv
value_64 = value;
break;
case ARMV8_SPSR_EL2:
- retval = dpm->instr_read_data_r0(dpm,
- ARMV8_MRS(SYSTEM_SPSR_EL2, 0), &value);
- value_64 = value;
+ if (curel < SYSTEM_CUREL_EL2) {
+ LOG_DEBUG("SPSR_EL2 not accessible in EL%u", curel);
+ retval = ERROR_FAIL;
+ break;
+ }
+ retval = dpm->instr_read_data_r0_64(dpm,
+ ARMV8_MRS(SYSTEM_SPSR_EL2, 0), &value_64);
break;
case ARMV8_SPSR_EL3:
if (curel < SYSTEM_CUREL_EL3) {
@@ -509,9 +513,13 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu
ARMV8_MSR_GP(SYSTEM_SPSR_EL1, 0), value);
break;
case ARMV8_SPSR_EL2:
- value = value_64;
- retval = dpm->instr_write_data_r0(dpm,
- ARMV8_MSR_GP(SYSTEM_SPSR_EL2, 0), value);
+ if (curel < SYSTEM_CUREL_EL2) {
+ LOG_DEBUG("SPSR_EL2 not accessible in EL%u", curel);
+ retval = ERROR_FAIL;
+ break;
+ }
+ retval = dpm->instr_write_data_r0_64(dpm,
+ ARMV8_MSR_GP(SYSTEM_SPSR_EL2, 0), value_64);
break;
case ARMV8_SPSR_EL3:
if (curel < SYSTEM_CUREL_EL3) {
@@ -1563,7 +1571,7 @@ static const struct {
NULL},
{ ARMV8_ESR_EL2, "ESR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked",
NULL},
- { ARMV8_SPSR_EL2, "SPSR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked",
+ { ARMV8_SPSR_EL2, "SPSR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_UINT64, "banked", "net.sourceforge.openocd.banked",
NULL},
{ ARMV8_ELR_EL3, "ELR_EL3", 64, ARMV8_64_EL3H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked",