All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/17] xen: Support grant mappings
@ 2024-04-30 16:49 Edgar E. Iglesias
  2024-04-30 16:49 ` [PATCH v4 01/17] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length() Edgar E. Iglesias
                   ` (17 more replies)
  0 siblings, 18 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel; +Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Hi,

This is a follow-up on Vikrams v3:
http://next.patchew.org/QEMU/20240227223501.28475-1-vikram.garhwal@amd.com/

Grant mappings are a mechanism in Xen for guests to grant each other
permissions to map and share pages. These grants can be temporary
so both map and unmaps must be respected. See here for more info:
https://github.com/xen-project/xen/blob/master/docs/misc/grant-tables.txt

Currently, the primary use-case for this is with QEMU's VirtIO backends.
Grant mappings will only work with models that use the address_space_map/unmap
interfaces, any other access will fail with appropriate error messages.

In response to feedback we got on v3, this version switches approach
from adding new MemoryRegion types and map/unmap hooks to instead reusing
the existing xen_map_cache() hooks (with extensions). Almost all of the
changes are now contained to the Xen modules.

This approach also refactors the mapcache to support multiple instances
(one for existing foreign mappings and another for grant mappings).

Patch 1 - 10 are refactorings with minimal functional changes.
Patch 3 - 10 could possibly get squashed into one but I've left them
separate to make them easier to review.

I've only enabled grants for the ARM PVH machine since that is what
I can currently test on.

Cheers,
Edgar

ChangeLog:

v3 -> v4:
* Major changes.
* Reuse existing xen_map_cache hooks.
* Reuse existing map-cache for both foreign and grant mappings.
* Only enable grants for the ARM PVH machine (removed i386).

v2 -> v3:
* Drop patch 1/7. This was done because device unplug is an x86-only case.
* Add missing qemu_mutex_unlock() before return.

v1 -> v2:
* Split patch 2/7 to keep phymem.c changes in a separate.
* In patch "xen: add map and unmap callbacks for grant" add check for total
  allowed grant < XEN_MAX_VIRTIO_GRANTS.
* Fix formatting issues and re-based with master latest.

Edgar E. Iglesias (15):
  xen: mapcache: Refactor lock functions for multi-instance
  xen: mapcache: Refactor xen_map_cache for multi-instance
  xen: mapcache: Refactor xen_remap_bucket for multi-instance
  xen: mapcache: Break out xen_ram_addr_from_mapcache_single
  xen: mapcache: Refactor xen_replace_cache_entry_unlocked
  xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked
  xen: mapcache: Break out xen_invalidate_map_cache_single()
  xen: mapcache: Break out xen_map_cache_init_single()
  xen: mapcache: Make MCACHE_BUCKET_SHIFT runtime configurable
  xen: mapcache: Unmap first entries in buckets
  softmmu: Pass RAM MemoryRegion and is_write xen_map_cache()
  xen: Add xen_mr_is_memory()
  xen: mapcache: Remove assumption of RAMBlock with 0 offset
  xen: mapcache: Add support for grant mappings
  hw/arm: xen: Enable use of grant mappings

Juergen Gross (2):
  softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
  xen: let xen_ram_addr_from_mapcache() return -1 in case of not found
    entry

 hw/arm/xen_arm.c                |   5 +
 hw/xen/xen-hvm-common.c         |  16 +-
 hw/xen/xen-mapcache.c           | 408 +++++++++++++++++++++-----------
 include/hw/xen/xen-hvm-common.h |   3 +
 include/sysemu/xen-mapcache.h   |  13 +-
 include/sysemu/xen.h            |  15 ++
 system/physmem.c                |  83 ++++---
 7 files changed, 365 insertions(+), 178 deletions(-)

-- 
2.40.1



^ permalink raw reply	[flat|nested] 58+ messages in thread

* [PATCH v4 01/17] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 15:56   ` David Hildenbrand
  2024-05-01 16:48   ` Peter Xu
  2024-04-30 16:49 ` [PATCH v4 02/17] xen: let xen_ram_addr_from_mapcache() return -1 in case of not found entry Edgar E. Iglesias
                   ` (16 subsequent siblings)
  17 siblings, 2 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Vikram Garhwal,
	Edgar E . Iglesias, Alex Bennée, Paolo Bonzini, Peter Xu,
	David Hildenbrand, Philippe Mathieu-Daudé

From: Juergen Gross <jgross@suse.com>

qemu_map_ram_ptr() and qemu_ram_ptr_length() share quite some code, so
modify qemu_ram_ptr_length() a little bit and use it for
qemu_map_ram_ptr(), too.

Signed-off-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 system/physmem.c | 56 ++++++++++++++++++++----------------------------
 1 file changed, 23 insertions(+), 33 deletions(-)

diff --git a/system/physmem.c b/system/physmem.c
index 1a81c226ba..f114b972a5 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2188,43 +2188,17 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
 }
 #endif /* !_WIN32 */
 
-/* Return a host pointer to ram allocated with qemu_ram_alloc.
- * This should not be used for general purpose DMA.  Use address_space_map
- * or address_space_rw instead. For local memory (e.g. video ram) that the
- * device owns, use memory_region_get_ram_ptr.
- *
- * Called within RCU critical section.
- */
-void *qemu_map_ram_ptr(RAMBlock *block, ram_addr_t addr)
-{
-    if (block == NULL) {
-        block = qemu_get_ram_block(addr);
-        addr -= block->offset;
-    }
-
-    if (xen_enabled() && block->host == NULL) {
-        /* We need to check if the requested address is in the RAM
-         * because we don't want to map the entire memory in QEMU.
-         * In that case just map until the end of the page.
-         */
-        if (block->offset == 0) {
-            return xen_map_cache(addr, 0, 0, false);
-        }
-
-        block->host = xen_map_cache(block->offset, block->max_length, 1, false);
-    }
-    return ramblock_ptr(block, addr);
-}
-
-/* Return a host pointer to guest's ram. Similar to qemu_map_ram_ptr
- * but takes a size argument.
+/*
+ * Return a host pointer to guest's ram.
  *
  * Called within RCU critical section.
  */
 static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
                                  hwaddr *size, bool lock)
 {
-    if (*size == 0) {
+    hwaddr len = 0;
+
+    if (size && *size == 0) {
         return NULL;
     }
 
@@ -2232,7 +2206,10 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
         block = qemu_get_ram_block(addr);
         addr -= block->offset;
     }
-    *size = MIN(*size, block->max_length - addr);
+    if (size) {
+        *size = MIN(*size, block->max_length - addr);
+        len = *size;
+    }
 
     if (xen_enabled() && block->host == NULL) {
         /* We need to check if the requested address is in the RAM
@@ -2240,7 +2217,7 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
          * In that case just map the requested area.
          */
         if (block->offset == 0) {
-            return xen_map_cache(addr, *size, lock, lock);
+            return xen_map_cache(addr, len, lock, lock);
         }
 
         block->host = xen_map_cache(block->offset, block->max_length, 1, lock);
@@ -2249,6 +2226,19 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
     return ramblock_ptr(block, addr);
 }
 
+/*
+ * Return a host pointer to ram allocated with qemu_ram_alloc.
+ * This should not be used for general purpose DMA.  Use address_space_map
+ * or address_space_rw instead. For local memory (e.g. video ram) that the
+ * device owns, use memory_region_get_ram_ptr.
+ *
+ * Called within RCU critical section.
+ */
+void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
+{
+    return qemu_ram_ptr_length(ram_block, addr, NULL, false);
+}
+
 /* Return the offset of a hostpointer within a ramblock */
 ram_addr_t qemu_ram_block_host_offset(RAMBlock *rb, void *host)
 {
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 02/17] xen: let xen_ram_addr_from_mapcache() return -1 in case of not found entry
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
  2024-04-30 16:49 ` [PATCH v4 01/17] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length() Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-04-30 16:49 ` [PATCH v4 03/17] xen: mapcache: Refactor lock functions for multi-instance Edgar E. Iglesias
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E . Iglesias,
	Alex Bennée, Anthony Perard, Paul Durrant, xen-devel

From: Juergen Gross <jgross@suse.com>

Today xen_ram_addr_from_mapcache() will either abort() or return 0 in
case it can't find a matching entry for a pointer value. Both cases
are bad, so change that to return an invalid address instead.

Signed-off-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 7f59080ba7..b7cefb78f7 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -394,13 +394,8 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
         }
     }
     if (!found) {
-        trace_xen_ram_addr_from_mapcache_not_found(ptr);
-        QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
-            trace_xen_ram_addr_from_mapcache_found(reventry->paddr_index,
-                                                   reventry->vaddr_req);
-        }
-        abort();
-        return 0;
+        mapcache_unlock();
+        return RAM_ADDR_INVALID;
     }
 
     entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
@@ -409,7 +404,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
     }
     if (!entry) {
         trace_xen_ram_addr_from_mapcache_not_in_cache(ptr);
-        raddr = 0;
+        raddr = RAM_ADDR_INVALID;
     } else {
         raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
              ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 03/17] xen: mapcache: Refactor lock functions for multi-instance
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
  2024-04-30 16:49 ` [PATCH v4 01/17] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length() Edgar E. Iglesias
  2024-04-30 16:49 ` [PATCH v4 02/17] xen: let xen_ram_addr_from_mapcache() return -1 in case of not found entry Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 20:39   ` Stefano Stabellini
  2024-05-06  9:52   ` Philippe Mathieu-Daudé
  2024-04-30 16:49 ` [PATCH v4 04/17] xen: mapcache: Refactor xen_map_cache " Edgar E. Iglesias
                   ` (14 subsequent siblings)
  17 siblings, 2 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Make the lock functions take MapCache * as argument. This is
in preparation for supporting multiple caches.

No functional changes.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index b7cefb78f7..3f11562075 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -74,14 +74,14 @@ typedef struct MapCache {
 
 static MapCache *mapcache;
 
-static inline void mapcache_lock(void)
+static inline void mapcache_lock(MapCache *mc)
 {
-    qemu_mutex_lock(&mapcache->lock);
+    qemu_mutex_lock(&mc->lock);
 }
 
-static inline void mapcache_unlock(void)
+static inline void mapcache_unlock(MapCache *mc)
 {
-    qemu_mutex_unlock(&mapcache->lock);
+    qemu_mutex_unlock(&mc->lock);
 }
 
 static inline int test_bits(int nr, int size, const unsigned long *addr)
@@ -369,9 +369,9 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
 {
     uint8_t *p;
 
-    mapcache_lock();
+    mapcache_lock(mapcache);
     p = xen_map_cache_unlocked(phys_addr, size, lock, dma);
-    mapcache_unlock();
+    mapcache_unlock(mapcache);
     return p;
 }
 
@@ -384,7 +384,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
     ram_addr_t raddr;
     int found = 0;
 
-    mapcache_lock();
+    mapcache_lock(mapcache);
     QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
         if (reventry->vaddr_req == ptr) {
             paddr_index = reventry->paddr_index;
@@ -394,7 +394,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
         }
     }
     if (!found) {
-        mapcache_unlock();
+        mapcache_unlock(mapcache);
         return RAM_ADDR_INVALID;
     }
 
@@ -409,7 +409,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
         raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
              ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
     }
-    mapcache_unlock();
+    mapcache_unlock(mapcache);
     return raddr;
 }
 
@@ -480,9 +480,9 @@ static void xen_invalidate_map_cache_entry_bh(void *opaque)
 {
     XenMapCacheData *data = opaque;
 
-    mapcache_lock();
+    mapcache_lock(mapcache);
     xen_invalidate_map_cache_entry_unlocked(data->buffer);
-    mapcache_unlock();
+    mapcache_unlock(mapcache);
 
     aio_co_wake(data->co);
 }
@@ -498,9 +498,9 @@ void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
                                 xen_invalidate_map_cache_entry_bh, &data);
         qemu_coroutine_yield();
     } else {
-        mapcache_lock();
+        mapcache_lock(mapcache);
         xen_invalidate_map_cache_entry_unlocked(buffer);
-        mapcache_unlock();
+        mapcache_unlock(mapcache);
     }
 }
 
@@ -512,7 +512,7 @@ void xen_invalidate_map_cache(void)
     /* Flush pending AIO before destroying the mapcache */
     bdrv_drain_all();
 
-    mapcache_lock();
+    mapcache_lock(mapcache);
 
     QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
         if (!reventry->dma) {
@@ -546,7 +546,7 @@ void xen_invalidate_map_cache(void)
 
     mapcache->last_entry = NULL;
 
-    mapcache_unlock();
+    mapcache_unlock(mapcache);
 }
 
 static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
@@ -606,8 +606,8 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
 {
     uint8_t *p;
 
-    mapcache_lock();
+    mapcache_lock(mapcache);
     p = xen_replace_cache_entry_unlocked(old_phys_addr, new_phys_addr, size);
-    mapcache_unlock();
+    mapcache_unlock(mapcache);
     return p;
 }
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 04/17] xen: mapcache: Refactor xen_map_cache for multi-instance
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (2 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 03/17] xen: mapcache: Refactor lock functions for multi-instance Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 20:40   ` Stefano Stabellini
  2024-05-06  9:53   ` Philippe Mathieu-Daudé
  2024-04-30 16:49 ` [PATCH v4 05/17] xen: mapcache: Refactor xen_remap_bucket " Edgar E. Iglesias
                   ` (13 subsequent siblings)
  17 siblings, 2 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Make xen_map_cache take a MapCache as argument. This is in
prepaparation to support multiple map caches.

No functional changes.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 3f11562075..896021d86f 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -240,7 +240,8 @@ static void xen_remap_bucket(MapCacheEntry *entry,
     g_free(err);
 }
 
-static uint8_t *xen_map_cache_unlocked(hwaddr phys_addr, hwaddr size,
+static uint8_t *xen_map_cache_unlocked(MapCache *mc,
+                                       hwaddr phys_addr, hwaddr size,
                                        uint8_t lock, bool dma)
 {
     MapCacheEntry *entry, *pentry = NULL,
@@ -269,16 +270,16 @@ tryagain:
         test_bit_size = XC_PAGE_SIZE;
     }
 
-    if (mapcache->last_entry != NULL &&
-        mapcache->last_entry->paddr_index == address_index &&
+    if (mc->last_entry != NULL &&
+        mc->last_entry->paddr_index == address_index &&
         !lock && !size &&
         test_bits(address_offset >> XC_PAGE_SHIFT,
                   test_bit_size >> XC_PAGE_SHIFT,
-                  mapcache->last_entry->valid_mapping)) {
+                  mc->last_entry->valid_mapping)) {
         trace_xen_map_cache_return(
-            mapcache->last_entry->vaddr_base + address_offset
+            mc->last_entry->vaddr_base + address_offset
         );
-        return mapcache->last_entry->vaddr_base + address_offset;
+        return mc->last_entry->vaddr_base + address_offset;
     }
 
     /* size is always a multiple of MCACHE_BUCKET_SIZE */
@@ -291,7 +292,7 @@ tryagain:
         cache_size = MCACHE_BUCKET_SIZE;
     }
 
-    entry = &mapcache->entry[address_index % mapcache->nr_buckets];
+    entry = &mc->entry[address_index % mc->nr_buckets];
 
     while (entry && (lock || entry->lock) && entry->vaddr_base &&
             (entry->paddr_index != address_index || entry->size != cache_size ||
@@ -326,10 +327,10 @@ tryagain:
     if(!test_bits(address_offset >> XC_PAGE_SHIFT,
                 test_bit_size >> XC_PAGE_SHIFT,
                 entry->valid_mapping)) {
-        mapcache->last_entry = NULL;
+        mc->last_entry = NULL;
 #ifdef XEN_COMPAT_PHYSMAP
-        if (!translated && mapcache->phys_offset_to_gaddr) {
-            phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size);
+        if (!translated && mc->phys_offset_to_gaddr) {
+            phys_addr = mc->phys_offset_to_gaddr(phys_addr, size);
             translated = true;
             goto tryagain;
         }
@@ -342,7 +343,7 @@ tryagain:
         return NULL;
     }
 
-    mapcache->last_entry = entry;
+    mc->last_entry = entry;
     if (lock) {
         MapCacheRev *reventry = g_new0(MapCacheRev, 1);
         entry->lock++;
@@ -352,16 +353,16 @@ tryagain:
             abort();
         }
         reventry->dma = dma;
-        reventry->vaddr_req = mapcache->last_entry->vaddr_base + address_offset;
-        reventry->paddr_index = mapcache->last_entry->paddr_index;
+        reventry->vaddr_req = mc->last_entry->vaddr_base + address_offset;
+        reventry->paddr_index = mc->last_entry->paddr_index;
         reventry->size = entry->size;
-        QTAILQ_INSERT_HEAD(&mapcache->locked_entries, reventry, next);
+        QTAILQ_INSERT_HEAD(&mc->locked_entries, reventry, next);
     }
 
     trace_xen_map_cache_return(
-        mapcache->last_entry->vaddr_base + address_offset
+        mc->last_entry->vaddr_base + address_offset
     );
-    return mapcache->last_entry->vaddr_base + address_offset;
+    return mc->last_entry->vaddr_base + address_offset;
 }
 
 uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
@@ -370,7 +371,7 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
     uint8_t *p;
 
     mapcache_lock(mapcache);
-    p = xen_map_cache_unlocked(phys_addr, size, lock, dma);
+    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma);
     mapcache_unlock(mapcache);
     return p;
 }
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 05/17] xen: mapcache: Refactor xen_remap_bucket for multi-instance
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (3 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 04/17] xen: mapcache: Refactor xen_map_cache " Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 20:42   ` Stefano Stabellini
  2024-05-06  9:54   ` Philippe Mathieu-Daudé
  2024-04-30 16:49 ` [PATCH v4 06/17] xen: mapcache: Break out xen_ram_addr_from_mapcache_single Edgar E. Iglesias
                   ` (12 subsequent siblings)
  17 siblings, 2 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Add MapCache argument to xen_remap_bucket in preparation
to support multiple map caches.

No functional changes.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 896021d86f..326a9b61ca 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -139,7 +139,8 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
     mapcache->entry = g_malloc0(size);
 }
 
-static void xen_remap_bucket(MapCacheEntry *entry,
+static void xen_remap_bucket(MapCache *mc,
+                             MapCacheEntry *entry,
                              void *vaddr,
                              hwaddr size,
                              hwaddr address_index,
@@ -313,14 +314,14 @@ tryagain:
     if (!entry) {
         entry = g_new0(MapCacheEntry, 1);
         pentry->next = entry;
-        xen_remap_bucket(entry, NULL, cache_size, address_index, dummy);
+        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
     } else if (!entry->lock) {
         if (!entry->vaddr_base || entry->paddr_index != address_index ||
                 entry->size != cache_size ||
                 !test_bits(address_offset >> XC_PAGE_SHIFT,
                     test_bit_size >> XC_PAGE_SHIFT,
                     entry->valid_mapping)) {
-            xen_remap_bucket(entry, NULL, cache_size, address_index, dummy);
+            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
         }
     }
 
@@ -587,7 +588,7 @@ static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
 
     trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
 
-    xen_remap_bucket(entry, entry->vaddr_base,
+    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
                      cache_size, address_index, false);
     if (!test_bits(address_offset >> XC_PAGE_SHIFT,
                 test_bit_size >> XC_PAGE_SHIFT,
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 06/17] xen: mapcache: Break out xen_ram_addr_from_mapcache_single
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (4 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 05/17] xen: mapcache: Refactor xen_remap_bucket " Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 20:43   ` Stefano Stabellini
  2024-05-06 10:22   ` Philippe Mathieu-Daudé
  2024-04-30 16:49 ` [PATCH v4 07/17] xen: mapcache: Refactor xen_replace_cache_entry_unlocked Edgar E. Iglesias
                   ` (11 subsequent siblings)
  17 siblings, 2 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Break out xen_ram_addr_from_mapcache_single(), a multi-cache
aware version of xen_ram_addr_from_mapcache.

No functional changes.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 326a9b61ca..d2deff70c8 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -377,7 +377,7 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
     return p;
 }
 
-ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
+static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
 {
     MapCacheEntry *entry = NULL;
     MapCacheRev *reventry;
@@ -386,8 +386,8 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
     ram_addr_t raddr;
     int found = 0;
 
-    mapcache_lock(mapcache);
-    QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+    mapcache_lock(mc);
+    QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
         if (reventry->vaddr_req == ptr) {
             paddr_index = reventry->paddr_index;
             size = reventry->size;
@@ -396,11 +396,11 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
         }
     }
     if (!found) {
-        mapcache_unlock(mapcache);
+        mapcache_unlock(mc);
         return RAM_ADDR_INVALID;
     }
 
-    entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
+    entry = &mc->entry[paddr_index % mc->nr_buckets];
     while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
         entry = entry->next;
     }
@@ -411,10 +411,15 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
         raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
              ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
     }
-    mapcache_unlock(mapcache);
+    mapcache_unlock(mc);
     return raddr;
 }
 
+ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
+{
+    return xen_ram_addr_from_mapcache_single(mapcache, ptr);
+}
+
 static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
 {
     MapCacheEntry *entry = NULL, *pentry = NULL;
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 07/17] xen: mapcache: Refactor xen_replace_cache_entry_unlocked
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (5 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 06/17] xen: mapcache: Break out xen_ram_addr_from_mapcache_single Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 20:46   ` Stefano Stabellini
  2024-04-30 16:49 ` [PATCH v4 08/17] xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked Edgar E. Iglesias
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Add MapCache argument to xen_replace_cache_entry_unlocked in
preparation for supporting multiple map caches.

No functional change.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index d2deff70c8..6e758eff94 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -556,7 +556,8 @@ void xen_invalidate_map_cache(void)
     mapcache_unlock(mapcache);
 }
 
-static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
+static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
+                                                 hwaddr old_phys_addr,
                                                  hwaddr new_phys_addr,
                                                  hwaddr size)
 {
@@ -578,7 +579,7 @@ static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
         cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE);
     }
 
-    entry = &mapcache->entry[address_index % mapcache->nr_buckets];
+    entry = &mc->entry[address_index % mc->nr_buckets];
     while (entry && !(entry->paddr_index == address_index &&
                       entry->size == cache_size)) {
         entry = entry->next;
@@ -614,7 +615,8 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
     uint8_t *p;
 
     mapcache_lock(mapcache);
-    p = xen_replace_cache_entry_unlocked(old_phys_addr, new_phys_addr, size);
+    p = xen_replace_cache_entry_unlocked(mapcache, old_phys_addr,
+                                         new_phys_addr, size);
     mapcache_unlock(mapcache);
     return p;
 }
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 08/17] xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (6 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 07/17] xen: mapcache: Refactor xen_replace_cache_entry_unlocked Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 20:47   ` Stefano Stabellini
  2024-05-06  9:55   ` Philippe Mathieu-Daudé
  2024-04-30 16:49 ` [PATCH v4 09/17] xen: mapcache: Break out xen_invalidate_map_cache_single() Edgar E. Iglesias
                   ` (9 subsequent siblings)
  17 siblings, 2 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Add MapCache argument to xen_invalidate_map_cache_entry_unlocked.
This is in preparation for supporting multiple map caches.

No functional changes.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 6e758eff94..34454da2f6 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -420,7 +420,8 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
     return xen_ram_addr_from_mapcache_single(mapcache, ptr);
 }
 
-static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
+static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
+                                                    uint8_t *buffer)
 {
     MapCacheEntry *entry = NULL, *pentry = NULL;
     MapCacheRev *reventry;
@@ -428,7 +429,7 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
     hwaddr size;
     int found = 0;
 
-    QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+    QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
         if (reventry->vaddr_req == buffer) {
             paddr_index = reventry->paddr_index;
             size = reventry->size;
@@ -438,7 +439,7 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
     }
     if (!found) {
         trace_xen_invalidate_map_cache_entry_unlocked_not_found(buffer);
-        QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+        QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
             trace_xen_invalidate_map_cache_entry_unlocked_found(
                 reventry->paddr_index,
                 reventry->vaddr_req
@@ -446,15 +447,15 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
         }
         return;
     }
-    QTAILQ_REMOVE(&mapcache->locked_entries, reventry, next);
+    QTAILQ_REMOVE(&mc->locked_entries, reventry, next);
     g_free(reventry);
 
-    if (mapcache->last_entry != NULL &&
-        mapcache->last_entry->paddr_index == paddr_index) {
-        mapcache->last_entry = NULL;
+    if (mc->last_entry != NULL &&
+        mc->last_entry->paddr_index == paddr_index) {
+        mc->last_entry = NULL;
     }
 
-    entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
+    entry = &mc->entry[paddr_index % mc->nr_buckets];
     while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
         pentry = entry;
         entry = entry->next;
@@ -488,7 +489,7 @@ static void xen_invalidate_map_cache_entry_bh(void *opaque)
     XenMapCacheData *data = opaque;
 
     mapcache_lock(mapcache);
-    xen_invalidate_map_cache_entry_unlocked(data->buffer);
+    xen_invalidate_map_cache_entry_unlocked(mapcache, data->buffer);
     mapcache_unlock(mapcache);
 
     aio_co_wake(data->co);
@@ -506,7 +507,7 @@ void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
         qemu_coroutine_yield();
     } else {
         mapcache_lock(mapcache);
-        xen_invalidate_map_cache_entry_unlocked(buffer);
+        xen_invalidate_map_cache_entry_unlocked(mapcache, buffer);
         mapcache_unlock(mapcache);
     }
 }
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 09/17] xen: mapcache: Break out xen_invalidate_map_cache_single()
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (7 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 08/17] xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 20:48   ` Stefano Stabellini
  2024-05-06 10:21   ` Philippe Mathieu-Daudé
  2024-04-30 16:49 ` [PATCH v4 10/17] xen: mapcache: Break out xen_map_cache_init_single() Edgar E. Iglesias
                   ` (8 subsequent siblings)
  17 siblings, 2 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Break out xen_invalidate_map_cache_single().

No functional changes.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 34454da2f6..dd08cd296b 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -512,17 +512,14 @@ void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
     }
 }
 
-void xen_invalidate_map_cache(void)
+static void xen_invalidate_map_cache_single(MapCache *mc)
 {
     unsigned long i;
     MapCacheRev *reventry;
 
-    /* Flush pending AIO before destroying the mapcache */
-    bdrv_drain_all();
-
-    mapcache_lock(mapcache);
+    mapcache_lock(mc);
 
-    QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+    QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
         if (!reventry->dma) {
             continue;
         }
@@ -530,8 +527,8 @@ void xen_invalidate_map_cache(void)
                                        reventry->vaddr_req);
     }
 
-    for (i = 0; i < mapcache->nr_buckets; i++) {
-        MapCacheEntry *entry = &mapcache->entry[i];
+    for (i = 0; i < mc->nr_buckets; i++) {
+        MapCacheEntry *entry = &mc->entry[i];
 
         if (entry->vaddr_base == NULL) {
             continue;
@@ -552,9 +549,17 @@ void xen_invalidate_map_cache(void)
         entry->valid_mapping = NULL;
     }
 
-    mapcache->last_entry = NULL;
+    mc->last_entry = NULL;
 
-    mapcache_unlock(mapcache);
+    mapcache_unlock(mc);
+}
+
+void xen_invalidate_map_cache(void)
+{
+    /* Flush pending AIO before destroying the mapcache */
+    bdrv_drain_all();
+
+    xen_invalidate_map_cache_single(mapcache);
 }
 
 static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 10/17] xen: mapcache: Break out xen_map_cache_init_single()
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (8 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 09/17] xen: mapcache: Break out xen_invalidate_map_cache_single() Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 20:51   ` Stefano Stabellini
  2024-04-30 16:49 ` [PATCH v4 11/17] xen: mapcache: Make MCACHE_BUCKET_SHIFT runtime configurable Edgar E. Iglesias
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Break out xen_map_cache_init_single() in preparation for
adding multiple map caches.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 53 ++++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 21 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index dd08cd296b..72a7e25e3e 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -93,23 +93,44 @@ static inline int test_bits(int nr, int size, const unsigned long *addr)
         return 0;
 }
 
-void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
+static MapCache *xen_map_cache_init_single(phys_offset_to_gaddr_t f,
+                                           void *opaque,
+                                           unsigned long max_size)
 {
     unsigned long size;
-    struct rlimit rlimit_as;
+    MapCache *mc;
+
+    mc = g_new0(MapCache, 1);
+
+    mc->phys_offset_to_gaddr = f;
+    mc->opaque = opaque;
+    qemu_mutex_init(&mc->lock);
+
+    QTAILQ_INIT(&mc->locked_entries);
 
-    mapcache = g_new0(MapCache, 1);
+    mc->max_mcache_size = max_size;
 
-    mapcache->phys_offset_to_gaddr = f;
-    mapcache->opaque = opaque;
-    qemu_mutex_init(&mapcache->lock);
+    mc->nr_buckets =
+        (((mc->max_mcache_size >> XC_PAGE_SHIFT) +
+          (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >>
+         (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT));
 
-    QTAILQ_INIT(&mapcache->locked_entries);
+    size = mc->nr_buckets * sizeof(MapCacheEntry);
+    size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
+    trace_xen_map_cache_init(mc->nr_buckets, size);
+    mc->entry = g_malloc0(size);
+    return mc;
+}
+
+void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
+{
+    struct rlimit rlimit_as;
+    unsigned long max_mcache_size;
 
     if (geteuid() == 0) {
         rlimit_as.rlim_cur = RLIM_INFINITY;
         rlimit_as.rlim_max = RLIM_INFINITY;
-        mapcache->max_mcache_size = MCACHE_MAX_SIZE;
+        max_mcache_size = MCACHE_MAX_SIZE;
     } else {
         getrlimit(RLIMIT_AS, &rlimit_as);
         rlimit_as.rlim_cur = rlimit_as.rlim_max;
@@ -119,24 +140,14 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
                         " memory is not infinity");
         }
         if (rlimit_as.rlim_max < MCACHE_MAX_SIZE + NON_MCACHE_MEMORY_SIZE) {
-            mapcache->max_mcache_size = rlimit_as.rlim_max -
-                NON_MCACHE_MEMORY_SIZE;
+            max_mcache_size = rlimit_as.rlim_max - NON_MCACHE_MEMORY_SIZE;
         } else {
-            mapcache->max_mcache_size = MCACHE_MAX_SIZE;
+            max_mcache_size = MCACHE_MAX_SIZE;
         }
     }
 
+    mapcache = xen_map_cache_init_single(f, opaque, max_mcache_size);
     setrlimit(RLIMIT_AS, &rlimit_as);
-
-    mapcache->nr_buckets =
-        (((mapcache->max_mcache_size >> XC_PAGE_SHIFT) +
-          (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >>
-         (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT));
-
-    size = mapcache->nr_buckets * sizeof (MapCacheEntry);
-    size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
-    trace_xen_map_cache_init(mapcache->nr_buckets, size);
-    mapcache->entry = g_malloc0(size);
 }
 
 static void xen_remap_bucket(MapCache *mc,
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 11/17] xen: mapcache: Make MCACHE_BUCKET_SHIFT runtime configurable
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (9 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 10/17] xen: mapcache: Break out xen_map_cache_init_single() Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 20:55   ` Stefano Stabellini
  2024-04-30 16:49 ` [PATCH v4 12/17] xen: mapcache: Unmap first entries in buckets Edgar E. Iglesias
                   ` (6 subsequent siblings)
  17 siblings, 1 reply; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Make MCACHE_BUCKET_SHIFT runtime configurable per cache instance.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 52 ++++++++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 21 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 72a7e25e3e..4f98d284dd 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -23,13 +23,10 @@
 
 
 #if HOST_LONG_BITS == 32
-#  define MCACHE_BUCKET_SHIFT 16
 #  define MCACHE_MAX_SIZE     (1UL<<31) /* 2GB Cap */
 #else
-#  define MCACHE_BUCKET_SHIFT 20
 #  define MCACHE_MAX_SIZE     (1UL<<35) /* 32GB Cap */
 #endif
-#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
 
 /* This is the size of the virtual address space reserve to QEMU that will not
  * be use by MapCache.
@@ -65,7 +62,8 @@ typedef struct MapCache {
     /* For most cases (>99.9%), the page address is the same. */
     MapCacheEntry *last_entry;
     unsigned long max_mcache_size;
-    unsigned int mcache_bucket_shift;
+    unsigned int bucket_shift;
+    unsigned long bucket_size;
 
     phys_offset_to_gaddr_t phys_offset_to_gaddr;
     QemuMutex lock;
@@ -95,6 +93,7 @@ static inline int test_bits(int nr, int size, const unsigned long *addr)
 
 static MapCache *xen_map_cache_init_single(phys_offset_to_gaddr_t f,
                                            void *opaque,
+                                           unsigned int bucket_shift,
                                            unsigned long max_size)
 {
     unsigned long size;
@@ -108,12 +107,14 @@ static MapCache *xen_map_cache_init_single(phys_offset_to_gaddr_t f,
 
     QTAILQ_INIT(&mc->locked_entries);
 
+    mc->bucket_shift = bucket_shift;
+    mc->bucket_size = 1UL << bucket_shift;
     mc->max_mcache_size = max_size;
 
     mc->nr_buckets =
         (((mc->max_mcache_size >> XC_PAGE_SHIFT) +
-          (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >>
-         (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT));
+          (1UL << (bucket_shift - XC_PAGE_SHIFT)) - 1) >>
+         (bucket_shift - XC_PAGE_SHIFT));
 
     size = mc->nr_buckets * sizeof(MapCacheEntry);
     size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
@@ -126,6 +127,13 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
 {
     struct rlimit rlimit_as;
     unsigned long max_mcache_size;
+    unsigned int bucket_shift;
+
+    if (HOST_LONG_BITS == 32) {
+        bucket_shift = 16;
+    } else {
+        bucket_shift = 20;
+    }
 
     if (geteuid() == 0) {
         rlimit_as.rlim_cur = RLIM_INFINITY;
@@ -146,7 +154,9 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
         }
     }
 
-    mapcache = xen_map_cache_init_single(f, opaque, max_mcache_size);
+    mapcache = xen_map_cache_init_single(f, opaque,
+                                         bucket_shift,
+                                         max_mcache_size);
     setrlimit(RLIMIT_AS, &rlimit_as);
 }
 
@@ -195,7 +205,7 @@ static void xen_remap_bucket(MapCache *mc,
     entry->valid_mapping = NULL;
 
     for (i = 0; i < nb_pfn; i++) {
-        pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i;
+        pfns[i] = (address_index << (mc->bucket_shift - XC_PAGE_SHIFT)) + i;
     }
 
     /*
@@ -266,8 +276,8 @@ static uint8_t *xen_map_cache_unlocked(MapCache *mc,
     bool dummy = false;
 
 tryagain:
-    address_index  = phys_addr >> MCACHE_BUCKET_SHIFT;
-    address_offset = phys_addr & (MCACHE_BUCKET_SIZE - 1);
+    address_index  = phys_addr >> mc->bucket_shift;
+    address_offset = phys_addr & (mc->bucket_size - 1);
 
     trace_xen_map_cache(phys_addr);
 
@@ -294,14 +304,14 @@ tryagain:
         return mc->last_entry->vaddr_base + address_offset;
     }
 
-    /* size is always a multiple of MCACHE_BUCKET_SIZE */
+    /* size is always a multiple of mc->bucket_size */
     if (size) {
         cache_size = size + address_offset;
-        if (cache_size % MCACHE_BUCKET_SIZE) {
-            cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE);
+        if (cache_size % mc->bucket_size) {
+            cache_size += mc->bucket_size - (cache_size % mc->bucket_size);
         }
     } else {
-        cache_size = MCACHE_BUCKET_SIZE;
+        cache_size = mc->bucket_size;
     }
 
     entry = &mc->entry[address_index % mc->nr_buckets];
@@ -419,7 +429,7 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
         trace_xen_ram_addr_from_mapcache_not_in_cache(ptr);
         raddr = RAM_ADDR_INVALID;
     } else {
-        raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
+        raddr = (reventry->paddr_index << mc->bucket_shift) +
              ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
     }
     mapcache_unlock(mc);
@@ -582,8 +592,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
     hwaddr address_index, address_offset;
     hwaddr test_bit_size, cache_size = size;
 
-    address_index  = old_phys_addr >> MCACHE_BUCKET_SHIFT;
-    address_offset = old_phys_addr & (MCACHE_BUCKET_SIZE - 1);
+    address_index  = old_phys_addr >> mc->bucket_shift;
+    address_offset = old_phys_addr & (mc->bucket_size - 1);
 
     assert(size);
     /* test_bit_size is always a multiple of XC_PAGE_SIZE */
@@ -592,8 +602,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
         test_bit_size += XC_PAGE_SIZE - (test_bit_size % XC_PAGE_SIZE);
     }
     cache_size = size + address_offset;
-    if (cache_size % MCACHE_BUCKET_SIZE) {
-        cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE);
+    if (cache_size % mc->bucket_size) {
+        cache_size += mc->bucket_size - (cache_size % mc->bucket_size);
     }
 
     entry = &mc->entry[address_index % mc->nr_buckets];
@@ -606,8 +616,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
         return NULL;
     }
 
-    address_index  = new_phys_addr >> MCACHE_BUCKET_SHIFT;
-    address_offset = new_phys_addr & (MCACHE_BUCKET_SIZE - 1);
+    address_index  = new_phys_addr >> mc->bucket_shift;
+    address_offset = new_phys_addr & (mc->bucket_size - 1);
 
     trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
 
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 12/17] xen: mapcache: Unmap first entries in buckets
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (10 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 11/17] xen: mapcache: Make MCACHE_BUCKET_SHIFT runtime configurable Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 21:01   ` Stefano Stabellini
  2024-05-02  7:34   ` Edgar E. Iglesias
  2024-04-30 16:49 ` [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache() Edgar E. Iglesias
                   ` (5 subsequent siblings)
  17 siblings, 2 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

When invalidating memory ranges, if we happen to hit the first
entry in a bucket we were never unmapping it. This was harmless
for foreign mappings but now that we're looking to reuse the
mapcache for transient grant mappings, we must unmap entries
when invalidated.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 4f98d284dd..0365311788 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -486,18 +486,22 @@ static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
         return;
     }
     entry->lock--;
-    if (entry->lock > 0 || pentry == NULL) {
+    if (entry->lock > 0) {
         return;
     }
 
-    pentry->next = entry->next;
     ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size);
     if (munmap(entry->vaddr_base, entry->size) != 0) {
         perror("unmap fails");
         exit(-1);
     }
-    g_free(entry->valid_mapping);
-    g_free(entry);
+    if (pentry) {
+        pentry->next = entry->next;
+        g_free(entry->valid_mapping);
+        g_free(entry);
+    } else {
+        memset(entry, 0, sizeof *entry);
+    }
 }
 
 typedef struct XenMapCacheData {
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache()
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (11 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 12/17] xen: mapcache: Unmap first entries in buckets Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 16:48   ` Peter Xu
                     ` (3 more replies)
  2024-04-30 16:49 ` [PATCH v4 14/17] xen: Add xen_mr_is_memory() Edgar E. Iglesias
                   ` (4 subsequent siblings)
  17 siblings, 4 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, Peter Xu,
	David Hildenbrand, Philippe Mathieu-Daudé, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Propagate MR and is_write to xen_map_cache().
This is in preparation for adding support for grant mappings.

No functional change.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c         | 10 ++++++----
 include/sysemu/xen-mapcache.h | 11 +++++++----
 system/physmem.c              | 31 +++++++++++++++++++++++--------
 3 files changed, 36 insertions(+), 16 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 0365311788..09b5f36d9c 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -264,7 +264,7 @@ static void xen_remap_bucket(MapCache *mc,
 
 static uint8_t *xen_map_cache_unlocked(MapCache *mc,
                                        hwaddr phys_addr, hwaddr size,
-                                       uint8_t lock, bool dma)
+                                       uint8_t lock, bool dma, bool is_write)
 {
     MapCacheEntry *entry, *pentry = NULL,
                   *free_entry = NULL, *free_pentry = NULL;
@@ -387,13 +387,15 @@ tryagain:
     return mc->last_entry->vaddr_base + address_offset;
 }
 
-uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
-                       uint8_t lock, bool dma)
+uint8_t *xen_map_cache(MemoryRegion *mr,
+                       hwaddr phys_addr, hwaddr size,
+                       uint8_t lock, bool dma,
+                       bool is_write)
 {
     uint8_t *p;
 
     mapcache_lock(mapcache);
-    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma);
+    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma, is_write);
     mapcache_unlock(mapcache);
     return p;
 }
diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
index 10c2e3082a..1ec9e66752 100644
--- a/include/sysemu/xen-mapcache.h
+++ b/include/sysemu/xen-mapcache.h
@@ -18,8 +18,9 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
 
 void xen_map_cache_init(phys_offset_to_gaddr_t f,
                         void *opaque);
-uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
-                       uint8_t lock, bool dma);
+uint8_t *xen_map_cache(MemoryRegion *mr, hwaddr phys_addr, hwaddr size,
+                       uint8_t lock, bool dma,
+                       bool is_write);
 ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
 void xen_invalidate_map_cache_entry(uint8_t *buffer);
 void xen_invalidate_map_cache(void);
@@ -33,10 +34,12 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
 {
 }
 
-static inline uint8_t *xen_map_cache(hwaddr phys_addr,
+static inline uint8_t *xen_map_cache(MemoryRegion *mr,
+                                     hwaddr phys_addr,
                                      hwaddr size,
                                      uint8_t lock,
-                                     bool dma)
+                                     bool dma,
+                                     bool is_write)
 {
     abort();
 }
diff --git a/system/physmem.c b/system/physmem.c
index f114b972a5..ad7a8c7d95 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2190,11 +2190,22 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
 
 /*
  * Return a host pointer to guest's ram.
+ * For Xen, foreign mappings get created if they don't already exist.
+ *
+ * @block: block for the RAM to lookup (optional and may be NULL).
+ * @addr: address within the memory region.
+ * @size: pointer to requested size (optional and may be NULL).
+ *        size may get modified and return a value smaller than
+ *        what was requested.
+ * @lock: wether to lock the mapping in xen-mapcache until invalidated.
+ * @is_write: hint wether to map RW or RO in the xen-mapcache.
+ *            (optional and may always be set to true).
  *
  * Called within RCU critical section.
  */
 static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
-                                 hwaddr *size, bool lock)
+                                 hwaddr *size, bool lock,
+                                 bool is_write)
 {
     hwaddr len = 0;
 
@@ -2217,10 +2228,13 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
          * In that case just map the requested area.
          */
         if (block->offset == 0) {
-            return xen_map_cache(addr, len, lock, lock);
+            return xen_map_cache(block->mr, addr, len, lock, lock,
+                                 is_write);
         }
 
-        block->host = xen_map_cache(block->offset, block->max_length, 1, lock);
+        block->host = xen_map_cache(block->mr, block->offset,
+                                    block->max_length, 1,
+                                    lock, is_write);
     }
 
     return ramblock_ptr(block, addr);
@@ -2236,7 +2250,7 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
  */
 void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
 {
-    return qemu_ram_ptr_length(ram_block, addr, NULL, false);
+    return qemu_ram_ptr_length(ram_block, addr, NULL, false, true);
 }
 
 /* Return the offset of a hostpointer within a ramblock */
@@ -2746,7 +2760,7 @@ static MemTxResult flatview_write_continue_step(MemTxAttrs attrs,
     } else {
         /* RAM case */
         uint8_t *ram_ptr = qemu_ram_ptr_length(mr->ram_block, mr_addr, l,
-                                               false);
+                                               false, true);
 
         memmove(ram_ptr, buf, *l);
         invalidate_and_set_dirty(mr, mr_addr, *l);
@@ -2839,7 +2853,7 @@ static MemTxResult flatview_read_continue_step(MemTxAttrs attrs, uint8_t *buf,
     } else {
         /* RAM case */
         uint8_t *ram_ptr = qemu_ram_ptr_length(mr->ram_block, mr_addr, l,
-                                               false);
+                                               false, false);
 
         memcpy(buf, ram_ptr, *l);
 
@@ -3233,7 +3247,7 @@ void *address_space_map(AddressSpace *as,
     *plen = flatview_extend_translation(fv, addr, len, mr, xlat,
                                         l, is_write, attrs);
     fuzz_dma_read_cb(addr, *plen, mr);
-    return qemu_ram_ptr_length(mr->ram_block, xlat, plen, true);
+    return qemu_ram_ptr_length(mr->ram_block, xlat, plen, true, is_write);
 }
 
 /* Unmaps a memory region previously mapped by address_space_map().
@@ -3329,7 +3343,8 @@ int64_t address_space_cache_init(MemoryRegionCache *cache,
         l = flatview_extend_translation(cache->fv, addr, len, mr,
                                         cache->xlat, l, is_write,
                                         MEMTXATTRS_UNSPECIFIED);
-        cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, &l, true);
+        cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, &l, true,
+                                         is_write);
     } else {
         cache->ptr = NULL;
     }
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 14/17] xen: Add xen_mr_is_memory()
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (12 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache() Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 21:06   ` Stefano Stabellini
  2024-05-02  7:26   ` David Hildenbrand
  2024-04-30 16:49 ` [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset Edgar E. Iglesias
                   ` (3 subsequent siblings)
  17 siblings, 2 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, Peter Xu,
	David Hildenbrand, Philippe Mathieu-Daudé, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Add xen_mr_is_memory() to abstract away tests for the
xen_memory MR.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-hvm-common.c | 8 +++++++-
 include/sysemu/xen.h    | 8 ++++++++
 system/physmem.c        | 2 +-
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index 1627da7398..0267b88d26 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -12,6 +12,12 @@
 
 MemoryRegion xen_memory;
 
+/* Check for xen memory.  */
+bool xen_mr_is_memory(MemoryRegion *mr)
+{
+    return mr == &xen_memory;
+}
+
 void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
                    Error **errp)
 {
@@ -28,7 +34,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
         return;
     }
 
-    if (mr == &xen_memory) {
+    if (xen_mr_is_memory(mr)) {
         return;
     }
 
diff --git a/include/sysemu/xen.h b/include/sysemu/xen.h
index 754ec2e6cb..dc72f83bcb 100644
--- a/include/sysemu/xen.h
+++ b/include/sysemu/xen.h
@@ -34,6 +34,8 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length);
 void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
                    struct MemoryRegion *mr, Error **errp);
 
+bool xen_mr_is_memory(MemoryRegion *mr);
+
 #else /* !CONFIG_XEN_IS_POSSIBLE */
 
 #define xen_enabled() 0
@@ -47,6 +49,12 @@ static inline void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
     g_assert_not_reached();
 }
 
+static inline bool xen_mr_is_memory(MemoryRegion *mr)
+{
+    g_assert_not_reached();
+    return false;
+}
+
 #endif /* CONFIG_XEN_IS_POSSIBLE */
 
 #endif
diff --git a/system/physmem.c b/system/physmem.c
index ad7a8c7d95..1a5ffcba2a 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2227,7 +2227,7 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
          * because we don't want to map the entire memory in QEMU.
          * In that case just map the requested area.
          */
-        if (block->offset == 0) {
+        if (xen_mr_is_memory(block->mr)) {
             return xen_map_cache(block->mr, addr, len, lock, lock,
                                  is_write);
         }
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (13 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 14/17] xen: Add xen_mr_is_memory() Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 21:24   ` Stefano Stabellini
  2024-04-30 16:49 ` [PATCH v4 16/17] xen: mapcache: Add support for grant mappings Edgar E. Iglesias
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, Peter Xu,
	David Hildenbrand, Philippe Mathieu-Daudé, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

The current mapcache assumes that all memory is mapped
in a single RAM MR (the first one with offset 0). Remove
this assumption and propagate the offset to the mapcache
so it can do reverse mappings (from hostptr -> ram_addr).

This is in preparation for adding grant mappings.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-mapcache.c         | 25 ++++++++++++++++++-------
 include/sysemu/xen-mapcache.h |  2 ++
 system/physmem.c              |  8 ++++----
 3 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 09b5f36d9c..1b32d0c003 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -43,6 +43,9 @@ typedef struct MapCacheEntry {
 #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
     uint8_t flags;
     hwaddr size;
+
+    /* Keep ram_addr offset for reverse mappings (hostptr -> ram_addr).  */
+    ram_addr_t ram_offset;
     struct MapCacheEntry *next;
 } MapCacheEntry;
 
@@ -165,7 +168,8 @@ static void xen_remap_bucket(MapCache *mc,
                              void *vaddr,
                              hwaddr size,
                              hwaddr address_index,
-                             bool dummy)
+                             bool dummy,
+                             ram_addr_t ram_offset)
 {
     uint8_t *vaddr_base;
     xen_pfn_t *pfns;
@@ -244,6 +248,7 @@ static void xen_remap_bucket(MapCache *mc,
     entry->size = size;
     entry->valid_mapping = g_new0(unsigned long,
                                   BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
+    entry->ram_offset = ram_offset;
 
     if (dummy) {
         entry->flags |= XEN_MAPCACHE_ENTRY_DUMMY;
@@ -264,6 +269,7 @@ static void xen_remap_bucket(MapCache *mc,
 
 static uint8_t *xen_map_cache_unlocked(MapCache *mc,
                                        hwaddr phys_addr, hwaddr size,
+                                       ram_addr_t ram_offset,
                                        uint8_t lock, bool dma, bool is_write)
 {
     MapCacheEntry *entry, *pentry = NULL,
@@ -335,14 +341,16 @@ tryagain:
     if (!entry) {
         entry = g_new0(MapCacheEntry, 1);
         pentry->next = entry;
-        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
+        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
+                         ram_offset);
     } else if (!entry->lock) {
         if (!entry->vaddr_base || entry->paddr_index != address_index ||
                 entry->size != cache_size ||
                 !test_bits(address_offset >> XC_PAGE_SHIFT,
                     test_bit_size >> XC_PAGE_SHIFT,
                     entry->valid_mapping)) {
-            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
+            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
+                             ram_offset);
         }
     }
 
@@ -389,13 +397,15 @@ tryagain:
 
 uint8_t *xen_map_cache(MemoryRegion *mr,
                        hwaddr phys_addr, hwaddr size,
+                       ram_addr_t ram_addr_offset,
                        uint8_t lock, bool dma,
                        bool is_write)
 {
     uint8_t *p;
 
     mapcache_lock(mapcache);
-    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma, is_write);
+    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
+                               lock, dma, is_write);
     mapcache_unlock(mapcache);
     return p;
 }
@@ -432,7 +442,8 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
         raddr = RAM_ADDR_INVALID;
     } else {
         raddr = (reventry->paddr_index << mc->bucket_shift) +
-             ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
+             ((unsigned long) ptr - (unsigned long) entry->vaddr_base) +
+             entry->ram_offset;
     }
     mapcache_unlock(mc);
     return raddr;
@@ -627,8 +638,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
 
     trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
 
-    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
-                     cache_size, address_index, false);
+    xen_remap_bucket(mc, entry, entry->vaddr_base,
+                     cache_size, address_index, false, entry->ram_offset);
     if (!test_bits(address_offset >> XC_PAGE_SHIFT,
                 test_bit_size >> XC_PAGE_SHIFT,
                 entry->valid_mapping)) {
diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
index 1ec9e66752..b5e3ea1bc0 100644
--- a/include/sysemu/xen-mapcache.h
+++ b/include/sysemu/xen-mapcache.h
@@ -19,6 +19,7 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
 void xen_map_cache_init(phys_offset_to_gaddr_t f,
                         void *opaque);
 uint8_t *xen_map_cache(MemoryRegion *mr, hwaddr phys_addr, hwaddr size,
+                       ram_addr_t ram_addr_offset,
                        uint8_t lock, bool dma,
                        bool is_write);
 ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
@@ -37,6 +38,7 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
 static inline uint8_t *xen_map_cache(MemoryRegion *mr,
                                      hwaddr phys_addr,
                                      hwaddr size,
+                                     ram_addr_t ram_addr_offset,
                                      uint8_t lock,
                                      bool dma,
                                      bool is_write)
diff --git a/system/physmem.c b/system/physmem.c
index 1a5ffcba2a..5b16eeccca 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2228,13 +2228,13 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
          * In that case just map the requested area.
          */
         if (xen_mr_is_memory(block->mr)) {
-            return xen_map_cache(block->mr, addr, len, lock, lock,
-                                 is_write);
+            return xen_map_cache(block->mr, addr, len, block->offset,
+                                 lock, lock, is_write);
         }
 
         block->host = xen_map_cache(block->mr, block->offset,
-                                    block->max_length, 1,
-                                    lock, is_write);
+                                    block->max_length, 0,
+                                    1, lock, is_write);
     }
 
     return ramblock_ptr(block, addr);
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 16/17] xen: mapcache: Add support for grant mappings
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (14 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-02 19:18   ` Stefano Stabellini
  2024-04-30 16:49 ` [PATCH v4 17/17] hw/arm: xen: Enable use of " Edgar E. Iglesias
  2024-05-06 10:36 ` [PATCH v4 00/17] xen: Support " Philippe Mathieu-Daudé
  17 siblings, 1 reply; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Add a second mapcache for grant mappings. The mapcache for
grants needs to work with XC_PAGE_SIZE granularity since
we can't map larger ranges than what has been granted to us.

Like with foreign mappings (xen_memory), machines using grants
are expected to initialize the xen_grants MR and map it
into their address-map accordingly.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/xen/xen-hvm-common.c         |  12 ++-
 hw/xen/xen-mapcache.c           | 158 +++++++++++++++++++++++++-------
 include/hw/xen/xen-hvm-common.h |   3 +
 include/sysemu/xen.h            |   7 ++
 4 files changed, 145 insertions(+), 35 deletions(-)

diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index 0267b88d26..fdec400491 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -10,12 +10,18 @@
 #include "hw/boards.h"
 #include "hw/xen/arch_hvm.h"
 
-MemoryRegion xen_memory;
+MemoryRegion xen_memory, xen_grants;
 
-/* Check for xen memory.  */
+/* Check for any kind of xen memory, foreign mappings or grants.  */
 bool xen_mr_is_memory(MemoryRegion *mr)
 {
-    return mr == &xen_memory;
+    return mr == &xen_memory || mr == &xen_grants;
+}
+
+/* Check specifically for grants.  */
+bool xen_mr_is_grants(MemoryRegion *mr)
+{
+    return mr == &xen_grants;
 }
 
 void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 1b32d0c003..96cd68e28d 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -14,6 +14,7 @@
 
 #include <sys/resource.h>
 
+#include "hw/xen/xen-hvm-common.h"
 #include "hw/xen/xen_native.h"
 #include "qemu/bitmap.h"
 
@@ -21,6 +22,8 @@
 #include "sysemu/xen-mapcache.h"
 #include "trace.h"
 
+#include <xenevtchn.h>
+#include <xengnttab.h>
 
 #if HOST_LONG_BITS == 32
 #  define MCACHE_MAX_SIZE     (1UL<<31) /* 2GB Cap */
@@ -41,6 +44,7 @@ typedef struct MapCacheEntry {
     unsigned long *valid_mapping;
     uint32_t lock;
 #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
+#define XEN_MAPCACHE_ENTRY_GRANT (1 << 1)
     uint8_t flags;
     hwaddr size;
 
@@ -74,6 +78,8 @@ typedef struct MapCache {
 } MapCache;
 
 static MapCache *mapcache;
+static MapCache *mapcache_grants;
+static xengnttab_handle *xen_region_gnttabdev;
 
 static inline void mapcache_lock(MapCache *mc)
 {
@@ -132,6 +138,12 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
     unsigned long max_mcache_size;
     unsigned int bucket_shift;
 
+    xen_region_gnttabdev = xengnttab_open(NULL, 0);
+    if (xen_region_gnttabdev == NULL) {
+        error_report("mapcache: Failed to open gnttab device");
+        exit(EXIT_FAILURE);
+    }
+
     if (HOST_LONG_BITS == 32) {
         bucket_shift = 16;
     } else {
@@ -160,6 +172,15 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
     mapcache = xen_map_cache_init_single(f, opaque,
                                          bucket_shift,
                                          max_mcache_size);
+
+    /*
+     * Grant mappings must use XC_PAGE_SIZE granularity since we can't
+     * map anything beyond the number of pages granted to us.
+     */
+    mapcache_grants = xen_map_cache_init_single(f, opaque,
+                                                XC_PAGE_SHIFT,
+                                                max_mcache_size);
+
     setrlimit(RLIMIT_AS, &rlimit_as);
 }
 
@@ -169,17 +190,25 @@ static void xen_remap_bucket(MapCache *mc,
                              hwaddr size,
                              hwaddr address_index,
                              bool dummy,
+                             bool grant,
+                             bool grant_is_write,
+                             hwaddr grant_ref,
                              ram_addr_t ram_offset)
 {
     uint8_t *vaddr_base;
-    xen_pfn_t *pfns;
+    uint32_t *refs = NULL;
+    xen_pfn_t *pfns = NULL;
     int *err;
     unsigned int i;
     hwaddr nb_pfn = size >> XC_PAGE_SHIFT;
 
     trace_xen_remap_bucket(address_index);
 
-    pfns = g_new0(xen_pfn_t, nb_pfn);
+    if (grant) {
+        refs = g_new0(uint32_t, nb_pfn);
+    } else {
+        pfns = g_new0(xen_pfn_t, nb_pfn);
+    }
     err = g_new0(int, nb_pfn);
 
     if (entry->vaddr_base != NULL) {
@@ -208,21 +237,45 @@ static void xen_remap_bucket(MapCache *mc,
     g_free(entry->valid_mapping);
     entry->valid_mapping = NULL;
 
-    for (i = 0; i < nb_pfn; i++) {
-        pfns[i] = (address_index << (mc->bucket_shift - XC_PAGE_SHIFT)) + i;
+    if (grant) {
+        for (i = 0; i < nb_pfn; i++) {
+            refs[i] = grant_ref + i;
+        }
+    } else {
+        for (i = 0; i < nb_pfn; i++) {
+            pfns[i] = (address_index << (mc->bucket_shift - XC_PAGE_SHIFT)) + i;
+        }
     }
 
-    /*
-     * If the caller has requested the mapping at a specific address use
-     * MAP_FIXED to make sure it's honored.
-     */
+    entry->flags &= ~XEN_MAPCACHE_ENTRY_GRANT;
+
     if (!dummy) {
-        vaddr_base = xenforeignmemory_map2(xen_fmem, xen_domid, vaddr,
-                                           PROT_READ | PROT_WRITE,
-                                           vaddr ? MAP_FIXED : 0,
-                                           nb_pfn, pfns, err);
+        if (grant) {
+            int prot = PROT_READ;
+
+            if (grant_is_write) {
+                prot |= PROT_WRITE;
+            }
+
+            entry->flags |= XEN_MAPCACHE_ENTRY_GRANT;
+            assert(vaddr == NULL);
+            vaddr_base = xengnttab_map_domain_grant_refs(xen_region_gnttabdev,
+                                                         nb_pfn,
+                                                         xen_domid, refs,
+                                                         prot);
+        } else {
+            /*
+             * If the caller has requested the mapping at a specific address use
+             * MAP_FIXED to make sure it's honored.
+             */
+            vaddr_base = xenforeignmemory_map2(xen_fmem, xen_domid, vaddr,
+                                               PROT_READ | PROT_WRITE,
+                                               vaddr ? MAP_FIXED : 0,
+                                               nb_pfn, pfns, err);
+        }
         if (vaddr_base == NULL) {
-            perror("xenforeignmemory_map2");
+            perror(grant ? "xengnttab_map_domain_grant_refs"
+                           : "xenforeignmemory_map2");
             exit(-1);
         }
     } else {
@@ -263,6 +316,7 @@ static void xen_remap_bucket(MapCache *mc,
         }
     }
 
+    g_free(refs);
     g_free(pfns);
     g_free(err);
 }
@@ -270,10 +324,12 @@ static void xen_remap_bucket(MapCache *mc,
 static uint8_t *xen_map_cache_unlocked(MapCache *mc,
                                        hwaddr phys_addr, hwaddr size,
                                        ram_addr_t ram_offset,
-                                       uint8_t lock, bool dma, bool is_write)
+                                       uint8_t lock, bool dma,
+                                       bool grant, bool is_write)
 {
     MapCacheEntry *entry, *pentry = NULL,
                   *free_entry = NULL, *free_pentry = NULL;
+    hwaddr grant_ref = phys_addr >> XC_PAGE_SHIFT;
     hwaddr address_index;
     hwaddr address_offset;
     hwaddr cache_size = size;
@@ -342,7 +398,7 @@ tryagain:
         entry = g_new0(MapCacheEntry, 1);
         pentry->next = entry;
         xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
-                         ram_offset);
+                         grant, is_write, grant_ref, ram_offset);
     } else if (!entry->lock) {
         if (!entry->vaddr_base || entry->paddr_index != address_index ||
                 entry->size != cache_size ||
@@ -350,7 +406,7 @@ tryagain:
                     test_bit_size >> XC_PAGE_SHIFT,
                     entry->valid_mapping)) {
             xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
-                             ram_offset);
+                             grant, is_write, grant_ref, ram_offset);
         }
     }
 
@@ -401,12 +457,28 @@ uint8_t *xen_map_cache(MemoryRegion *mr,
                        uint8_t lock, bool dma,
                        bool is_write)
 {
+    bool grant = xen_mr_is_grants(mr);
+    MapCache *mc = grant ? mapcache_grants : mapcache;
     uint8_t *p;
 
-    mapcache_lock(mapcache);
-    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
-                               lock, dma, is_write);
-    mapcache_unlock(mapcache);
+    if (grant) {
+        /*
+         * Grants are only supported via address_space_map(). Anything
+         * else is considered a user/guest error.
+         *
+         * QEMU generally doesn't expect these mappings to ever fail, so
+         * if this happens we report an error message and abort().
+         */
+        if (!lock) {
+            error_report("Trying access a grant reference without mapping it.");
+            abort();
+        }
+    }
+
+    mapcache_lock(mc);
+    p = xen_map_cache_unlocked(mc, phys_addr, size, ram_addr_offset,
+                               lock, dma, grant, is_write);
+    mapcache_unlock(mc);
     return p;
 }
 
@@ -451,7 +523,14 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
 
 ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
 {
-    return xen_ram_addr_from_mapcache_single(mapcache, ptr);
+    ram_addr_t addr;
+
+    addr = xen_ram_addr_from_mapcache_single(mapcache, ptr);
+    if (addr == RAM_ADDR_INVALID) {
+        addr = xen_ram_addr_from_mapcache_single(mapcache_grants, ptr);
+    }
+
+    return addr;
 }
 
 static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
@@ -504,9 +583,14 @@ static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
     }
 
     ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size);
-    if (munmap(entry->vaddr_base, entry->size) != 0) {
-        perror("unmap fails");
-        exit(-1);
+    if (entry->flags & XEN_MAPCACHE_ENTRY_GRANT) {
+        xengnttab_unmap(xen_region_gnttabdev, entry->vaddr_base,
+                    (entry->size + mc->bucket_size - 1) >> mc->bucket_shift);
+    } else {
+        if (munmap(entry->vaddr_base, entry->size) != 0) {
+            perror("unmap fails");
+            exit(-1);
+        }
     }
     if (pentry) {
         pentry->next = entry->next;
@@ -522,14 +606,24 @@ typedef struct XenMapCacheData {
     uint8_t *buffer;
 } XenMapCacheData;
 
+static void xen_invalidate_map_cache_entry_single(MapCache *mc, uint8_t *buffer)
+{
+    mapcache_lock(mc);
+    xen_invalidate_map_cache_entry_unlocked(mc, buffer);
+    mapcache_unlock(mc);
+}
+
+static void xen_invalidate_map_cache_entry_all(uint8_t *buffer)
+{
+    xen_invalidate_map_cache_entry_single(mapcache, buffer);
+    xen_invalidate_map_cache_entry_single(mapcache_grants, buffer);
+}
+
 static void xen_invalidate_map_cache_entry_bh(void *opaque)
 {
     XenMapCacheData *data = opaque;
 
-    mapcache_lock(mapcache);
-    xen_invalidate_map_cache_entry_unlocked(mapcache, data->buffer);
-    mapcache_unlock(mapcache);
-
+    xen_invalidate_map_cache_entry_all(data->buffer);
     aio_co_wake(data->co);
 }
 
@@ -544,9 +638,7 @@ void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
                                 xen_invalidate_map_cache_entry_bh, &data);
         qemu_coroutine_yield();
     } else {
-        mapcache_lock(mapcache);
-        xen_invalidate_map_cache_entry_unlocked(mapcache, buffer);
-        mapcache_unlock(mapcache);
+        xen_invalidate_map_cache_entry_all(buffer);
     }
 }
 
@@ -598,6 +690,7 @@ void xen_invalidate_map_cache(void)
     bdrv_drain_all();
 
     xen_invalidate_map_cache_single(mapcache);
+    xen_invalidate_map_cache_single(mapcache_grants);
 }
 
 static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
@@ -639,7 +732,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
     trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
 
     xen_remap_bucket(mc, entry, entry->vaddr_base,
-                     cache_size, address_index, false, entry->ram_offset);
+                     cache_size, address_index, false,
+                     false, false, 0, entry->ram_offset);
     if (!test_bits(address_offset >> XC_PAGE_SHIFT,
                 test_bit_size >> XC_PAGE_SHIFT,
                 entry->valid_mapping)) {
diff --git a/include/hw/xen/xen-hvm-common.h b/include/hw/xen/xen-hvm-common.h
index 65a51aac2e..3d796235dc 100644
--- a/include/hw/xen/xen-hvm-common.h
+++ b/include/hw/xen/xen-hvm-common.h
@@ -16,6 +16,7 @@
 #include <xen/hvm/ioreq.h>
 
 extern MemoryRegion xen_memory;
+extern MemoryRegion xen_grants;
 extern MemoryListener xen_io_listener;
 extern DeviceListener xen_device_listener;
 
@@ -29,6 +30,8 @@ extern DeviceListener xen_device_listener;
     do { } while (0)
 #endif
 
+#define XEN_GRANT_ADDR_OFF (1ULL << 63)
+
 static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
 {
     return shared_page->vcpu_ioreq[i].vp_eport;
diff --git a/include/sysemu/xen.h b/include/sysemu/xen.h
index dc72f83bcb..19dccf4d71 100644
--- a/include/sysemu/xen.h
+++ b/include/sysemu/xen.h
@@ -35,6 +35,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
                    struct MemoryRegion *mr, Error **errp);
 
 bool xen_mr_is_memory(MemoryRegion *mr);
+bool xen_mr_is_grants(MemoryRegion *mr);
 
 #else /* !CONFIG_XEN_IS_POSSIBLE */
 
@@ -55,6 +56,12 @@ static inline bool xen_mr_is_memory(MemoryRegion *mr)
     return false;
 }
 
+static inline bool xen_mr_is_grants(MemoryRegion *mr)
+{
+    g_assert_not_reached();
+    return false;
+}
+
 #endif /* CONFIG_XEN_IS_POSSIBLE */
 
 #endif
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v4 17/17] hw/arm: xen: Enable use of grant mappings
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (15 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 16/17] xen: mapcache: Add support for grant mappings Edgar E. Iglesias
@ 2024-04-30 16:49 ` Edgar E. Iglesias
  2024-05-01 22:11   ` Stefano Stabellini
  2024-05-06 10:36 ` [PATCH v4 00/17] xen: Support " Philippe Mathieu-Daudé
  17 siblings, 1 reply; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-04-30 16:49 UTC (permalink / raw
  To: qemu-devel
  Cc: edgar.iglesias, sstabellini, jgross, Edgar E. Iglesias,
	Peter Maydell, qemu-arm

From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
---
 hw/arm/xen_arm.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
index 15fa7dfa84..6fad829ede 100644
--- a/hw/arm/xen_arm.c
+++ b/hw/arm/xen_arm.c
@@ -125,6 +125,11 @@ static void xen_init_ram(MachineState *machine)
                                  GUEST_RAM1_BASE, ram_size[1]);
         memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, &ram_hi);
     }
+
+    /* Setup support for grants.  */
+    memory_region_init_ram(&xen_grants, NULL, "xen.grants", block_len,
+                           &error_fatal);
+    memory_region_add_subregion(sysmem, XEN_GRANT_ADDR_OFF, &xen_grants);
 }
 
 void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 01/17] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
  2024-04-30 16:49 ` [PATCH v4 01/17] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length() Edgar E. Iglesias
@ 2024-05-01 15:56   ` David Hildenbrand
  2024-05-01 16:48   ` Peter Xu
  1 sibling, 0 replies; 58+ messages in thread
From: David Hildenbrand @ 2024-05-01 15:56 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Vikram Garhwal, Edgar E . Iglesias,
	Alex Bennée, Paolo Bonzini, Peter Xu,
	Philippe Mathieu-Daudé

On 30.04.24 18:49, Edgar E. Iglesias wrote:
> From: Juergen Gross <jgross@suse.com>
> 
> qemu_map_ram_ptr() and qemu_ram_ptr_length() share quite some code, so
> modify qemu_ram_ptr_length() a little bit and use it for
> qemu_map_ram_ptr(), too.
> 
> Signed-off-by: Juergen Gross <jgross@suse.com>
> Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---

Acked-by: David Hildenbrand <david@redhat.com>

-- 
Cheers,

David / dhildenb



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache()
  2024-04-30 16:49 ` [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache() Edgar E. Iglesias
@ 2024-05-01 16:48   ` Peter Xu
  2024-05-01 21:03   ` Stefano Stabellini
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 58+ messages in thread
From: Peter Xu @ 2024-05-01 16:48 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, David Hildenbrand,
	Philippe Mathieu-Daudé, xen-devel

On Tue, Apr 30, 2024 at 06:49:35PM +0200, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Propagate MR and is_write to xen_map_cache().
> This is in preparation for adding support for grant mappings.
> 
> No functional change.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Acked-by: Peter Xu <peterx@redhat.com>

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 01/17] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
  2024-04-30 16:49 ` [PATCH v4 01/17] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length() Edgar E. Iglesias
  2024-05-01 15:56   ` David Hildenbrand
@ 2024-05-01 16:48   ` Peter Xu
  1 sibling, 0 replies; 58+ messages in thread
From: Peter Xu @ 2024-05-01 16:48 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Vikram Garhwal,
	Edgar E . Iglesias, Alex Bennée, Paolo Bonzini,
	David Hildenbrand, Philippe Mathieu-Daudé

On Tue, Apr 30, 2024 at 06:49:23PM +0200, Edgar E. Iglesias wrote:
> From: Juergen Gross <jgross@suse.com>
> 
> qemu_map_ram_ptr() and qemu_ram_ptr_length() share quite some code, so
> modify qemu_ram_ptr_length() a little bit and use it for
> qemu_map_ram_ptr(), too.
> 
> Signed-off-by: Juergen Gross <jgross@suse.com>
> Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Peter Xu <peterx@redhat.com>

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 03/17] xen: mapcache: Refactor lock functions for multi-instance
  2024-04-30 16:49 ` [PATCH v4 03/17] xen: mapcache: Refactor lock functions for multi-instance Edgar E. Iglesias
@ 2024-05-01 20:39   ` Stefano Stabellini
  2024-05-06  9:52   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 20:39 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Make the lock functions take MapCache * as argument. This is
> in preparation for supporting multiple caches.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c | 34 +++++++++++++++++-----------------
>  1 file changed, 17 insertions(+), 17 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index b7cefb78f7..3f11562075 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -74,14 +74,14 @@ typedef struct MapCache {
>  
>  static MapCache *mapcache;
>  
> -static inline void mapcache_lock(void)
> +static inline void mapcache_lock(MapCache *mc)
>  {
> -    qemu_mutex_lock(&mapcache->lock);
> +    qemu_mutex_lock(&mc->lock);
>  }
>  
> -static inline void mapcache_unlock(void)
> +static inline void mapcache_unlock(MapCache *mc)
>  {
> -    qemu_mutex_unlock(&mapcache->lock);
> +    qemu_mutex_unlock(&mc->lock);
>  }
>  
>  static inline int test_bits(int nr, int size, const unsigned long *addr)
> @@ -369,9 +369,9 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
>  {
>      uint8_t *p;
>  
> -    mapcache_lock();
> +    mapcache_lock(mapcache);
>      p = xen_map_cache_unlocked(phys_addr, size, lock, dma);
> -    mapcache_unlock();
> +    mapcache_unlock(mapcache);
>      return p;
>  }
>  
> @@ -384,7 +384,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>      ram_addr_t raddr;
>      int found = 0;
>  
> -    mapcache_lock();
> +    mapcache_lock(mapcache);
>      QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
>          if (reventry->vaddr_req == ptr) {
>              paddr_index = reventry->paddr_index;
> @@ -394,7 +394,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>          }
>      }
>      if (!found) {
> -        mapcache_unlock();
> +        mapcache_unlock(mapcache);
>          return RAM_ADDR_INVALID;
>      }
>  
> @@ -409,7 +409,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>          raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
>               ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
>      }
> -    mapcache_unlock();
> +    mapcache_unlock(mapcache);
>      return raddr;
>  }
>  
> @@ -480,9 +480,9 @@ static void xen_invalidate_map_cache_entry_bh(void *opaque)
>  {
>      XenMapCacheData *data = opaque;
>  
> -    mapcache_lock();
> +    mapcache_lock(mapcache);
>      xen_invalidate_map_cache_entry_unlocked(data->buffer);
> -    mapcache_unlock();
> +    mapcache_unlock(mapcache);
>  
>      aio_co_wake(data->co);
>  }
> @@ -498,9 +498,9 @@ void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
>                                  xen_invalidate_map_cache_entry_bh, &data);
>          qemu_coroutine_yield();
>      } else {
> -        mapcache_lock();
> +        mapcache_lock(mapcache);
>          xen_invalidate_map_cache_entry_unlocked(buffer);
> -        mapcache_unlock();
> +        mapcache_unlock(mapcache);
>      }
>  }
>  
> @@ -512,7 +512,7 @@ void xen_invalidate_map_cache(void)
>      /* Flush pending AIO before destroying the mapcache */
>      bdrv_drain_all();
>  
> -    mapcache_lock();
> +    mapcache_lock(mapcache);
>  
>      QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
>          if (!reventry->dma) {
> @@ -546,7 +546,7 @@ void xen_invalidate_map_cache(void)
>  
>      mapcache->last_entry = NULL;
>  
> -    mapcache_unlock();
> +    mapcache_unlock(mapcache);
>  }
>  
>  static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
> @@ -606,8 +606,8 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
>  {
>      uint8_t *p;
>  
> -    mapcache_lock();
> +    mapcache_lock(mapcache);
>      p = xen_replace_cache_entry_unlocked(old_phys_addr, new_phys_addr, size);
> -    mapcache_unlock();
> +    mapcache_unlock(mapcache);
>      return p;
>  }
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 04/17] xen: mapcache: Refactor xen_map_cache for multi-instance
  2024-04-30 16:49 ` [PATCH v4 04/17] xen: mapcache: Refactor xen_map_cache " Edgar E. Iglesias
@ 2024-05-01 20:40   ` Stefano Stabellini
  2024-05-06  9:53   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 20:40 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Make xen_map_cache take a MapCache as argument. This is in
> prepaparation to support multiple map caches.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c | 35 ++++++++++++++++++-----------------
>  1 file changed, 18 insertions(+), 17 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 3f11562075..896021d86f 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -240,7 +240,8 @@ static void xen_remap_bucket(MapCacheEntry *entry,
>      g_free(err);
>  }
>  
> -static uint8_t *xen_map_cache_unlocked(hwaddr phys_addr, hwaddr size,
> +static uint8_t *xen_map_cache_unlocked(MapCache *mc,
> +                                       hwaddr phys_addr, hwaddr size,
>                                         uint8_t lock, bool dma)
>  {
>      MapCacheEntry *entry, *pentry = NULL,
> @@ -269,16 +270,16 @@ tryagain:
>          test_bit_size = XC_PAGE_SIZE;
>      }
>  
> -    if (mapcache->last_entry != NULL &&
> -        mapcache->last_entry->paddr_index == address_index &&
> +    if (mc->last_entry != NULL &&
> +        mc->last_entry->paddr_index == address_index &&
>          !lock && !size &&
>          test_bits(address_offset >> XC_PAGE_SHIFT,
>                    test_bit_size >> XC_PAGE_SHIFT,
> -                  mapcache->last_entry->valid_mapping)) {
> +                  mc->last_entry->valid_mapping)) {
>          trace_xen_map_cache_return(
> -            mapcache->last_entry->vaddr_base + address_offset
> +            mc->last_entry->vaddr_base + address_offset
>          );
> -        return mapcache->last_entry->vaddr_base + address_offset;
> +        return mc->last_entry->vaddr_base + address_offset;
>      }
>  
>      /* size is always a multiple of MCACHE_BUCKET_SIZE */
> @@ -291,7 +292,7 @@ tryagain:
>          cache_size = MCACHE_BUCKET_SIZE;
>      }
>  
> -    entry = &mapcache->entry[address_index % mapcache->nr_buckets];
> +    entry = &mc->entry[address_index % mc->nr_buckets];
>  
>      while (entry && (lock || entry->lock) && entry->vaddr_base &&
>              (entry->paddr_index != address_index || entry->size != cache_size ||
> @@ -326,10 +327,10 @@ tryagain:
>      if(!test_bits(address_offset >> XC_PAGE_SHIFT,
>                  test_bit_size >> XC_PAGE_SHIFT,
>                  entry->valid_mapping)) {
> -        mapcache->last_entry = NULL;
> +        mc->last_entry = NULL;
>  #ifdef XEN_COMPAT_PHYSMAP
> -        if (!translated && mapcache->phys_offset_to_gaddr) {
> -            phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size);
> +        if (!translated && mc->phys_offset_to_gaddr) {
> +            phys_addr = mc->phys_offset_to_gaddr(phys_addr, size);
>              translated = true;
>              goto tryagain;
>          }
> @@ -342,7 +343,7 @@ tryagain:
>          return NULL;
>      }
>  
> -    mapcache->last_entry = entry;
> +    mc->last_entry = entry;
>      if (lock) {
>          MapCacheRev *reventry = g_new0(MapCacheRev, 1);
>          entry->lock++;
> @@ -352,16 +353,16 @@ tryagain:
>              abort();
>          }
>          reventry->dma = dma;
> -        reventry->vaddr_req = mapcache->last_entry->vaddr_base + address_offset;
> -        reventry->paddr_index = mapcache->last_entry->paddr_index;
> +        reventry->vaddr_req = mc->last_entry->vaddr_base + address_offset;
> +        reventry->paddr_index = mc->last_entry->paddr_index;
>          reventry->size = entry->size;
> -        QTAILQ_INSERT_HEAD(&mapcache->locked_entries, reventry, next);
> +        QTAILQ_INSERT_HEAD(&mc->locked_entries, reventry, next);
>      }
>  
>      trace_xen_map_cache_return(
> -        mapcache->last_entry->vaddr_base + address_offset
> +        mc->last_entry->vaddr_base + address_offset
>      );
> -    return mapcache->last_entry->vaddr_base + address_offset;
> +    return mc->last_entry->vaddr_base + address_offset;
>  }
>  
>  uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
> @@ -370,7 +371,7 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
>      uint8_t *p;
>  
>      mapcache_lock(mapcache);
> -    p = xen_map_cache_unlocked(phys_addr, size, lock, dma);
> +    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma);
>      mapcache_unlock(mapcache);
>      return p;
>  }
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 05/17] xen: mapcache: Refactor xen_remap_bucket for multi-instance
  2024-04-30 16:49 ` [PATCH v4 05/17] xen: mapcache: Refactor xen_remap_bucket " Edgar E. Iglesias
@ 2024-05-01 20:42   ` Stefano Stabellini
  2024-05-06  9:54   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 20:42 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Add MapCache argument to xen_remap_bucket in preparation
> to support multiple map caches.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 896021d86f..326a9b61ca 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -139,7 +139,8 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
>      mapcache->entry = g_malloc0(size);
>  }
>  
> -static void xen_remap_bucket(MapCacheEntry *entry,
> +static void xen_remap_bucket(MapCache *mc,
> +                             MapCacheEntry *entry,
>                               void *vaddr,
>                               hwaddr size,
>                               hwaddr address_index,
> @@ -313,14 +314,14 @@ tryagain:
>      if (!entry) {
>          entry = g_new0(MapCacheEntry, 1);
>          pentry->next = entry;
> -        xen_remap_bucket(entry, NULL, cache_size, address_index, dummy);
> +        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
>      } else if (!entry->lock) {
>          if (!entry->vaddr_base || entry->paddr_index != address_index ||
>                  entry->size != cache_size ||
>                  !test_bits(address_offset >> XC_PAGE_SHIFT,
>                      test_bit_size >> XC_PAGE_SHIFT,
>                      entry->valid_mapping)) {
> -            xen_remap_bucket(entry, NULL, cache_size, address_index, dummy);
> +            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
>          }
>      }
>  
> @@ -587,7 +588,7 @@ static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
>  
>      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
>  
> -    xen_remap_bucket(entry, entry->vaddr_base,
> +    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
>                       cache_size, address_index, false);
>      if (!test_bits(address_offset >> XC_PAGE_SHIFT,
>                  test_bit_size >> XC_PAGE_SHIFT,
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 06/17] xen: mapcache: Break out xen_ram_addr_from_mapcache_single
  2024-04-30 16:49 ` [PATCH v4 06/17] xen: mapcache: Break out xen_ram_addr_from_mapcache_single Edgar E. Iglesias
@ 2024-05-01 20:43   ` Stefano Stabellini
  2024-05-06 10:22   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 20:43 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Break out xen_ram_addr_from_mapcache_single(), a multi-cache
> aware version of xen_ram_addr_from_mapcache.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c | 17 +++++++++++------
>  1 file changed, 11 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 326a9b61ca..d2deff70c8 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -377,7 +377,7 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
>      return p;
>  }
>  
> -ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
> +static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
>  {
>      MapCacheEntry *entry = NULL;
>      MapCacheRev *reventry;
> @@ -386,8 +386,8 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>      ram_addr_t raddr;
>      int found = 0;
>  
> -    mapcache_lock(mapcache);
> -    QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
> +    mapcache_lock(mc);
> +    QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
>          if (reventry->vaddr_req == ptr) {
>              paddr_index = reventry->paddr_index;
>              size = reventry->size;
> @@ -396,11 +396,11 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>          }
>      }
>      if (!found) {
> -        mapcache_unlock(mapcache);
> +        mapcache_unlock(mc);
>          return RAM_ADDR_INVALID;
>      }
>  
> -    entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
> +    entry = &mc->entry[paddr_index % mc->nr_buckets];
>      while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
>          entry = entry->next;
>      }
> @@ -411,10 +411,15 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>          raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
>               ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
>      }
> -    mapcache_unlock(mapcache);
> +    mapcache_unlock(mc);
>      return raddr;
>  }
>  
> +ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
> +{
> +    return xen_ram_addr_from_mapcache_single(mapcache, ptr);
> +}
> +
>  static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
>  {
>      MapCacheEntry *entry = NULL, *pentry = NULL;
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 07/17] xen: mapcache: Refactor xen_replace_cache_entry_unlocked
  2024-04-30 16:49 ` [PATCH v4 07/17] xen: mapcache: Refactor xen_replace_cache_entry_unlocked Edgar E. Iglesias
@ 2024-05-01 20:46   ` Stefano Stabellini
  2024-05-02  6:32     ` Edgar E. Iglesias
  0 siblings, 1 reply; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 20:46 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Add MapCache argument to xen_replace_cache_entry_unlocked in
> preparation for supporting multiple map caches.
> 
> No functional change.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>  hw/xen/xen-mapcache.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index d2deff70c8..6e758eff94 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -556,7 +556,8 @@ void xen_invalidate_map_cache(void)
>      mapcache_unlock(mapcache);
>  }
>  
> -static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
> +static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> +                                                 hwaddr old_phys_addr,
>                                                   hwaddr new_phys_addr,
>                                                   hwaddr size)
>  {
> @@ -578,7 +579,7 @@ static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
>          cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE);
>      }
>  
> -    entry = &mapcache->entry[address_index % mapcache->nr_buckets];
> +    entry = &mc->entry[address_index % mc->nr_buckets];
>      while (entry && !(entry->paddr_index == address_index &&
>                        entry->size == cache_size)) {
>          entry = entry->next;

There is still a global mapcache pointer in use in this function:

  xen_remap_bucket(mapcache, entry, entry->vaddr_base,


> @@ -614,7 +615,8 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
>      uint8_t *p;
>  
>      mapcache_lock(mapcache);
> -    p = xen_replace_cache_entry_unlocked(old_phys_addr, new_phys_addr, size);
> +    p = xen_replace_cache_entry_unlocked(mapcache, old_phys_addr,
> +                                         new_phys_addr, size);
>      mapcache_unlock(mapcache);
>      return p;
>  }
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 08/17] xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked
  2024-04-30 16:49 ` [PATCH v4 08/17] xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked Edgar E. Iglesias
@ 2024-05-01 20:47   ` Stefano Stabellini
  2024-05-06  9:55   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 20:47 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Add MapCache argument to xen_invalidate_map_cache_entry_unlocked.
> This is in preparation for supporting multiple map caches.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c | 21 +++++++++++----------
>  1 file changed, 11 insertions(+), 10 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 6e758eff94..34454da2f6 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -420,7 +420,8 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>      return xen_ram_addr_from_mapcache_single(mapcache, ptr);
>  }
>  
> -static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
> +static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
> +                                                    uint8_t *buffer)
>  {
>      MapCacheEntry *entry = NULL, *pentry = NULL;
>      MapCacheRev *reventry;
> @@ -428,7 +429,7 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
>      hwaddr size;
>      int found = 0;
>  
> -    QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
> +    QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
>          if (reventry->vaddr_req == buffer) {
>              paddr_index = reventry->paddr_index;
>              size = reventry->size;
> @@ -438,7 +439,7 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
>      }
>      if (!found) {
>          trace_xen_invalidate_map_cache_entry_unlocked_not_found(buffer);
> -        QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
> +        QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
>              trace_xen_invalidate_map_cache_entry_unlocked_found(
>                  reventry->paddr_index,
>                  reventry->vaddr_req
> @@ -446,15 +447,15 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
>          }
>          return;
>      }
> -    QTAILQ_REMOVE(&mapcache->locked_entries, reventry, next);
> +    QTAILQ_REMOVE(&mc->locked_entries, reventry, next);
>      g_free(reventry);
>  
> -    if (mapcache->last_entry != NULL &&
> -        mapcache->last_entry->paddr_index == paddr_index) {
> -        mapcache->last_entry = NULL;
> +    if (mc->last_entry != NULL &&
> +        mc->last_entry->paddr_index == paddr_index) {
> +        mc->last_entry = NULL;
>      }
>  
> -    entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
> +    entry = &mc->entry[paddr_index % mc->nr_buckets];
>      while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
>          pentry = entry;
>          entry = entry->next;
> @@ -488,7 +489,7 @@ static void xen_invalidate_map_cache_entry_bh(void *opaque)
>      XenMapCacheData *data = opaque;
>  
>      mapcache_lock(mapcache);
> -    xen_invalidate_map_cache_entry_unlocked(data->buffer);
> +    xen_invalidate_map_cache_entry_unlocked(mapcache, data->buffer);
>      mapcache_unlock(mapcache);
>  
>      aio_co_wake(data->co);
> @@ -506,7 +507,7 @@ void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
>          qemu_coroutine_yield();
>      } else {
>          mapcache_lock(mapcache);
> -        xen_invalidate_map_cache_entry_unlocked(buffer);
> +        xen_invalidate_map_cache_entry_unlocked(mapcache, buffer);
>          mapcache_unlock(mapcache);
>      }
>  }
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 09/17] xen: mapcache: Break out xen_invalidate_map_cache_single()
  2024-04-30 16:49 ` [PATCH v4 09/17] xen: mapcache: Break out xen_invalidate_map_cache_single() Edgar E. Iglesias
@ 2024-05-01 20:48   ` Stefano Stabellini
  2024-05-06 10:21   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 20:48 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Break out xen_invalidate_map_cache_single().
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c | 25 +++++++++++++++----------
>  1 file changed, 15 insertions(+), 10 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 34454da2f6..dd08cd296b 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -512,17 +512,14 @@ void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
>      }
>  }
>  
> -void xen_invalidate_map_cache(void)
> +static void xen_invalidate_map_cache_single(MapCache *mc)
>  {
>      unsigned long i;
>      MapCacheRev *reventry;
>  
> -    /* Flush pending AIO before destroying the mapcache */
> -    bdrv_drain_all();
> -
> -    mapcache_lock(mapcache);
> +    mapcache_lock(mc);
>  
> -    QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
> +    QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
>          if (!reventry->dma) {
>              continue;
>          }
> @@ -530,8 +527,8 @@ void xen_invalidate_map_cache(void)
>                                         reventry->vaddr_req);
>      }
>  
> -    for (i = 0; i < mapcache->nr_buckets; i++) {
> -        MapCacheEntry *entry = &mapcache->entry[i];
> +    for (i = 0; i < mc->nr_buckets; i++) {
> +        MapCacheEntry *entry = &mc->entry[i];
>  
>          if (entry->vaddr_base == NULL) {
>              continue;
> @@ -552,9 +549,17 @@ void xen_invalidate_map_cache(void)
>          entry->valid_mapping = NULL;
>      }
>  
> -    mapcache->last_entry = NULL;
> +    mc->last_entry = NULL;
>  
> -    mapcache_unlock(mapcache);
> +    mapcache_unlock(mc);
> +}
> +
> +void xen_invalidate_map_cache(void)
> +{
> +    /* Flush pending AIO before destroying the mapcache */
> +    bdrv_drain_all();
> +
> +    xen_invalidate_map_cache_single(mapcache);
>  }
>  
>  static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 10/17] xen: mapcache: Break out xen_map_cache_init_single()
  2024-04-30 16:49 ` [PATCH v4 10/17] xen: mapcache: Break out xen_map_cache_init_single() Edgar E. Iglesias
@ 2024-05-01 20:51   ` Stefano Stabellini
  0 siblings, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 20:51 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Break out xen_map_cache_init_single() in preparation for
> adding multiple map caches.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c | 53 ++++++++++++++++++++++++++-----------------
>  1 file changed, 32 insertions(+), 21 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index dd08cd296b..72a7e25e3e 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -93,23 +93,44 @@ static inline int test_bits(int nr, int size, const unsigned long *addr)
>          return 0;
>  }
>  
> -void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
> +static MapCache *xen_map_cache_init_single(phys_offset_to_gaddr_t f,
> +                                           void *opaque,
> +                                           unsigned long max_size)
>  {
>      unsigned long size;
> -    struct rlimit rlimit_as;
> +    MapCache *mc;
> +
> +    mc = g_new0(MapCache, 1);
> +
> +    mc->phys_offset_to_gaddr = f;
> +    mc->opaque = opaque;
> +    qemu_mutex_init(&mc->lock);
> +
> +    QTAILQ_INIT(&mc->locked_entries);
>  
> -    mapcache = g_new0(MapCache, 1);
> +    mc->max_mcache_size = max_size;
>  
> -    mapcache->phys_offset_to_gaddr = f;
> -    mapcache->opaque = opaque;
> -    qemu_mutex_init(&mapcache->lock);
> +    mc->nr_buckets =
> +        (((mc->max_mcache_size >> XC_PAGE_SHIFT) +
> +          (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >>
> +         (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT));
>  
> -    QTAILQ_INIT(&mapcache->locked_entries);
> +    size = mc->nr_buckets * sizeof(MapCacheEntry);
> +    size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
> +    trace_xen_map_cache_init(mc->nr_buckets, size);
> +    mc->entry = g_malloc0(size);
> +    return mc;
> +}
> +
> +void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
> +{
> +    struct rlimit rlimit_as;
> +    unsigned long max_mcache_size;
>  
>      if (geteuid() == 0) {
>          rlimit_as.rlim_cur = RLIM_INFINITY;
>          rlimit_as.rlim_max = RLIM_INFINITY;
> -        mapcache->max_mcache_size = MCACHE_MAX_SIZE;
> +        max_mcache_size = MCACHE_MAX_SIZE;
>      } else {
>          getrlimit(RLIMIT_AS, &rlimit_as);
>          rlimit_as.rlim_cur = rlimit_as.rlim_max;
> @@ -119,24 +140,14 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
>                          " memory is not infinity");
>          }
>          if (rlimit_as.rlim_max < MCACHE_MAX_SIZE + NON_MCACHE_MEMORY_SIZE) {
> -            mapcache->max_mcache_size = rlimit_as.rlim_max -
> -                NON_MCACHE_MEMORY_SIZE;
> +            max_mcache_size = rlimit_as.rlim_max - NON_MCACHE_MEMORY_SIZE;
>          } else {
> -            mapcache->max_mcache_size = MCACHE_MAX_SIZE;
> +            max_mcache_size = MCACHE_MAX_SIZE;
>          }
>      }
>  
> +    mapcache = xen_map_cache_init_single(f, opaque, max_mcache_size);
>      setrlimit(RLIMIT_AS, &rlimit_as);
> -
> -    mapcache->nr_buckets =
> -        (((mapcache->max_mcache_size >> XC_PAGE_SHIFT) +
> -          (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >>
> -         (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT));
> -
> -    size = mapcache->nr_buckets * sizeof (MapCacheEntry);
> -    size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
> -    trace_xen_map_cache_init(mapcache->nr_buckets, size);
> -    mapcache->entry = g_malloc0(size);
>  }
>  
>  static void xen_remap_bucket(MapCache *mc,
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 11/17] xen: mapcache: Make MCACHE_BUCKET_SHIFT runtime configurable
  2024-04-30 16:49 ` [PATCH v4 11/17] xen: mapcache: Make MCACHE_BUCKET_SHIFT runtime configurable Edgar E. Iglesias
@ 2024-05-01 20:55   ` Stefano Stabellini
  0 siblings, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 20:55 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Make MCACHE_BUCKET_SHIFT runtime configurable per cache instance.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c | 52 ++++++++++++++++++++++++++-----------------
>  1 file changed, 31 insertions(+), 21 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 72a7e25e3e..4f98d284dd 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -23,13 +23,10 @@
>  
>  
>  #if HOST_LONG_BITS == 32
> -#  define MCACHE_BUCKET_SHIFT 16
>  #  define MCACHE_MAX_SIZE     (1UL<<31) /* 2GB Cap */
>  #else
> -#  define MCACHE_BUCKET_SHIFT 20
>  #  define MCACHE_MAX_SIZE     (1UL<<35) /* 32GB Cap */
>  #endif
> -#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
>  
>  /* This is the size of the virtual address space reserve to QEMU that will not
>   * be use by MapCache.
> @@ -65,7 +62,8 @@ typedef struct MapCache {
>      /* For most cases (>99.9%), the page address is the same. */
>      MapCacheEntry *last_entry;
>      unsigned long max_mcache_size;
> -    unsigned int mcache_bucket_shift;
> +    unsigned int bucket_shift;
> +    unsigned long bucket_size;
>  
>      phys_offset_to_gaddr_t phys_offset_to_gaddr;
>      QemuMutex lock;
> @@ -95,6 +93,7 @@ static inline int test_bits(int nr, int size, const unsigned long *addr)
>  
>  static MapCache *xen_map_cache_init_single(phys_offset_to_gaddr_t f,
>                                             void *opaque,
> +                                           unsigned int bucket_shift,
>                                             unsigned long max_size)
>  {
>      unsigned long size;
> @@ -108,12 +107,14 @@ static MapCache *xen_map_cache_init_single(phys_offset_to_gaddr_t f,
>  
>      QTAILQ_INIT(&mc->locked_entries);
>  
> +    mc->bucket_shift = bucket_shift;
> +    mc->bucket_size = 1UL << bucket_shift;
>      mc->max_mcache_size = max_size;
>  
>      mc->nr_buckets =
>          (((mc->max_mcache_size >> XC_PAGE_SHIFT) +
> -          (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >>
> -         (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT));
> +          (1UL << (bucket_shift - XC_PAGE_SHIFT)) - 1) >>
> +         (bucket_shift - XC_PAGE_SHIFT));
>  
>      size = mc->nr_buckets * sizeof(MapCacheEntry);
>      size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
> @@ -126,6 +127,13 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
>  {
>      struct rlimit rlimit_as;
>      unsigned long max_mcache_size;
> +    unsigned int bucket_shift;
> +
> +    if (HOST_LONG_BITS == 32) {
> +        bucket_shift = 16;
> +    } else {
> +        bucket_shift = 20;
> +    }
>  
>      if (geteuid() == 0) {
>          rlimit_as.rlim_cur = RLIM_INFINITY;
> @@ -146,7 +154,9 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
>          }
>      }
>  
> -    mapcache = xen_map_cache_init_single(f, opaque, max_mcache_size);
> +    mapcache = xen_map_cache_init_single(f, opaque,
> +                                         bucket_shift,
> +                                         max_mcache_size);
>      setrlimit(RLIMIT_AS, &rlimit_as);
>  }
>  
> @@ -195,7 +205,7 @@ static void xen_remap_bucket(MapCache *mc,
>      entry->valid_mapping = NULL;
>  
>      for (i = 0; i < nb_pfn; i++) {
> -        pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i;
> +        pfns[i] = (address_index << (mc->bucket_shift - XC_PAGE_SHIFT)) + i;
>      }
>  
>      /*
> @@ -266,8 +276,8 @@ static uint8_t *xen_map_cache_unlocked(MapCache *mc,
>      bool dummy = false;
>  
>  tryagain:
> -    address_index  = phys_addr >> MCACHE_BUCKET_SHIFT;
> -    address_offset = phys_addr & (MCACHE_BUCKET_SIZE - 1);
> +    address_index  = phys_addr >> mc->bucket_shift;
> +    address_offset = phys_addr & (mc->bucket_size - 1);
>  
>      trace_xen_map_cache(phys_addr);
>  
> @@ -294,14 +304,14 @@ tryagain:
>          return mc->last_entry->vaddr_base + address_offset;
>      }
>  
> -    /* size is always a multiple of MCACHE_BUCKET_SIZE */
> +    /* size is always a multiple of mc->bucket_size */
>      if (size) {
>          cache_size = size + address_offset;
> -        if (cache_size % MCACHE_BUCKET_SIZE) {
> -            cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE);
> +        if (cache_size % mc->bucket_size) {
> +            cache_size += mc->bucket_size - (cache_size % mc->bucket_size);
>          }
>      } else {
> -        cache_size = MCACHE_BUCKET_SIZE;
> +        cache_size = mc->bucket_size;
>      }
>  
>      entry = &mc->entry[address_index % mc->nr_buckets];
> @@ -419,7 +429,7 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
>          trace_xen_ram_addr_from_mapcache_not_in_cache(ptr);
>          raddr = RAM_ADDR_INVALID;
>      } else {
> -        raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
> +        raddr = (reventry->paddr_index << mc->bucket_shift) +
>               ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
>      }
>      mapcache_unlock(mc);
> @@ -582,8 +592,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
>      hwaddr address_index, address_offset;
>      hwaddr test_bit_size, cache_size = size;
>  
> -    address_index  = old_phys_addr >> MCACHE_BUCKET_SHIFT;
> -    address_offset = old_phys_addr & (MCACHE_BUCKET_SIZE - 1);
> +    address_index  = old_phys_addr >> mc->bucket_shift;
> +    address_offset = old_phys_addr & (mc->bucket_size - 1);
>  
>      assert(size);
>      /* test_bit_size is always a multiple of XC_PAGE_SIZE */
> @@ -592,8 +602,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
>          test_bit_size += XC_PAGE_SIZE - (test_bit_size % XC_PAGE_SIZE);
>      }
>      cache_size = size + address_offset;
> -    if (cache_size % MCACHE_BUCKET_SIZE) {
> -        cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE);
> +    if (cache_size % mc->bucket_size) {
> +        cache_size += mc->bucket_size - (cache_size % mc->bucket_size);
>      }
>  
>      entry = &mc->entry[address_index % mc->nr_buckets];
> @@ -606,8 +616,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
>          return NULL;
>      }
>  
> -    address_index  = new_phys_addr >> MCACHE_BUCKET_SHIFT;
> -    address_offset = new_phys_addr & (MCACHE_BUCKET_SIZE - 1);
> +    address_index  = new_phys_addr >> mc->bucket_shift;
> +    address_offset = new_phys_addr & (mc->bucket_size - 1);
>  
>      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
>  
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 12/17] xen: mapcache: Unmap first entries in buckets
  2024-04-30 16:49 ` [PATCH v4 12/17] xen: mapcache: Unmap first entries in buckets Edgar E. Iglesias
@ 2024-05-01 21:01   ` Stefano Stabellini
  2024-05-02  7:34   ` Edgar E. Iglesias
  1 sibling, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 21:01 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> When invalidating memory ranges, if we happen to hit the first
> entry in a bucket we were never unmapping it. This was harmless
> for foreign mappings but now that we're looking to reuse the
> mapcache for transient grant mappings, we must unmap entries
> when invalidated.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 4f98d284dd..0365311788 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -486,18 +486,22 @@ static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
>          return;
>      }
>      entry->lock--;
> -    if (entry->lock > 0 || pentry == NULL) {
> +    if (entry->lock > 0) {
>          return;
>      }
>  
> -    pentry->next = entry->next;
>      ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size);
>      if (munmap(entry->vaddr_base, entry->size) != 0) {
>          perror("unmap fails");
>          exit(-1);
>      }
> -    g_free(entry->valid_mapping);
> -    g_free(entry);
> +    if (pentry) {
> +        pentry->next = entry->next;
> +        g_free(entry->valid_mapping);
> +        g_free(entry);
> +    } else {
> +        memset(entry, 0, sizeof *entry);
> +    }
>  }
>  
>  typedef struct XenMapCacheData {
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache()
  2024-04-30 16:49 ` [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache() Edgar E. Iglesias
  2024-05-01 16:48   ` Peter Xu
@ 2024-05-01 21:03   ` Stefano Stabellini
  2024-05-02  7:24   ` David Hildenbrand
  2024-05-06  9:56   ` Philippe Mathieu-Daudé
  3 siblings, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 21:03 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, Peter Xu,
	David Hildenbrand, Philippe Mathieu-Daudé, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Propagate MR and is_write to xen_map_cache().
> This is in preparation for adding support for grant mappings.
> 
> No functional change.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/xen/xen-mapcache.c         | 10 ++++++----
>  include/sysemu/xen-mapcache.h | 11 +++++++----
>  system/physmem.c              | 31 +++++++++++++++++++++++--------
>  3 files changed, 36 insertions(+), 16 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 0365311788..09b5f36d9c 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -264,7 +264,7 @@ static void xen_remap_bucket(MapCache *mc,
>  
>  static uint8_t *xen_map_cache_unlocked(MapCache *mc,
>                                         hwaddr phys_addr, hwaddr size,
> -                                       uint8_t lock, bool dma)
> +                                       uint8_t lock, bool dma, bool is_write)
>  {
>      MapCacheEntry *entry, *pentry = NULL,
>                    *free_entry = NULL, *free_pentry = NULL;
> @@ -387,13 +387,15 @@ tryagain:
>      return mc->last_entry->vaddr_base + address_offset;
>  }
>  
> -uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
> -                       uint8_t lock, bool dma)
> +uint8_t *xen_map_cache(MemoryRegion *mr,
> +                       hwaddr phys_addr, hwaddr size,
> +                       uint8_t lock, bool dma,
> +                       bool is_write)
>  {
>      uint8_t *p;
>  
>      mapcache_lock(mapcache);
> -    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma);
> +    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma, is_write);
>      mapcache_unlock(mapcache);
>      return p;
>  }
> diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
> index 10c2e3082a..1ec9e66752 100644
> --- a/include/sysemu/xen-mapcache.h
> +++ b/include/sysemu/xen-mapcache.h
> @@ -18,8 +18,9 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
>  
>  void xen_map_cache_init(phys_offset_to_gaddr_t f,
>                          void *opaque);
> -uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
> -                       uint8_t lock, bool dma);
> +uint8_t *xen_map_cache(MemoryRegion *mr, hwaddr phys_addr, hwaddr size,
> +                       uint8_t lock, bool dma,
> +                       bool is_write);
>  ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
>  void xen_invalidate_map_cache_entry(uint8_t *buffer);
>  void xen_invalidate_map_cache(void);
> @@ -33,10 +34,12 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
>  {
>  }
>  
> -static inline uint8_t *xen_map_cache(hwaddr phys_addr,
> +static inline uint8_t *xen_map_cache(MemoryRegion *mr,
> +                                     hwaddr phys_addr,
>                                       hwaddr size,
>                                       uint8_t lock,
> -                                     bool dma)
> +                                     bool dma,
> +                                     bool is_write)
>  {
>      abort();
>  }
> diff --git a/system/physmem.c b/system/physmem.c
> index f114b972a5..ad7a8c7d95 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -2190,11 +2190,22 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
>  
>  /*
>   * Return a host pointer to guest's ram.
> + * For Xen, foreign mappings get created if they don't already exist.
> + *
> + * @block: block for the RAM to lookup (optional and may be NULL).
> + * @addr: address within the memory region.
> + * @size: pointer to requested size (optional and may be NULL).
> + *        size may get modified and return a value smaller than
> + *        what was requested.
> + * @lock: wether to lock the mapping in xen-mapcache until invalidated.
> + * @is_write: hint wether to map RW or RO in the xen-mapcache.
> + *            (optional and may always be set to true).
>   *
>   * Called within RCU critical section.
>   */
>  static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
> -                                 hwaddr *size, bool lock)
> +                                 hwaddr *size, bool lock,
> +                                 bool is_write)
>  {
>      hwaddr len = 0;
>  
> @@ -2217,10 +2228,13 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
>           * In that case just map the requested area.
>           */
>          if (block->offset == 0) {
> -            return xen_map_cache(addr, len, lock, lock);
> +            return xen_map_cache(block->mr, addr, len, lock, lock,
> +                                 is_write);
>          }
>  
> -        block->host = xen_map_cache(block->offset, block->max_length, 1, lock);
> +        block->host = xen_map_cache(block->mr, block->offset,
> +                                    block->max_length, 1,
> +                                    lock, is_write);
>      }
>  
>      return ramblock_ptr(block, addr);
> @@ -2236,7 +2250,7 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
>   */
>  void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
>  {
> -    return qemu_ram_ptr_length(ram_block, addr, NULL, false);
> +    return qemu_ram_ptr_length(ram_block, addr, NULL, false, true);
>  }
>  
>  /* Return the offset of a hostpointer within a ramblock */
> @@ -2746,7 +2760,7 @@ static MemTxResult flatview_write_continue_step(MemTxAttrs attrs,
>      } else {
>          /* RAM case */
>          uint8_t *ram_ptr = qemu_ram_ptr_length(mr->ram_block, mr_addr, l,
> -                                               false);
> +                                               false, true);
>  
>          memmove(ram_ptr, buf, *l);
>          invalidate_and_set_dirty(mr, mr_addr, *l);
> @@ -2839,7 +2853,7 @@ static MemTxResult flatview_read_continue_step(MemTxAttrs attrs, uint8_t *buf,
>      } else {
>          /* RAM case */
>          uint8_t *ram_ptr = qemu_ram_ptr_length(mr->ram_block, mr_addr, l,
> -                                               false);
> +                                               false, false);
>  
>          memcpy(buf, ram_ptr, *l);
>  
> @@ -3233,7 +3247,7 @@ void *address_space_map(AddressSpace *as,
>      *plen = flatview_extend_translation(fv, addr, len, mr, xlat,
>                                          l, is_write, attrs);
>      fuzz_dma_read_cb(addr, *plen, mr);
> -    return qemu_ram_ptr_length(mr->ram_block, xlat, plen, true);
> +    return qemu_ram_ptr_length(mr->ram_block, xlat, plen, true, is_write);
>  }
>  
>  /* Unmaps a memory region previously mapped by address_space_map().
> @@ -3329,7 +3343,8 @@ int64_t address_space_cache_init(MemoryRegionCache *cache,
>          l = flatview_extend_translation(cache->fv, addr, len, mr,
>                                          cache->xlat, l, is_write,
>                                          MEMTXATTRS_UNSPECIFIED);
> -        cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, &l, true);
> +        cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, &l, true,
> +                                         is_write);
>      } else {
>          cache->ptr = NULL;
>      }
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 14/17] xen: Add xen_mr_is_memory()
  2024-04-30 16:49 ` [PATCH v4 14/17] xen: Add xen_mr_is_memory() Edgar E. Iglesias
@ 2024-05-01 21:06   ` Stefano Stabellini
  2024-05-02  7:26   ` David Hildenbrand
  1 sibling, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 21:06 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, Peter Xu,
	David Hildenbrand, Philippe Mathieu-Daudé, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Add xen_mr_is_memory() to abstract away tests for the
> xen_memory MR.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

There is an important change in this patch below


> ---
>  hw/xen/xen-hvm-common.c | 8 +++++++-
>  include/sysemu/xen.h    | 8 ++++++++
>  system/physmem.c        | 2 +-
>  3 files changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
> index 1627da7398..0267b88d26 100644
> --- a/hw/xen/xen-hvm-common.c
> +++ b/hw/xen/xen-hvm-common.c
> @@ -12,6 +12,12 @@
>  
>  MemoryRegion xen_memory;
>  
> +/* Check for xen memory.  */
> +bool xen_mr_is_memory(MemoryRegion *mr)
> +{
> +    return mr == &xen_memory;
> +}
> +
>  void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
>                     Error **errp)
>  {
> @@ -28,7 +34,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
>          return;
>      }
>  
> -    if (mr == &xen_memory) {
> +    if (xen_mr_is_memory(mr)) {
>          return;
>      }
>  
> diff --git a/include/sysemu/xen.h b/include/sysemu/xen.h
> index 754ec2e6cb..dc72f83bcb 100644
> --- a/include/sysemu/xen.h
> +++ b/include/sysemu/xen.h
> @@ -34,6 +34,8 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length);
>  void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
>                     struct MemoryRegion *mr, Error **errp);
>  
> +bool xen_mr_is_memory(MemoryRegion *mr);
> +
>  #else /* !CONFIG_XEN_IS_POSSIBLE */
>  
>  #define xen_enabled() 0
> @@ -47,6 +49,12 @@ static inline void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
>      g_assert_not_reached();
>  }
>  
> +static inline bool xen_mr_is_memory(MemoryRegion *mr)
> +{
> +    g_assert_not_reached();
> +    return false;
> +}
> +
>  #endif /* CONFIG_XEN_IS_POSSIBLE */
>  
>  #endif
> diff --git a/system/physmem.c b/system/physmem.c
> index ad7a8c7d95..1a5ffcba2a 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -2227,7 +2227,7 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
>           * because we don't want to map the entire memory in QEMU.
>           * In that case just map the requested area.
>           */
> -        if (block->offset == 0) {
> +        if (xen_mr_is_memory(block->mr)) {

This changes this check from block->offset == 0 to block->mr ==
&xen_memory. I think that's correct in all cases (x86 machines, ARM
machines) but I wanted to highlight it.

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>





>              return xen_map_cache(block->mr, addr, len, lock, lock,
>                                   is_write);
>          }
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset
  2024-04-30 16:49 ` [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset Edgar E. Iglesias
@ 2024-05-01 21:24   ` Stefano Stabellini
  2024-05-02  7:22     ` Edgar E. Iglesias
  0 siblings, 1 reply; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 21:24 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, Peter Xu,
	David Hildenbrand, Philippe Mathieu-Daudé, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> The current mapcache assumes that all memory is mapped
> in a single RAM MR (the first one with offset 0). Remove
> this assumption and propagate the offset to the mapcache
> so it can do reverse mappings (from hostptr -> ram_addr).
> 
> This is in preparation for adding grant mappings.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>


Looking at xen_remap_bucket, it is only using address_index (without
adding ram_offset) to map foreign memory. From xen_remap_bucket, I would
understand that address_index already includes the ram_offset.

Meaning that if we want to map foreign mapping at address 0x5000, then
address_index would be 0x5000, even if ram_offset is 0x1000.

But then looking xen_ram_addr_from_mapcache_single ram_offset is added
to paddr_index to calculate the physical address. So in that case we
would want address_index to be 0x4000 and ram_offset to be 0x1000. But
xen_remap_bucket would have to sum address_index and ram_offset to map
foreign memory.

So I am a bit confused, did I get it wrong? One more comment below.


> ---
>  hw/xen/xen-mapcache.c         | 25 ++++++++++++++++++-------
>  include/sysemu/xen-mapcache.h |  2 ++
>  system/physmem.c              |  8 ++++----
>  3 files changed, 24 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 09b5f36d9c..1b32d0c003 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -43,6 +43,9 @@ typedef struct MapCacheEntry {
>  #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
>      uint8_t flags;
>      hwaddr size;
> +
> +    /* Keep ram_addr offset for reverse mappings (hostptr -> ram_addr).  */
> +    ram_addr_t ram_offset;
>      struct MapCacheEntry *next;
>  } MapCacheEntry;
>  
> @@ -165,7 +168,8 @@ static void xen_remap_bucket(MapCache *mc,
>                               void *vaddr,
>                               hwaddr size,
>                               hwaddr address_index,
> -                             bool dummy)
> +                             bool dummy,
> +                             ram_addr_t ram_offset)
>  {
>      uint8_t *vaddr_base;
>      xen_pfn_t *pfns;
> @@ -244,6 +248,7 @@ static void xen_remap_bucket(MapCache *mc,
>      entry->size = size;
>      entry->valid_mapping = g_new0(unsigned long,
>                                    BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
> +    entry->ram_offset = ram_offset;
>  
>      if (dummy) {
>          entry->flags |= XEN_MAPCACHE_ENTRY_DUMMY;
> @@ -264,6 +269,7 @@ static void xen_remap_bucket(MapCache *mc,
>  
>  static uint8_t *xen_map_cache_unlocked(MapCache *mc,
>                                         hwaddr phys_addr, hwaddr size,
> +                                       ram_addr_t ram_offset,
>                                         uint8_t lock, bool dma, bool is_write)
>  {
>      MapCacheEntry *entry, *pentry = NULL,
> @@ -335,14 +341,16 @@ tryagain:
>      if (!entry) {
>          entry = g_new0(MapCacheEntry, 1);
>          pentry->next = entry;
> -        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> +        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> +                         ram_offset);
>      } else if (!entry->lock) {
>          if (!entry->vaddr_base || entry->paddr_index != address_index ||
>                  entry->size != cache_size ||
>                  !test_bits(address_offset >> XC_PAGE_SHIFT,
>                      test_bit_size >> XC_PAGE_SHIFT,
>                      entry->valid_mapping)) {
> -            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> +            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> +                             ram_offset);
>          }
>      }
>  
> @@ -389,13 +397,15 @@ tryagain:
>  
>  uint8_t *xen_map_cache(MemoryRegion *mr,
>                         hwaddr phys_addr, hwaddr size,
> +                       ram_addr_t ram_addr_offset,
>                         uint8_t lock, bool dma,
>                         bool is_write)
>  {
>      uint8_t *p;
>  
>      mapcache_lock(mapcache);
> -    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma, is_write);
> +    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
> +                               lock, dma, is_write);
>      mapcache_unlock(mapcache);
>      return p;
>  }
> @@ -432,7 +442,8 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
>          raddr = RAM_ADDR_INVALID;
>      } else {
>          raddr = (reventry->paddr_index << mc->bucket_shift) +
> -             ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
> +             ((unsigned long) ptr - (unsigned long) entry->vaddr_base) +
> +             entry->ram_offset;
>      }
>      mapcache_unlock(mc);
>      return raddr;
> @@ -627,8 +638,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
>  
>      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
>  
> -    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
> -                     cache_size, address_index, false);
> +    xen_remap_bucket(mc, entry, entry->vaddr_base,
> +                     cache_size, address_index, false, entry->ram_offset);
>      if (!test_bits(address_offset >> XC_PAGE_SHIFT,
>                  test_bit_size >> XC_PAGE_SHIFT,
>                  entry->valid_mapping)) {
> diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
> index 1ec9e66752..b5e3ea1bc0 100644
> --- a/include/sysemu/xen-mapcache.h
> +++ b/include/sysemu/xen-mapcache.h
> @@ -19,6 +19,7 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
>  void xen_map_cache_init(phys_offset_to_gaddr_t f,
>                          void *opaque);
>  uint8_t *xen_map_cache(MemoryRegion *mr, hwaddr phys_addr, hwaddr size,
> +                       ram_addr_t ram_addr_offset,
>                         uint8_t lock, bool dma,
>                         bool is_write);
>  ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
> @@ -37,6 +38,7 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
>  static inline uint8_t *xen_map_cache(MemoryRegion *mr,
>                                       hwaddr phys_addr,
>                                       hwaddr size,
> +                                     ram_addr_t ram_addr_offset,
>                                       uint8_t lock,
>                                       bool dma,
>                                       bool is_write)
> diff --git a/system/physmem.c b/system/physmem.c
> index 1a5ffcba2a..5b16eeccca 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -2228,13 +2228,13 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
>           * In that case just map the requested area.
>           */
>          if (xen_mr_is_memory(block->mr)) {
> -            return xen_map_cache(block->mr, addr, len, lock, lock,
> -                                 is_write);
> +            return xen_map_cache(block->mr, addr, len, block->offset,
> +                                 lock, lock, is_write);

Have you considered not tracking offset and address separately and
simply do this?

            return xen_map_cache(block->mr, addr + block->offset, len, 
                                 lock, lock, is_write);


>          }
>  
>          block->host = xen_map_cache(block->mr, block->offset,
> -                                    block->max_length, 1,
> -                                    lock, is_write);
> +                                    block->max_length, 0,
> +                                    1, lock, is_write);
>      }
>  
>      return ramblock_ptr(block, addr);
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 17/17] hw/arm: xen: Enable use of grant mappings
  2024-04-30 16:49 ` [PATCH v4 17/17] hw/arm: xen: Enable use of " Edgar E. Iglesias
@ 2024-05-01 22:11   ` Stefano Stabellini
  0 siblings, 0 replies; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-01 22:11 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias, Peter Maydell,
	qemu-arm

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
>  hw/arm/xen_arm.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index 15fa7dfa84..6fad829ede 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -125,6 +125,11 @@ static void xen_init_ram(MachineState *machine)
>                                   GUEST_RAM1_BASE, ram_size[1]);
>          memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, &ram_hi);
>      }
> +
> +    /* Setup support for grants.  */
> +    memory_region_init_ram(&xen_grants, NULL, "xen.grants", block_len,
> +                           &error_fatal);
> +    memory_region_add_subregion(sysmem, XEN_GRANT_ADDR_OFF, &xen_grants);
>  }
>  
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 07/17] xen: mapcache: Refactor xen_replace_cache_entry_unlocked
  2024-05-01 20:46   ` Stefano Stabellini
@ 2024-05-02  6:32     ` Edgar E. Iglesias
  2024-05-06 10:21       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-05-02  6:32 UTC (permalink / raw
  To: Stefano Stabellini
  Cc: qemu-devel, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On Wed, May 1, 2024 at 10:46 PM Stefano Stabellini
<sstabellini@kernel.org> wrote:
>
> On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> >
> > Add MapCache argument to xen_replace_cache_entry_unlocked in
> > preparation for supporting multiple map caches.
> >
> > No functional change.
> >
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> > ---
> >  hw/xen/xen-mapcache.c | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > index d2deff70c8..6e758eff94 100644
> > --- a/hw/xen/xen-mapcache.c
> > +++ b/hw/xen/xen-mapcache.c
> > @@ -556,7 +556,8 @@ void xen_invalidate_map_cache(void)
> >      mapcache_unlock(mapcache);
> >  }
> >
> > -static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
> > +static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> > +                                                 hwaddr old_phys_addr,
> >                                                   hwaddr new_phys_addr,
> >                                                   hwaddr size)
> >  {
> > @@ -578,7 +579,7 @@ static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
> >          cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE);
> >      }
> >
> > -    entry = &mapcache->entry[address_index % mapcache->nr_buckets];
> > +    entry = &mc->entry[address_index % mc->nr_buckets];
> >      while (entry && !(entry->paddr_index == address_index &&
> >                        entry->size == cache_size)) {
> >          entry = entry->next;
>
> There is still a global mapcache pointer in use in this function:
>
>   xen_remap_bucket(mapcache, entry, entry->vaddr_base,
>


Thanks! I had accidentally put the change to use mc in future patches.
Will fix in v5.

Cheers,
Edgar


>
> > @@ -614,7 +615,8 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
> >      uint8_t *p;
> >
> >      mapcache_lock(mapcache);
> > -    p = xen_replace_cache_entry_unlocked(old_phys_addr, new_phys_addr, size);
> > +    p = xen_replace_cache_entry_unlocked(mapcache, old_phys_addr,
> > +                                         new_phys_addr, size);
> >      mapcache_unlock(mapcache);
> >      return p;
> >  }
> > --
> > 2.40.1
> >


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset
  2024-05-01 21:24   ` Stefano Stabellini
@ 2024-05-02  7:22     ` Edgar E. Iglesias
  2024-05-02 18:53       ` Stefano Stabellini
  0 siblings, 1 reply; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-05-02  7:22 UTC (permalink / raw
  To: Stefano Stabellini
  Cc: qemu-devel, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, Paolo Bonzini, Peter Xu, David Hildenbrand,
	Philippe Mathieu-Daudé, xen-devel

On Wed, May 1, 2024 at 11:24 PM Stefano Stabellini
<sstabellini@kernel.org> wrote:
>
> On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> >
> > The current mapcache assumes that all memory is mapped
> > in a single RAM MR (the first one with offset 0). Remove
> > this assumption and propagate the offset to the mapcache
> > so it can do reverse mappings (from hostptr -> ram_addr).
> >
> > This is in preparation for adding grant mappings.
> >
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
>
>
> Looking at xen_remap_bucket, it is only using address_index (without
> adding ram_offset) to map foreign memory. From xen_remap_bucket, I would
> understand that address_index already includes the ram_offset.
>
> Meaning that if we want to map foreign mapping at address 0x5000, then
> address_index would be 0x5000, even if ram_offset is 0x1000.
>
> But then looking xen_ram_addr_from_mapcache_single ram_offset is added
> to paddr_index to calculate the physical address. So in that case we
> would want address_index to be 0x4000 and ram_offset to be 0x1000. But
> xen_remap_bucket would have to sum address_index and ram_offset to map
> foreign memory.
>
> So I am a bit confused, did I get it wrong? One more comment below.
>

Thanks Stefano,

I think the confusion is that this ram_addr_offset is not related to
guest address-space.
It's a QEMU internal thing and it shouldn't be included in the address
used to map foreign memory.
The mapcache can treat this ram_addr offset like a cookie that we keep
around to be able to do
reverse mappings from host pointers into ram_addr space
(xen_ram_addr_from_mapcache).

The current mapcache implementation works because we've really only
been using foreign mappings
on RAMBlocks with offset 0. We're also creating RAM's such that the
offset into the RAM is also
the guest physical address, for x86 this is natural since RAM starts
at zero (for lowmem) but for
ARM we're creating larger than needed RAM's (GUEST_RAM0_BASE + ram-size) to
make this assumption true. Anyway, In this series I'm not addressing
this second assumption.

There's a second call in physmem.c to xen_map_cache using the
block->offset as an address.
I was considering removing that second call since I can't see how it can work
(except perhaps in some specific use-case by luck?). Anyway, for now
I've left it unmodified.


>
> > ---
> >  hw/xen/xen-mapcache.c         | 25 ++++++++++++++++++-------
> >  include/sysemu/xen-mapcache.h |  2 ++
> >  system/physmem.c              |  8 ++++----
> >  3 files changed, 24 insertions(+), 11 deletions(-)
> >
> > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > index 09b5f36d9c..1b32d0c003 100644
> > --- a/hw/xen/xen-mapcache.c
> > +++ b/hw/xen/xen-mapcache.c
> > @@ -43,6 +43,9 @@ typedef struct MapCacheEntry {
> >  #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
> >      uint8_t flags;
> >      hwaddr size;
> > +
> > +    /* Keep ram_addr offset for reverse mappings (hostptr -> ram_addr).  */
> > +    ram_addr_t ram_offset;
> >      struct MapCacheEntry *next;
> >  } MapCacheEntry;
> >
> > @@ -165,7 +168,8 @@ static void xen_remap_bucket(MapCache *mc,
> >                               void *vaddr,
> >                               hwaddr size,
> >                               hwaddr address_index,
> > -                             bool dummy)
> > +                             bool dummy,
> > +                             ram_addr_t ram_offset)
> >  {
> >      uint8_t *vaddr_base;
> >      xen_pfn_t *pfns;
> > @@ -244,6 +248,7 @@ static void xen_remap_bucket(MapCache *mc,
> >      entry->size = size;
> >      entry->valid_mapping = g_new0(unsigned long,
> >                                    BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
> > +    entry->ram_offset = ram_offset;
> >
> >      if (dummy) {
> >          entry->flags |= XEN_MAPCACHE_ENTRY_DUMMY;
> > @@ -264,6 +269,7 @@ static void xen_remap_bucket(MapCache *mc,
> >
> >  static uint8_t *xen_map_cache_unlocked(MapCache *mc,
> >                                         hwaddr phys_addr, hwaddr size,
> > +                                       ram_addr_t ram_offset,
> >                                         uint8_t lock, bool dma, bool is_write)
> >  {
> >      MapCacheEntry *entry, *pentry = NULL,
> > @@ -335,14 +341,16 @@ tryagain:
> >      if (!entry) {
> >          entry = g_new0(MapCacheEntry, 1);
> >          pentry->next = entry;
> > -        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > +        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > +                         ram_offset);
> >      } else if (!entry->lock) {
> >          if (!entry->vaddr_base || entry->paddr_index != address_index ||
> >                  entry->size != cache_size ||
> >                  !test_bits(address_offset >> XC_PAGE_SHIFT,
> >                      test_bit_size >> XC_PAGE_SHIFT,
> >                      entry->valid_mapping)) {
> > -            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > +            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > +                             ram_offset);
> >          }
> >      }
> >
> > @@ -389,13 +397,15 @@ tryagain:
> >
> >  uint8_t *xen_map_cache(MemoryRegion *mr,
> >                         hwaddr phys_addr, hwaddr size,
> > +                       ram_addr_t ram_addr_offset,
> >                         uint8_t lock, bool dma,
> >                         bool is_write)
> >  {
> >      uint8_t *p;
> >
> >      mapcache_lock(mapcache);
> > -    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma, is_write);
> > +    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
> > +                               lock, dma, is_write);
> >      mapcache_unlock(mapcache);
> >      return p;
> >  }
> > @@ -432,7 +442,8 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
> >          raddr = RAM_ADDR_INVALID;
> >      } else {
> >          raddr = (reventry->paddr_index << mc->bucket_shift) +
> > -             ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
> > +             ((unsigned long) ptr - (unsigned long) entry->vaddr_base) +
> > +             entry->ram_offset;
> >      }
> >      mapcache_unlock(mc);
> >      return raddr;
> > @@ -627,8 +638,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> >
> >      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
> >
> > -    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
> > -                     cache_size, address_index, false);
> > +    xen_remap_bucket(mc, entry, entry->vaddr_base,
> > +                     cache_size, address_index, false, entry->ram_offset);
> >      if (!test_bits(address_offset >> XC_PAGE_SHIFT,
> >                  test_bit_size >> XC_PAGE_SHIFT,
> >                  entry->valid_mapping)) {
> > diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
> > index 1ec9e66752..b5e3ea1bc0 100644
> > --- a/include/sysemu/xen-mapcache.h
> > +++ b/include/sysemu/xen-mapcache.h
> > @@ -19,6 +19,7 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
> >  void xen_map_cache_init(phys_offset_to_gaddr_t f,
> >                          void *opaque);
> >  uint8_t *xen_map_cache(MemoryRegion *mr, hwaddr phys_addr, hwaddr size,
> > +                       ram_addr_t ram_addr_offset,
> >                         uint8_t lock, bool dma,
> >                         bool is_write);
> >  ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
> > @@ -37,6 +38,7 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
> >  static inline uint8_t *xen_map_cache(MemoryRegion *mr,
> >                                       hwaddr phys_addr,
> >                                       hwaddr size,
> > +                                     ram_addr_t ram_addr_offset,
> >                                       uint8_t lock,
> >                                       bool dma,
> >                                       bool is_write)
> > diff --git a/system/physmem.c b/system/physmem.c
> > index 1a5ffcba2a..5b16eeccca 100644
> > --- a/system/physmem.c
> > +++ b/system/physmem.c
> > @@ -2228,13 +2228,13 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
> >           * In that case just map the requested area.
> >           */
> >          if (xen_mr_is_memory(block->mr)) {
> > -            return xen_map_cache(block->mr, addr, len, lock, lock,
> > -                                 is_write);
> > +            return xen_map_cache(block->mr, addr, len, block->offset,
> > +                                 lock, lock, is_write);
>
> Have you considered not tracking offset and address separately and
> simply do this?
>
>             return xen_map_cache(block->mr, addr + block->offset, len,
>                                  lock, lock, is_write);
>

Unfortunately this won't work since block->offset is not related to where this
ram is mapped in guest address-space. In the case of grant's, we'd get the
wrong grant ref. See my previous comment.

Cheers,
Edgar


>
> >          }
> >
> >          block->host = xen_map_cache(block->mr, block->offset,
> > -                                    block->max_length, 1,
> > -                                    lock, is_write);
> > +                                    block->max_length, 0,
> > +                                    1, lock, is_write);
> >      }
> >
> >      return ramblock_ptr(block, addr);
> > --
> > 2.40.1
> >


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache()
  2024-04-30 16:49 ` [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache() Edgar E. Iglesias
  2024-05-01 16:48   ` Peter Xu
  2024-05-01 21:03   ` Stefano Stabellini
@ 2024-05-02  7:24   ` David Hildenbrand
  2024-05-02  7:31     ` Edgar E. Iglesias
  2024-05-06  9:56   ` Philippe Mathieu-Daudé
  3 siblings, 1 reply; 58+ messages in thread
From: David Hildenbrand @ 2024-05-02  7:24 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, Paolo Bonzini, Peter Xu,
	Philippe Mathieu-Daudé, xen-devel

On 30.04.24 18:49, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Propagate MR and is_write to xen_map_cache().

I'm pretty sure the patch subject is missing a "to" :)

> This is in preparation for adding support for grant mappings.
> 
> No functional change.
> 

Reviewed-by: David Hildenbrand <david@redhat.com>
-- 
Cheers,

David / dhildenb



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 14/17] xen: Add xen_mr_is_memory()
  2024-04-30 16:49 ` [PATCH v4 14/17] xen: Add xen_mr_is_memory() Edgar E. Iglesias
  2024-05-01 21:06   ` Stefano Stabellini
@ 2024-05-02  7:26   ` David Hildenbrand
  2024-05-06  9:59     ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 58+ messages in thread
From: David Hildenbrand @ 2024-05-02  7:26 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, Paolo Bonzini, Peter Xu,
	Philippe Mathieu-Daudé, xen-devel

On 30.04.24 18:49, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Add xen_mr_is_memory() to abstract away tests for the
> xen_memory MR.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---

[...]

>   #endif
> diff --git a/system/physmem.c b/system/physmem.c
> index ad7a8c7d95..1a5ffcba2a 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -2227,7 +2227,7 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
>            * because we don't want to map the entire memory in QEMU.
>            * In that case just map the requested area.
>            */
> -        if (block->offset == 0) {
> +        if (xen_mr_is_memory(block->mr)) {
>               return xen_map_cache(block->mr, addr, len, lock, lock,
>                                    is_write);
>           }

I'd have moved that into a separate patch, because this is not a simple 
abstraction here.

Acked-by: David Hildenbrand <david@redhat.com>

-- 
Cheers,

David / dhildenb



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache()
  2024-05-02  7:24   ` David Hildenbrand
@ 2024-05-02  7:31     ` Edgar E. Iglesias
  0 siblings, 0 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-05-02  7:31 UTC (permalink / raw
  To: David Hildenbrand
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, Peter Xu,
	Philippe Mathieu-Daudé, xen-devel

On Thu, May 2, 2024 at 9:24 AM David Hildenbrand <david@redhat.com> wrote:
>
> On 30.04.24 18:49, Edgar E. Iglesias wrote:
> > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> >
> > Propagate MR and is_write to xen_map_cache().
>
> I'm pretty sure the patch subject is missing a "to" :)

Thanks David! I'll fix it in v5!

Cheers,
Edgar


>
> > This is in preparation for adding support for grant mappings.
> >
> > No functional change.
> >
>
> Reviewed-by: David Hildenbrand <david@redhat.com>
> --
> Cheers,
>
> David / dhildenb
>


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 12/17] xen: mapcache: Unmap first entries in buckets
  2024-04-30 16:49 ` [PATCH v4 12/17] xen: mapcache: Unmap first entries in buckets Edgar E. Iglesias
  2024-05-01 21:01   ` Stefano Stabellini
@ 2024-05-02  7:34   ` Edgar E. Iglesias
  1 sibling, 0 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-05-02  7:34 UTC (permalink / raw
  To: qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On Tue, Apr 30, 2024 at 6:50 PM Edgar E. Iglesias
<edgar.iglesias@gmail.com> wrote:
>
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
>
> When invalidating memory ranges, if we happen to hit the first
> entry in a bucket we were never unmapping it. This was harmless
> for foreign mappings but now that we're looking to reuse the
> mapcache for transient grant mappings, we must unmap entries
> when invalidated.
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>  hw/xen/xen-mapcache.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 4f98d284dd..0365311788 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -486,18 +486,22 @@ static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
>          return;
>      }
>      entry->lock--;
> -    if (entry->lock > 0 || pentry == NULL) {
> +    if (entry->lock > 0) {
>          return;
>      }
>
> -    pentry->next = entry->next;
>      ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size);
>      if (munmap(entry->vaddr_base, entry->size) != 0) {
>          perror("unmap fails");
>          exit(-1);
>      }
> -    g_free(entry->valid_mapping);
> -    g_free(entry);
> +    if (pentry) {
> +        pentry->next = entry->next;
> +        g_free(entry->valid_mapping);
> +        g_free(entry);
> +    } else {
> +        memset(entry, 0, sizeof *entry);

I noticed that we're leaking entry->valid_mapping here. I'll fix this for v5.

Cheers,
Edgar


> +    }
>  }
>
>  typedef struct XenMapCacheData {
> --
> 2.40.1
>


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset
  2024-05-02  7:22     ` Edgar E. Iglesias
@ 2024-05-02 18:53       ` Stefano Stabellini
  2024-05-02 19:42         ` Edgar E. Iglesias
  0 siblings, 1 reply; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-02 18:53 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: Stefano Stabellini, qemu-devel, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, Peter Xu,
	David Hildenbrand, Philippe Mathieu-Daudé, xen-devel,
	Xenia.Ragiadakou

[-- Attachment #1: Type: text/plain, Size: 11064 bytes --]

+Xenia

On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> On Wed, May 1, 2024 at 11:24 PM Stefano Stabellini
> <sstabellini@kernel.org> wrote:
> >
> > On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> > >
> > > The current mapcache assumes that all memory is mapped
> > > in a single RAM MR (the first one with offset 0). Remove
> > > this assumption and propagate the offset to the mapcache
> > > so it can do reverse mappings (from hostptr -> ram_addr).
> > >
> > > This is in preparation for adding grant mappings.
> > >
> > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> >
> >
> > Looking at xen_remap_bucket, it is only using address_index (without
> > adding ram_offset) to map foreign memory. From xen_remap_bucket, I would
> > understand that address_index already includes the ram_offset.
> >
> > Meaning that if we want to map foreign mapping at address 0x5000, then
> > address_index would be 0x5000, even if ram_offset is 0x1000.
> >
> > But then looking xen_ram_addr_from_mapcache_single ram_offset is added
> > to paddr_index to calculate the physical address. So in that case we
> > would want address_index to be 0x4000 and ram_offset to be 0x1000. But
> > xen_remap_bucket would have to sum address_index and ram_offset to map
> > foreign memory.
> >
> > So I am a bit confused, did I get it wrong? One more comment below.
> >
> 
> Thanks Stefano,
> 
> I think the confusion is that this ram_addr_offset is not related to
> guest address-space.
> It's a QEMU internal thing and it shouldn't be included in the address
> used to map foreign memory.
> The mapcache can treat this ram_addr offset like a cookie that we keep
> around to be able to do
> reverse mappings from host pointers into ram_addr space
> (xen_ram_addr_from_mapcache).
> 
> The current mapcache implementation works because we've really only
> been using foreign mappings
> on RAMBlocks with offset 0. We're also creating RAM's such that the
> offset into the RAM is also
> the guest physical address, for x86 this is natural since RAM starts
> at zero (for lowmem) but for
> ARM we're creating larger than needed RAM's (GUEST_RAM0_BASE + ram-size) to
> make this assumption true. Anyway, In this series I'm not addressing
> this second assumption.

Let's see if I understand correctly.

The ram_addr space is an internal QEMU address space which is different
from the guest physical address space and thus cannot and should not be
used to do foreign mappings (foreign mapping hypercalls take a guest
physical or a real physical address to map). Is that correct?

If so, then I understand.



> There's a second call in physmem.c to xen_map_cache using the
> block->offset as an address.
> I was considering removing that second call since I can't see how it can work
> (except perhaps in some specific use-case by luck?). Anyway, for now
> I've left it unmodified.

Yes, that code was written with the assumption that block->offset is an
offset in the guest physical address space and could be used as a guest
physical address. Actually, you might have spotted a real bug.
 
The intent was for smaller regions (not the bit RAM region, things like
a ROM region for instance) we could map them in full. So here we were
trying to map the whole thing from start to finish using block->offset
as start.


> > > ---
> > >  hw/xen/xen-mapcache.c         | 25 ++++++++++++++++++-------
> > >  include/sysemu/xen-mapcache.h |  2 ++
> > >  system/physmem.c              |  8 ++++----
> > >  3 files changed, 24 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > > index 09b5f36d9c..1b32d0c003 100644
> > > --- a/hw/xen/xen-mapcache.c
> > > +++ b/hw/xen/xen-mapcache.c
> > > @@ -43,6 +43,9 @@ typedef struct MapCacheEntry {
> > >  #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
> > >      uint8_t flags;
> > >      hwaddr size;
> > > +
> > > +    /* Keep ram_addr offset for reverse mappings (hostptr -> ram_addr).  */
> > > +    ram_addr_t ram_offset;
> > >      struct MapCacheEntry *next;
> > >  } MapCacheEntry;
> > >
> > > @@ -165,7 +168,8 @@ static void xen_remap_bucket(MapCache *mc,
> > >                               void *vaddr,
> > >                               hwaddr size,
> > >                               hwaddr address_index,
> > > -                             bool dummy)
> > > +                             bool dummy,
> > > +                             ram_addr_t ram_offset)
> > >  {
> > >      uint8_t *vaddr_base;
> > >      xen_pfn_t *pfns;
> > > @@ -244,6 +248,7 @@ static void xen_remap_bucket(MapCache *mc,
> > >      entry->size = size;
> > >      entry->valid_mapping = g_new0(unsigned long,
> > >                                    BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
> > > +    entry->ram_offset = ram_offset;
> > >
> > >      if (dummy) {
> > >          entry->flags |= XEN_MAPCACHE_ENTRY_DUMMY;
> > > @@ -264,6 +269,7 @@ static void xen_remap_bucket(MapCache *mc,
> > >
> > >  static uint8_t *xen_map_cache_unlocked(MapCache *mc,
> > >                                         hwaddr phys_addr, hwaddr size,
> > > +                                       ram_addr_t ram_offset,
> > >                                         uint8_t lock, bool dma, bool is_write)
> > >  {
> > >      MapCacheEntry *entry, *pentry = NULL,
> > > @@ -335,14 +341,16 @@ tryagain:
> > >      if (!entry) {
> > >          entry = g_new0(MapCacheEntry, 1);
> > >          pentry->next = entry;
> > > -        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > > +        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > > +                         ram_offset);
> > >      } else if (!entry->lock) {
> > >          if (!entry->vaddr_base || entry->paddr_index != address_index ||
> > >                  entry->size != cache_size ||
> > >                  !test_bits(address_offset >> XC_PAGE_SHIFT,
> > >                      test_bit_size >> XC_PAGE_SHIFT,
> > >                      entry->valid_mapping)) {
> > > -            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > > +            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > > +                             ram_offset);
> > >          }
> > >      }
> > >
> > > @@ -389,13 +397,15 @@ tryagain:
> > >
> > >  uint8_t *xen_map_cache(MemoryRegion *mr,
> > >                         hwaddr phys_addr, hwaddr size,
> > > +                       ram_addr_t ram_addr_offset,
> > >                         uint8_t lock, bool dma,
> > >                         bool is_write)
> > >  {
> > >      uint8_t *p;
> > >
> > >      mapcache_lock(mapcache);
> > > -    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma, is_write);
> > > +    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
> > > +                               lock, dma, is_write);
> > >      mapcache_unlock(mapcache);
> > >      return p;
> > >  }
> > > @@ -432,7 +442,8 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
> > >          raddr = RAM_ADDR_INVALID;
> > >      } else {
> > >          raddr = (reventry->paddr_index << mc->bucket_shift) +
> > > -             ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
> > > +             ((unsigned long) ptr - (unsigned long) entry->vaddr_base) +
> > > +             entry->ram_offset;
> > >      }
> > >      mapcache_unlock(mc);
> > >      return raddr;
> > > @@ -627,8 +638,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> > >
> > >      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
> > >
> > > -    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
> > > -                     cache_size, address_index, false);
> > > +    xen_remap_bucket(mc, entry, entry->vaddr_base,
> > > +                     cache_size, address_index, false, entry->ram_offset);
> > >      if (!test_bits(address_offset >> XC_PAGE_SHIFT,
> > >                  test_bit_size >> XC_PAGE_SHIFT,
> > >                  entry->valid_mapping)) {
> > > diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
> > > index 1ec9e66752..b5e3ea1bc0 100644
> > > --- a/include/sysemu/xen-mapcache.h
> > > +++ b/include/sysemu/xen-mapcache.h
> > > @@ -19,6 +19,7 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
> > >  void xen_map_cache_init(phys_offset_to_gaddr_t f,
> > >                          void *opaque);
> > >  uint8_t *xen_map_cache(MemoryRegion *mr, hwaddr phys_addr, hwaddr size,
> > > +                       ram_addr_t ram_addr_offset,
> > >                         uint8_t lock, bool dma,
> > >                         bool is_write);
> > >  ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
> > > @@ -37,6 +38,7 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
> > >  static inline uint8_t *xen_map_cache(MemoryRegion *mr,
> > >                                       hwaddr phys_addr,
> > >                                       hwaddr size,
> > > +                                     ram_addr_t ram_addr_offset,
> > >                                       uint8_t lock,
> > >                                       bool dma,
> > >                                       bool is_write)
> > > diff --git a/system/physmem.c b/system/physmem.c
> > > index 1a5ffcba2a..5b16eeccca 100644
> > > --- a/system/physmem.c
> > > +++ b/system/physmem.c
> > > @@ -2228,13 +2228,13 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
> > >           * In that case just map the requested area.
> > >           */
> > >          if (xen_mr_is_memory(block->mr)) {
> > > -            return xen_map_cache(block->mr, addr, len, lock, lock,
> > > -                                 is_write);
> > > +            return xen_map_cache(block->mr, addr, len, block->offset,
> > > +                                 lock, lock, is_write);
> >
> > Have you considered not tracking offset and address separately and
> > simply do this?
> >
> >             return xen_map_cache(block->mr, addr + block->offset, len,
> >                                  lock, lock, is_write);
> >
> 
> Unfortunately this won't work since block->offset is not related to where this
> ram is mapped in guest address-space. In the case of grant's, we'd get the
> wrong grant ref. See my previous comment.

OK, this code below (the second xen_map_cache call passing block->offset
as start address) was wrong before this patch. Can we fix it before
changing it further with this patch? I worry about making things even
worse.


> > >          }
> > >
> > >          block->host = xen_map_cache(block->mr, block->offset,
> > > -                                    block->max_length, 1,
> > > -                                    lock, is_write);
> > > +                                    block->max_length, 0,
> > > +                                    1, lock, is_write);
> > >      }
> > >
> > >      return ramblock_ptr(block, addr);
> > > --
> > > 2.40.1
> > >
> 

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 16/17] xen: mapcache: Add support for grant mappings
  2024-04-30 16:49 ` [PATCH v4 16/17] xen: mapcache: Add support for grant mappings Edgar E. Iglesias
@ 2024-05-02 19:18   ` Stefano Stabellini
  2024-05-02 19:49     ` Edgar E. Iglesias
  0 siblings, 1 reply; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-02 19:18 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: qemu-devel, sstabellini, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, xen-devel

On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Add a second mapcache for grant mappings. The mapcache for
> grants needs to work with XC_PAGE_SIZE granularity since
> we can't map larger ranges than what has been granted to us.
> 
> Like with foreign mappings (xen_memory), machines using grants
> are expected to initialize the xen_grants MR and map it
> into their address-map accordingly.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>  hw/xen/xen-hvm-common.c         |  12 ++-
>  hw/xen/xen-mapcache.c           | 158 +++++++++++++++++++++++++-------
>  include/hw/xen/xen-hvm-common.h |   3 +
>  include/sysemu/xen.h            |   7 ++
>  4 files changed, 145 insertions(+), 35 deletions(-)
> 
> diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
> index 0267b88d26..fdec400491 100644
> --- a/hw/xen/xen-hvm-common.c
> +++ b/hw/xen/xen-hvm-common.c
> @@ -10,12 +10,18 @@
>  #include "hw/boards.h"
>  #include "hw/xen/arch_hvm.h"
>  
> -MemoryRegion xen_memory;
> +MemoryRegion xen_memory, xen_grants;
>  
> -/* Check for xen memory.  */
> +/* Check for any kind of xen memory, foreign mappings or grants.  */
>  bool xen_mr_is_memory(MemoryRegion *mr)
>  {
> -    return mr == &xen_memory;
> +    return mr == &xen_memory || mr == &xen_grants;
> +}
> +
> +/* Check specifically for grants.  */
> +bool xen_mr_is_grants(MemoryRegion *mr)
> +{
> +    return mr == &xen_grants;
>  }
>  
>  void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 1b32d0c003..96cd68e28d 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -14,6 +14,7 @@
>  
>  #include <sys/resource.h>
>  
> +#include "hw/xen/xen-hvm-common.h"
>  #include "hw/xen/xen_native.h"
>  #include "qemu/bitmap.h"
>  
> @@ -21,6 +22,8 @@
>  #include "sysemu/xen-mapcache.h"
>  #include "trace.h"
>  
> +#include <xenevtchn.h>
> +#include <xengnttab.h>
>  
>  #if HOST_LONG_BITS == 32
>  #  define MCACHE_MAX_SIZE     (1UL<<31) /* 2GB Cap */
> @@ -41,6 +44,7 @@ typedef struct MapCacheEntry {
>      unsigned long *valid_mapping;
>      uint32_t lock;
>  #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
> +#define XEN_MAPCACHE_ENTRY_GRANT (1 << 1)
>      uint8_t flags;
>      hwaddr size;
>  
> @@ -74,6 +78,8 @@ typedef struct MapCache {
>  } MapCache;
>  
>  static MapCache *mapcache;
> +static MapCache *mapcache_grants;
> +static xengnttab_handle *xen_region_gnttabdev;
>  
>  static inline void mapcache_lock(MapCache *mc)
>  {
> @@ -132,6 +138,12 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
>      unsigned long max_mcache_size;
>      unsigned int bucket_shift;
>  
> +    xen_region_gnttabdev = xengnttab_open(NULL, 0);
> +    if (xen_region_gnttabdev == NULL) {
> +        error_report("mapcache: Failed to open gnttab device");
> +        exit(EXIT_FAILURE);
> +    }
> +
>      if (HOST_LONG_BITS == 32) {
>          bucket_shift = 16;
>      } else {
> @@ -160,6 +172,15 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
>      mapcache = xen_map_cache_init_single(f, opaque,
>                                           bucket_shift,
>                                           max_mcache_size);
> +
> +    /*
> +     * Grant mappings must use XC_PAGE_SIZE granularity since we can't
> +     * map anything beyond the number of pages granted to us.
> +     */
> +    mapcache_grants = xen_map_cache_init_single(f, opaque,
> +                                                XC_PAGE_SHIFT,
> +                                                max_mcache_size);
> +
>      setrlimit(RLIMIT_AS, &rlimit_as);
>  }
>  
> @@ -169,17 +190,25 @@ static void xen_remap_bucket(MapCache *mc,
>                               hwaddr size,
>                               hwaddr address_index,
>                               bool dummy,
> +                             bool grant,
> +                             bool grant_is_write,
> +                             hwaddr grant_ref,
>                               ram_addr_t ram_offset)

Any chance we could pass grant_ref as address_index ?

Also instead of grant_is_write we could have a generic is_write that
applies to both.

I am not sure about this, but instead of bool grant, we could check on
address_index using XEN_GRANT_ADDR_OFF? This one might not work.

I admit that there is no real advantage on these suggestions except to
consolidate the parameters and make them look a bit more similar in the
two cases.



>  {
>      uint8_t *vaddr_base;
> -    xen_pfn_t *pfns;
> +    uint32_t *refs = NULL;
> +    xen_pfn_t *pfns = NULL;
>      int *err;
>      unsigned int i;
>      hwaddr nb_pfn = size >> XC_PAGE_SHIFT;
>  
>      trace_xen_remap_bucket(address_index);
>  
> -    pfns = g_new0(xen_pfn_t, nb_pfn);
> +    if (grant) {
> +        refs = g_new0(uint32_t, nb_pfn);
> +    } else {
> +        pfns = g_new0(xen_pfn_t, nb_pfn);
> +    }
>      err = g_new0(int, nb_pfn);
>  
>      if (entry->vaddr_base != NULL) {
> @@ -208,21 +237,45 @@ static void xen_remap_bucket(MapCache *mc,
>      g_free(entry->valid_mapping);
>      entry->valid_mapping = NULL;
>  
> -    for (i = 0; i < nb_pfn; i++) {
> -        pfns[i] = (address_index << (mc->bucket_shift - XC_PAGE_SHIFT)) + i;
> +    if (grant) {
> +        for (i = 0; i < nb_pfn; i++) {
> +            refs[i] = grant_ref + i;
> +        }
> +    } else {
> +        for (i = 0; i < nb_pfn; i++) {
> +            pfns[i] = (address_index << (mc->bucket_shift - XC_PAGE_SHIFT)) + i;
> +        }
>      }
>  
> -    /*
> -     * If the caller has requested the mapping at a specific address use
> -     * MAP_FIXED to make sure it's honored.
> -     */
> +    entry->flags &= ~XEN_MAPCACHE_ENTRY_GRANT;
> +
>      if (!dummy) {
> -        vaddr_base = xenforeignmemory_map2(xen_fmem, xen_domid, vaddr,
> -                                           PROT_READ | PROT_WRITE,
> -                                           vaddr ? MAP_FIXED : 0,
> -                                           nb_pfn, pfns, err);
> +        if (grant) {
> +            int prot = PROT_READ;
> +
> +            if (grant_is_write) {
> +                prot |= PROT_WRITE;
> +            }
> +
> +            entry->flags |= XEN_MAPCACHE_ENTRY_GRANT;
> +            assert(vaddr == NULL);
> +            vaddr_base = xengnttab_map_domain_grant_refs(xen_region_gnttabdev,
> +                                                         nb_pfn,
> +                                                         xen_domid, refs,
> +                                                         prot);
> +        } else {
> +            /*
> +             * If the caller has requested the mapping at a specific address use
> +             * MAP_FIXED to make sure it's honored.
> +             */
> +            vaddr_base = xenforeignmemory_map2(xen_fmem, xen_domid, vaddr,
> +                                               PROT_READ | PROT_WRITE,
> +                                               vaddr ? MAP_FIXED : 0,
> +                                               nb_pfn, pfns, err);
> +        }
>          if (vaddr_base == NULL) {
> -            perror("xenforeignmemory_map2");
> +            perror(grant ? "xengnttab_map_domain_grant_refs"
> +                           : "xenforeignmemory_map2");
>              exit(-1);
>          }
>      } else {
> @@ -263,6 +316,7 @@ static void xen_remap_bucket(MapCache *mc,
>          }
>      }
>  
> +    g_free(refs);
>      g_free(pfns);
>      g_free(err);
>  }
> @@ -270,10 +324,12 @@ static void xen_remap_bucket(MapCache *mc,
>  static uint8_t *xen_map_cache_unlocked(MapCache *mc,
>                                         hwaddr phys_addr, hwaddr size,
>                                         ram_addr_t ram_offset,
> -                                       uint8_t lock, bool dma, bool is_write)
> +                                       uint8_t lock, bool dma,
> +                                       bool grant, bool is_write)
>  {
>      MapCacheEntry *entry, *pentry = NULL,
>                    *free_entry = NULL, *free_pentry = NULL;
> +    hwaddr grant_ref = phys_addr >> XC_PAGE_SHIFT;
>      hwaddr address_index;
>      hwaddr address_offset;
>      hwaddr cache_size = size;
> @@ -342,7 +398,7 @@ tryagain:
>          entry = g_new0(MapCacheEntry, 1);
>          pentry->next = entry;
>          xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> -                         ram_offset);
> +                         grant, is_write, grant_ref, ram_offset);
>      } else if (!entry->lock) {
>          if (!entry->vaddr_base || entry->paddr_index != address_index ||
>                  entry->size != cache_size ||
> @@ -350,7 +406,7 @@ tryagain:
>                      test_bit_size >> XC_PAGE_SHIFT,
>                      entry->valid_mapping)) {
>              xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> -                             ram_offset);
> +                             grant, is_write, grant_ref, ram_offset);
>          }
>      }
>  
> @@ -401,12 +457,28 @@ uint8_t *xen_map_cache(MemoryRegion *mr,
>                         uint8_t lock, bool dma,
>                         bool is_write)
>  {
> +    bool grant = xen_mr_is_grants(mr);
> +    MapCache *mc = grant ? mapcache_grants : mapcache;
>      uint8_t *p;
>  
> -    mapcache_lock(mapcache);
> -    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
> -                               lock, dma, is_write);
> -    mapcache_unlock(mapcache);
> +    if (grant) {
> +        /*
> +         * Grants are only supported via address_space_map(). Anything
> +         * else is considered a user/guest error.
> +         *
> +         * QEMU generally doesn't expect these mappings to ever fail, so
> +         * if this happens we report an error message and abort().
> +         */
> +        if (!lock) {
> +            error_report("Trying access a grant reference without mapping it.");
> +            abort();
> +        }
> +    }
> +
> +    mapcache_lock(mc);
> +    p = xen_map_cache_unlocked(mc, phys_addr, size, ram_addr_offset,
> +                               lock, dma, grant, is_write);
> +    mapcache_unlock(mc);
>      return p;
>  }
>  
> @@ -451,7 +523,14 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
>  
>  ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>  {
> -    return xen_ram_addr_from_mapcache_single(mapcache, ptr);
> +    ram_addr_t addr;
> +
> +    addr = xen_ram_addr_from_mapcache_single(mapcache, ptr);
> +    if (addr == RAM_ADDR_INVALID) {
> +        addr = xen_ram_addr_from_mapcache_single(mapcache_grants, ptr);
> +    }
> +
> +    return addr;
>  }
>  
>  static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
> @@ -504,9 +583,14 @@ static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
>      }
>  
>      ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size);
> -    if (munmap(entry->vaddr_base, entry->size) != 0) {
> -        perror("unmap fails");
> -        exit(-1);
> +    if (entry->flags & XEN_MAPCACHE_ENTRY_GRANT) {
> +        xengnttab_unmap(xen_region_gnttabdev, entry->vaddr_base,
> +                    (entry->size + mc->bucket_size - 1) >> mc->bucket_shift);

Am I getting this right that the + mc->bucket_size - 1 is unnecessary
because the bucket size is PAGE_SIZE and we can only map at page
granularity?

Also can we check for return errors?


> +    } else {
> +        if (munmap(entry->vaddr_base, entry->size) != 0) {
> +            perror("unmap fails");
> +            exit(-1);
> +        }
>      }
>      if (pentry) {
>          pentry->next = entry->next;
> @@ -522,14 +606,24 @@ typedef struct XenMapCacheData {
>      uint8_t *buffer;
>  } XenMapCacheData;
>  
> +static void xen_invalidate_map_cache_entry_single(MapCache *mc, uint8_t *buffer)
> +{
> +    mapcache_lock(mc);
> +    xen_invalidate_map_cache_entry_unlocked(mc, buffer);
> +    mapcache_unlock(mc);
> +}
> +
> +static void xen_invalidate_map_cache_entry_all(uint8_t *buffer)
> +{
> +    xen_invalidate_map_cache_entry_single(mapcache, buffer);
> +    xen_invalidate_map_cache_entry_single(mapcache_grants, buffer);
> +}
> +
>  static void xen_invalidate_map_cache_entry_bh(void *opaque)
>  {
>      XenMapCacheData *data = opaque;
>  
> -    mapcache_lock(mapcache);
> -    xen_invalidate_map_cache_entry_unlocked(mapcache, data->buffer);
> -    mapcache_unlock(mapcache);
> -
> +    xen_invalidate_map_cache_entry_all(data->buffer);
>      aio_co_wake(data->co);
>  }
>  
> @@ -544,9 +638,7 @@ void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
>                                  xen_invalidate_map_cache_entry_bh, &data);
>          qemu_coroutine_yield();
>      } else {
> -        mapcache_lock(mapcache);
> -        xen_invalidate_map_cache_entry_unlocked(mapcache, buffer);
> -        mapcache_unlock(mapcache);
> +        xen_invalidate_map_cache_entry_all(buffer);
>      }
>  }
>  
> @@ -598,6 +690,7 @@ void xen_invalidate_map_cache(void)
>      bdrv_drain_all();
>  
>      xen_invalidate_map_cache_single(mapcache);
> +    xen_invalidate_map_cache_single(mapcache_grants);
>  }
>  
>  static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> @@ -639,7 +732,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
>      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
>  
>      xen_remap_bucket(mc, entry, entry->vaddr_base,
> -                     cache_size, address_index, false, entry->ram_offset);
> +                     cache_size, address_index, false,
> +                     false, false, 0, entry->ram_offset);

If I understand correctly, xen_replace_cache_entry_unlocked cannot be
called on grants because xen_replace_cache_entry_unlocked is always
called on unlocked entries while grants are always locked. Should we
have an assert on !entry->lock and/or !(entry->flags & XEN_MAPCACHE_ENTRY_GRANT)?



>      if (!test_bits(address_offset >> XC_PAGE_SHIFT,
>                  test_bit_size >> XC_PAGE_SHIFT,
>                  entry->valid_mapping)) {
> diff --git a/include/hw/xen/xen-hvm-common.h b/include/hw/xen/xen-hvm-common.h
> index 65a51aac2e..3d796235dc 100644
> --- a/include/hw/xen/xen-hvm-common.h
> +++ b/include/hw/xen/xen-hvm-common.h
> @@ -16,6 +16,7 @@
>  #include <xen/hvm/ioreq.h>
>  
>  extern MemoryRegion xen_memory;
> +extern MemoryRegion xen_grants;
>  extern MemoryListener xen_io_listener;
>  extern DeviceListener xen_device_listener;
>  
> @@ -29,6 +30,8 @@ extern DeviceListener xen_device_listener;
>      do { } while (0)
>  #endif
>  
> +#define XEN_GRANT_ADDR_OFF (1ULL << 63)
> +
>  static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
>  {
>      return shared_page->vcpu_ioreq[i].vp_eport;
> diff --git a/include/sysemu/xen.h b/include/sysemu/xen.h
> index dc72f83bcb..19dccf4d71 100644
> --- a/include/sysemu/xen.h
> +++ b/include/sysemu/xen.h
> @@ -35,6 +35,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
>                     struct MemoryRegion *mr, Error **errp);
>  
>  bool xen_mr_is_memory(MemoryRegion *mr);
> +bool xen_mr_is_grants(MemoryRegion *mr);
>  
>  #else /* !CONFIG_XEN_IS_POSSIBLE */
>  
> @@ -55,6 +56,12 @@ static inline bool xen_mr_is_memory(MemoryRegion *mr)
>      return false;
>  }
>  
> +static inline bool xen_mr_is_grants(MemoryRegion *mr)
> +{
> +    g_assert_not_reached();
> +    return false;
> +}
> +
>  #endif /* CONFIG_XEN_IS_POSSIBLE */
>  
>  #endif
> -- 
> 2.40.1
> 


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset
  2024-05-02 18:53       ` Stefano Stabellini
@ 2024-05-02 19:42         ` Edgar E. Iglesias
  2024-05-02 20:02           ` Stefano Stabellini
  0 siblings, 1 reply; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-05-02 19:42 UTC (permalink / raw
  To: Stefano Stabellini
  Cc: qemu-devel, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, Paolo Bonzini, Peter Xu, David Hildenbrand,
	Philippe Mathieu-Daudé, xen-devel, Xenia.Ragiadakou

On Thu, May 2, 2024 at 8:53 PM Stefano Stabellini
<sstabellini@kernel.org> wrote:
>
> +Xenia
>
> On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> > On Wed, May 1, 2024 at 11:24 PM Stefano Stabellini
> > <sstabellini@kernel.org> wrote:
> > >
> > > On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > > > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> > > >
> > > > The current mapcache assumes that all memory is mapped
> > > > in a single RAM MR (the first one with offset 0). Remove
> > > > this assumption and propagate the offset to the mapcache
> > > > so it can do reverse mappings (from hostptr -> ram_addr).
> > > >
> > > > This is in preparation for adding grant mappings.
> > > >
> > > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> > >
> > >
> > > Looking at xen_remap_bucket, it is only using address_index (without
> > > adding ram_offset) to map foreign memory. From xen_remap_bucket, I would
> > > understand that address_index already includes the ram_offset.
> > >
> > > Meaning that if we want to map foreign mapping at address 0x5000, then
> > > address_index would be 0x5000, even if ram_offset is 0x1000.
> > >
> > > But then looking xen_ram_addr_from_mapcache_single ram_offset is added
> > > to paddr_index to calculate the physical address. So in that case we
> > > would want address_index to be 0x4000 and ram_offset to be 0x1000. But
> > > xen_remap_bucket would have to sum address_index and ram_offset to map
> > > foreign memory.
> > >
> > > So I am a bit confused, did I get it wrong? One more comment below.
> > >
> >
> > Thanks Stefano,
> >
> > I think the confusion is that this ram_addr_offset is not related to
> > guest address-space.
> > It's a QEMU internal thing and it shouldn't be included in the address
> > used to map foreign memory.
> > The mapcache can treat this ram_addr offset like a cookie that we keep
> > around to be able to do
> > reverse mappings from host pointers into ram_addr space
> > (xen_ram_addr_from_mapcache).
> >
> > The current mapcache implementation works because we've really only
> > been using foreign mappings
> > on RAMBlocks with offset 0. We're also creating RAM's such that the
> > offset into the RAM is also
> > the guest physical address, for x86 this is natural since RAM starts
> > at zero (for lowmem) but for
> > ARM we're creating larger than needed RAM's (GUEST_RAM0_BASE + ram-size) to
> > make this assumption true. Anyway, In this series I'm not addressing
> > this second assumption.
>
> Let's see if I understand correctly.
>
> The ram_addr space is an internal QEMU address space which is different
> from the guest physical address space and thus cannot and should not be
> used to do foreign mappings (foreign mapping hypercalls take a guest
> physical or a real physical address to map). Is that correct?
>
> If so, then I understand.
>

Yes, that matches my understanding.

>
>
> > There's a second call in physmem.c to xen_map_cache using the
> > block->offset as an address.
> > I was considering removing that second call since I can't see how it can work
> > (except perhaps in some specific use-case by luck?). Anyway, for now
> > I've left it unmodified.
>
> Yes, that code was written with the assumption that block->offset is an
> offset in the guest physical address space and could be used as a guest
> physical address. Actually, you might have spotted a real bug.
>
> The intent was for smaller regions (not the bit RAM region, things like
> a ROM region for instance) we could map them in full. So here we were
> trying to map the whole thing from start to finish using block->offset
> as start.
>
>
> > > > ---
> > > >  hw/xen/xen-mapcache.c         | 25 ++++++++++++++++++-------
> > > >  include/sysemu/xen-mapcache.h |  2 ++
> > > >  system/physmem.c              |  8 ++++----
> > > >  3 files changed, 24 insertions(+), 11 deletions(-)
> > > >
> > > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > > > index 09b5f36d9c..1b32d0c003 100644
> > > > --- a/hw/xen/xen-mapcache.c
> > > > +++ b/hw/xen/xen-mapcache.c
> > > > @@ -43,6 +43,9 @@ typedef struct MapCacheEntry {
> > > >  #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
> > > >      uint8_t flags;
> > > >      hwaddr size;
> > > > +
> > > > +    /* Keep ram_addr offset for reverse mappings (hostptr -> ram_addr).  */
> > > > +    ram_addr_t ram_offset;
> > > >      struct MapCacheEntry *next;
> > > >  } MapCacheEntry;
> > > >
> > > > @@ -165,7 +168,8 @@ static void xen_remap_bucket(MapCache *mc,
> > > >                               void *vaddr,
> > > >                               hwaddr size,
> > > >                               hwaddr address_index,
> > > > -                             bool dummy)
> > > > +                             bool dummy,
> > > > +                             ram_addr_t ram_offset)
> > > >  {
> > > >      uint8_t *vaddr_base;
> > > >      xen_pfn_t *pfns;
> > > > @@ -244,6 +248,7 @@ static void xen_remap_bucket(MapCache *mc,
> > > >      entry->size = size;
> > > >      entry->valid_mapping = g_new0(unsigned long,
> > > >                                    BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
> > > > +    entry->ram_offset = ram_offset;
> > > >
> > > >      if (dummy) {
> > > >          entry->flags |= XEN_MAPCACHE_ENTRY_DUMMY;
> > > > @@ -264,6 +269,7 @@ static void xen_remap_bucket(MapCache *mc,
> > > >
> > > >  static uint8_t *xen_map_cache_unlocked(MapCache *mc,
> > > >                                         hwaddr phys_addr, hwaddr size,
> > > > +                                       ram_addr_t ram_offset,
> > > >                                         uint8_t lock, bool dma, bool is_write)
> > > >  {
> > > >      MapCacheEntry *entry, *pentry = NULL,
> > > > @@ -335,14 +341,16 @@ tryagain:
> > > >      if (!entry) {
> > > >          entry = g_new0(MapCacheEntry, 1);
> > > >          pentry->next = entry;
> > > > -        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > > > +        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > > > +                         ram_offset);
> > > >      } else if (!entry->lock) {
> > > >          if (!entry->vaddr_base || entry->paddr_index != address_index ||
> > > >                  entry->size != cache_size ||
> > > >                  !test_bits(address_offset >> XC_PAGE_SHIFT,
> > > >                      test_bit_size >> XC_PAGE_SHIFT,
> > > >                      entry->valid_mapping)) {
> > > > -            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > > > +            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > > > +                             ram_offset);
> > > >          }
> > > >      }
> > > >
> > > > @@ -389,13 +397,15 @@ tryagain:
> > > >
> > > >  uint8_t *xen_map_cache(MemoryRegion *mr,
> > > >                         hwaddr phys_addr, hwaddr size,
> > > > +                       ram_addr_t ram_addr_offset,
> > > >                         uint8_t lock, bool dma,
> > > >                         bool is_write)
> > > >  {
> > > >      uint8_t *p;
> > > >
> > > >      mapcache_lock(mapcache);
> > > > -    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma, is_write);
> > > > +    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
> > > > +                               lock, dma, is_write);
> > > >      mapcache_unlock(mapcache);
> > > >      return p;
> > > >  }
> > > > @@ -432,7 +442,8 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
> > > >          raddr = RAM_ADDR_INVALID;
> > > >      } else {
> > > >          raddr = (reventry->paddr_index << mc->bucket_shift) +
> > > > -             ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
> > > > +             ((unsigned long) ptr - (unsigned long) entry->vaddr_base) +
> > > > +             entry->ram_offset;
> > > >      }
> > > >      mapcache_unlock(mc);
> > > >      return raddr;
> > > > @@ -627,8 +638,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> > > >
> > > >      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
> > > >
> > > > -    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
> > > > -                     cache_size, address_index, false);
> > > > +    xen_remap_bucket(mc, entry, entry->vaddr_base,
> > > > +                     cache_size, address_index, false, entry->ram_offset);
> > > >      if (!test_bits(address_offset >> XC_PAGE_SHIFT,
> > > >                  test_bit_size >> XC_PAGE_SHIFT,
> > > >                  entry->valid_mapping)) {
> > > > diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
> > > > index 1ec9e66752..b5e3ea1bc0 100644
> > > > --- a/include/sysemu/xen-mapcache.h
> > > > +++ b/include/sysemu/xen-mapcache.h
> > > > @@ -19,6 +19,7 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
> > > >  void xen_map_cache_init(phys_offset_to_gaddr_t f,
> > > >                          void *opaque);
> > > >  uint8_t *xen_map_cache(MemoryRegion *mr, hwaddr phys_addr, hwaddr size,
> > > > +                       ram_addr_t ram_addr_offset,
> > > >                         uint8_t lock, bool dma,
> > > >                         bool is_write);
> > > >  ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
> > > > @@ -37,6 +38,7 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
> > > >  static inline uint8_t *xen_map_cache(MemoryRegion *mr,
> > > >                                       hwaddr phys_addr,
> > > >                                       hwaddr size,
> > > > +                                     ram_addr_t ram_addr_offset,
> > > >                                       uint8_t lock,
> > > >                                       bool dma,
> > > >                                       bool is_write)
> > > > diff --git a/system/physmem.c b/system/physmem.c
> > > > index 1a5ffcba2a..5b16eeccca 100644
> > > > --- a/system/physmem.c
> > > > +++ b/system/physmem.c
> > > > @@ -2228,13 +2228,13 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
> > > >           * In that case just map the requested area.
> > > >           */
> > > >          if (xen_mr_is_memory(block->mr)) {
> > > > -            return xen_map_cache(block->mr, addr, len, lock, lock,
> > > > -                                 is_write);
> > > > +            return xen_map_cache(block->mr, addr, len, block->offset,
> > > > +                                 lock, lock, is_write);
> > >
> > > Have you considered not tracking offset and address separately and
> > > simply do this?
> > >
> > >             return xen_map_cache(block->mr, addr + block->offset, len,
> > >                                  lock, lock, is_write);
> > >
> >
> > Unfortunately this won't work since block->offset is not related to where this
> > ram is mapped in guest address-space. In the case of grant's, we'd get the
> > wrong grant ref. See my previous comment.
>
> OK, this code below (the second xen_map_cache call passing block->offset
> as start address) was wrong before this patch. Can we fix it before
> changing it further with this patch? I worry about making things even
> worse.
>

I'll dig around and see if we can find something that explains more.
There's some older code that implements some sort of address-translation
for x86 between ram_addr space and guest physical addresses but
that code is turned off with newer Xen versions (disabled in my build).

https://github.com/qemu/qemu/blob/master/hw/xen/xen-mapcache.c#L330
https://github.com/qemu/qemu/blob/master/hw/i386/xen/xen-hvm.c#L193

Cheers,
Edgar


> > > >          }
> > > >
> > > >          block->host = xen_map_cache(block->mr, block->offset,
> > > > -                                    block->max_length, 1,
> > > > -                                    lock, is_write);
> > > > +                                    block->max_length, 0,
> > > > +                                    1, lock, is_write);
> > > >      }
> > > >
> > > >      return ramblock_ptr(block, addr);
> > > > --
> > > > 2.40.1
> > > >
> >


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 16/17] xen: mapcache: Add support for grant mappings
  2024-05-02 19:18   ` Stefano Stabellini
@ 2024-05-02 19:49     ` Edgar E. Iglesias
  0 siblings, 0 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-05-02 19:49 UTC (permalink / raw
  To: Stefano Stabellini
  Cc: qemu-devel, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On Thu, May 2, 2024 at 9:18 PM Stefano Stabellini
<sstabellini@kernel.org> wrote:
>
> On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> >
> > Add a second mapcache for grant mappings. The mapcache for
> > grants needs to work with XC_PAGE_SIZE granularity since
> > we can't map larger ranges than what has been granted to us.
> >
> > Like with foreign mappings (xen_memory), machines using grants
> > are expected to initialize the xen_grants MR and map it
> > into their address-map accordingly.
> >
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> > ---
> >  hw/xen/xen-hvm-common.c         |  12 ++-
> >  hw/xen/xen-mapcache.c           | 158 +++++++++++++++++++++++++-------
> >  include/hw/xen/xen-hvm-common.h |   3 +
> >  include/sysemu/xen.h            |   7 ++
> >  4 files changed, 145 insertions(+), 35 deletions(-)
> >
> > diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
> > index 0267b88d26..fdec400491 100644
> > --- a/hw/xen/xen-hvm-common.c
> > +++ b/hw/xen/xen-hvm-common.c
> > @@ -10,12 +10,18 @@
> >  #include "hw/boards.h"
> >  #include "hw/xen/arch_hvm.h"
> >
> > -MemoryRegion xen_memory;
> > +MemoryRegion xen_memory, xen_grants;
> >
> > -/* Check for xen memory.  */
> > +/* Check for any kind of xen memory, foreign mappings or grants.  */
> >  bool xen_mr_is_memory(MemoryRegion *mr)
> >  {
> > -    return mr == &xen_memory;
> > +    return mr == &xen_memory || mr == &xen_grants;
> > +}
> > +
> > +/* Check specifically for grants.  */
> > +bool xen_mr_is_grants(MemoryRegion *mr)
> > +{
> > +    return mr == &xen_grants;
> >  }
> >
> >  void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
> > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > index 1b32d0c003..96cd68e28d 100644
> > --- a/hw/xen/xen-mapcache.c
> > +++ b/hw/xen/xen-mapcache.c
> > @@ -14,6 +14,7 @@
> >
> >  #include <sys/resource.h>
> >
> > +#include "hw/xen/xen-hvm-common.h"
> >  #include "hw/xen/xen_native.h"
> >  #include "qemu/bitmap.h"
> >
> > @@ -21,6 +22,8 @@
> >  #include "sysemu/xen-mapcache.h"
> >  #include "trace.h"
> >
> > +#include <xenevtchn.h>
> > +#include <xengnttab.h>
> >
> >  #if HOST_LONG_BITS == 32
> >  #  define MCACHE_MAX_SIZE     (1UL<<31) /* 2GB Cap */
> > @@ -41,6 +44,7 @@ typedef struct MapCacheEntry {
> >      unsigned long *valid_mapping;
> >      uint32_t lock;
> >  #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
> > +#define XEN_MAPCACHE_ENTRY_GRANT (1 << 1)
> >      uint8_t flags;
> >      hwaddr size;
> >
> > @@ -74,6 +78,8 @@ typedef struct MapCache {
> >  } MapCache;
> >
> >  static MapCache *mapcache;
> > +static MapCache *mapcache_grants;
> > +static xengnttab_handle *xen_region_gnttabdev;
> >
> >  static inline void mapcache_lock(MapCache *mc)
> >  {
> > @@ -132,6 +138,12 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
> >      unsigned long max_mcache_size;
> >      unsigned int bucket_shift;
> >
> > +    xen_region_gnttabdev = xengnttab_open(NULL, 0);
> > +    if (xen_region_gnttabdev == NULL) {
> > +        error_report("mapcache: Failed to open gnttab device");
> > +        exit(EXIT_FAILURE);
> > +    }
> > +
> >      if (HOST_LONG_BITS == 32) {
> >          bucket_shift = 16;
> >      } else {
> > @@ -160,6 +172,15 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
> >      mapcache = xen_map_cache_init_single(f, opaque,
> >                                           bucket_shift,
> >                                           max_mcache_size);
> > +
> > +    /*
> > +     * Grant mappings must use XC_PAGE_SIZE granularity since we can't
> > +     * map anything beyond the number of pages granted to us.
> > +     */
> > +    mapcache_grants = xen_map_cache_init_single(f, opaque,
> > +                                                XC_PAGE_SHIFT,
> > +                                                max_mcache_size);
> > +
> >      setrlimit(RLIMIT_AS, &rlimit_as);
> >  }
> >
> > @@ -169,17 +190,25 @@ static void xen_remap_bucket(MapCache *mc,
> >                               hwaddr size,
> >                               hwaddr address_index,
> >                               bool dummy,
> > +                             bool grant,
> > +                             bool grant_is_write,
> > +                             hwaddr grant_ref,
> >                               ram_addr_t ram_offset)
>
> Any chance we could pass grant_ref as address_index ?
>

Yes, good catch :-)
grant_ref is already the same as address_index.


> Also instead of grant_is_write we could have a generic is_write that
> applies to both.

Sounds good.

>
> I am not sure about this, but instead of bool grant, we could check on
> address_index using XEN_GRANT_ADDR_OFF? This one might not work.
>

Yeah, this won't work since we're only getting the offset into the
xen_grants memory region.

> I admit that there is no real advantage on these suggestions except to
> consolidate the parameters and make them look a bit more similar in the
> two cases.
>
>
>
> >  {
> >      uint8_t *vaddr_base;
> > -    xen_pfn_t *pfns;
> > +    uint32_t *refs = NULL;
> > +    xen_pfn_t *pfns = NULL;
> >      int *err;
> >      unsigned int i;
> >      hwaddr nb_pfn = size >> XC_PAGE_SHIFT;
> >
> >      trace_xen_remap_bucket(address_index);
> >
> > -    pfns = g_new0(xen_pfn_t, nb_pfn);
> > +    if (grant) {
> > +        refs = g_new0(uint32_t, nb_pfn);
> > +    } else {
> > +        pfns = g_new0(xen_pfn_t, nb_pfn);
> > +    }
> >      err = g_new0(int, nb_pfn);
> >
> >      if (entry->vaddr_base != NULL) {
> > @@ -208,21 +237,45 @@ static void xen_remap_bucket(MapCache *mc,
> >      g_free(entry->valid_mapping);
> >      entry->valid_mapping = NULL;
> >
> > -    for (i = 0; i < nb_pfn; i++) {
> > -        pfns[i] = (address_index << (mc->bucket_shift - XC_PAGE_SHIFT)) + i;
> > +    if (grant) {
> > +        for (i = 0; i < nb_pfn; i++) {
> > +            refs[i] = grant_ref + i;
> > +        }
> > +    } else {
> > +        for (i = 0; i < nb_pfn; i++) {
> > +            pfns[i] = (address_index << (mc->bucket_shift - XC_PAGE_SHIFT)) + i;
> > +        }
> >      }
> >
> > -    /*
> > -     * If the caller has requested the mapping at a specific address use
> > -     * MAP_FIXED to make sure it's honored.
> > -     */
> > +    entry->flags &= ~XEN_MAPCACHE_ENTRY_GRANT;
> > +
> >      if (!dummy) {
> > -        vaddr_base = xenforeignmemory_map2(xen_fmem, xen_domid, vaddr,
> > -                                           PROT_READ | PROT_WRITE,
> > -                                           vaddr ? MAP_FIXED : 0,
> > -                                           nb_pfn, pfns, err);
> > +        if (grant) {
> > +            int prot = PROT_READ;
> > +
> > +            if (grant_is_write) {
> > +                prot |= PROT_WRITE;
> > +            }
> > +
> > +            entry->flags |= XEN_MAPCACHE_ENTRY_GRANT;
> > +            assert(vaddr == NULL);
> > +            vaddr_base = xengnttab_map_domain_grant_refs(xen_region_gnttabdev,
> > +                                                         nb_pfn,
> > +                                                         xen_domid, refs,
> > +                                                         prot);
> > +        } else {
> > +            /*
> > +             * If the caller has requested the mapping at a specific address use
> > +             * MAP_FIXED to make sure it's honored.
> > +             */
> > +            vaddr_base = xenforeignmemory_map2(xen_fmem, xen_domid, vaddr,
> > +                                               PROT_READ | PROT_WRITE,
> > +                                               vaddr ? MAP_FIXED : 0,
> > +                                               nb_pfn, pfns, err);
> > +        }
> >          if (vaddr_base == NULL) {
> > -            perror("xenforeignmemory_map2");
> > +            perror(grant ? "xengnttab_map_domain_grant_refs"
> > +                           : "xenforeignmemory_map2");
> >              exit(-1);
> >          }
> >      } else {
> > @@ -263,6 +316,7 @@ static void xen_remap_bucket(MapCache *mc,
> >          }
> >      }
> >
> > +    g_free(refs);
> >      g_free(pfns);
> >      g_free(err);
> >  }
> > @@ -270,10 +324,12 @@ static void xen_remap_bucket(MapCache *mc,
> >  static uint8_t *xen_map_cache_unlocked(MapCache *mc,
> >                                         hwaddr phys_addr, hwaddr size,
> >                                         ram_addr_t ram_offset,
> > -                                       uint8_t lock, bool dma, bool is_write)
> > +                                       uint8_t lock, bool dma,
> > +                                       bool grant, bool is_write)
> >  {
> >      MapCacheEntry *entry, *pentry = NULL,
> >                    *free_entry = NULL, *free_pentry = NULL;
> > +    hwaddr grant_ref = phys_addr >> XC_PAGE_SHIFT;
> >      hwaddr address_index;
> >      hwaddr address_offset;
> >      hwaddr cache_size = size;
> > @@ -342,7 +398,7 @@ tryagain:
> >          entry = g_new0(MapCacheEntry, 1);
> >          pentry->next = entry;
> >          xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > -                         ram_offset);
> > +                         grant, is_write, grant_ref, ram_offset);
> >      } else if (!entry->lock) {
> >          if (!entry->vaddr_base || entry->paddr_index != address_index ||
> >                  entry->size != cache_size ||
> > @@ -350,7 +406,7 @@ tryagain:
> >                      test_bit_size >> XC_PAGE_SHIFT,
> >                      entry->valid_mapping)) {
> >              xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > -                             ram_offset);
> > +                             grant, is_write, grant_ref, ram_offset);
> >          }
> >      }
> >
> > @@ -401,12 +457,28 @@ uint8_t *xen_map_cache(MemoryRegion *mr,
> >                         uint8_t lock, bool dma,
> >                         bool is_write)
> >  {
> > +    bool grant = xen_mr_is_grants(mr);
> > +    MapCache *mc = grant ? mapcache_grants : mapcache;
> >      uint8_t *p;
> >
> > -    mapcache_lock(mapcache);
> > -    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
> > -                               lock, dma, is_write);
> > -    mapcache_unlock(mapcache);
> > +    if (grant) {
> > +        /*
> > +         * Grants are only supported via address_space_map(). Anything
> > +         * else is considered a user/guest error.
> > +         *
> > +         * QEMU generally doesn't expect these mappings to ever fail, so
> > +         * if this happens we report an error message and abort().
> > +         */
> > +        if (!lock) {
> > +            error_report("Trying access a grant reference without mapping it.");
> > +            abort();
> > +        }
> > +    }
> > +
> > +    mapcache_lock(mc);
> > +    p = xen_map_cache_unlocked(mc, phys_addr, size, ram_addr_offset,
> > +                               lock, dma, grant, is_write);
> > +    mapcache_unlock(mc);
> >      return p;
> >  }
> >
> > @@ -451,7 +523,14 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
> >
> >  ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
> >  {
> > -    return xen_ram_addr_from_mapcache_single(mapcache, ptr);
> > +    ram_addr_t addr;
> > +
> > +    addr = xen_ram_addr_from_mapcache_single(mapcache, ptr);
> > +    if (addr == RAM_ADDR_INVALID) {
> > +        addr = xen_ram_addr_from_mapcache_single(mapcache_grants, ptr);
> > +    }
> > +
> > +    return addr;
> >  }
> >
> >  static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
> > @@ -504,9 +583,14 @@ static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
> >      }
> >
> >      ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size);
> > -    if (munmap(entry->vaddr_base, entry->size) != 0) {
> > -        perror("unmap fails");
> > -        exit(-1);
> > +    if (entry->flags & XEN_MAPCACHE_ENTRY_GRANT) {
> > +        xengnttab_unmap(xen_region_gnttabdev, entry->vaddr_base,
> > +                    (entry->size + mc->bucket_size - 1) >> mc->bucket_shift);
>
> Am I getting this right that the + mc->bucket_size - 1 is unnecessary
> because the bucket size is PAGE_SIZE and we can only map at page
> granularity?
>

Yes, you're right.
I'll fix this up in the next version.


> Also can we check for return errors?

Yes, I'll add error checking.


>
>
> > +    } else {
> > +        if (munmap(entry->vaddr_base, entry->size) != 0) {
> > +            perror("unmap fails");
> > +            exit(-1);
> > +        }
> >      }
> >      if (pentry) {
> >          pentry->next = entry->next;
> > @@ -522,14 +606,24 @@ typedef struct XenMapCacheData {
> >      uint8_t *buffer;
> >  } XenMapCacheData;
> >
> > +static void xen_invalidate_map_cache_entry_single(MapCache *mc, uint8_t *buffer)
> > +{
> > +    mapcache_lock(mc);
> > +    xen_invalidate_map_cache_entry_unlocked(mc, buffer);
> > +    mapcache_unlock(mc);
> > +}
> > +
> > +static void xen_invalidate_map_cache_entry_all(uint8_t *buffer)
> > +{
> > +    xen_invalidate_map_cache_entry_single(mapcache, buffer);
> > +    xen_invalidate_map_cache_entry_single(mapcache_grants, buffer);
> > +}
> > +
> >  static void xen_invalidate_map_cache_entry_bh(void *opaque)
> >  {
> >      XenMapCacheData *data = opaque;
> >
> > -    mapcache_lock(mapcache);
> > -    xen_invalidate_map_cache_entry_unlocked(mapcache, data->buffer);
> > -    mapcache_unlock(mapcache);
> > -
> > +    xen_invalidate_map_cache_entry_all(data->buffer);
> >      aio_co_wake(data->co);
> >  }
> >
> > @@ -544,9 +638,7 @@ void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
> >                                  xen_invalidate_map_cache_entry_bh, &data);
> >          qemu_coroutine_yield();
> >      } else {
> > -        mapcache_lock(mapcache);
> > -        xen_invalidate_map_cache_entry_unlocked(mapcache, buffer);
> > -        mapcache_unlock(mapcache);
> > +        xen_invalidate_map_cache_entry_all(buffer);
> >      }
> >  }
> >
> > @@ -598,6 +690,7 @@ void xen_invalidate_map_cache(void)
> >      bdrv_drain_all();
> >
> >      xen_invalidate_map_cache_single(mapcache);
> > +    xen_invalidate_map_cache_single(mapcache_grants);
> >  }
> >
> >  static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> > @@ -639,7 +732,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> >      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
> >
> >      xen_remap_bucket(mc, entry, entry->vaddr_base,
> > -                     cache_size, address_index, false, entry->ram_offset);
> > +                     cache_size, address_index, false,
> > +                     false, false, 0, entry->ram_offset);
>
> If I understand correctly, xen_replace_cache_entry_unlocked cannot be
> called on grants because xen_replace_cache_entry_unlocked is always
> called on unlocked entries while grants are always locked. Should we
> have an assert on !entry->lock and/or !(entry->flags & XEN_MAPCACHE_ENTRY_GRANT)?
>

Sounds good, I'll add this in the next version as well.

>
>
> >      if (!test_bits(address_offset >> XC_PAGE_SHIFT,
> >                  test_bit_size >> XC_PAGE_SHIFT,
> >                  entry->valid_mapping)) {
> > diff --git a/include/hw/xen/xen-hvm-common.h b/include/hw/xen/xen-hvm-common.h
> > index 65a51aac2e..3d796235dc 100644
> > --- a/include/hw/xen/xen-hvm-common.h
> > +++ b/include/hw/xen/xen-hvm-common.h
> > @@ -16,6 +16,7 @@
> >  #include <xen/hvm/ioreq.h>
> >
> >  extern MemoryRegion xen_memory;
> > +extern MemoryRegion xen_grants;
> >  extern MemoryListener xen_io_listener;
> >  extern DeviceListener xen_device_listener;
> >
> > @@ -29,6 +30,8 @@ extern DeviceListener xen_device_listener;
> >      do { } while (0)
> >  #endif
> >
> > +#define XEN_GRANT_ADDR_OFF (1ULL << 63)
> > +
> >  static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
> >  {
> >      return shared_page->vcpu_ioreq[i].vp_eport;
> > diff --git a/include/sysemu/xen.h b/include/sysemu/xen.h
> > index dc72f83bcb..19dccf4d71 100644
> > --- a/include/sysemu/xen.h
> > +++ b/include/sysemu/xen.h
> > @@ -35,6 +35,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
> >                     struct MemoryRegion *mr, Error **errp);
> >
> >  bool xen_mr_is_memory(MemoryRegion *mr);
> > +bool xen_mr_is_grants(MemoryRegion *mr);
> >
> >  #else /* !CONFIG_XEN_IS_POSSIBLE */
> >
> > @@ -55,6 +56,12 @@ static inline bool xen_mr_is_memory(MemoryRegion *mr)
> >      return false;
> >  }
> >
> > +static inline bool xen_mr_is_grants(MemoryRegion *mr)
> > +{
> > +    g_assert_not_reached();
> > +    return false;
> > +}
> > +
> >  #endif /* CONFIG_XEN_IS_POSSIBLE */
> >
> >  #endif
> > --
> > 2.40.1
> >


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset
  2024-05-02 19:42         ` Edgar E. Iglesias
@ 2024-05-02 20:02           ` Stefano Stabellini
  2024-05-07 17:18             ` Edgar E. Iglesias
  0 siblings, 1 reply; 58+ messages in thread
From: Stefano Stabellini @ 2024-05-02 20:02 UTC (permalink / raw
  To: Edgar E. Iglesias
  Cc: Stefano Stabellini, qemu-devel, jgross, Edgar E. Iglesias,
	Anthony Perard, Paul Durrant, Paolo Bonzini, Peter Xu,
	David Hildenbrand, Philippe Mathieu-Daudé, xen-devel,
	Xenia.Ragiadakou

[-- Attachment #1: Type: text/plain, Size: 12298 bytes --]

On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> On Thu, May 2, 2024 at 8:53 PM Stefano Stabellini
> <sstabellini@kernel.org> wrote:
> >
> > +Xenia
> >
> > On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> > > On Wed, May 1, 2024 at 11:24 PM Stefano Stabellini
> > > <sstabellini@kernel.org> wrote:
> > > >
> > > > On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > > > > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> > > > >
> > > > > The current mapcache assumes that all memory is mapped
> > > > > in a single RAM MR (the first one with offset 0). Remove
> > > > > this assumption and propagate the offset to the mapcache
> > > > > so it can do reverse mappings (from hostptr -> ram_addr).
> > > > >
> > > > > This is in preparation for adding grant mappings.
> > > > >
> > > > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> > > >
> > > >
> > > > Looking at xen_remap_bucket, it is only using address_index (without
> > > > adding ram_offset) to map foreign memory. From xen_remap_bucket, I would
> > > > understand that address_index already includes the ram_offset.
> > > >
> > > > Meaning that if we want to map foreign mapping at address 0x5000, then
> > > > address_index would be 0x5000, even if ram_offset is 0x1000.
> > > >
> > > > But then looking xen_ram_addr_from_mapcache_single ram_offset is added
> > > > to paddr_index to calculate the physical address. So in that case we
> > > > would want address_index to be 0x4000 and ram_offset to be 0x1000. But
> > > > xen_remap_bucket would have to sum address_index and ram_offset to map
> > > > foreign memory.
> > > >
> > > > So I am a bit confused, did I get it wrong? One more comment below.
> > > >
> > >
> > > Thanks Stefano,
> > >
> > > I think the confusion is that this ram_addr_offset is not related to
> > > guest address-space.
> > > It's a QEMU internal thing and it shouldn't be included in the address
> > > used to map foreign memory.
> > > The mapcache can treat this ram_addr offset like a cookie that we keep
> > > around to be able to do
> > > reverse mappings from host pointers into ram_addr space
> > > (xen_ram_addr_from_mapcache).
> > >
> > > The current mapcache implementation works because we've really only
> > > been using foreign mappings
> > > on RAMBlocks with offset 0. We're also creating RAM's such that the
> > > offset into the RAM is also
> > > the guest physical address, for x86 this is natural since RAM starts
> > > at zero (for lowmem) but for
> > > ARM we're creating larger than needed RAM's (GUEST_RAM0_BASE + ram-size) to
> > > make this assumption true. Anyway, In this series I'm not addressing
> > > this second assumption.
> >
> > Let's see if I understand correctly.
> >
> > The ram_addr space is an internal QEMU address space which is different
> > from the guest physical address space and thus cannot and should not be
> > used to do foreign mappings (foreign mapping hypercalls take a guest
> > physical or a real physical address to map). Is that correct?
> >
> > If so, then I understand.
> >
> 
> Yes, that matches my understanding.
> 
> >
> >
> > > There's a second call in physmem.c to xen_map_cache using the
> > > block->offset as an address.
> > > I was considering removing that second call since I can't see how it can work
> > > (except perhaps in some specific use-case by luck?). Anyway, for now
> > > I've left it unmodified.
> >
> > Yes, that code was written with the assumption that block->offset is an
> > offset in the guest physical address space and could be used as a guest
> > physical address. Actually, you might have spotted a real bug.
> >
> > The intent was for smaller regions (not the bit RAM region, things like
> > a ROM region for instance) we could map them in full. So here we were
> > trying to map the whole thing from start to finish using block->offset
> > as start.
> >
> >
> > > > > ---
> > > > >  hw/xen/xen-mapcache.c         | 25 ++++++++++++++++++-------
> > > > >  include/sysemu/xen-mapcache.h |  2 ++
> > > > >  system/physmem.c              |  8 ++++----
> > > > >  3 files changed, 24 insertions(+), 11 deletions(-)
> > > > >
> > > > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > > > > index 09b5f36d9c..1b32d0c003 100644
> > > > > --- a/hw/xen/xen-mapcache.c
> > > > > +++ b/hw/xen/xen-mapcache.c
> > > > > @@ -43,6 +43,9 @@ typedef struct MapCacheEntry {
> > > > >  #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
> > > > >      uint8_t flags;
> > > > >      hwaddr size;
> > > > > +
> > > > > +    /* Keep ram_addr offset for reverse mappings (hostptr -> ram_addr).  */
> > > > > +    ram_addr_t ram_offset;
> > > > >      struct MapCacheEntry *next;
> > > > >  } MapCacheEntry;
> > > > >
> > > > > @@ -165,7 +168,8 @@ static void xen_remap_bucket(MapCache *mc,
> > > > >                               void *vaddr,
> > > > >                               hwaddr size,
> > > > >                               hwaddr address_index,
> > > > > -                             bool dummy)
> > > > > +                             bool dummy,
> > > > > +                             ram_addr_t ram_offset)
> > > > >  {
> > > > >      uint8_t *vaddr_base;
> > > > >      xen_pfn_t *pfns;
> > > > > @@ -244,6 +248,7 @@ static void xen_remap_bucket(MapCache *mc,
> > > > >      entry->size = size;
> > > > >      entry->valid_mapping = g_new0(unsigned long,
> > > > >                                    BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
> > > > > +    entry->ram_offset = ram_offset;
> > > > >
> > > > >      if (dummy) {
> > > > >          entry->flags |= XEN_MAPCACHE_ENTRY_DUMMY;
> > > > > @@ -264,6 +269,7 @@ static void xen_remap_bucket(MapCache *mc,
> > > > >
> > > > >  static uint8_t *xen_map_cache_unlocked(MapCache *mc,
> > > > >                                         hwaddr phys_addr, hwaddr size,
> > > > > +                                       ram_addr_t ram_offset,
> > > > >                                         uint8_t lock, bool dma, bool is_write)
> > > > >  {
> > > > >      MapCacheEntry *entry, *pentry = NULL,
> > > > > @@ -335,14 +341,16 @@ tryagain:
> > > > >      if (!entry) {
> > > > >          entry = g_new0(MapCacheEntry, 1);
> > > > >          pentry->next = entry;
> > > > > -        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > > > > +        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > > > > +                         ram_offset);
> > > > >      } else if (!entry->lock) {
> > > > >          if (!entry->vaddr_base || entry->paddr_index != address_index ||
> > > > >                  entry->size != cache_size ||
> > > > >                  !test_bits(address_offset >> XC_PAGE_SHIFT,
> > > > >                      test_bit_size >> XC_PAGE_SHIFT,
> > > > >                      entry->valid_mapping)) {
> > > > > -            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > > > > +            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > > > > +                             ram_offset);
> > > > >          }
> > > > >      }
> > > > >
> > > > > @@ -389,13 +397,15 @@ tryagain:
> > > > >
> > > > >  uint8_t *xen_map_cache(MemoryRegion *mr,
> > > > >                         hwaddr phys_addr, hwaddr size,
> > > > > +                       ram_addr_t ram_addr_offset,
> > > > >                         uint8_t lock, bool dma,
> > > > >                         bool is_write)
> > > > >  {
> > > > >      uint8_t *p;
> > > > >
> > > > >      mapcache_lock(mapcache);
> > > > > -    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma, is_write);
> > > > > +    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
> > > > > +                               lock, dma, is_write);
> > > > >      mapcache_unlock(mapcache);
> > > > >      return p;
> > > > >  }
> > > > > @@ -432,7 +442,8 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
> > > > >          raddr = RAM_ADDR_INVALID;
> > > > >      } else {
> > > > >          raddr = (reventry->paddr_index << mc->bucket_shift) +
> > > > > -             ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
> > > > > +             ((unsigned long) ptr - (unsigned long) entry->vaddr_base) +
> > > > > +             entry->ram_offset;
> > > > >      }
> > > > >      mapcache_unlock(mc);
> > > > >      return raddr;
> > > > > @@ -627,8 +638,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> > > > >
> > > > >      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
> > > > >
> > > > > -    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
> > > > > -                     cache_size, address_index, false);
> > > > > +    xen_remap_bucket(mc, entry, entry->vaddr_base,
> > > > > +                     cache_size, address_index, false, entry->ram_offset);
> > > > >      if (!test_bits(address_offset >> XC_PAGE_SHIFT,
> > > > >                  test_bit_size >> XC_PAGE_SHIFT,
> > > > >                  entry->valid_mapping)) {
> > > > > diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
> > > > > index 1ec9e66752..b5e3ea1bc0 100644
> > > > > --- a/include/sysemu/xen-mapcache.h
> > > > > +++ b/include/sysemu/xen-mapcache.h
> > > > > @@ -19,6 +19,7 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
> > > > >  void xen_map_cache_init(phys_offset_to_gaddr_t f,
> > > > >                          void *opaque);
> > > > >  uint8_t *xen_map_cache(MemoryRegion *mr, hwaddr phys_addr, hwaddr size,
> > > > > +                       ram_addr_t ram_addr_offset,
> > > > >                         uint8_t lock, bool dma,
> > > > >                         bool is_write);
> > > > >  ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
> > > > > @@ -37,6 +38,7 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
> > > > >  static inline uint8_t *xen_map_cache(MemoryRegion *mr,
> > > > >                                       hwaddr phys_addr,
> > > > >                                       hwaddr size,
> > > > > +                                     ram_addr_t ram_addr_offset,
> > > > >                                       uint8_t lock,
> > > > >                                       bool dma,
> > > > >                                       bool is_write)
> > > > > diff --git a/system/physmem.c b/system/physmem.c
> > > > > index 1a5ffcba2a..5b16eeccca 100644
> > > > > --- a/system/physmem.c
> > > > > +++ b/system/physmem.c
> > > > > @@ -2228,13 +2228,13 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
> > > > >           * In that case just map the requested area.
> > > > >           */
> > > > >          if (xen_mr_is_memory(block->mr)) {
> > > > > -            return xen_map_cache(block->mr, addr, len, lock, lock,
> > > > > -                                 is_write);
> > > > > +            return xen_map_cache(block->mr, addr, len, block->offset,
> > > > > +                                 lock, lock, is_write);
> > > >
> > > > Have you considered not tracking offset and address separately and
> > > > simply do this?
> > > >
> > > >             return xen_map_cache(block->mr, addr + block->offset, len,
> > > >                                  lock, lock, is_write);
> > > >
> > >
> > > Unfortunately this won't work since block->offset is not related to where this
> > > ram is mapped in guest address-space. In the case of grant's, we'd get the
> > > wrong grant ref. See my previous comment.
> >
> > OK, this code below (the second xen_map_cache call passing block->offset
> > as start address) was wrong before this patch. Can we fix it before
> > changing it further with this patch? I worry about making things even
> > worse.
> >
> 
> I'll dig around and see if we can find something that explains more.
> There's some older code that implements some sort of address-translation
> for x86 between ram_addr space and guest physical addresses but
> that code is turned off with newer Xen versions (disabled in my build).
> 
> https://github.com/qemu/qemu/blob/master/hw/xen/xen-mapcache.c#L330
> https://github.com/qemu/qemu/blob/master/hw/i386/xen/xen-hvm.c#L193

I don't have any more insights but I think Xenia might have a better
idea as she has fixed bugs related to this to get virtio-gpu to work.

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 03/17] xen: mapcache: Refactor lock functions for multi-instance
  2024-04-30 16:49 ` [PATCH v4 03/17] xen: mapcache: Refactor lock functions for multi-instance Edgar E. Iglesias
  2024-05-01 20:39   ` Stefano Stabellini
@ 2024-05-06  9:52   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06  9:52 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On 30/4/24 18:49, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Make the lock functions take MapCache * as argument. This is
> in preparation for supporting multiple caches.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>   hw/xen/xen-mapcache.c | 34 +++++++++++++++++-----------------
>   1 file changed, 17 insertions(+), 17 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 04/17] xen: mapcache: Refactor xen_map_cache for multi-instance
  2024-04-30 16:49 ` [PATCH v4 04/17] xen: mapcache: Refactor xen_map_cache " Edgar E. Iglesias
  2024-05-01 20:40   ` Stefano Stabellini
@ 2024-05-06  9:53   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06  9:53 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On 30/4/24 18:49, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Make xen_map_cache take a MapCache as argument. This is in
> prepaparation to support multiple map caches.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>   hw/xen/xen-mapcache.c | 35 ++++++++++++++++++-----------------
>   1 file changed, 18 insertions(+), 17 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 05/17] xen: mapcache: Refactor xen_remap_bucket for multi-instance
  2024-04-30 16:49 ` [PATCH v4 05/17] xen: mapcache: Refactor xen_remap_bucket " Edgar E. Iglesias
  2024-05-01 20:42   ` Stefano Stabellini
@ 2024-05-06  9:54   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06  9:54 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On 30/4/24 18:49, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Add MapCache argument to xen_remap_bucket in preparation
> to support multiple map caches.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>   hw/xen/xen-mapcache.c | 9 +++++----
>   1 file changed, 5 insertions(+), 4 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 08/17] xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked
  2024-04-30 16:49 ` [PATCH v4 08/17] xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked Edgar E. Iglesias
  2024-05-01 20:47   ` Stefano Stabellini
@ 2024-05-06  9:55   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06  9:55 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On 30/4/24 18:49, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Add MapCache argument to xen_invalidate_map_cache_entry_unlocked.
> This is in preparation for supporting multiple map caches.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>   hw/xen/xen-mapcache.c | 21 +++++++++++----------
>   1 file changed, 11 insertions(+), 10 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache()
  2024-04-30 16:49 ` [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache() Edgar E. Iglesias
                     ` (2 preceding siblings ...)
  2024-05-02  7:24   ` David Hildenbrand
@ 2024-05-06  9:56   ` Philippe Mathieu-Daudé
  3 siblings, 0 replies; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06  9:56 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, Paolo Bonzini, Peter Xu, David Hildenbrand,
	xen-devel

On 30/4/24 18:49, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Propagate MR and is_write to xen_map_cache().
> This is in preparation for adding support for grant mappings.
> 
> No functional change.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>   hw/xen/xen-mapcache.c         | 10 ++++++----
>   include/sysemu/xen-mapcache.h | 11 +++++++----
>   system/physmem.c              | 31 +++++++++++++++++++++++--------
>   3 files changed, 36 insertions(+), 16 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 14/17] xen: Add xen_mr_is_memory()
  2024-05-02  7:26   ` David Hildenbrand
@ 2024-05-06  9:59     ` Philippe Mathieu-Daudé
  2024-05-06 13:26       ` Edgar E. Iglesias
  0 siblings, 1 reply; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06  9:59 UTC (permalink / raw
  To: David Hildenbrand, Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, Paolo Bonzini, Peter Xu, xen-devel

On 2/5/24 09:26, David Hildenbrand wrote:
> On 30.04.24 18:49, Edgar E. Iglesias wrote:
>> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
>>
>> Add xen_mr_is_memory() to abstract away tests for the
>> xen_memory MR.
>>
>> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
>> ---
> 
> [...]
> 
>>   #endif
>> diff --git a/system/physmem.c b/system/physmem.c
>> index ad7a8c7d95..1a5ffcba2a 100644
>> --- a/system/physmem.c
>> +++ b/system/physmem.c
>> @@ -2227,7 +2227,7 @@ static void *qemu_ram_ptr_length(RAMBlock 
>> *block, ram_addr_t addr,
>>            * because we don't want to map the entire memory in QEMU.
>>            * In that case just map the requested area.
>>            */
>> -        if (block->offset == 0) {
>> +        if (xen_mr_is_memory(block->mr)) {
>>               return xen_map_cache(block->mr, addr, len, lock, lock,
>>                                    is_write);
>>           }
> 
> I'd have moved that into a separate patch, because this is not a simple 
> abstraction here.

Yes please, maybe using Stefano review comment in the description.

> 
> Acked-by: David Hildenbrand <david@redhat.com>
> 



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 09/17] xen: mapcache: Break out xen_invalidate_map_cache_single()
  2024-04-30 16:49 ` [PATCH v4 09/17] xen: mapcache: Break out xen_invalidate_map_cache_single() Edgar E. Iglesias
  2024-05-01 20:48   ` Stefano Stabellini
@ 2024-05-06 10:21   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06 10:21 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On 30/4/24 18:49, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Break out xen_invalidate_map_cache_single().
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>   hw/xen/xen-mapcache.c | 25 +++++++++++++++----------
>   1 file changed, 15 insertions(+), 10 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 07/17] xen: mapcache: Refactor xen_replace_cache_entry_unlocked
  2024-05-02  6:32     ` Edgar E. Iglesias
@ 2024-05-06 10:21       ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06 10:21 UTC (permalink / raw
  To: Edgar E. Iglesias, Stefano Stabellini
  Cc: qemu-devel, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On 2/5/24 08:32, Edgar E. Iglesias wrote:
> On Wed, May 1, 2024 at 10:46 PM Stefano Stabellini
> <sstabellini@kernel.org> wrote:
>>
>> On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
>>> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
>>>
>>> Add MapCache argument to xen_replace_cache_entry_unlocked in
>>> preparation for supporting multiple map caches.
>>>
>>> No functional change.
>>>
>>> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
>>> ---
>>>   hw/xen/xen-mapcache.c | 8 +++++---
>>>   1 file changed, 5 insertions(+), 3 deletions(-)


>>> -static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
>>> +static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
>>> +                                                 hwaddr old_phys_addr,
>>>                                                    hwaddr new_phys_addr,
>>>                                                    hwaddr size)
>>>   {
>>> @@ -578,7 +579,7 @@ static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
>>>           cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE);
>>>       }
>>>
>>> -    entry = &mapcache->entry[address_index % mapcache->nr_buckets];
>>> +    entry = &mc->entry[address_index % mc->nr_buckets];
>>>       while (entry && !(entry->paddr_index == address_index &&
>>>                         entry->size == cache_size)) {
>>>           entry = entry->next;
>>
>> There is still a global mapcache pointer in use in this function:
>>
>>    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
>>
> 
> 
> Thanks! I had accidentally put the change to use mc in future patches.
> Will fix in v5.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 06/17] xen: mapcache: Break out xen_ram_addr_from_mapcache_single
  2024-04-30 16:49 ` [PATCH v4 06/17] xen: mapcache: Break out xen_ram_addr_from_mapcache_single Edgar E. Iglesias
  2024-05-01 20:43   ` Stefano Stabellini
@ 2024-05-06 10:22   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06 10:22 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel
  Cc: sstabellini, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, xen-devel

On 30/4/24 18:49, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> 
> Break out xen_ram_addr_from_mapcache_single(), a multi-cache
> aware version of xen_ram_addr_from_mapcache.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> ---
>   hw/xen/xen-mapcache.c | 17 +++++++++++------
>   1 file changed, 11 insertions(+), 6 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 00/17] xen: Support grant mappings
  2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
                   ` (16 preceding siblings ...)
  2024-04-30 16:49 ` [PATCH v4 17/17] hw/arm: xen: Enable use of " Edgar E. Iglesias
@ 2024-05-06 10:36 ` Philippe Mathieu-Daudé
  17 siblings, 0 replies; 58+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-06 10:36 UTC (permalink / raw
  To: Edgar E. Iglesias, qemu-devel; +Cc: sstabellini, jgross, Edgar E. Iglesias

Hi,

On 30/4/24 18:49, Edgar E. Iglesias wrote:

 > Juergen Gross (2):
 >    softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
 >    xen: let xen_ram_addr_from_mapcache() return -1 if not found entry

> Edgar E. Iglesias (15):
>    xen: mapcache: Refactor lock functions for multi-instance
>    xen: mapcache: Refactor xen_map_cache for multi-instance
>    xen: mapcache: Refactor xen_remap_bucket for multi-instance
>    xen: mapcache: Break out xen_ram_addr_from_mapcache_single
>    xen: mapcache: Refactor xen_replace_cache_entry_unlocked
>    xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked
>    xen: mapcache: Break out xen_invalidate_map_cache_single()
>    xen: mapcache: Break out xen_map_cache_init_single()

>    softmmu: Pass RAM MemoryRegion and is_write xen_map_cache()

I'm queuing 1-10 & 13 to alleviate the respin, thanks.



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 14/17] xen: Add xen_mr_is_memory()
  2024-05-06  9:59     ` Philippe Mathieu-Daudé
@ 2024-05-06 13:26       ` Edgar E. Iglesias
  0 siblings, 0 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-05-06 13:26 UTC (permalink / raw
  To: Philippe Mathieu-Daudé
  Cc: David Hildenbrand, qemu-devel, sstabellini, jgross,
	Edgar E. Iglesias, Anthony Perard, Paul Durrant, Paolo Bonzini,
	Peter Xu, xen-devel

On Mon, May 6, 2024 at 11:59 AM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 2/5/24 09:26, David Hildenbrand wrote:
> > On 30.04.24 18:49, Edgar E. Iglesias wrote:
> >> From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> >>
> >> Add xen_mr_is_memory() to abstract away tests for the
> >> xen_memory MR.
> >>
> >> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> >> ---
> >
> > [...]
> >
> >>   #endif
> >> diff --git a/system/physmem.c b/system/physmem.c
> >> index ad7a8c7d95..1a5ffcba2a 100644
> >> --- a/system/physmem.c
> >> +++ b/system/physmem.c
> >> @@ -2227,7 +2227,7 @@ static void *qemu_ram_ptr_length(RAMBlock
> >> *block, ram_addr_t addr,
> >>            * because we don't want to map the entire memory in QEMU.
> >>            * In that case just map the requested area.
> >>            */
> >> -        if (block->offset == 0) {
> >> +        if (xen_mr_is_memory(block->mr)) {
> >>               return xen_map_cache(block->mr, addr, len, lock, lock,
> >>                                    is_write);
> >>           }
> >
> > I'd have moved that into a separate patch, because this is not a simple
> > abstraction here.
>
> Yes please, maybe using Stefano review comment in the description.
>

Thanks, for v5 I've split out this particular change into a separate patch:

    softmmu: Replace check for RAMBlock offset 0 with xen_mr_is_memory

    For xen, when checking for the first RAM (xen_memory), use
    xen_mr_is_memory() rather than checking for a RAMBlock with
    offset 0.

    All Xen machines create xen_memory first so this has no
    functional change for existing machines.

    Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>

diff --git a/system/physmem.c b/system/physmem.c
index ad7a8c7d95..1a5ffcba2a 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2227,7 +2227,7 @@ static void *qemu_ram_ptr_length(RAMBlock
*block, ram_addr_t addr,
          * because we don't want to map the entire memory in QEMU.
          * In that case just map the requested area.
          */
-        if (block->offset == 0) {
+        if (xen_mr_is_memory(block->mr)) {
             return xen_map_cache(block->mr, addr, len, lock, lock,
                                  is_write);
         }



> >
> > Acked-by: David Hildenbrand <david@redhat.com>
> >
>


^ permalink raw reply related	[flat|nested] 58+ messages in thread

* Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset
  2024-05-02 20:02           ` Stefano Stabellini
@ 2024-05-07 17:18             ` Edgar E. Iglesias
  0 siblings, 0 replies; 58+ messages in thread
From: Edgar E. Iglesias @ 2024-05-07 17:18 UTC (permalink / raw
  To: Stefano Stabellini
  Cc: qemu-devel, jgross, Edgar E. Iglesias, Anthony Perard,
	Paul Durrant, Paolo Bonzini, Peter Xu, David Hildenbrand,
	Philippe Mathieu-Daudé, xen-devel, Xenia.Ragiadakou

On Thu, May 2, 2024 at 10:02 PM Stefano Stabellini
<sstabellini@kernel.org> wrote:
>
> On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> > On Thu, May 2, 2024 at 8:53 PM Stefano Stabellini
> > <sstabellini@kernel.org> wrote:
> > >
> > > +Xenia
> > >
> > > On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> > > > On Wed, May 1, 2024 at 11:24 PM Stefano Stabellini
> > > > <sstabellini@kernel.org> wrote:
> > > > >
> > > > > On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > > > > > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
> > > > > >
> > > > > > The current mapcache assumes that all memory is mapped
> > > > > > in a single RAM MR (the first one with offset 0). Remove
> > > > > > this assumption and propagate the offset to the mapcache
> > > > > > so it can do reverse mappings (from hostptr -> ram_addr).
> > > > > >
> > > > > > This is in preparation for adding grant mappings.
> > > > > >
> > > > > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
> > > > >
> > > > >
> > > > > Looking at xen_remap_bucket, it is only using address_index (without
> > > > > adding ram_offset) to map foreign memory. From xen_remap_bucket, I would
> > > > > understand that address_index already includes the ram_offset.
> > > > >
> > > > > Meaning that if we want to map foreign mapping at address 0x5000, then
> > > > > address_index would be 0x5000, even if ram_offset is 0x1000.
> > > > >
> > > > > But then looking xen_ram_addr_from_mapcache_single ram_offset is added
> > > > > to paddr_index to calculate the physical address. So in that case we
> > > > > would want address_index to be 0x4000 and ram_offset to be 0x1000. But
> > > > > xen_remap_bucket would have to sum address_index and ram_offset to map
> > > > > foreign memory.
> > > > >
> > > > > So I am a bit confused, did I get it wrong? One more comment below.
> > > > >
> > > >
> > > > Thanks Stefano,
> > > >
> > > > I think the confusion is that this ram_addr_offset is not related to
> > > > guest address-space.
> > > > It's a QEMU internal thing and it shouldn't be included in the address
> > > > used to map foreign memory.
> > > > The mapcache can treat this ram_addr offset like a cookie that we keep
> > > > around to be able to do
> > > > reverse mappings from host pointers into ram_addr space
> > > > (xen_ram_addr_from_mapcache).
> > > >
> > > > The current mapcache implementation works because we've really only
> > > > been using foreign mappings
> > > > on RAMBlocks with offset 0. We're also creating RAM's such that the
> > > > offset into the RAM is also
> > > > the guest physical address, for x86 this is natural since RAM starts
> > > > at zero (for lowmem) but for
> > > > ARM we're creating larger than needed RAM's (GUEST_RAM0_BASE + ram-size) to
> > > > make this assumption true. Anyway, In this series I'm not addressing
> > > > this second assumption.
> > >
> > > Let's see if I understand correctly.
> > >
> > > The ram_addr space is an internal QEMU address space which is different
> > > from the guest physical address space and thus cannot and should not be
> > > used to do foreign mappings (foreign mapping hypercalls take a guest
> > > physical or a real physical address to map). Is that correct?
> > >
> > > If so, then I understand.
> > >
> >
> > Yes, that matches my understanding.
> >
> > >
> > >
> > > > There's a second call in physmem.c to xen_map_cache using the
> > > > block->offset as an address.
> > > > I was considering removing that second call since I can't see how it can work
> > > > (except perhaps in some specific use-case by luck?). Anyway, for now
> > > > I've left it unmodified.
> > >
> > > Yes, that code was written with the assumption that block->offset is an
> > > offset in the guest physical address space and could be used as a guest
> > > physical address. Actually, you might have spotted a real bug.
> > >
> > > The intent was for smaller regions (not the bit RAM region, things like
> > > a ROM region for instance) we could map them in full. So here we were
> > > trying to map the whole thing from start to finish using block->offset
> > > as start.
> > >
> > >
> > > > > > ---
> > > > > >  hw/xen/xen-mapcache.c         | 25 ++++++++++++++++++-------
> > > > > >  include/sysemu/xen-mapcache.h |  2 ++
> > > > > >  system/physmem.c              |  8 ++++----
> > > > > >  3 files changed, 24 insertions(+), 11 deletions(-)
> > > > > >
> > > > > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > > > > > index 09b5f36d9c..1b32d0c003 100644
> > > > > > --- a/hw/xen/xen-mapcache.c
> > > > > > +++ b/hw/xen/xen-mapcache.c
> > > > > > @@ -43,6 +43,9 @@ typedef struct MapCacheEntry {
> > > > > >  #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
> > > > > >      uint8_t flags;
> > > > > >      hwaddr size;
> > > > > > +
> > > > > > +    /* Keep ram_addr offset for reverse mappings (hostptr -> ram_addr).  */
> > > > > > +    ram_addr_t ram_offset;
> > > > > >      struct MapCacheEntry *next;
> > > > > >  } MapCacheEntry;
> > > > > >
> > > > > > @@ -165,7 +168,8 @@ static void xen_remap_bucket(MapCache *mc,
> > > > > >                               void *vaddr,
> > > > > >                               hwaddr size,
> > > > > >                               hwaddr address_index,
> > > > > > -                             bool dummy)
> > > > > > +                             bool dummy,
> > > > > > +                             ram_addr_t ram_offset)
> > > > > >  {
> > > > > >      uint8_t *vaddr_base;
> > > > > >      xen_pfn_t *pfns;
> > > > > > @@ -244,6 +248,7 @@ static void xen_remap_bucket(MapCache *mc,
> > > > > >      entry->size = size;
> > > > > >      entry->valid_mapping = g_new0(unsigned long,
> > > > > >                                    BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
> > > > > > +    entry->ram_offset = ram_offset;
> > > > > >
> > > > > >      if (dummy) {
> > > > > >          entry->flags |= XEN_MAPCACHE_ENTRY_DUMMY;
> > > > > > @@ -264,6 +269,7 @@ static void xen_remap_bucket(MapCache *mc,
> > > > > >
> > > > > >  static uint8_t *xen_map_cache_unlocked(MapCache *mc,
> > > > > >                                         hwaddr phys_addr, hwaddr size,
> > > > > > +                                       ram_addr_t ram_offset,
> > > > > >                                         uint8_t lock, bool dma, bool is_write)
> > > > > >  {
> > > > > >      MapCacheEntry *entry, *pentry = NULL,
> > > > > > @@ -335,14 +341,16 @@ tryagain:
> > > > > >      if (!entry) {
> > > > > >          entry = g_new0(MapCacheEntry, 1);
> > > > > >          pentry->next = entry;
> > > > > > -        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > > > > > +        xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > > > > > +                         ram_offset);
> > > > > >      } else if (!entry->lock) {
> > > > > >          if (!entry->vaddr_base || entry->paddr_index != address_index ||
> > > > > >                  entry->size != cache_size ||
> > > > > >                  !test_bits(address_offset >> XC_PAGE_SHIFT,
> > > > > >                      test_bit_size >> XC_PAGE_SHIFT,
> > > > > >                      entry->valid_mapping)) {
> > > > > > -            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy);
> > > > > > +            xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
> > > > > > +                             ram_offset);
> > > > > >          }
> > > > > >      }
> > > > > >
> > > > > > @@ -389,13 +397,15 @@ tryagain:
> > > > > >
> > > > > >  uint8_t *xen_map_cache(MemoryRegion *mr,
> > > > > >                         hwaddr phys_addr, hwaddr size,
> > > > > > +                       ram_addr_t ram_addr_offset,
> > > > > >                         uint8_t lock, bool dma,
> > > > > >                         bool is_write)
> > > > > >  {
> > > > > >      uint8_t *p;
> > > > > >
> > > > > >      mapcache_lock(mapcache);
> > > > > > -    p = xen_map_cache_unlocked(mapcache, phys_addr, size, lock, dma, is_write);
> > > > > > +    p = xen_map_cache_unlocked(mapcache, phys_addr, size, ram_addr_offset,
> > > > > > +                               lock, dma, is_write);
> > > > > >      mapcache_unlock(mapcache);
> > > > > >      return p;
> > > > > >  }
> > > > > > @@ -432,7 +442,8 @@ static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
> > > > > >          raddr = RAM_ADDR_INVALID;
> > > > > >      } else {
> > > > > >          raddr = (reventry->paddr_index << mc->bucket_shift) +
> > > > > > -             ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
> > > > > > +             ((unsigned long) ptr - (unsigned long) entry->vaddr_base) +
> > > > > > +             entry->ram_offset;
> > > > > >      }
> > > > > >      mapcache_unlock(mc);
> > > > > >      return raddr;
> > > > > > @@ -627,8 +638,8 @@ static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
> > > > > >
> > > > > >      trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
> > > > > >
> > > > > > -    xen_remap_bucket(mapcache, entry, entry->vaddr_base,
> > > > > > -                     cache_size, address_index, false);
> > > > > > +    xen_remap_bucket(mc, entry, entry->vaddr_base,
> > > > > > +                     cache_size, address_index, false, entry->ram_offset);
> > > > > >      if (!test_bits(address_offset >> XC_PAGE_SHIFT,
> > > > > >                  test_bit_size >> XC_PAGE_SHIFT,
> > > > > >                  entry->valid_mapping)) {
> > > > > > diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
> > > > > > index 1ec9e66752..b5e3ea1bc0 100644
> > > > > > --- a/include/sysemu/xen-mapcache.h
> > > > > > +++ b/include/sysemu/xen-mapcache.h
> > > > > > @@ -19,6 +19,7 @@ typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
> > > > > >  void xen_map_cache_init(phys_offset_to_gaddr_t f,
> > > > > >                          void *opaque);
> > > > > >  uint8_t *xen_map_cache(MemoryRegion *mr, hwaddr phys_addr, hwaddr size,
> > > > > > +                       ram_addr_t ram_addr_offset,
> > > > > >                         uint8_t lock, bool dma,
> > > > > >                         bool is_write);
> > > > > >  ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
> > > > > > @@ -37,6 +38,7 @@ static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
> > > > > >  static inline uint8_t *xen_map_cache(MemoryRegion *mr,
> > > > > >                                       hwaddr phys_addr,
> > > > > >                                       hwaddr size,
> > > > > > +                                     ram_addr_t ram_addr_offset,
> > > > > >                                       uint8_t lock,
> > > > > >                                       bool dma,
> > > > > >                                       bool is_write)
> > > > > > diff --git a/system/physmem.c b/system/physmem.c
> > > > > > index 1a5ffcba2a..5b16eeccca 100644
> > > > > > --- a/system/physmem.c
> > > > > > +++ b/system/physmem.c
> > > > > > @@ -2228,13 +2228,13 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
> > > > > >           * In that case just map the requested area.
> > > > > >           */
> > > > > >          if (xen_mr_is_memory(block->mr)) {
> > > > > > -            return xen_map_cache(block->mr, addr, len, lock, lock,
> > > > > > -                                 is_write);
> > > > > > +            return xen_map_cache(block->mr, addr, len, block->offset,
> > > > > > +                                 lock, lock, is_write);
> > > > >
> > > > > Have you considered not tracking offset and address separately and
> > > > > simply do this?
> > > > >
> > > > >             return xen_map_cache(block->mr, addr + block->offset, len,
> > > > >                                  lock, lock, is_write);
> > > > >
> > > >
> > > > Unfortunately this won't work since block->offset is not related to where this
> > > > ram is mapped in guest address-space. In the case of grant's, we'd get the
> > > > wrong grant ref. See my previous comment.
> > >
> > > OK, this code below (the second xen_map_cache call passing block->offset
> > > as start address) was wrong before this patch. Can we fix it before
> > > changing it further with this patch? I worry about making things even
> > > worse.
> > >
> >
> > I'll dig around and see if we can find something that explains more.
> > There's some older code that implements some sort of address-translation
> > for x86 between ram_addr space and guest physical addresses but
> > that code is turned off with newer Xen versions (disabled in my build).
> >
> > https://github.com/qemu/qemu/blob/master/hw/xen/xen-mapcache.c#L330
> > https://github.com/qemu/qemu/blob/master/hw/i386/xen/xen-hvm.c#L193
>
> I don't have any more insights but I think Xenia might have a better
> idea as she has fixed bugs related to this to get virtio-gpu to work.

Hi again,

I found the reason this works today is because for RAM's created after
xen_memory,
QEMU hypercalls into Xen to populate the guest memory map with RAM at the given
ram_offset.
https://github.com/qemu/qemu/blob/master/hw/xen/xen-hvm-common.c#L44

The current grant series does not affect this current behaviour but I
think it would be
good to make the offset handling a little more explicit by adding the
addr+ram_offset
in the map-cache (except for the special grant region) and always
passing them in
the same argument slots. I'll try to improve this in the next version
and add some
comments and we can discuss from there.

Cheers,
Edgar


^ permalink raw reply	[flat|nested] 58+ messages in thread

end of thread, other threads:[~2024-05-07 17:20 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-30 16:49 [PATCH v4 00/17] xen: Support grant mappings Edgar E. Iglesias
2024-04-30 16:49 ` [PATCH v4 01/17] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length() Edgar E. Iglesias
2024-05-01 15:56   ` David Hildenbrand
2024-05-01 16:48   ` Peter Xu
2024-04-30 16:49 ` [PATCH v4 02/17] xen: let xen_ram_addr_from_mapcache() return -1 in case of not found entry Edgar E. Iglesias
2024-04-30 16:49 ` [PATCH v4 03/17] xen: mapcache: Refactor lock functions for multi-instance Edgar E. Iglesias
2024-05-01 20:39   ` Stefano Stabellini
2024-05-06  9:52   ` Philippe Mathieu-Daudé
2024-04-30 16:49 ` [PATCH v4 04/17] xen: mapcache: Refactor xen_map_cache " Edgar E. Iglesias
2024-05-01 20:40   ` Stefano Stabellini
2024-05-06  9:53   ` Philippe Mathieu-Daudé
2024-04-30 16:49 ` [PATCH v4 05/17] xen: mapcache: Refactor xen_remap_bucket " Edgar E. Iglesias
2024-05-01 20:42   ` Stefano Stabellini
2024-05-06  9:54   ` Philippe Mathieu-Daudé
2024-04-30 16:49 ` [PATCH v4 06/17] xen: mapcache: Break out xen_ram_addr_from_mapcache_single Edgar E. Iglesias
2024-05-01 20:43   ` Stefano Stabellini
2024-05-06 10:22   ` Philippe Mathieu-Daudé
2024-04-30 16:49 ` [PATCH v4 07/17] xen: mapcache: Refactor xen_replace_cache_entry_unlocked Edgar E. Iglesias
2024-05-01 20:46   ` Stefano Stabellini
2024-05-02  6:32     ` Edgar E. Iglesias
2024-05-06 10:21       ` Philippe Mathieu-Daudé
2024-04-30 16:49 ` [PATCH v4 08/17] xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked Edgar E. Iglesias
2024-05-01 20:47   ` Stefano Stabellini
2024-05-06  9:55   ` Philippe Mathieu-Daudé
2024-04-30 16:49 ` [PATCH v4 09/17] xen: mapcache: Break out xen_invalidate_map_cache_single() Edgar E. Iglesias
2024-05-01 20:48   ` Stefano Stabellini
2024-05-06 10:21   ` Philippe Mathieu-Daudé
2024-04-30 16:49 ` [PATCH v4 10/17] xen: mapcache: Break out xen_map_cache_init_single() Edgar E. Iglesias
2024-05-01 20:51   ` Stefano Stabellini
2024-04-30 16:49 ` [PATCH v4 11/17] xen: mapcache: Make MCACHE_BUCKET_SHIFT runtime configurable Edgar E. Iglesias
2024-05-01 20:55   ` Stefano Stabellini
2024-04-30 16:49 ` [PATCH v4 12/17] xen: mapcache: Unmap first entries in buckets Edgar E. Iglesias
2024-05-01 21:01   ` Stefano Stabellini
2024-05-02  7:34   ` Edgar E. Iglesias
2024-04-30 16:49 ` [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache() Edgar E. Iglesias
2024-05-01 16:48   ` Peter Xu
2024-05-01 21:03   ` Stefano Stabellini
2024-05-02  7:24   ` David Hildenbrand
2024-05-02  7:31     ` Edgar E. Iglesias
2024-05-06  9:56   ` Philippe Mathieu-Daudé
2024-04-30 16:49 ` [PATCH v4 14/17] xen: Add xen_mr_is_memory() Edgar E. Iglesias
2024-05-01 21:06   ` Stefano Stabellini
2024-05-02  7:26   ` David Hildenbrand
2024-05-06  9:59     ` Philippe Mathieu-Daudé
2024-05-06 13:26       ` Edgar E. Iglesias
2024-04-30 16:49 ` [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset Edgar E. Iglesias
2024-05-01 21:24   ` Stefano Stabellini
2024-05-02  7:22     ` Edgar E. Iglesias
2024-05-02 18:53       ` Stefano Stabellini
2024-05-02 19:42         ` Edgar E. Iglesias
2024-05-02 20:02           ` Stefano Stabellini
2024-05-07 17:18             ` Edgar E. Iglesias
2024-04-30 16:49 ` [PATCH v4 16/17] xen: mapcache: Add support for grant mappings Edgar E. Iglesias
2024-05-02 19:18   ` Stefano Stabellini
2024-05-02 19:49     ` Edgar E. Iglesias
2024-04-30 16:49 ` [PATCH v4 17/17] hw/arm: xen: Enable use of " Edgar E. Iglesias
2024-05-01 22:11   ` Stefano Stabellini
2024-05-06 10:36 ` [PATCH v4 00/17] xen: Support " Philippe Mathieu-Daudé

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.