aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-01-07 17:07:58 +0000
committerPeter Maydell <peter.maydell@linaro.org>2022-01-07 17:07:58 +0000
commite5487a413904973ca77999c904be8949da2e8f31 (patch)
treece9e41c829840d3cfb5ebb647bc81ae957b492ce /hw
parent62df780e3d4e918d984797f2d75b0cced157b757 (diff)
hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params()
The extract_table_params() decodes the fields in the GITS_BASER<n> registers into TableDesc structs. Since the fields are the same for all the GITS_BASER<n> registers, there is currently a lot of code duplication within the switch (type) statement. Refactor so that the cases include only what is genuinely different for each type: the calculation of the number of bits in the ID value that indexes into the table. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/arm_gicv3_its.c97
1 files changed, 40 insertions, 57 deletions
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index c97b9982ae..84808b1e29 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -758,6 +758,9 @@ static void extract_table_params(GICv3ITSState *s)
uint64_t value;
for (int i = 0; i < 8; i++) {
+ TableDesc *td;
+ int idbits;
+
value = s->baser[i];
if (!value) {
@@ -789,73 +792,53 @@ static void extract_table_params(GICv3ITSState *s)
type = FIELD_EX64(value, GITS_BASER, TYPE);
switch (type) {
-
case GITS_BASER_TYPE_DEVICE:
- memset(&s->dt, 0 , sizeof(s->dt));
- s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
-
- if (!s->dt.valid) {
- break;
- }
-
- s->dt.page_sz = page_sz;
- s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
- s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
-
- if (!s->dt.indirect) {
- s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz;
- } else {
- s->dt.max_entries = (((num_pages * page_sz) /
- L1TABLE_ENTRY_SIZE) *
- (page_sz / s->dt.entry_sz));
- }
-
- s->dt.max_ids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
- DEVBITS) + 1));
-
- s->dt.base_addr = baser_base_addr(value, page_sz);
-
+ td = &s->dt;
+ idbits = FIELD_EX64(s->typer, GITS_TYPER, DEVBITS) + 1;
break;
-
case GITS_BASER_TYPE_COLLECTION:
- memset(&s->ct, 0 , sizeof(s->ct));
- s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
-
- /*
- * GITS_TYPER.HCC is 0 for this implementation
- * hence writes are discarded if ct.valid is 0
- */
- if (!s->ct.valid) {
- break;
- }
-
- s->ct.page_sz = page_sz;
- s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
- s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
-
- if (!s->ct.indirect) {
- s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz;
- } else {
- s->ct.max_entries = (((num_pages * page_sz) /
- L1TABLE_ENTRY_SIZE) *
- (page_sz / s->ct.entry_sz));
- }
-
+ td = &s->ct;
if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
- s->ct.max_ids = (1UL << (FIELD_EX64(s->typer,
- GITS_TYPER, CIDBITS) + 1));
+ idbits = FIELD_EX64(s->typer, GITS_TYPER, CIDBITS) + 1;
} else {
/* 16-bit CollectionId supported when CIL == 0 */
- s->ct.max_ids = (1UL << 16);
+ idbits = 16;
}
-
- s->ct.base_addr = baser_base_addr(value, page_sz);
-
break;
-
default:
- break;
+ /*
+ * GITS_BASER<n>.TYPE is read-only, so GITS_BASER_RO_MASK
+ * ensures we will only see type values corresponding to
+ * the values set up in gicv3_its_reset().
+ */
+ g_assert_not_reached();
+ }
+
+ memset(td, 0, sizeof(*td));
+ td->valid = FIELD_EX64(value, GITS_BASER, VALID);
+ /*
+ * If GITS_BASER<n>.Valid is 0 for any <n> then we will not process
+ * interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we
+ * do not have a special case where the GITS_BASER<n>.Valid bit is 0
+ * for the register corresponding to the Collection table but we
+ * still have to process interrupts using non-memory-backed
+ * Collection table entries.)
+ */
+ if (!td->valid) {
+ continue;
+ }
+ td->page_sz = page_sz;
+ td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
+ td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
+ td->base_addr = baser_base_addr(value, page_sz);
+ if (!td->indirect) {
+ td->max_entries = (num_pages * page_sz) / td->entry_sz;
+ } else {
+ td->max_entries = (((num_pages * page_sz) /
+ L1TABLE_ENTRY_SIZE) *
+ (page_sz / td->entry_sz));
}
+ td->max_ids = 1ULL << idbits;
}
}