|
From: openocd-gerrit <ope...@us...> - 2023-01-15 14:54:15
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via d0436b0cdabb2106701222628d78932c973a1e62 (commit)
from d96dc47ef67e427cd64a07d9825fd297e3a81633 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d0436b0cdabb2106701222628d78932c973a1e62
Author: Koudai Iwahori <ko...@go...>
Date: Tue Oct 4 04:21:35 2022 -0700
armv8: Add support of pointer authentication
When pointer authentication is enabled, some upper bits of the link
register (LR[63:VA_SIZE]) are used to store a signature. Therefore, GDB
need to remove the signature to get backtraces.
GDB has support of pointer authentication. When pointer authenticaion is
enabled, GDB requests 8-bytes mask to the target to remove the
signature. mask[63:VA_SIZE] should be all set and mask[VA_SIZE-1:0]
should be all cleared. GDB removes the signature by addr&~mask or
addr|mask.
I added a feature to provide the mask for pointer authentication.
Signed-off-by: Koudai Iwahori <ko...@go...>
Change-Id: I56fbbf9cc23619b6536ecd326f350c8bf137f322
Reviewed-on: https://review.openocd.org/c/openocd/+/7248
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index c7fee3e71..aa1707b7d 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -10297,6 +10297,16 @@ the target, the exception catch must be disabled again with @command{$target_nam
Issuing the command without options prints the current configuration.
@end deffn
+@deffn {Command} {$target_name pauth} [@option{off}|@option{on}]
+Enable or disable pointer authentication features.
+When pointer authentication is used on ARM cores, GDB asks GDB servers for an 8-bytes mask to remove signature bits added by pointer authentication.
+If this feature is enabled, OpenOCD provides GDB with an 8-bytes mask.
+Pointer authentication feature is broken until gdb 12.1, going to be fixed.
+Consider using a newer version of gdb if you want to enable pauth feature.
+The default configuration is @option{off}.
+@end deffn
+
+
@section EnSilica eSi-RISC Architecture
eSi-RISC is a highly configurable microprocessor architecture for embedded systems
diff --git a/src/target/armv8.c b/src/target/armv8.c
index de0bddb3e..ff71a8e63 100644
--- a/src/target/armv8.c
+++ b/src/target/armv8.c
@@ -114,6 +114,166 @@ const char *armv8_mode_name(unsigned psr_mode)
return "UNRECOGNIZED";
}
+static uint8_t armv8_pa_size(uint32_t ps)
+{
+ uint8_t ret = 0;
+ switch (ps) {
+ case 0:
+ ret = 32;
+ break;
+ case 1:
+ ret = 36;
+ break;
+ case 2:
+ ret = 40;
+ break;
+ case 3:
+ ret = 42;
+ break;
+ case 4:
+ ret = 44;
+ break;
+ case 5:
+ ret = 48;
+ break;
+ default:
+ LOG_INFO("Unknown physical address size");
+ break;
+ }
+ return ret;
+}
+
+static __attribute__((unused)) int armv8_read_ttbcr32(struct target *target)
+{
+ struct armv8_common *armv8 = target_to_armv8(target);
+ struct arm_dpm *dpm = armv8->arm.dpm;
+ uint32_t ttbcr, ttbcr_n;
+ int retval = dpm->prepare(dpm);
+ if (retval != ERROR_OK)
+ goto done;
+ /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
+ &ttbcr);
+ if (retval != ERROR_OK)
+ goto done;
+
+ LOG_DEBUG("ttbcr %" PRIx32, ttbcr);
+
+ ttbcr_n = ttbcr & 0x7;
+ armv8->armv8_mmu.ttbcr = ttbcr;
+
+ /*
+ * ARM Architecture Reference Manual (ARMv7-A and ARMv7-R edition),
+ * document # ARM DDI 0406C
+ */
+ armv8->armv8_mmu.ttbr_range[0] = 0xffffffff >> ttbcr_n;
+ armv8->armv8_mmu.ttbr_range[1] = 0xffffffff;
+ armv8->armv8_mmu.ttbr_mask[0] = 0xffffffff << (14 - ttbcr_n);
+ armv8->armv8_mmu.ttbr_mask[1] = 0xffffffff << 14;
+
+ LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32 " ttbr1_mask %" PRIx32,
+ (ttbcr_n != 0) ? "used" : "not used",
+ armv8->armv8_mmu.ttbr_mask[0],
+ armv8->armv8_mmu.ttbr_mask[1]);
+
+done:
+ dpm->finish(dpm);
+ return retval;
+}
+
+static int armv8_read_ttbcr(struct target *target)
+{
+ struct armv8_common *armv8 = target_to_armv8(target);
+ struct arm_dpm *dpm = armv8->arm.dpm;
+ struct arm *arm = &armv8->arm;
+ uint32_t ttbcr;
+ uint64_t ttbcr_64;
+
+ int retval = dpm->prepare(dpm);
+ if (retval != ERROR_OK)
+ goto done;
+
+ /* clear ttrr1_used and ttbr0_mask */
+ memset(&armv8->armv8_mmu.ttbr1_used, 0, sizeof(armv8->armv8_mmu.ttbr1_used));
+ memset(&armv8->armv8_mmu.ttbr0_mask, 0, sizeof(armv8->armv8_mmu.ttbr0_mask));
+
+ switch (armv8_curel_from_core_mode(arm->core_mode)) {
+ case SYSTEM_CUREL_EL3:
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV8_MRS(SYSTEM_TCR_EL3, 0),
+ &ttbcr);
+ retval += dpm->instr_read_data_r0_64(dpm,
+ ARMV8_MRS(SYSTEM_TTBR0_EL3, 0),
+ &armv8->ttbr_base);
+ if (retval != ERROR_OK)
+ goto done;
+ armv8->va_size = 64 - (ttbcr & 0x3F);
+ armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
+ armv8->page_size = (ttbcr >> 14) & 3;
+ break;
+ case SYSTEM_CUREL_EL2:
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV8_MRS(SYSTEM_TCR_EL2, 0),
+ &ttbcr);
+ retval += dpm->instr_read_data_r0_64(dpm,
+ ARMV8_MRS(SYSTEM_TTBR0_EL2, 0),
+ &armv8->ttbr_base);
+ if (retval != ERROR_OK)
+ goto done;
+ armv8->va_size = 64 - (ttbcr & 0x3F);
+ armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
+ armv8->page_size = (ttbcr >> 14) & 3;
+ break;
+ case SYSTEM_CUREL_EL0:
+ armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H);
+ /* fall through */
+ case SYSTEM_CUREL_EL1:
+ retval = dpm->instr_read_data_r0_64(dpm,
+ ARMV8_MRS(SYSTEM_TCR_EL1, 0),
+ &ttbcr_64);
+ armv8->va_size = 64 - (ttbcr_64 & 0x3F);
+ armv8->pa_size = armv8_pa_size((ttbcr_64 >> 32) & 7);
+ armv8->page_size = (ttbcr_64 >> 14) & 3;
+ armv8->armv8_mmu.ttbr1_used = (((ttbcr_64 >> 16) & 0x3F) != 0) ? 1 : 0;
+ armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFF;
+ retval += dpm->instr_read_data_r0_64(dpm,
+ ARMV8_MRS(SYSTEM_TTBR0_EL1 | (armv8->armv8_mmu.ttbr1_used), 0),
+ &armv8->ttbr_base);
+ if (retval != ERROR_OK)
+ goto done;
+ break;
+ default:
+ LOG_ERROR("unknown core state");
+ retval = ERROR_FAIL;
+ break;
+ }
+ if (retval != ERROR_OK)
+ goto done;
+
+ if (armv8->armv8_mmu.ttbr1_used == 1)
+ LOG_INFO("TTBR0 access above %" PRIx64, (uint64_t)(armv8->armv8_mmu.ttbr0_mask));
+
+done:
+ armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
+ dpm->finish(dpm);
+ return retval;
+}
+
+static int armv8_get_pauth_mask(struct armv8_common *armv8, uint64_t *mask)
+{
+ struct arm *arm = &armv8->arm;
+ int retval = ERROR_OK;
+ if (armv8->va_size == 0)
+ retval = armv8_read_ttbcr(arm->target);
+ if (retval != ERROR_OK)
+ return retval;
+
+ *mask = ~(((uint64_t)1 << armv8->va_size) - 1);
+
+ return retval;
+}
+
static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regval)
{
struct arm_dpm *dpm = &armv8->dpm;
@@ -191,6 +351,10 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv
ARMV8_MRS(SYSTEM_SPSR_EL3, 0), &value);
value_64 = value;
break;
+ case ARMV8_PAUTH_CMASK:
+ case ARMV8_PAUTH_DMASK:
+ retval = armv8_get_pauth_mask(armv8, &value_64);
+ break;
default:
retval = ERROR_FAIL;
break;
@@ -772,152 +936,6 @@ static __attribute__((unused)) void armv8_show_fault_registers(struct target *ta
armv8_show_fault_registers32(armv8);
}
-static uint8_t armv8_pa_size(uint32_t ps)
-{
- uint8_t ret = 0;
- switch (ps) {
- case 0:
- ret = 32;
- break;
- case 1:
- ret = 36;
- break;
- case 2:
- ret = 40;
- break;
- case 3:
- ret = 42;
- break;
- case 4:
- ret = 44;
- break;
- case 5:
- ret = 48;
- break;
- default:
- LOG_INFO("Unknown physical address size");
- break;
- }
- return ret;
-}
-
-static __attribute__((unused)) int armv8_read_ttbcr32(struct target *target)
-{
- struct armv8_common *armv8 = target_to_armv8(target);
- struct arm_dpm *dpm = armv8->arm.dpm;
- uint32_t ttbcr, ttbcr_n;
- int retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
- /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
- &ttbcr);
- if (retval != ERROR_OK)
- goto done;
-
- LOG_DEBUG("ttbcr %" PRIx32, ttbcr);
-
- ttbcr_n = ttbcr & 0x7;
- armv8->armv8_mmu.ttbcr = ttbcr;
-
- /*
- * ARM Architecture Reference Manual (ARMv7-A and ARMv7-R edition),
- * document # ARM DDI 0406C
- */
- armv8->armv8_mmu.ttbr_range[0] = 0xffffffff >> ttbcr_n;
- armv8->armv8_mmu.ttbr_range[1] = 0xffffffff;
- armv8->armv8_mmu.ttbr_mask[0] = 0xffffffff << (14 - ttbcr_n);
- armv8->armv8_mmu.ttbr_mask[1] = 0xffffffff << 14;
-
- LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32 " ttbr1_mask %" PRIx32,
- (ttbcr_n != 0) ? "used" : "not used",
- armv8->armv8_mmu.ttbr_mask[0],
- armv8->armv8_mmu.ttbr_mask[1]);
-
-done:
- dpm->finish(dpm);
- return retval;
-}
-
-static __attribute__((unused)) int armv8_read_ttbcr(struct target *target)
-{
- struct armv8_common *armv8 = target_to_armv8(target);
- struct arm_dpm *dpm = armv8->arm.dpm;
- struct arm *arm = &armv8->arm;
- uint32_t ttbcr;
- uint64_t ttbcr_64;
-
- int retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- /* clear ttrr1_used and ttbr0_mask */
- memset(&armv8->armv8_mmu.ttbr1_used, 0, sizeof(armv8->armv8_mmu.ttbr1_used));
- memset(&armv8->armv8_mmu.ttbr0_mask, 0, sizeof(armv8->armv8_mmu.ttbr0_mask));
-
- switch (armv8_curel_from_core_mode(arm->core_mode)) {
- case SYSTEM_CUREL_EL3:
- retval = dpm->instr_read_data_r0(dpm,
- ARMV8_MRS(SYSTEM_TCR_EL3, 0),
- &ttbcr);
- retval += dpm->instr_read_data_r0_64(dpm,
- ARMV8_MRS(SYSTEM_TTBR0_EL3, 0),
- &armv8->ttbr_base);
- if (retval != ERROR_OK)
- goto done;
- armv8->va_size = 64 - (ttbcr & 0x3F);
- armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
- armv8->page_size = (ttbcr >> 14) & 3;
- break;
- case SYSTEM_CUREL_EL2:
- retval = dpm->instr_read_data_r0(dpm,
- ARMV8_MRS(SYSTEM_TCR_EL2, 0),
- &ttbcr);
- retval += dpm->instr_read_data_r0_64(dpm,
- ARMV8_MRS(SYSTEM_TTBR0_EL2, 0),
- &armv8->ttbr_base);
- if (retval != ERROR_OK)
- goto done;
- armv8->va_size = 64 - (ttbcr & 0x3F);
- armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
- armv8->page_size = (ttbcr >> 14) & 3;
- break;
- case SYSTEM_CUREL_EL0:
- armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H);
- /* fall through */
- case SYSTEM_CUREL_EL1:
- retval = dpm->instr_read_data_r0_64(dpm,
- ARMV8_MRS(SYSTEM_TCR_EL1, 0),
- &ttbcr_64);
- armv8->va_size = 64 - (ttbcr_64 & 0x3F);
- armv8->pa_size = armv8_pa_size((ttbcr_64 >> 32) & 7);
- armv8->page_size = (ttbcr_64 >> 14) & 3;
- armv8->armv8_mmu.ttbr1_used = (((ttbcr_64 >> 16) & 0x3F) != 0) ? 1 : 0;
- armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFF;
- retval += dpm->instr_read_data_r0_64(dpm,
- ARMV8_MRS(SYSTEM_TTBR0_EL1 | (armv8->armv8_mmu.ttbr1_used), 0),
- &armv8->ttbr_base);
- if (retval != ERROR_OK)
- goto done;
- break;
- default:
- LOG_ERROR("unknown core state");
- retval = ERROR_FAIL;
- break;
- }
- if (retval != ERROR_OK)
- goto done;
-
- if (armv8->armv8_mmu.ttbr1_used == 1)
- LOG_INFO("TTBR0 access above %" PRIx64, (uint64_t)(armv8->armv8_mmu.ttbr0_mask));
-
-done:
- armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
- dpm->finish(dpm);
- return retval;
-}
-
/* method adapted to cortex A : reused arm v4 v5 method*/
int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr_t *val)
{
@@ -1083,6 +1101,15 @@ COMMAND_HANDLER(armv8_handle_exception_catch_command)
return ERROR_OK;
}
+COMMAND_HANDLER(armv8_pauth_command)
+{
+ struct target *target = get_current_target(CMD_CTX);
+ struct armv8_common *armv8 = target_to_armv8(target);
+ return CALL_COMMAND_HANDLER(handle_command_parse_bool,
+ &armv8->enable_pauth,
+ "pauth feature");
+}
+
int armv8_handle_cache_info_command(struct command_invocation *cmd,
struct armv8_cache_common *armv8_cache)
{
@@ -1421,6 +1448,8 @@ static const struct {
NULL},
{ ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked",
NULL},
+ { ARMV8_PAUTH_DMASK, "pauth_dmask", 64, ARM_MODE_ANY, REG_TYPE_UINT64, NULL, "org.gnu.gdb.aarch64.pauth", NULL},
+ { ARMV8_PAUTH_CMASK, "pauth_cmask", 64, ARM_MODE_ANY, REG_TYPE_UINT64, NULL, "org.gnu.gdb.aarch64.pauth", NULL},
};
static const struct {
@@ -1650,6 +1679,9 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
*reg_list[i].reg_data_type = *armv8_regs[i].data_type;
} else
LOG_ERROR("unable to allocate reg type list");
+
+ if (i == ARMV8_PAUTH_CMASK || i == ARMV8_PAUTH_DMASK)
+ reg_list[i].hidden = !armv8->enable_pauth;
}
arm->cpsr = reg_list + ARMV8_XPSR;
@@ -1745,6 +1777,17 @@ const struct command_registration armv8_command_handlers[] = {
.help = "configure exception catch",
.usage = "[(nsec_el1,nsec_el2,sec_el1,sec_el3)+,off]",
},
+ {
+ .name = "pauth",
+ .handler = armv8_pauth_command,
+ .mode = COMMAND_CONFIG,
+ .help = "enable or disable providing GDB with an 8-bytes mask to "
+ "remove signature bits added by pointer authentication."
+ "Pointer authentication feature is broken until gdb 12.1, going to be fixed. "
+ "Consider using a newer version of gdb if you want enable "
+ "pauth feature.",
+ .usage = "[on|off]",
+ },
COMMAND_REGISTRATION_DONE
};
diff --git a/src/target/armv8.h b/src/target/armv8.h
index 2ed3a65ac..54aa08634 100644
--- a/src/target/armv8.h
+++ b/src/target/armv8.h
@@ -98,6 +98,10 @@ enum {
ARMV8_ESR_EL3 = 75,
ARMV8_SPSR_EL3 = 76,
+ /* Pseudo registers defined by GDB to remove the pauth signature. */
+ ARMV8_PAUTH_DMASK = 77,
+ ARMV8_PAUTH_CMASK = 78,
+
ARMV8_LAST_REG,
};
@@ -205,6 +209,9 @@ struct armv8_common {
struct arm_cti *cti;
+ /* True if OpenOCD provides pointer auth related info to GDB */
+ bool enable_pauth;
+
/* last run-control command issued to this target (resume, halt, step) */
enum run_control_op last_run_control_op;
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 10 ++
src/target/armv8.c | 335 ++++++++++++++++++++++++++++++-----------------------
src/target/armv8.h | 7 ++
3 files changed, 206 insertions(+), 146 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|