On 5/19/26 12:37 PM, Shameer Kolothum wrote:
> Some hardware accelerators DMA directly to the host physical address
s/DMA/perform DMA accesses
> of a guest-resident buffer (e.g. set up via IOMMUFD). The HPA is
> contiguous only within a single host backing page; a buffer larger
> than the smallest backing page in use may span non-contiguous host
> pages and fault.
>
> Introduce qemu_ram_backend_pagesize_min(), which returns the smallest
> page size among RAM regions backed by a memory-backend object. Falls
Don't you have means to be more precise? I mean you know the GPA of the
cmdq, can't you make sure it belongs to a specific ramblock and check
its min page_size?

By the way there is find_min_backend_pagesize() that exists. Can't you
reuse that?

Thanks

Eric
> back to qemu_real_host_page_size() if no memory-backend RAM blocks
> are found. Callers can use this to bound the size of buffers that
> must remain host-physically contiguous.
>
> A subsequent Tegra241 CMDQV support patch will use this to bound the
> command queue size exposed to the guest.
>
> Cc: Peter Xu <[email protected]>
> Cc: "Philippe Mathieu-Daudé" <[email protected]>
> Signed-off-by: Shameer Kolothum <[email protected]>
> ---
>  include/system/ramblock.h |  1 +
>  system/physmem.c          | 29 +++++++++++++++++++++++++++++
>  2 files changed, 30 insertions(+)
>
> diff --git a/include/system/ramblock.h b/include/system/ramblock.h
> index 4435f8d55f..7f7ea53557 100644
> --- a/include/system/ramblock.h
> +++ b/include/system/ramblock.h
> @@ -175,6 +175,7 @@ int qemu_ram_get_fd(const RAMBlock *rb);
>  
>  size_t qemu_ram_pagesize(const RAMBlock *block);
>  size_t qemu_ram_pagesize_largest(void);
> +size_t qemu_ram_backend_pagesize_min(void);
>  #include "exec/target_page.h"
>  #include "exec/hwaddr.h"
>  
> diff --git a/system/physmem.c b/system/physmem.c
> index 46b36c7b10..7ccec52aa2 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -1999,6 +1999,35 @@ size_t qemu_ram_pagesize_largest(void)
>      return largest;
>  }
>  
> +/*
> + * Returns the smallest page size among RAM regions backed by a
> + * memory-backend object. Falls back to qemu_real_host_page_size() if no
> + * memory-backend RAM blocks are found.
> + */
> +size_t qemu_ram_backend_pagesize_min(void)
> +{
> +    RAMBlock *rb;
> +    size_t pg, min_pg = SIZE_MAX;
> +
> +    RAMBLOCK_FOREACH(rb) {
> +        MemoryRegion *mr = rb->mr;
> +
> +        if (!mr || !memory_region_is_ram(mr)) {
> +            continue;
> +        }
> +        if (!object_dynamic_cast(mr->owner, TYPE_MEMORY_BACKEND)) {
> +            continue;
> +        }
> +
> +        pg = qemu_ram_pagesize(rb);
> +        if (pg && pg < min_pg) {
> +            min_pg = pg;
> +        }
> +    }
> +
> +    return (min_pg == SIZE_MAX) ? qemu_real_host_page_size() : min_pg;
> +}
> +
>  static int memory_try_enable_merging(void *addr, size_t len)
>  {
>      if (!machine_mem_merge(current_machine)) {


Reply via email to