Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F97635437
D28415.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D28415.diff
View Options
diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -350,7 +350,7 @@
MRS_FIELD(ID_AA64DFR0, PMSVer, false, MRS_EXACT, id_aa64dfr0_pmsver),
MRS_FIELD(ID_AA64DFR0, CTX_CMPs, false, MRS_EXACT,
id_aa64dfr0_ctx_cmps),
- MRS_FIELD(ID_AA64DFR0, WRPs, false, MRS_EXACT, id_aa64dfr0_wrps),
+ MRS_FIELD(ID_AA64DFR0, WRPs, false, MRS_LOWER, id_aa64dfr0_wrps),
MRS_FIELD(ID_AA64DFR0, BRPs, false, MRS_LOWER, id_aa64dfr0_brps),
MRS_FIELD(ID_AA64DFR0, PMUVer, false, MRS_EXACT, id_aa64dfr0_pmuver),
MRS_FIELD(ID_AA64DFR0, TraceVer, false, MRS_EXACT,
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -321,8 +321,8 @@
fill_dbregs(struct thread *td, struct dbreg *regs)
{
struct debug_monitor_state *monitor;
- int count, i;
- uint8_t debug_ver, nbkpts;
+ int i;
+ uint8_t debug_ver, nbkpts, nwtpts;
memset(regs, 0, sizeof(*regs));
@@ -330,23 +330,30 @@
&debug_ver);
extract_user_id_field(ID_AA64DFR0_EL1, ID_AA64DFR0_BRPs_SHIFT,
&nbkpts);
+ extract_user_id_field(ID_AA64DFR0_EL1, ID_AA64DFR0_WRPs_SHIFT,
+ &nwtpts);
/*
* The BRPs field contains the number of breakpoints - 1. Armv8-A
* allows the hardware to provide 2-16 breakpoints so this won't
- * overflow an 8 bit value.
+ * overflow an 8 bit value. The same applies to the WRPs field.
*/
- count = nbkpts + 1;
+ nbkpts++;
+ nwtpts++;
- regs->db_info = debug_ver;
- regs->db_info <<= 8;
- regs->db_info |= count;
+ regs->db_debug_ver = debug_ver;
+ regs->db_nbkpts = nbkpts;
+ regs->db_nwtpts = nwtpts;
monitor = &td->td_pcb->pcb_dbg_regs;
if ((monitor->dbg_flags & DBGMON_ENABLED) != 0) {
- for (i = 0; i < count; i++) {
- regs->db_regs[i].dbr_addr = monitor->dbg_bvr[i];
- regs->db_regs[i].dbr_ctrl = monitor->dbg_bcr[i];
+ for (i = 0; i < nbkpts; i++) {
+ regs->db_breakregs[i].dbr_addr = monitor->dbg_bvr[i];
+ regs->db_breakregs[i].dbr_ctrl = monitor->dbg_bcr[i];
+ }
+ for (i = 0; i < nwtpts; i++) {
+ regs->db_watchregs[i].dbw_addr = monitor->dbg_wvr[i];
+ regs->db_watchregs[i].dbw_ctrl = monitor->dbg_wcr[i];
}
}
@@ -365,9 +372,10 @@
monitor = &td->td_pcb->pcb_dbg_regs;
count = 0;
monitor->dbg_enable_count = 0;
+
for (i = 0; i < DBG_BRP_MAX; i++) {
- addr = regs->db_regs[i].dbr_addr;
- ctrl = regs->db_regs[i].dbr_ctrl;
+ addr = regs->db_breakregs[i].dbr_addr;
+ ctrl = regs->db_breakregs[i].dbr_ctrl;
/* Don't let the user set a breakpoint on a kernel address. */
if (addr >= VM_MAXUSER_ADDRESS)
@@ -399,6 +407,45 @@
monitor->dbg_bvr[i] = addr;
monitor->dbg_bcr[i] = ctrl;
}
+
+ for (i = 0; i < DBG_WRP_MAX; i++) {
+ addr = regs->db_watchregs[i].dbw_addr;
+ ctrl = regs->db_watchregs[i].dbw_ctrl;
+
+ /* Don't let the user set a watchpoint on a kernel address. */
+ if (addr >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+
+ /*
+ * Some control fields are ignored, and other bits reserved.
+ * Only unlinked watchpoints are supported.
+ */
+ ctrl &= DBG_WCR_EN | DBG_WCR_PAC | DBG_WCR_LSC | DBG_WCR_BAS |
+ DBG_WCR_MASK;
+
+ if ((ctrl & DBG_WCR_EN) != 0) {
+ /* Only target EL0. */
+ if ((ctrl & DBG_WCR_PAC) != DBG_WCR_PAC_EL0)
+ return (EINVAL);
+
+ /* Must set at least one of the load/store bits. */
+ if ((ctrl & DBG_WCR_LSC) == 0)
+ return (EINVAL);
+
+ /*
+ * When specifying the address range with BAS, the MASK
+ * field must be zero.
+ */
+ if ((ctrl & DBG_WCR_BAS) != DBG_WCR_BAS_MASK &&
+ (ctrl & DBG_WCR_MASK) != 0)
+ return (EINVAL);
+
+ monitor->dbg_enable_count++;
+ }
+ monitor->dbg_wvr[i] = addr;
+ monitor->dbg_wcr[i] = ctrl;
+ }
+
if (monitor->dbg_enable_count > 0)
monitor->dbg_flags |= DBGMON_ENABLED;
diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -962,6 +962,28 @@
#define DBG_BCR_BT_SHIFT 20
#define DBG_BCR_BT (0xf << DBG_BCR_BT_SHIFT)
+/* Debug Watchpoint Control Registers */
+#define DBG_WCR_EN 0x1
+#define DBG_WCR_PAC_SHIFT 1
+#define DBG_WCR_PAC (0x3 << DBG_WCR_PAC_SHIFT)
+#define DBG_WCR_PAC_EL1 (0x1 << DBG_WCR_PAC_SHIFT)
+#define DBG_WCR_PAC_EL0 (0x2 << DBG_WCR_PAC_SHIFT)
+#define DBG_WCR_LSC_SHIFT 3
+#define DBG_WCR_LSC (0x3 << DBG_WCR_LSC_SHIFT)
+#define DBG_WCR_BAS_SHIFT 5
+#define DBG_WCR_BAS (0xff << DBG_WCR_BAS_SHIFT)
+#define DBG_WCR_BAS_MASK DBG_WCR_BAS
+#define DBG_WCR_HMC_SHIFT 13
+#define DBG_WCR_HMC (0x1 << DBG_WCR_HMC_SHIFT)
+#define DBG_WCR_SSC_SHIFT 14
+#define DBG_WCR_SSC (0x3 << DBG_WCR_SSC_SHIFT)
+#define DBG_WCR_LBN_SHIFT 16
+#define DBG_WCR_LBN (0xf << DBG_WCR_LBN_SHIFT)
+#define DBG_WCR_WT_SHIFT 20
+#define DBG_WCR_WT (0x1 << DBG_WCR_WT_SHIFT)
+#define DBG_WCR_MASK_SHIFT 24
+#define DBG_WCR_MASK (0x1f << DBG_WCR_MASK_SHIFT)
+
/* Perfomance Monitoring Counters */
#define PMCR_E (1 << 0) /* Enable all counters */
#define PMCR_P (1 << 1) /* Reset all counters */
diff --git a/sys/arm64/include/reg.h b/sys/arm64/include/reg.h
--- a/sys/arm64/include/reg.h
+++ b/sys/arm64/include/reg.h
@@ -60,14 +60,21 @@
};
struct dbreg {
- uint32_t db_info;
- uint32_t db_pad;
+ uint8_t db_debug_ver;
+ uint8_t db_nbkpts;
+ uint8_t db_nwtpts;
+ uint8_t db_pad[5];
struct {
uint64_t dbr_addr;
uint32_t dbr_ctrl;
uint32_t dbr_pad;
- } db_regs[16];
+ } db_breakregs[16];
+ struct {
+ uint64_t dbw_addr;
+ uint32_t dbw_ctrl;
+ uint32_t dbw_pad;
+ } db_watchregs[16];
};
struct dbreg32 {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Oct 1, 12:22 PM (21 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13250361
Default Alt Text
D28415.diff (5 KB)
Attached To
Mode
D28415: arm64: extend struct db_reg to include watchpoint registers
Attached
Detach File
Event Timeline
Log In to Comment