diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2026-05-11 13:39:22 +0200 |
|---|---|---|
| committer | Michael Tokarev <mjt@tls.msk.ru> | 2026-06-16 17:45:21 +0300 |
| commit | 57a8fe8c3d070c7c65fb8b4d73c0eb4248b97824 (patch) | |
| tree | d21aa3dad3b921df0c14b8e3f24c1c2630f15ad0 | |
| parent | b5c8e7d2918168b8fe80c864e7c583d68211c289 (diff) | |
| download | qemu-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.c | 6 |
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); } |
