* Tue Aug 11 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-26el10nv.1
- memory: Make ram device region directly accessible [VOYAGER-1010] - Resolves: VOYAGER-1010 (Guest hang due to exhausted bounce buffer on compiling cuda-samples)
This commit is contained in:
parent
2d2c3aeaac
commit
e0cf08c577
@ -0,0 +1,82 @@
|
||||
From 22dbe118100e71df437677c58e74b3df6bcf5b6b Mon Sep 17 00:00:00 2001
|
||||
From: Gavin Shan <gshan@redhat.com>
|
||||
Date: Wed, 29 Jul 2026 09:57:35 +1000
|
||||
Subject: [PATCH 1/4] system/memory: Use memmove() for directly accessible
|
||||
regions
|
||||
|
||||
RH-Author: Gavin Shan <gshan@redhat.com>
|
||||
RH-MergeRequest: 512: memory: Make ram device region directly accessible
|
||||
RH-Jira: VOYAGER-1010
|
||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
|
||||
RH-Commit: [1/3] c336d9555d (gwshan/qemu-centos10)
|
||||
|
||||
JIRA: https://redhat.atlassian.net/browse/VOYAGER-1010
|
||||
UPSTREAM: no, https://gitlab.com/peterx/qemu.git (branch: next) 1efb05224dc2
|
||||
|
||||
Similar to what's done in commit 4a73aee88140 ("softmmu: Use memmove in
|
||||
flatview_write_continue"), there are more sites where the overlapping
|
||||
source and destination buffer are allowed for the directly accessible
|
||||
regions. Use memmove() in those sites, listed as below.
|
||||
|
||||
hw/remote/vfio-user-obj.c::vfu_object_mr_rw
|
||||
include/system/memory.h::address_space_read
|
||||
system/physmem.c::flatview_read_continue_step
|
||||
|
||||
Signed-off-by: Gavin Shan <gshan@redhat.com>
|
||||
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Reviewed-by: Peter Xu <peterx@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20260728031731.286666-2-gshan@redhat.com
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
(cherry picked from commit 1efb05224dc2544f27687ad2970082e2a8c0a37d)
|
||||
Signed-off-by: Gavin Shan <gshan@redhat.com>
|
||||
---
|
||||
hw/remote/vfio-user-obj.c | 4 ++--
|
||||
include/system/memory.h | 2 +-
|
||||
system/physmem.c | 2 +-
|
||||
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c
|
||||
index ea6165ebdc..494fea565c 100644
|
||||
--- a/hw/remote/vfio-user-obj.c
|
||||
+++ b/hw/remote/vfio-user-obj.c
|
||||
@@ -368,9 +368,9 @@ static int vfu_object_mr_rw(MemoryRegion *mr, uint8_t *buf, hwaddr offset,
|
||||
ram_ptr = memory_region_get_ram_ptr(mr);
|
||||
|
||||
if (is_write) {
|
||||
- memcpy((ram_ptr + offset), buf, size);
|
||||
+ memmove((ram_ptr + offset), buf, size);
|
||||
} else {
|
||||
- memcpy(buf, (ram_ptr + offset), size);
|
||||
+ memmove(buf, (ram_ptr + offset), size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/include/system/memory.h b/include/system/memory.h
|
||||
index 8e60f03d44..b39ec9a5d3 100644
|
||||
--- a/include/system/memory.h
|
||||
+++ b/include/system/memory.h
|
||||
@@ -3184,7 +3184,7 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
|
||||
mr = flatview_translate(fv, addr, &addr1, &l, false, attrs);
|
||||
if (len == l && memory_access_is_direct(mr, false, attrs)) {
|
||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
||||
- memcpy(buf, ptr, len);
|
||||
+ memmove(buf, ptr, len);
|
||||
} else {
|
||||
result = flatview_read_continue(fv, addr, attrs, buf, len,
|
||||
addr1, l, mr);
|
||||
diff --git a/system/physmem.c b/system/physmem.c
|
||||
index 4a1294f8a0..697e75dad7 100644
|
||||
--- a/system/physmem.c
|
||||
+++ b/system/physmem.c
|
||||
@@ -3074,7 +3074,7 @@ static MemTxResult flatview_read_continue_step(MemTxAttrs attrs, uint8_t *buf,
|
||||
uint8_t *ram_ptr = qemu_ram_ptr_length(mr->ram_block, mr_addr, l,
|
||||
false, false);
|
||||
|
||||
- memcpy(buf, ram_ptr, *l);
|
||||
+ memmove(buf, ram_ptr, *l);
|
||||
|
||||
return MEMTX_OK;
|
||||
}
|
||||
--
|
||||
2.52.0
|
||||
|
||||
270
0485-system-memory-Use-qemu_ram_move-for-directly-accessi.patch
Normal file
270
0485-system-memory-Use-qemu_ram_move-for-directly-accessi.patch
Normal file
@ -0,0 +1,270 @@
|
||||
From 8d21a40d17e2fcd9156cc18adb9706a8e694a265 Mon Sep 17 00:00:00 2001
|
||||
From: Gavin Shan <gshan@redhat.com>
|
||||
Date: Wed, 29 Jul 2026 09:57:35 +1000
|
||||
Subject: [PATCH 2/4] system/memory: Use qemu_ram_move() for directly
|
||||
accessible regions
|
||||
|
||||
RH-Author: Gavin Shan <gshan@redhat.com>
|
||||
RH-MergeRequest: 512: memory: Make ram device region directly accessible
|
||||
RH-Jira: VOYAGER-1010
|
||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
|
||||
RH-Commit: [2/3] f53487900c (gwshan/qemu-centos10)
|
||||
|
||||
JIRA: https://redhat.atlassian.net/browse/VOYAGER-1010
|
||||
UPSTREAM: no, https://gitlab.com/peterx/qemu.git (branch: next) 9f32b8e96244
|
||||
|
||||
All ram device regions were turned to be indirectly accessible by commit
|
||||
4a2e242bbb ("memory: Don't use memcpy for ram_device regions"). This leads
|
||||
to guest hang on attempt to build 'cuda-samples' as reported by Julia. The
|
||||
guest is started by the following command lines, with GH100 GPU card passed
|
||||
from the host.
|
||||
|
||||
host$ lspci | grep GH100
|
||||
0009:01:00.0 3D controller: NVIDIA Corporation GH100 [GH200 120GB / 480GB] (rev a1)
|
||||
host$ /home/sandbox/gavin/qemu.main/build/qemu-system-aarch64 \
|
||||
-machine virt,gic-version=host,ras=on,highmem-mmio-size=4T \
|
||||
-accel kvm -cpu host -smp cpus=48 -m size=8G \
|
||||
-drive file=/home/gavin/sandbox/images/disk.qcow2,if=none,id=d0 \
|
||||
-device virtio-blk-pci,id=vb0,bus=pcie.0,drive=d0,num-queues=4 \
|
||||
-device vfio-pci-nohotplug,host=0009:01:00.0,bus=pcie.1.0
|
||||
:
|
||||
guest$ cd cuda-samples/build
|
||||
guest$ make -j 20 clean
|
||||
guest$ make -j 20
|
||||
:
|
||||
[ 54%] Linking CUDA executable graphMemoryNodes
|
||||
[ 54%] Built target graphMemoryNodes
|
||||
<no more output afterwards, guest becomes frozen here>
|
||||
|
||||
guest$ qemu-system-aarch64: virtio: bogus descriptor or out of resources
|
||||
[ 555.814025] virtio_blk virtio0: [vda] new size: 268435456 512-byte logical blocks (137 GB/128 GiB)
|
||||
|
||||
When the GPU's driver (NVidia open driver) is loaded on guest bootup,
|
||||
the memory blocks residing in the PCI BAR#4 of the GH100 GPU card can
|
||||
be presented to the guest through memory hot-add. The page cache can
|
||||
then be allocated from the hot added memory blocks when cuda-samples
|
||||
is being built. Afterwards, the page cache is sent to QEMU's virtio-blk
|
||||
device as part of the DMA request, the bounce buffer has to be used to
|
||||
accomodate the request as the corresponding memory region (MemoryRegion)
|
||||
is an indirectly accessible ram device region in qemu. However, the max
|
||||
bounce bufer size is only 4096 bytes by default and that is exhausted
|
||||
quickly, leading to a reset on the virtio-blk device and frozen guest
|
||||
eventually.
|
||||
|
||||
QEMU
|
||||
====
|
||||
virtio_blk_handle_output
|
||||
virtio_blk_handle_vq
|
||||
virtio_blk_get_request
|
||||
virtqueue_pop
|
||||
virtqueue_split_pop
|
||||
virtqueue_map_desc
|
||||
address_space_map
|
||||
memory_access_is_direct # Return false
|
||||
memory_region_supports_direct_access
|
||||
|
||||
(qemu) info mtree
|
||||
memory-region: pci_bridge_pci
|
||||
0000000000000000-ffffffffffffffff (prio 0, container): pci_bridge_pci
|
||||
0000042000000000-0000043fffffffff (prio 1, i/o): 0009:01:00.0 base BAR 4
|
||||
0000042000000000-0000043fffffffff (prio 0, i/o): 0009:01:00.0 BAR 4
|
||||
0000042000000000-000004379fffffff (prio 0, ramd): 0009:01:00.0 BAR 4 mmaps[0]
|
||||
|
||||
This adds qemu_ram_move() where the aligned and small-sized accesses are
|
||||
handled by qatomics, and fall back to memmove() otherwise. The memove()
|
||||
for the directly accessible regions is replaced by qemu_ram_move() so that
|
||||
the issue covered by commit 4a2e242bbb (MMIO access instructions were
|
||||
optimized to SSE instructions) is fixed. This makes 'ram_device_mem_ops'
|
||||
redundant, paving the way to revert that commit to make the ram device
|
||||
region directly accessible again in the next patch.
|
||||
|
||||
Besides, this also fixes the issue of the unexpected frozen reception on
|
||||
e1000 NIC in the scenario of DPDK due to the wrong Rx queue full indication
|
||||
caused by the following memcpy(), which is turned to 3 consective 'strb'
|
||||
instructions to the same location by glibc-2.24+ for aarch64. With this
|
||||
applied, the syntax of one-byte store is strictly ensured by a one-byte
|
||||
qatomic set.
|
||||
|
||||
QEMU
|
||||
====
|
||||
e1000_receive_iov
|
||||
pci_dma_write
|
||||
pci_dma_rw
|
||||
dma_memory_rw
|
||||
dma_memory_rw_relaxed
|
||||
address_space_rw
|
||||
address_space_write
|
||||
flatview_write
|
||||
flatview_write_continue
|
||||
flatview_write_continue_step
|
||||
memcpy # 3 consective 'strb' instructions
|
||||
|
||||
Reported-by: Julia Graham <jugraham@redhat.com>
|
||||
Reported-by: Liu Gang <liugang24219@sangfor.com.cn>
|
||||
Reported-by: Ding Hui <dinghui@sangfor.com.cn>
|
||||
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Suggested-by: Peter Xu <peterx@redhat.com>
|
||||
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Gavin Shan <gshan@redhat.com>
|
||||
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20260728031731.286666-3-gshan@redhat.com
|
||||
[peterx: remove src==dst check, fix doc, enhance comments, per PeterM, add R-b]
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
(cherry picked from commit 9f32b8e9624459856f9b93c04dd56d4f5c66f58a)
|
||||
Signed-off-by: Gavin Shan <gshan@redhat.com>
|
||||
Conflicts:
|
||||
include/system/memory.h
|
||||
Contextual conflict due to missed upstream commit 47b23339a5bb
|
||||
("system/memory: Constify various AddressSpace arguments (access)")
|
||||
---
|
||||
hw/remote/vfio-user-obj.c | 4 ++--
|
||||
include/system/memory.h | 35 +++++++++++++++++++++++++++-
|
||||
system/physmem.c | 48 +++++++++++++++++++++++++++++++++++++--
|
||||
3 files changed, 82 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c
|
||||
index 494fea565c..c56ee70a0d 100644
|
||||
--- a/hw/remote/vfio-user-obj.c
|
||||
+++ b/hw/remote/vfio-user-obj.c
|
||||
@@ -368,9 +368,9 @@ static int vfu_object_mr_rw(MemoryRegion *mr, uint8_t *buf, hwaddr offset,
|
||||
ram_ptr = memory_region_get_ram_ptr(mr);
|
||||
|
||||
if (is_write) {
|
||||
- memmove((ram_ptr + offset), buf, size);
|
||||
+ qemu_ram_move((ram_ptr + offset), buf, size);
|
||||
} else {
|
||||
- memmove(buf, (ram_ptr + offset), size);
|
||||
+ qemu_ram_move(buf, (ram_ptr + offset), size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/include/system/memory.h b/include/system/memory.h
|
||||
index b39ec9a5d3..351cf1253c 100644
|
||||
--- a/include/system/memory.h
|
||||
+++ b/include/system/memory.h
|
||||
@@ -3103,6 +3103,39 @@ void address_space_register_map_client(AddressSpace *as, QEMUBH *bh);
|
||||
void address_space_unregister_map_client(AddressSpace *as, QEMUBH *bh);
|
||||
|
||||
/* Internal functions, part of the implementation of address_space_read. */
|
||||
+
|
||||
+/**
|
||||
+ * qemu_ram_move: move data from or to ramblock
|
||||
+ *
|
||||
+ * @dst: destination where the data is moved to
|
||||
+ * @src: source where the data is moved from
|
||||
+ * @n: length of data to be moved
|
||||
+ *
|
||||
+ * Move @n bytes from @src to @dst, the memory areas may overlap. This
|
||||
+ * provides the same semantics as memmove(), plus an additional stronger
|
||||
+ * guarantee: if @n is 1, 2 or 4 or 8 bytes, and @src and @dst are both
|
||||
+ * naturally aligned for that access size, then both the load and the store
|
||||
+ * will be done as a single atomic access (with the semantics of
|
||||
+ * qatomic_read() and qatomic_set()).
|
||||
+ *
|
||||
+ * This is the underlying function that we use to implement accesses by
|
||||
+ * a guest vCPU or a device DMA operation to a ram block. The atomic
|
||||
+ * guarantee is needed for two major cases: (A) When the ram block is
|
||||
+ * backed by a PCI BAR passed through from a host device (and so it might
|
||||
+ * be hardware registers that must be accessed exactly once at the right
|
||||
+ * width); (B) When an emulated device updates a data structure shared in
|
||||
+ * guest memory with guest software (e.g. a network device's set of tx and
|
||||
+ * rx descriptor blocks), if a write to memory is accidentally performed
|
||||
+ * multiple times then it can break the guest code when it busy polls the
|
||||
+ * guest memory.
|
||||
+ *
|
||||
+ * We don't attempt to perform the exact access when it would be unaligned
|
||||
+ * because this can't be done on all host architectures. Although this is
|
||||
+ * strictly speaking not doing what would happen on real hardware, we don't
|
||||
+ * think there are going to be situations where that matters in practice.
|
||||
+ */
|
||||
+void qemu_ram_move(void *dst, const void *src, size_t n);
|
||||
+
|
||||
MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
|
||||
MemTxAttrs attrs, void *buf, hwaddr len);
|
||||
MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
|
||||
@@ -3184,7 +3217,7 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
|
||||
mr = flatview_translate(fv, addr, &addr1, &l, false, attrs);
|
||||
if (len == l && memory_access_is_direct(mr, false, attrs)) {
|
||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
||||
- memmove(buf, ptr, len);
|
||||
+ qemu_ram_move(buf, ptr, len);
|
||||
} else {
|
||||
result = flatview_read_continue(fv, addr, attrs, buf, len,
|
||||
addr1, l, mr);
|
||||
diff --git a/system/physmem.c b/system/physmem.c
|
||||
index 697e75dad7..d88349616e 100644
|
||||
--- a/system/physmem.c
|
||||
+++ b/system/physmem.c
|
||||
@@ -2869,6 +2869,50 @@ void memory_region_flush_rom_device(MemoryRegion *mr, hwaddr addr, hwaddr size)
|
||||
invalidate_and_set_dirty(mr, addr, size);
|
||||
}
|
||||
|
||||
+void qemu_ram_move(void *dst, const void *src, size_t n)
|
||||
+{
|
||||
+ uintptr_t test, len;
|
||||
+
|
||||
+ if (n == 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Calculate "the lowest set bit" over @src, @dst and @n, result put
|
||||
+ * into @len (which guarantees a power-of-two). With that and the
|
||||
+ * later check (len!=n), it makes sure that we will only do the atomic
|
||||
+ * ops when:
|
||||
+ *
|
||||
+ * (1) @n is a power-of-two
|
||||
+ * (2) @src and @dst addresses are both aligned to @n
|
||||
+ */
|
||||
+ test = (uintptr_t)src | (uintptr_t)dst | n;
|
||||
+ len = test & -test;
|
||||
+
|
||||
+ /* Overlapping buffers, unaligned or oversized access */
|
||||
+ if (n > 8 || len != n) {
|
||||
+ memmove(dst, src, n);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ switch (len) {
|
||||
+ case 1:
|
||||
+ qatomic_set((uint8_t *)dst, qatomic_read((uint8_t *)src));
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ qatomic_set((uint16_t *)dst, qatomic_read((uint16_t *)src));
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ qatomic_set((uint32_t *)dst, qatomic_read((uint32_t *)src));
|
||||
+ break;
|
||||
+ case 8:
|
||||
+ qatomic_set((uint64_t *)dst, qatomic_read((uint64_t *)src));
|
||||
+ break;
|
||||
+ default:
|
||||
+ g_assert_not_reached();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
|
||||
{
|
||||
unsigned access_size_max = mr->ops->valid.max_access_size;
|
||||
@@ -2981,7 +3025,7 @@ static MemTxResult flatview_write_continue_step(MemTxAttrs attrs,
|
||||
uint8_t *ram_ptr = qemu_ram_ptr_length(mr->ram_block, mr_addr, l,
|
||||
false, true);
|
||||
|
||||
- memmove(ram_ptr, buf, *l);
|
||||
+ qemu_ram_move(ram_ptr, buf, *l);
|
||||
invalidate_and_set_dirty(mr, mr_addr, *l);
|
||||
|
||||
return MEMTX_OK;
|
||||
@@ -3074,7 +3118,7 @@ static MemTxResult flatview_read_continue_step(MemTxAttrs attrs, uint8_t *buf,
|
||||
uint8_t *ram_ptr = qemu_ram_ptr_length(mr->ram_block, mr_addr, l,
|
||||
false, false);
|
||||
|
||||
- memmove(buf, ram_ptr, *l);
|
||||
+ qemu_ram_move(buf, ram_ptr, *l);
|
||||
|
||||
return MEMTX_OK;
|
||||
}
|
||||
--
|
||||
2.52.0
|
||||
|
||||
143
0486-system-memory-Make-ram-device-region-directly-access.patch
Normal file
143
0486-system-memory-Make-ram-device-region-directly-access.patch
Normal file
@ -0,0 +1,143 @@
|
||||
From 3381c6df9468e50b96233a86e375116f95a91629 Mon Sep 17 00:00:00 2001
|
||||
From: Gavin Shan <gshan@redhat.com>
|
||||
Date: Wed, 29 Jul 2026 09:57:35 +1000
|
||||
Subject: [PATCH 3/4] system/memory: Make ram device region directly accessible
|
||||
|
||||
RH-Author: Gavin Shan <gshan@redhat.com>
|
||||
RH-MergeRequest: 512: memory: Make ram device region directly accessible
|
||||
RH-Jira: VOYAGER-1010
|
||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
|
||||
RH-Commit: [3/3] 76101a2851 (gwshan/qemu-centos10)
|
||||
|
||||
JIRA: https://redhat.atlassian.net/browse/VOYAGER-1010
|
||||
UPSTREAM: no, https://gitlab.com/peterx/qemu.git (branch: next) 4fa94987b760
|
||||
|
||||
This basically reverts 4a2e242bbb30 ("memory: Don't use memcpy for
|
||||
ram_device regions") to make ram device region directly accessible
|
||||
again. With this, the bounce buffer is bypassed in address_space_map()
|
||||
when a ram device region is involved, potentially avoid to overrun
|
||||
the (small) bounce buffer.
|
||||
|
||||
Reported-by: Julia Graham <jugraham@redhat.com>
|
||||
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Suggested-by: Peter Xu <peterx@redhat.com>
|
||||
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Gavin Shan <gshan@redhat.com>
|
||||
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20260728031731.286666-4-gshan@redhat.com
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
(cherry picked from commit 4fa94987b760f8a137e8911decf72d363ae1306e)
|
||||
Signed-off-by: Gavin Shan <gshan@redhat.com>
|
||||
Conflicts:
|
||||
system/memory.c
|
||||
Conflict due to missed upstream commit 5cb466d7ca56 ("memory: Add
|
||||
internal memory_region_set_ops helper function") and 8fe668d0b492
|
||||
("memory: Shorten memory_region_init_ram_device_ptr and
|
||||
memory_region_init_rom_device") where MemoryRegion::{ops, opqaue}
|
||||
of a ram device region are set by memory_region_set_ops() and
|
||||
memory_region_init_io(). Drop MemoryRegion::{ops, opqaue} for a
|
||||
ram device region in memory_region_init_ram_device_ptr(), which is
|
||||
exactly what's done in commit 4a2e242bbb30 ("memory: Don't use memcpy
|
||||
for ram_device regions").
|
||||
---
|
||||
include/system/memory.h | 11 ++---------
|
||||
system/memory.c | 39 ---------------------------------------
|
||||
system/trace-events | 2 --
|
||||
3 files changed, 2 insertions(+), 50 deletions(-)
|
||||
|
||||
diff --git a/include/system/memory.h b/include/system/memory.h
|
||||
index 351cf1253c..161d1944e0 100644
|
||||
--- a/include/system/memory.h
|
||||
+++ b/include/system/memory.h
|
||||
@@ -3161,15 +3161,8 @@ static inline bool memory_region_supports_direct_access(MemoryRegion *mr)
|
||||
if (memory_region_is_romd(mr)) {
|
||||
return true;
|
||||
}
|
||||
- if (!memory_region_is_ram(mr)) {
|
||||
- return false;
|
||||
- }
|
||||
- /*
|
||||
- * RAM DEVICE regions can be accessed directly using memcpy, but it might
|
||||
- * be MMIO and access using mempy can be wrong (e.g., using instructions not
|
||||
- * intended for MMIO access). So we treat this as IO.
|
||||
- */
|
||||
- return !memory_region_is_ram_device(mr);
|
||||
+
|
||||
+ return memory_region_is_ram(mr);
|
||||
}
|
||||
|
||||
static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write,
|
||||
diff --git a/system/memory.c b/system/memory.c
|
||||
index bdd53369a9..9bc5413f31 100644
|
||||
--- a/system/memory.c
|
||||
+++ b/system/memory.c
|
||||
@@ -1360,43 +1360,6 @@ const MemoryRegionOps unassigned_mem_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
-static uint64_t memory_region_ram_device_read(void *opaque,
|
||||
- hwaddr addr, unsigned size)
|
||||
-{
|
||||
- MemoryRegion *mr = opaque;
|
||||
- uint64_t data = ldn_he_p(mr->ram_block->host + addr, size);
|
||||
-
|
||||
- trace_memory_region_ram_device_read(get_cpu_index(), mr, addr, data, size);
|
||||
-
|
||||
- return data;
|
||||
-}
|
||||
-
|
||||
-static void memory_region_ram_device_write(void *opaque, hwaddr addr,
|
||||
- uint64_t data, unsigned size)
|
||||
-{
|
||||
- MemoryRegion *mr = opaque;
|
||||
-
|
||||
- trace_memory_region_ram_device_write(get_cpu_index(), mr, addr, data, size);
|
||||
-
|
||||
- stn_he_p(mr->ram_block->host + addr, size, data);
|
||||
-}
|
||||
-
|
||||
-static const MemoryRegionOps ram_device_mem_ops = {
|
||||
- .read = memory_region_ram_device_read,
|
||||
- .write = memory_region_ram_device_write,
|
||||
- .endianness = HOST_BIG_ENDIAN ? DEVICE_BIG_ENDIAN : DEVICE_LITTLE_ENDIAN,
|
||||
- .valid = {
|
||||
- .min_access_size = 1,
|
||||
- .max_access_size = 8,
|
||||
- .unaligned = true,
|
||||
- },
|
||||
- .impl = {
|
||||
- .min_access_size = 1,
|
||||
- .max_access_size = 8,
|
||||
- .unaligned = true,
|
||||
- },
|
||||
-};
|
||||
-
|
||||
bool memory_region_access_valid(MemoryRegion *mr,
|
||||
hwaddr addr,
|
||||
unsigned size,
|
||||
@@ -1711,8 +1674,6 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr,
|
||||
mr->ram = true;
|
||||
mr->terminates = true;
|
||||
mr->ram_device = true;
|
||||
- mr->ops = &ram_device_mem_ops;
|
||||
- mr->opaque = mr;
|
||||
mr->destructor = memory_region_destructor_ram;
|
||||
|
||||
/* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */
|
||||
diff --git a/system/trace-events b/system/trace-events
|
||||
index 82856e44f2..eb3e7681ab 100644
|
||||
--- a/system/trace-events
|
||||
+++ b/system/trace-events
|
||||
@@ -20,8 +20,6 @@ memory_region_ops_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, u
|
||||
memory_region_ops_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size, const char *name) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u name '%s'"
|
||||
memory_region_subpage_read(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
||||
memory_region_subpage_write(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
||||
-memory_region_ram_device_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
||||
-memory_region_ram_device_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
|
||||
memory_region_sync_dirty(const char *mr, const char *listener, int global) "mr '%s' listener '%s' synced (global=%d)"
|
||||
flatview_new(void *view, void *root) "%p (root %p)"
|
||||
flatview_destroy(void *view, void *root) "%p (root %p)"
|
||||
--
|
||||
2.52.0
|
||||
|
||||
71
0487-vfio-region-Clarify-dma-buf-failure-messages.patch
Normal file
71
0487-vfio-region-Clarify-dma-buf-failure-messages.patch
Normal file
@ -0,0 +1,71 @@
|
||||
From aac829caec814bb2a65372bd54f15a559ccf3b58 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
|
||||
Date: Wed, 15 Jul 2026 10:00:00 +0200
|
||||
Subject: [PATCH 4/4] vfio/region: Clarify dma-buf failure messages
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Rodolfo Vick <None>
|
||||
RH-MergeRequest: 514: vfio/region: Clarify dma-buf failure messages
|
||||
RH-Jira: RHEL-224652
|
||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
|
||||
RH-Commit: [1/1] 290b4b792bd444608b01bab64514a0e0725e9f89 (rovick1/qemu-kvm)
|
||||
|
||||
The dma-buf failure messages in vfio_region_create_dma_buf() say "PCI
|
||||
BAR IOMMU mappings may fail", which suggests the BAR is broken. In
|
||||
practice, only P2P DMA is affected -- normal passthrough uses the mmap
|
||||
fallback.
|
||||
|
||||
Reword both messages to mention P2P DMA explicitly and clarify that
|
||||
the mmap fallback is in use. Use warn_report_err_once() at the call
|
||||
site so per-BAR repetition on mdev devices is suppressed.
|
||||
|
||||
Fixes: dcf1b77e834d ("hw/vfio/region: Create dmabuf for PCI BAR per region")
|
||||
Cc: Nicolin Chen <nicolinc@nvidia.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
|
||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
||||
(cherry picked from commit 4b2e6505d59b7b16c6e15a2494942d00648e8510)
|
||||
|
||||
Patch-name: kvm-vfio-region-Clarify-dma-buf-failure-messages.patch
|
||||
Patch-id: 480
|
||||
Patch-present-in-specfile: True
|
||||
---
|
||||
hw/vfio/region.c | 11 +++++------
|
||||
1 file changed, 5 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/hw/vfio/region.c b/hw/vfio/region.c
|
||||
index 1e9915fdd3..9258ab6847 100644
|
||||
--- a/hw/vfio/region.c
|
||||
+++ b/hw/vfio/region.c
|
||||
@@ -316,13 +316,12 @@ static bool vfio_region_create_dma_buf(VFIORegion *region, Error **errp)
|
||||
ret = vfio_device_get_feature(vbasedev, feature);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOTTY) {
|
||||
- warn_report_once("VFIO dma-buf not supported in kernel: "
|
||||
- "PCI BAR IOMMU mappings may fail");
|
||||
+ warn_report_once("VFIO dma-buf not supported in kernel, "
|
||||
+ "using mmap fallback, P2P DMA will not work");
|
||||
return true;
|
||||
}
|
||||
- /* P2P DMA or exposing device memory use cases are not supported. */
|
||||
- error_setg_errno(errp, -ret, "%s: failed to create dma-buf: "
|
||||
- "PCI BAR IOMMU mappings may fail",
|
||||
+ error_setg_errno(errp, -ret, "%s: dma-buf unavailable, "
|
||||
+ "using mmap fallback, P2P DMA will not work",
|
||||
memory_region_name(region->mem));
|
||||
return false;
|
||||
}
|
||||
@@ -443,7 +442,7 @@ int vfio_region_mmap(VFIORegion *region)
|
||||
}
|
||||
|
||||
if (!vfio_region_create_dma_buf(region, &local_err)) {
|
||||
- error_report_err(local_err);
|
||||
+ warn_report_err_once(local_err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -143,7 +143,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \
|
||||
Summary: QEMU is a machine emulator and virtualizer
|
||||
Name: qemu-kvm
|
||||
Version: 10.1.0
|
||||
Release: 25%{?rcrel}%{?dist}%{?cc_suffix}.1
|
||||
Release: 26%{?rcrel}%{?dist}%{?cc_suffix}.1
|
||||
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
|
||||
# Epoch 15 used for RHEL 8
|
||||
# Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5)
|
||||
@ -654,6 +654,10 @@ Patch480: 0480-s390x-kvm-clamp-stsi-3.2.2-size.patch
|
||||
Patch481: 0481-s390x-sclp-prevent-re-reading-the-sclp-header.patch
|
||||
Patch482: 0482-s390x-sclpcpi-check-event-length-field-before-readin.patch
|
||||
Patch483: 0483-s390x-css-firm-up-handling-of-chained-TIC-CCWs.patch
|
||||
Patch484: 0484-system-memory-Use-memmove-for-directly-accessible-re.patch
|
||||
Patch485: 0485-system-memory-Use-qemu_ram_move-for-directly-accessi.patch
|
||||
Patch486: 0486-system-memory-Make-ram-device-region-directly-access.patch
|
||||
Patch487: 0487-vfio-region-Clarify-dma-buf-failure-messages.patch
|
||||
|
||||
%if %{have_clang}
|
||||
BuildRequires: clang
|
||||
@ -1736,6 +1740,14 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue Aug 11 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-26el10nv.1
|
||||
- memory: Make ram device region directly accessible [VOYAGER-1010]
|
||||
- Resolves: VOYAGER-1010
|
||||
(Guest hang due to exhausted bounce buffer on compiling cuda-samples)
|
||||
|
||||
* Tue Aug 11 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-26
|
||||
- kvm-vfio-region-Clarify-dma-buf-failure-messages.patch [RHEL-224652]
|
||||
|
||||
* Thu Aug 06 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-25.el10nv.1
|
||||
- Enable EGM for Voyager-2603 [VOYAGER-1105 VOYAGER-1106]
|
||||
- Resolves: VOYAGER-1105
|
||||
|
||||
Loading…
Reference in New Issue
Block a user