aboutsummaryrefslogtreecommitdiff
path: root/hw/intc
diff options
context:
space:
mode:
authorGlenn Miles <milesg@linux.ibm.com>2025-05-12 13:10:12 +1000
committerCédric Le Goater <clg@redhat.com>2025-07-21 08:03:52 +0200
commitf16697292add6c3c15014a20fd5fce70b8c56734 (patch)
treef47ce3ad995e2fbcb135c059140457d383a23418 /hw/intc
parentf0aab779418ed883ea2b5ffcc3985ef26f6e3545 (diff)
downloadqemu-f16697292add6c3c15014a20fd5fce70b8c56734.zip
qemu-f16697292add6c3c15014a20fd5fce70b8c56734.tar.gz
qemu-f16697292add6c3c15014a20fd5fce70b8c56734.tar.bz2
ppc/xive2: Fix calculation of END queue sizes
The queue size of an Event Notification Descriptor (END) is determined by the 'cl' and QsZ fields of the END. If the cl field is 1, then the queue size (in bytes) will be the size of a cache line 128B * 2^QsZ and QsZ is limited to 4. Otherwise, it will be 4096B * 2^QsZ with QsZ limited to 12. Fixes: f8a233dedf2 ("ppc/xive2: Introduce a XIVE2 core framework") Signed-off-by: Glenn Miles <milesg@linux.ibm.com> Reviewed-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Michael Kowal <kowal@linux.ibm.com> Reviewed-by: Caleb Schlossin <calebs@linux.ibm.com> Tested-by: Gautam Menghani <gautam@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20250512031100.439842-4-npiggin@gmail.com Signed-off-by: Cédric Le Goater <clg@redhat.com>
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/xive2.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c
index a08cf90..cb75ca8 100644
--- a/hw/intc/xive2.c
+++ b/hw/intc/xive2.c
@@ -188,12 +188,27 @@ void xive2_eas_pic_print_info(Xive2Eas *eas, uint32_t lisn, GString *buf)
(uint32_t) xive_get_field64(EAS2_END_DATA, eas->w));
}
+#define XIVE2_QSIZE_CHUNK_CL 128
+#define XIVE2_QSIZE_CHUNK_4k 4096
+/* Calculate max number of queue entries for an END */
+static uint32_t xive2_end_get_qentries(Xive2End *end)
+{
+ uint32_t w3 = end->w3;
+ uint32_t qsize = xive_get_field32(END2_W3_QSIZE, w3);
+ if (xive_get_field32(END2_W3_CL, w3)) {
+ g_assert(qsize <= 4);
+ return (XIVE2_QSIZE_CHUNK_CL << qsize) / sizeof(uint32_t);
+ } else {
+ g_assert(qsize <= 12);
+ return (XIVE2_QSIZE_CHUNK_4k << qsize) / sizeof(uint32_t);
+ }
+}
+
void xive2_end_queue_pic_print_info(Xive2End *end, uint32_t width, GString *buf)
{
uint64_t qaddr_base = xive2_end_qaddr(end);
- uint32_t qsize = xive_get_field32(END2_W3_QSIZE, end->w3);
uint32_t qindex = xive_get_field32(END2_W1_PAGE_OFF, end->w1);
- uint32_t qentries = 1 << (qsize + 10);
+ uint32_t qentries = xive2_end_get_qentries(end);
int i;
/*
@@ -223,8 +238,7 @@ void xive2_end_pic_print_info(Xive2End *end, uint32_t end_idx, GString *buf)
uint64_t qaddr_base = xive2_end_qaddr(end);
uint32_t qindex = xive_get_field32(END2_W1_PAGE_OFF, end->w1);
uint32_t qgen = xive_get_field32(END2_W1_GENERATION, end->w1);
- uint32_t qsize = xive_get_field32(END2_W3_QSIZE, end->w3);
- uint32_t qentries = 1 << (qsize + 10);
+ uint32_t qentries = xive2_end_get_qentries(end);
uint32_t nvx_blk = xive_get_field32(END2_W6_VP_BLOCK, end->w6);
uint32_t nvx_idx = xive_get_field32(END2_W6_VP_OFFSET, end->w6);
@@ -341,13 +355,12 @@ void xive2_nvgc_pic_print_info(Xive2Nvgc *nvgc, uint32_t nvgc_idx, GString *buf)
static void xive2_end_enqueue(Xive2End *end, uint32_t data)
{
uint64_t qaddr_base = xive2_end_qaddr(end);
- uint32_t qsize = xive_get_field32(END2_W3_QSIZE, end->w3);
uint32_t qindex = xive_get_field32(END2_W1_PAGE_OFF, end->w1);
uint32_t qgen = xive_get_field32(END2_W1_GENERATION, end->w1);
uint64_t qaddr = qaddr_base + (qindex << 2);
uint32_t qdata = cpu_to_be32((qgen << 31) | (data & 0x7fffffff));
- uint32_t qentries = 1 << (qsize + 10);
+ uint32_t qentries = xive2_end_get_qentries(end);
if (dma_memory_write(&address_space_memory, qaddr, &qdata, sizeof(qdata),
MEMTXATTRS_UNSPECIFIED)) {