Skip to content

Commit e4f5489

Browse files
authored
Merge pull request #1127 from sunnyzhu-learning/Songhe-develop
target/riscv: Mismatch napot when mcontrol.maskmax is not expected
2 parents 841b61a + 85c836b commit e4f5489

File tree

1 file changed

+68
-43
lines changed

1 file changed

+68
-43
lines changed

src/target/riscv/riscv.c

Lines changed: 68 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,17 @@ static int find_first_trigger_by_id(struct target *target, int unique_id)
621621
return -1;
622622
}
623623

624-
static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdata1, riscv_reg_t tdata2,
625-
riscv_reg_t tdata1_ignore_mask)
624+
static unsigned int count_trailing_ones(riscv_reg_t reg)
625+
{
626+
assert(sizeof(riscv_reg_t) * 8 == 64);
627+
for (unsigned int i = 0; i < 64; i++) {
628+
if ((1 & (reg >> i)) == 0)
629+
return i;
630+
}
631+
return 64;
632+
}
633+
634+
static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdata1, riscv_reg_t tdata2)
626635
{
627636
RISCV_INFO(r);
628637
assert(r->reserved_triggers);
@@ -655,20 +664,51 @@ static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdat
655664
return ERROR_FAIL;
656665
if (riscv_reg_get(target, &tdata2_rb, GDB_REGNO_TDATA2) != ERROR_OK)
657666
return ERROR_FAIL;
658-
bool tdata1_config_denied = (tdata1 & ~tdata1_ignore_mask) != (tdata1_rb & ~tdata1_ignore_mask);
659-
bool tdata2_config_denied = tdata2 != tdata2_rb;
660-
if (tdata1_config_denied || tdata2_config_denied) {
667+
668+
const uint32_t type = get_field(tdata1, CSR_TDATA1_TYPE(riscv_xlen(target)));
669+
const bool is_mcontrol = type == CSR_TDATA1_TYPE_MCONTROL;
670+
671+
/* Determine if tdata1 supports what we need.
672+
* For mcontrol triggers, we don't care about
673+
* the value in the read-only "maskmax" field.
674+
*/
675+
const riscv_reg_t tdata1_ignore_mask = is_mcontrol ? CSR_MCONTROL_MASKMAX(riscv_xlen(target)) : 0;
676+
const bool tdata1_config_denied = (tdata1 & ~tdata1_ignore_mask) != (tdata1_rb & ~tdata1_ignore_mask);
677+
678+
/* Determine if tdata1.maxmask is sufficient
679+
* (only relevant for mcontrol triggers and NAPOT match type)
680+
*/
681+
bool unsupported_napot_range = false;
682+
riscv_reg_t maskmax_value = 0;
683+
if (!tdata1_config_denied) {
684+
const bool is_napot_match = get_field(tdata1_rb, CSR_MCONTROL_MATCH) == CSR_MCONTROL_MATCH_NAPOT;
685+
if (is_mcontrol && is_napot_match) {
686+
maskmax_value = get_field(tdata1_rb, CSR_MCONTROL_MASKMAX(riscv_xlen(target)));
687+
const unsigned int napot_size = count_trailing_ones(tdata2) + 1;
688+
if (maskmax_value < napot_size)
689+
unsupported_napot_range = true;
690+
}
691+
}
692+
693+
const bool tdata2_config_denied = tdata2 != tdata2_rb;
694+
if (tdata1_config_denied || tdata2_config_denied || unsupported_napot_range) {
661695
LOG_TARGET_DEBUG(target, "Trigger %u doesn't support what we need.", idx);
662696

663697
if (tdata1_config_denied)
664698
LOG_TARGET_DEBUG(target,
665-
"After writing 0x%" PRIx64 " to tdata1 it contains 0x%" PRIx64 "; tdata1_ignore_mask=0x%" PRIx64,
666-
tdata1, tdata1_rb, tdata1_ignore_mask);
699+
"After writing 0x%" PRIx64 " to tdata1 it contains 0x%" PRIx64,
700+
tdata1, tdata1_rb);
667701

668702
if (tdata2_config_denied)
669703
LOG_TARGET_DEBUG(target,
670-
"wrote 0x%" PRIx64 " to tdata2 but read back 0x%" PRIx64,
704+
"After writing 0x%" PRIx64 " to tdata2 it contains 0x%" PRIx64,
671705
tdata2, tdata2_rb);
706+
707+
if (unsupported_napot_range)
708+
LOG_TARGET_DEBUG(target,
709+
"The requested NAPOT match range (tdata2=0x%" PRIx64 ") exceeds maskmax_value=0x%" PRIx64,
710+
tdata2, maskmax_value);
711+
672712
if (riscv_reg_set(target, GDB_REGNO_TDATA1, 0) != ERROR_OK)
673713
return ERROR_FAIL;
674714
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@@ -717,7 +757,7 @@ static int maybe_add_trigger_t1(struct target *target, struct trigger *trigger)
717757
tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); /* cause bp exception */
718758
tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); /* exact match */
719759
tdata2 = trigger->address;
720-
ret = set_trigger(target, idx, tdata1, tdata2, 0);
760+
ret = set_trigger(target, idx, tdata1, tdata2);
721761
if (ret != ERROR_OK)
722762
return ret;
723763
r->trigger_unique_id[idx] = trigger->unique_id;
@@ -727,13 +767,11 @@ static int maybe_add_trigger_t1(struct target *target, struct trigger *trigger)
727767
struct trigger_request_info {
728768
riscv_reg_t tdata1;
729769
riscv_reg_t tdata2;
730-
riscv_reg_t tdata1_ignore_mask;
731770
};
732771

733772
static void log_trigger_request_info(struct trigger_request_info trig_info)
734773
{
735-
LOG_DEBUG("tdata1=%" PRIx64 ", tdata2=%" PRIx64 ", tdata1_ignore_mask=%" PRIx64,
736-
trig_info.tdata1, trig_info.tdata2, trig_info.tdata1_ignore_mask);
774+
LOG_DEBUG("tdata1=%" PRIx64 ", tdata2=%" PRIx64, trig_info.tdata1, trig_info.tdata2);
737775
};
738776

739777
static struct tdata1_cache *tdata1_cache_alloc(struct list_head *tdata1_cache_head, riscv_reg_t tdata1)
@@ -816,12 +854,12 @@ static bool wp_triggers_cache_search(struct target *target, unsigned int idx,
816854
}
817855

818856
static int try_use_trigger_and_cache_result(struct target *target, unsigned int idx, riscv_reg_t tdata1,
819-
riscv_reg_t tdata2, riscv_reg_t tdata1_ignore_mask)
857+
riscv_reg_t tdata2)
820858
{
821859
if (wp_triggers_cache_search(target, idx, tdata1, tdata2))
822860
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
823861

824-
int ret = set_trigger(target, idx, tdata1, tdata2, tdata1_ignore_mask);
862+
int ret = set_trigger(target, idx, tdata1, tdata2);
825863

826864
/* Add these values to the cache to remember that they are not supported. */
827865
if (ret == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
@@ -844,8 +882,7 @@ static int try_setup_single_match_trigger(struct target *target,
844882
for (unsigned int idx = 0;
845883
find_next_free_trigger(target, trigger_type, false, &idx) == ERROR_OK;
846884
++idx) {
847-
ret = try_use_trigger_and_cache_result(target, idx, trig_info.tdata1, trig_info.tdata2,
848-
trig_info.tdata1_ignore_mask);
885+
ret = try_use_trigger_and_cache_result(target, idx, trig_info.tdata1, trig_info.tdata2);
849886

850887
if (ret == ERROR_OK) {
851888
r->trigger_unique_id[idx] = trigger->unique_id;
@@ -873,24 +910,22 @@ static int try_setup_chained_match_triggers(struct target *target,
873910
for (unsigned int idx = 0;
874911
find_next_free_trigger(target, trigger_type, true, &idx) == ERROR_OK;
875912
++idx) {
876-
ret = try_use_trigger_and_cache_result(target, idx, t1.tdata1, t1.tdata2,
877-
t1.tdata1_ignore_mask);
913+
ret = try_use_trigger_and_cache_result(target, idx, t1.tdata1, t1.tdata2);
878914

879915
if (ret == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
880916
continue;
881917
else if (ret != ERROR_OK)
882918
return ret;
883919

884-
ret = try_use_trigger_and_cache_result(target, idx + 1, t2.tdata1, t2.tdata2,
885-
t2.tdata1_ignore_mask);
920+
ret = try_use_trigger_and_cache_result(target, idx + 1, t2.tdata1, t2.tdata2);
886921

887922
if (ret == ERROR_OK) {
888923
r->trigger_unique_id[idx] = trigger->unique_id;
889924
r->trigger_unique_id[idx + 1] = trigger->unique_id;
890925
return ERROR_OK;
891926
}
892927
/* Undo the setting of the previous trigger */
893-
int ret_undo = set_trigger(target, idx, 0, 0, 0);
928+
int ret_undo = set_trigger(target, idx, 0, 0);
894929
if (ret_undo != ERROR_OK)
895930
return ret_undo;
896931

@@ -918,7 +953,6 @@ struct match_triggers_tdata1_fields {
918953
riscv_reg_t ge;
919954
riscv_reg_t eq;
920955
} match;
921-
riscv_reg_t tdata1_ignore_mask;
922956
};
923957

924958
static struct match_triggers_tdata1_fields fill_match_triggers_tdata1_fields_t2(struct target *target,
@@ -951,8 +985,7 @@ static struct match_triggers_tdata1_fields fill_match_triggers_tdata1_fields_t2(
951985
.lt = field_value(CSR_MCONTROL_MATCH, CSR_MCONTROL_MATCH_LT),
952986
.ge = field_value(CSR_MCONTROL_MATCH, CSR_MCONTROL_MATCH_GE),
953987
.eq = field_value(CSR_MCONTROL_MATCH, CSR_MCONTROL_MATCH_EQUAL)
954-
},
955-
.tdata1_ignore_mask = CSR_MCONTROL_MASKMAX(riscv_xlen(target))
988+
}
956989
};
957990
return result;
958991
}
@@ -989,8 +1022,7 @@ static struct match_triggers_tdata1_fields fill_match_triggers_tdata1_fields_t6(
9891022
.lt = field_value(CSR_MCONTROL6_MATCH, CSR_MCONTROL6_MATCH_LT),
9901023
.ge = field_value(CSR_MCONTROL6_MATCH, CSR_MCONTROL6_MATCH_GE),
9911024
.eq = field_value(CSR_MCONTROL6_MATCH, CSR_MCONTROL6_MATCH_EQUAL)
992-
},
993-
.tdata1_ignore_mask = 0
1025+
}
9941026
};
9951027
return result;
9961028
}
@@ -1009,8 +1041,7 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target,
10091041
struct trigger_request_info napot = {
10101042
.tdata1 = fields.common | fields.size.any |
10111043
fields.chain.disable | fields.match.napot,
1012-
.tdata2 = trigger->address | ((trigger->length - 1) >> 1),
1013-
.tdata1_ignore_mask = fields.tdata1_ignore_mask
1044+
.tdata2 = trigger->address | ((trigger->length - 1) >> 1)
10141045
};
10151046
ret = try_setup_single_match_trigger(target, trigger, napot);
10161047
if (ret != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
@@ -1026,14 +1057,12 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target,
10261057
struct trigger_request_info ge_1 = {
10271058
.tdata1 = fields.common | fields.size.any | fields.chain.enable |
10281059
fields.match.ge,
1029-
.tdata2 = trigger->address,
1030-
.tdata1_ignore_mask = fields.tdata1_ignore_mask
1060+
.tdata2 = trigger->address
10311061
};
10321062
struct trigger_request_info lt_2 = {
10331063
.tdata1 = fields.common | fields.size.any | fields.chain.disable |
10341064
fields.match.lt,
1035-
.tdata2 = trigger->address + trigger->length,
1036-
.tdata1_ignore_mask = fields.tdata1_ignore_mask
1065+
.tdata2 = trigger->address + trigger->length
10371066
};
10381067
ret = try_setup_chained_match_triggers(target, trigger, ge_1, lt_2);
10391068
if (ret != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
@@ -1043,14 +1072,12 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target,
10431072
struct trigger_request_info lt_1 = {
10441073
.tdata1 = fields.common | fields.size.any | fields.chain.enable |
10451074
fields.match.lt,
1046-
.tdata2 = trigger->address + trigger->length,
1047-
.tdata1_ignore_mask = fields.tdata1_ignore_mask
1075+
.tdata2 = trigger->address + trigger->length
10481076
};
10491077
struct trigger_request_info ge_2 = {
10501078
.tdata1 = fields.common | fields.size.any | fields.chain.disable |
10511079
fields.match.ge,
1052-
.tdata2 = trigger->address,
1053-
.tdata1_ignore_mask = fields.tdata1_ignore_mask
1080+
.tdata2 = trigger->address
10541081
};
10551082
ret = try_setup_chained_match_triggers(target, trigger, lt_1, ge_2);
10561083
if (ret != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
@@ -1066,8 +1093,7 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target,
10661093
struct trigger_request_info eq = {
10671094
.tdata1 = fields.common | fields.size.any | fields.chain.disable |
10681095
fields.match.eq,
1069-
.tdata2 = trigger->address,
1070-
.tdata1_ignore_mask = fields.tdata1_ignore_mask
1096+
.tdata2 = trigger->address
10711097
};
10721098
ret = try_setup_single_match_trigger(target, trigger, eq);
10731099
if (ret != ERROR_OK)
@@ -1104,8 +1130,7 @@ static int maybe_add_trigger_t2_t6_for_bp(struct target *target,
11041130
struct trigger_request_info eq = {
11051131
.tdata1 = fields.common | fields.size.any | fields.chain.disable |
11061132
fields.match.eq,
1107-
.tdata2 = trigger->address,
1108-
.tdata1_ignore_mask = fields.tdata1_ignore_mask
1133+
.tdata2 = trigger->address
11091134
};
11101135

11111136
return try_setup_single_match_trigger(target, trigger, eq);
@@ -1148,7 +1173,7 @@ static int maybe_add_trigger_t3(struct target *target, bool vs, bool vu,
11481173
ret = find_next_free_trigger(target, CSR_TDATA1_TYPE_ICOUNT, false, &idx);
11491174
if (ret != ERROR_OK)
11501175
return ret;
1151-
ret = set_trigger(target, idx, tdata1, 0, 0);
1176+
ret = set_trigger(target, idx, tdata1, 0);
11521177
if (ret != ERROR_OK)
11531178
return ret;
11541179
r->trigger_unique_id[idx] = unique_id;
@@ -1181,7 +1206,7 @@ static int maybe_add_trigger_t4(struct target *target, bool vs, bool vu,
11811206
ret = find_next_free_trigger(target, CSR_TDATA1_TYPE_ITRIGGER, false, &idx);
11821207
if (ret != ERROR_OK)
11831208
return ret;
1184-
ret = set_trigger(target, idx, tdata1, tdata2, 0);
1209+
ret = set_trigger(target, idx, tdata1, tdata2);
11851210
if (ret != ERROR_OK)
11861211
return ret;
11871212
r->trigger_unique_id[idx] = unique_id;
@@ -1213,7 +1238,7 @@ static int maybe_add_trigger_t5(struct target *target, bool vs, bool vu,
12131238
ret = find_next_free_trigger(target, CSR_TDATA1_TYPE_ETRIGGER, false, &idx);
12141239
if (ret != ERROR_OK)
12151240
return ret;
1216-
ret = set_trigger(target, idx, tdata1, tdata2, 0);
1241+
ret = set_trigger(target, idx, tdata1, tdata2);
12171242
if (ret != ERROR_OK)
12181243
return ret;
12191244
r->trigger_unique_id[idx] = unique_id;

0 commit comments

Comments
 (0)