[PATCH 1/2] hw/riscv: Make s-mode IMSIC stride explicit
Joel Stanley <[email protected]>
| Newsgroups | org.nongnu.qemu-devel,org.nongnu.qemu-riscv |
|---|---|
| Message-ID | <[email protected]> |
Existing machines tightly coupled s-mode IMSIC stride with the guest
bits value. There need to be enough bits to describe the guest in
GEILEN, but that's a minimum bound and machines may choose to use a
larger stride. This change decouples the two and updates Atlantis and
Virt to use the new API.
AIA guest count used by the Atlantis machine was not correct. It looks
like a placeholder value was chosen in order to size the stride to
0x40000, but this gives the wrong guest count. From the (currently
internal) docs, the guest count is 5:
> |NUM_GEILEN|5 (0 - 64)|Number of supported guest index from the S-mode interrupt domain|
Add that value to a define, and add a separate define for the stride, to
reduce the opportunity for future confusion.
Fixes: 7778f4b27bb1 ("hw/riscv: Add Tenstorrent Atlantis machine")
Signed-off-by: Joel Stanley <[email protected]>
---
hw/riscv/aia.h | 1 +
hw/riscv/aia.c | 5 ++---
hw/riscv/tt_atlantis.c | 19 +++++++++++--------
hw/riscv/virt.c | 2 ++
4 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/hw/riscv/aia.h b/hw/riscv/aia.h
index 565f91accc09..3b6d7f962506 100644
--- a/hw/riscv/aia.h
+++ b/hw/riscv/aia.h
@@ -15,6 +15,7 @@ uint32_t imsic_num_bits(uint32_t count);
DeviceState *riscv_create_aia(bool msimode, int aia_guests,
uint32_t m_imsic_stride,
+ uint32_t s_imsic_stride,
uint16_t num_sources,
const MemMapEntry *aplic_m,
const MemMapEntry *aplic_s,
diff --git a/hw/riscv/aia.c b/hw/riscv/aia.c
index ed8916002945..c33a3b32bd45 100644
--- a/hw/riscv/aia.c
+++ b/hw/riscv/aia.c
@@ -26,6 +26,7 @@ uint32_t imsic_num_bits(uint32_t count)
DeviceState *riscv_create_aia(bool msimode, int aia_guests,
uint32_t m_imsic_stride,
+ uint32_t s_imsic_stride,
uint16_t num_sources,
const MemMapEntry *aplic_m,
const MemMapEntry *aplic_s,
@@ -36,7 +37,6 @@ DeviceState *riscv_create_aia(bool msimode, int aia_guests,
{
int i;
hwaddr addr = 0;
- uint32_t guest_bits;
DeviceState *aplic_s_dev = NULL;
DeviceState *aplic_m_dev = NULL;
@@ -55,10 +55,9 @@ DeviceState *riscv_create_aia(bool msimode, int aia_guests,
}
/* Per-socket S-level IMSICs */
- guest_bits = imsic_num_bits(aia_guests + 1);
addr = imsic_s->base + socket * (1U << IMSIC_MMIO_GROUP_MIN_SHIFT);
for (i = 0; i < hart_count; i++) {
- riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits),
+ riscv_imsic_create(addr + i * s_imsic_stride,
base_hartid + i, false, 1 + aia_guests,
num_msis);
}
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index d808bcc11c34..88c375684412 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -37,8 +37,12 @@
#define TT_IRQCHIP_NUM_MSIS 255
#define TT_IRQCHIP_NUM_SOURCES 128
#define TT_IRQCHIP_NUM_PRIO_BITS 3
-#define TT_IRQCHIP_GUESTS 63 /* aia_guests, gives guest_index_bits=6 */
-#define TT_IRQCHIP_MIMSIC_STRIDE 0x40000
+#define TT_IMSIC_GUESTS 5
+#define TT_IMSIC_STRIDE 0x40000 /* Same stride for M and S */
+#define TT_IMSIC_GUEST_BITS 6
+
+/* Stride is fixed by hardware, check it's consistent with guest bits. */
+QEMU_BUILD_BUG_ON(TT_IMSIC_STRIDE != (0x1000 << TT_IMSIC_GUEST_BITS));
#define TT_ACLINT_MTIME_SIZE 0x8050
#define TT_ACLINT_MTIME 0x0
@@ -231,18 +235,16 @@ static void create_fdt_cpu(TTAtlantisState *s, const MemMapEntry *memmap,
create_fdt_aclint(s, intc_phandles);
- uint32_t imsic_guest_bits = imsic_num_bits(TT_IRQCHIP_GUESTS + 1);
-
/* M-level IMSIC node */
uint32_t msi_m_phandle = next_phandle();
create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_MIMSIC], ms->smp.cpus,
intc_phandles, msi_m_phandle,
- IRQ_M_EXT, imsic_guest_bits);
+ IRQ_M_EXT, TT_IMSIC_GUEST_BITS);
/* S-level IMSIC node */
create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_SIMSIC], ms->smp.cpus,
intc_phandles, imsic_s_phandle,
- IRQ_S_EXT, imsic_guest_bits);
+ IRQ_S_EXT, TT_IMSIC_GUEST_BITS);
uint32_t aplic_m_phandle = next_phandle();
@@ -493,8 +495,9 @@ static void tt_atlantis_machine_init(MachineState *machine)
&error_abort);
sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
- s->irqchip = riscv_create_aia(true, TT_IRQCHIP_GUESTS,
- TT_IRQCHIP_MIMSIC_STRIDE,
+ s->irqchip = riscv_create_aia(true, TT_IMSIC_GUESTS,
+ TT_IMSIC_STRIDE,
+ TT_IMSIC_STRIDE,
TT_IRQCHIP_NUM_SOURCES,
&s->memmap[TT_ATL_MAPLIC],
&s->memmap[TT_ATL_SAPLIC],
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index d58656f70d1b..42d28f4f5a02 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1410,9 +1410,11 @@ static void virt_machine_init(MachineState *machine)
s->irqchip[i] = virt_create_plic(s->memmap, i,
base_hartid, hart_count);
} else {
+ int imsic_bits = imsic_num_bits(s->aia_guests + 1);
s->irqchip[i] = riscv_create_aia(s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC,
s->aia_guests,
IMSIC_HART_SIZE(0),
+ IMSIC_HART_SIZE(imsic_bits),
s->num_sources,
&s->memmap[VIRT_APLIC_M],
&s->memmap[VIRT_APLIC_S],
--
2.47.3