summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2026-05-11 13:39:22 +0200
committerMichael Tokarev <mjt@tls.msk.ru>2026-06-16 17:45:21 +0300
commit57a8fe8c3d070c7c65fb8b4d73c0eb4248b97824 (patch)
treed21aa3dad3b921df0c14b8e3f24c1c2630f15ad0
parentb5c8e7d2918168b8fe80c864e7c583d68211c289 (diff)
downloadqemu-57a8fe8c3d070c7c65fb8b4d73c0eb4248b97824.tar.gz
qemu-57a8fe8c3d070c7c65fb8b4d73c0eb4248b97824.zip
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> (cherry picked from commit 3097d54016ea9f8f0436f0b20e1b4d78a02b6aeb) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
-rw-r--r--hw/i386/amd_iommu.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 37447dca25..4405ce8988 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -674,7 +674,8 @@ static inline void amdvi_handle_devtab_write(AMDVIState *s)
static inline void amdvi_handle_cmdhead_write(AMDVIState *s)
{
s->cmdbuf_head = amdvi_readq(s, AMDVI_MMIO_COMMAND_HEAD)
- & AMDVI_MMIO_CMDBUF_HEAD_MASK;
+ & AMDVI_MMIO_CMDBUF_HEAD_MASK
+ & (s->cmdbuf_len * AMDVI_COMMAND_SIZE - 1);
amdvi_cmdbuf_run(s);
}
@@ -690,7 +691,8 @@ static inline void amdvi_handle_cmdbase_write(AMDVIState *s)
static inline void amdvi_handle_cmdtail_write(AMDVIState *s)
{
s->cmdbuf_tail = amdvi_readq(s, AMDVI_MMIO_COMMAND_TAIL)
- & AMDVI_MMIO_CMDBUF_TAIL_MASK;
+ & AMDVI_MMIO_CMDBUF_TAIL_MASK
+ & (s->cmdbuf_len * AMDVI_COMMAND_SIZE - 1);
amdvi_cmdbuf_run(s);
}