@samitouri / QOSamiQemu / commits / 3097d54016

amd_iommu: restrict command buffer head/tail ranges to ring size

The AMD IOMMU command buffer is a ring buffer of cmdbuf_len (a power of two) entries. Each entry is 16 bytes and the head pointer cycles through the set: [0, 16, 32, ..., (cmdbuf_len - 1) * AMDVI_COMMAND_SIZE] The tail pointer is written by the guest through the COMMAND_TAIL MMIO register (offset 0x2008); the while loop in amdvi_cmdbuf_run() only terminates when head == tail. If tail is set to a value higher than cmdbuf_len * 16, head will cycle through all the elements of the ring buffer indefinitely, without ever matching tail. Fix this by further masking tail (and head, for consistency) against the size of the ring buffer. Reported-by: Yunhe Wang <yunhewwww@163.com> Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260511113923.2478812-1-pbonzini@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

Paolo Bonzini committed May 11, 2026 at 13:39 UTC 3097d54016ea9f8f0436f0b20e1b4d78a02b6aeb
1 file changed +4 -2
hw/i386/amd_iommu.c
+4 -2
@@ -1578,7 +1578,8 @@ static inline void amdvi_handle_devtab_write(AMDVIState *s)
1578 static inline void amdvi_handle_cmdhead_write(AMDVIState *s)
1579 {
1580 s->cmdbuf_head = amdvi_readq(s, AMDVI_MMIO_COMMAND_HEAD)
1581 - & AMDVI_MMIO_CMDBUF_HEAD_MASK;
1581 + & AMDVI_MMIO_CMDBUF_HEAD_MASK
1582 + & (s->cmdbuf_len * AMDVI_COMMAND_SIZE - 1);
1583 amdvi_cmdbuf_run(s);
1584 }
1585
@@ -1594,7 +1595,8 @@ static inline void amdvi_handle_cmdbase_write(AMDVIState *s)
1595 static inline void amdvi_handle_cmdtail_write(AMDVIState *s)
1596 {
1597 s->cmdbuf_tail = amdvi_readq(s, AMDVI_MMIO_COMMAND_TAIL)
1597 - & AMDVI_MMIO_CMDBUF_TAIL_MASK;
1598 + & AMDVI_MMIO_CMDBUF_TAIL_MASK
1599 + & (s->cmdbuf_len * AMDVI_COMMAND_SIZE - 1);
1600 amdvi_cmdbuf_run(s);
1601 }
1602