target/arm: Use field names for accessing DBGWCRn

While defining these names, use the correct field width of 5 not 4 for
DBGWCR.MASK.  This typo prevented setting a watchpoint larger than 32k.

Reported-by: Chris Howard <cvz185@web.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 20220427051926.295223-1-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2022-04-26 22:19:26 -07:00 committed by Peter Maydell
parent eb851c1151
commit 8b7a5bbecf
4 changed files with 28 additions and 16 deletions

View File

@ -143,9 +143,9 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
* Non-Secure to simplify the code slightly compared to the full * Non-Secure to simplify the code slightly compared to the full
* table in the ARM ARM. * table in the ARM ARM.
*/ */
pac = extract64(cr, 1, 2); pac = FIELD_EX64(cr, DBGWCR, PAC);
hmc = extract64(cr, 13, 1); hmc = FIELD_EX64(cr, DBGWCR, HMC);
ssc = extract64(cr, 14, 2); ssc = FIELD_EX64(cr, DBGWCR, SSC);
switch (ssc) { switch (ssc) {
case 0: case 0:
@ -184,8 +184,8 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
g_assert_not_reached(); g_assert_not_reached();
} }
wt = extract64(cr, 20, 1); wt = FIELD_EX64(cr, DBGWCR, WT);
lbn = extract64(cr, 16, 4); lbn = FIELD_EX64(cr, DBGWCR, LBN);
if (wt && !linked_bp_matches(cpu, lbn)) { if (wt && !linked_bp_matches(cpu, lbn)) {
return false; return false;

View File

@ -6320,12 +6320,12 @@ void hw_watchpoint_update(ARMCPU *cpu, int n)
env->cpu_watchpoint[n] = NULL; env->cpu_watchpoint[n] = NULL;
} }
if (!extract64(wcr, 0, 1)) { if (!FIELD_EX64(wcr, DBGWCR, E)) {
/* E bit clear : watchpoint disabled */ /* E bit clear : watchpoint disabled */
return; return;
} }
switch (extract64(wcr, 3, 2)) { switch (FIELD_EX64(wcr, DBGWCR, LSC)) {
case 0: case 0:
/* LSC 00 is reserved and must behave as if the wp is disabled */ /* LSC 00 is reserved and must behave as if the wp is disabled */
return; return;
@ -6344,7 +6344,7 @@ void hw_watchpoint_update(ARMCPU *cpu, int n)
* CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case, * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case,
* thus generating a watchpoint for every byte in the masked region. * thus generating a watchpoint for every byte in the masked region.
*/ */
mask = extract64(wcr, 24, 4); mask = FIELD_EX64(wcr, DBGWCR, MASK);
if (mask == 1 || mask == 2) { if (mask == 1 || mask == 2) {
/* Reserved values of MASK; we must act as if the mask value was /* Reserved values of MASK; we must act as if the mask value was
* some non-reserved value, or as if the watchpoint were disabled. * some non-reserved value, or as if the watchpoint were disabled.
@ -6361,7 +6361,7 @@ void hw_watchpoint_update(ARMCPU *cpu, int n)
wvr &= ~(len - 1); wvr &= ~(len - 1);
} else { } else {
/* Watchpoint covers bytes defined by the byte address select bits */ /* Watchpoint covers bytes defined by the byte address select bits */
int bas = extract64(wcr, 5, 8); int bas = FIELD_EX64(wcr, DBGWCR, BAS);
int basstart; int basstart;
if (extract64(wvr, 2, 1)) { if (extract64(wvr, 2, 1)) {

View File

@ -81,6 +81,18 @@ FIELD(V7M_EXCRET, RES1, 7, 25) /* including the must-be-1 prefix */
*/ */
#define FNC_RETURN_MIN_MAGIC 0xfefffffe #define FNC_RETURN_MIN_MAGIC 0xfefffffe
/* Bit definitions for DBGWCRn and DBGWCRn_EL1 */
FIELD(DBGWCR, E, 0, 1)
FIELD(DBGWCR, PAC, 1, 2)
FIELD(DBGWCR, LSC, 3, 2)
FIELD(DBGWCR, BAS, 5, 8)
FIELD(DBGWCR, HMC, 13, 1)
FIELD(DBGWCR, SSC, 14, 2)
FIELD(DBGWCR, LBN, 16, 4)
FIELD(DBGWCR, WT, 20, 1)
FIELD(DBGWCR, MASK, 24, 5)
FIELD(DBGWCR, SSCE, 29, 1)
/* We use a few fake FSR values for internal purposes in M profile. /* We use a few fake FSR values for internal purposes in M profile.
* M profile cores don't have A/R format FSRs, but currently our * M profile cores don't have A/R format FSRs, but currently our
* get_phys_addr() code assumes A/R profile and reports failures via * get_phys_addr() code assumes A/R profile and reports failures via

View File

@ -208,7 +208,7 @@ static int insert_hw_watchpoint(target_ulong addr,
target_ulong len, int type) target_ulong len, int type)
{ {
HWWatchpoint wp = { HWWatchpoint wp = {
.wcr = 1, /* E=1, enable */ .wcr = R_DBGWCR_E_MASK, /* E=1, enable */
.wvr = addr & (~0x7ULL), .wvr = addr & (~0x7ULL),
.details = { .vaddr = addr, .len = len } .details = { .vaddr = addr, .len = len }
}; };
@ -221,19 +221,19 @@ static int insert_hw_watchpoint(target_ulong addr,
* HMC=0 SSC=0 PAC=3 will hit EL0 or EL1, any security state, * HMC=0 SSC=0 PAC=3 will hit EL0 or EL1, any security state,
* valid whether EL3 is implemented or not * valid whether EL3 is implemented or not
*/ */
wp.wcr = deposit32(wp.wcr, 1, 2, 3); wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, PAC, 3);
switch (type) { switch (type) {
case GDB_WATCHPOINT_READ: case GDB_WATCHPOINT_READ:
wp.wcr = deposit32(wp.wcr, 3, 2, 1); wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 1);
wp.details.flags = BP_MEM_READ; wp.details.flags = BP_MEM_READ;
break; break;
case GDB_WATCHPOINT_WRITE: case GDB_WATCHPOINT_WRITE:
wp.wcr = deposit32(wp.wcr, 3, 2, 2); wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 2);
wp.details.flags = BP_MEM_WRITE; wp.details.flags = BP_MEM_WRITE;
break; break;
case GDB_WATCHPOINT_ACCESS: case GDB_WATCHPOINT_ACCESS:
wp.wcr = deposit32(wp.wcr, 3, 2, 3); wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 3);
wp.details.flags = BP_MEM_ACCESS; wp.details.flags = BP_MEM_ACCESS;
break; break;
default: default:
@ -252,8 +252,8 @@ static int insert_hw_watchpoint(target_ulong addr,
int bits = ctz64(len); int bits = ctz64(len);
wp.wvr &= ~((1 << bits) - 1); wp.wvr &= ~((1 << bits) - 1);
wp.wcr = deposit32(wp.wcr, 24, 4, bits); wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, MASK, bits);
wp.wcr = deposit32(wp.wcr, 5, 8, 0xff); wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, BAS, 0xff);
} else { } else {
return -ENOBUFS; return -ENOBUFS;
} }