Re: [PATCH v6 7/8] xen: mapcache: Add support for grant mappings

2024-05-23 Thread Stefano Stabellini
On Thu, 23 May 2024, Edgar E. Iglesias wrote:
> On Thu, May 23, 2024 at 9:47 AM Manos Pitsidianakis 
>  wrote:
>   On Thu, 16 May 2024 18:48, "Edgar E. Iglesias" 
>  wrote:
>   >From: "Edgar E. Iglesias" 
>   >
>   >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 
>   >Reviewed-by: Stefano Stabellini 
>   >---
>   > hw/xen/xen-hvm-common.c         |  12 ++-
>   > hw/xen/xen-mapcache.c           | 163 ++--
>   > include/hw/xen/xen-hvm-common.h |   3 +
>   > include/sysemu/xen.h            |   7 ++
>   > 4 files changed, 152 insertions(+), 33 deletions(-)
>   >
>   >diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
>   >index a0a0252da0..b8ace1c368 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 == _memory;
>   >+    return mr == _memory || mr == _grants;
>   >+}
>   >+
>   >+/* Check specifically for grants.  */
>   >+bool xen_mr_is_grants(MemoryRegion *mr)
>   >+{
>   >+    return mr == _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 a07c47b0b1..1cbc2aeaa9 100644
>   >--- a/hw/xen/xen-mapcache.c
>   >+++ b/hw/xen/xen-mapcache.c
>   >@@ -14,6 +14,7 @@
>   >
>   > #include 
>   >
>   >+#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 
>   >+#include 
>   >
>   > #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)
> 
>   Might we get more entry kinds in the future? (for example foreign maps).
>   Maybe this could be an enum.
> 
> 
> Perhaps. Foreign mappings are already supported, this flag separates ordinary 
> foreign mappings from grant foreign mappings.
> IMO, since this is not an external interface it's probably better to change 
> it once we have a concrete use-case at hand.
> 
>  
>   >     uint8_t flags;
>   >     hwaddr size;
>   >     struct MapCacheEntry *next;
>   >@@ -71,6 +75,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)
>   > {
>   >@@ -131,6 +137,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 {
>   >@@ -159,6 +171,15 @@ void xen_map_cache_ini

Re: [PATCH v6 6/8] xen: mapcache: Pass the ram_addr offset to xen_map_cache()

2024-05-16 Thread Stefano Stabellini
On Thu, 16 May 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> Pass the ram_addr offset to xen_map_cache.
> This is in preparation for adding grant mappings that need
> to compute the address within the RAMBlock.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias 

Reviewed-by: Stefano Stabellini 




Re: [PATCH v5 7/8] xen: mapcache: Add support for grant mappings

2024-05-15 Thread Stefano Stabellini
On Fri, 3 May 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 

Reviewed-by: Stefano Stabellini 




Re: [PATCH v5 6/8] xen: mapcache: Pass the ram_addr offset to xen_map_cache()

2024-05-15 Thread Stefano Stabellini
On Fri, 3 May 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> Pass the ram_addr offset to xen_map_cache.
> This is in preparation for adding grant mappings that need
> to compute the address within the RAMBlock.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias 
> ---
>  hw/xen/xen-mapcache.c | 16 +++-
>  include/sysemu/xen-mapcache.h |  2 ++
>  system/physmem.c  |  9 +
>  3 files changed, 18 insertions(+), 9 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index ec95445696..26bc38a9e3 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -167,7 +167,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;
> @@ -266,6 +267,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,
> @@ -337,14 +339,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);
>  }
>  }
>  
> @@ -391,13 +395,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;
>  }
> @@ -632,7 +638,7 @@ 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);
> + cache_size, address_index, false, new_phys_addr);

Everything else makes sense, but I don't understand how can it be that
new_phys_addr is the block->offset here?


>  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 b7847db1a2..33d09f7571 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -2231,13 +2231,14 @@ static void *qemu_ram_ptr_length(RAMBlock *block, 
> ram_addr_t addr,
>   */
>  if 

Re: [PATCH v5 5/8] softmmu: Replace check for RAMBlock offset 0 with xen_mr_is_memory

2024-05-15 Thread Stefano Stabellini
On Fri, 3 May 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 

Reviewed-by: Stefano Stabellini 


> ---
>  system/physmem.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/system/physmem.c b/system/physmem.c
> index 5e6257ef65..b7847db1a2 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -2229,7 +2229,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, block->offset + addr,
>   len, lock, lock,
>   is_write);
> -- 
> 2.40.1
> 



Re: [PATCH v5 4/8] softmmu: xen: Always pass offset + addr to xen_map_cache

2024-05-15 Thread Stefano Stabellini
On Fri, 3 May 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> Always pass address with offset to xen_map_cache().
> This is in preparation for support for grant mappings.
> 
> Since this is within a block that checks for offset == 0,
> this has no functional changes.
> 
> Signed-off-by: Edgar E. Iglesias 

Reviewed-by: Stefano Stabellini 


> ---
>  system/physmem.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/system/physmem.c b/system/physmem.c
> index 342b7a8fd4..5e6257ef65 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -2230,7 +2230,8 @@ 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(block->mr, addr, len, lock, lock,
> +return xen_map_cache(block->mr, block->offset + addr,
> + len, lock, lock,
>   is_write);
>  }
>  
> -- 
> 2.40.1
> 



Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset

2024-05-02 Thread Stefano Stabellini
On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> On Thu, May 2, 2024 at 8:53 PM Stefano Stabellini
>  wrote:
> >
> > +Xenia
> >
> > On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> > > On Wed, May 1, 2024 at 11:24 PM Stefano Stabellini
> > >  wrote:
> > > >
> > > > On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > > > > From: "Edgar E. Iglesias" 
> > > > >
> > > > > 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 
> > > >
> > > >
> > > > 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(-)
> > > > &

Re: [PATCH v4 16/17] xen: mapcache: Add support for grant mappings

2024-05-02 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 
> ---
>  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 == _memory;
> +return mr == _memory || mr == _grants;
> +}
> +
> +/* Check specifically for grants.  */
> +bool xen_mr_is_grants(MemoryRegion *mr)
> +{
> +return mr == _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 
>  
> +#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 
> +#include 
>  
>  #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, _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 @@ 

Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset

2024-05-02 Thread Stefano Stabellini
+Xenia

On Thu, 2 May 2024, Edgar E. Iglesias wrote:
> On Wed, May 1, 2024 at 11:24 PM Stefano Stabellini
>  wrote:
> >
> > On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> > > From: "Edgar E. Iglesias" 
> > >
> > > 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 
> >
> >
> > 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_offse

Re: [PATCH v4 17/17] hw/arm: xen: Enable use of grant mappings

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> Signed-off-by: Edgar E. Iglesias 

Reviewed-by: Stefano Stabellini 


> ---
>  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, _hi);
>  }
> +
> +/* Setup support for grants.  */
> +memory_region_init_ram(_grants, NULL, "xen.grants", block_len,
> +   _fatal);
> +memory_region_add_subregion(sysmem, XEN_GRANT_ADDR_OFF, _grants);
>  }
>  
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
> -- 
> 2.40.1
> 



Re: [PATCH v4 15/17] xen: mapcache: Remove assumption of RAMBlock with 0 offset

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 


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 

Re: [PATCH v4 14/17] xen: Add xen_mr_is_memory()

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> Add xen_mr_is_memory() to abstract away tests for the
> xen_memory MR.
> 
> Signed-off-by: Edgar E. Iglesias 

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 == _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 == _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 ==
_memory. I think that's correct in all cases (x86 machines, ARM
machines) but I wanted to highlight it.

Reviewed-by: Stefano Stabellini 





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



Re: [PATCH v4 13/17] softmmu: Pass RAM MemoryRegion and is_write xen_map_cache()

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 

Reviewed-by: Stefano Stabellini 


> ---
>  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, l

Re: [PATCH v4 12/17] xen: mapcache: Unmap first entries in buckets

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 

Reviewed-by: Stefano Stabellini 


> ---
>  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
> 



Re: [PATCH v4 11/17] xen: mapcache: Make MCACHE_BUCKET_SHIFT runtime configurable

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> Make MCACHE_BUCKET_SHIFT runtime configurable per cache instance.
> 
> Signed-off-by: Edgar E. Iglesias 

Reviewed-by: Stefano Stabellini 


> ---
>  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(>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, _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) {
> +ca

Re: [PATCH v4 10/17] xen: mapcache: Break out xen_map_cache_init_single()

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> Break out xen_map_cache_init_single() in preparation for
> adding multiple map caches.
> 
> Signed-off-by: Edgar E. Iglesias 

Reviewed-by: Stefano Stabellini 


> ---
>  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(>lock);
> +
> +QTAILQ_INIT(>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(>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(>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, _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, _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
> 



Re: [PATCH v4 09/17] xen: mapcache: Break out xen_invalidate_map_cache_single()

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> Break out xen_invalidate_map_cache_single().
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias 

Reviewed-by: Stefano Stabellini 


> ---
>  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, >locked_entries, next) {
> +QTAILQ_FOREACH(reventry, >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 = >entry[i];
> +for (i = 0; i < mc->nr_buckets; i++) {
> +MapCacheEntry *entry = >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
> 



Re: [PATCH v4 08/17] xen: mapcache: Refactor xen_invalidate_map_cache_entry_unlocked

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 

Reviewed-by: Stefano Stabellini 


> ---
>  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, >locked_entries, next) {
> +QTAILQ_FOREACH(reventry, >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, >locked_entries, next) {
> +QTAILQ_FOREACH(reventry, >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(>locked_entries, reventry, next);
> +QTAILQ_REMOVE(>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 = >entry[paddr_index % mapcache->nr_buckets];
> +entry = >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
> 



Re: [PATCH v4 07/17] xen: mapcache: Refactor xen_replace_cache_entry_unlocked

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 
> ---
>  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 = >entry[address_index % mapcache->nr_buckets];
> +entry = >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
> 



Re: [PATCH v4 06/17] xen: mapcache: Break out xen_ram_addr_from_mapcache_single

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 

Reviewed-by: Stefano Stabellini 


> ---
>  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, >locked_entries, next) {
> +mapcache_lock(mc);
> +QTAILQ_FOREACH(reventry, >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 = >entry[paddr_index % mapcache->nr_buckets];
> +entry = >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
> 



Re: [PATCH v4 05/17] xen: mapcache: Refactor xen_remap_bucket for multi-instance

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> Add MapCache argument to xen_remap_bucket in preparation
> to support multiple map caches.
> 
> No functional changes.
> 
> Signed-off-by: Edgar E. Iglesias 

Reviewed-by: Stefano Stabellini 


> ---
>  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
> 



Re: [PATCH v4 04/17] xen: mapcache: Refactor xen_map_cache for multi-instance

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 

Reviewed-by: Stefano Stabellini 


> ---
>  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 = >entry[address_index % mapcache->nr_buckets];
> +entry = >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(>locked_entries, reventry, next);
> +QTAILQ_INSERT_HEAD(>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
> 



Re: [PATCH v4 03/17] xen: mapcache: Refactor lock functions for multi-instance

2024-05-01 Thread Stefano Stabellini
On Tue, 30 Apr 2024, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" 
> 
> 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 

Reviewed-by: Stefano Stabellini 


> ---
>  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(>lock);
> +qemu_mutex_lock(>lock);
>  }
>  
> -static inline void mapcache_unlock(void)
> +static inline void mapcache_unlock(MapCache *mc)
>  {
> -qemu_mutex_unlock(>lock);
> +qemu_mutex_unlock(>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, >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, );
>  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, >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
> 



Re: [PATCH] MAINTAINERS: Update my email address

2024-04-29 Thread Stefano Stabellini
On Mon, 29 Apr 2024, Anthony PERARD wrote:
> From: Anthony PERARD 
> 
> Signed-off-by: Anthony PERARD 

Acked-by: Stefano Stabellini 

> ---
>  MAINTAINERS | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 302b6fd00c..ea9672fc52 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -532,7 +532,7 @@ Guest CPU Cores (Xen)
>  -----
>  X86 Xen CPUs
>  M: Stefano Stabellini 
> -M: Anthony Perard 
> +M: Anthony PERARD 
>  M: Paul Durrant 
>  L: xen-de...@lists.xenproject.org
>  S: Supported
> -- 
> Anthony PERARD
> 



Re: [QEMU][PATCH v3 6/7] xen: add map and unmap callbacks for grant region

2024-02-29 Thread Stefano Stabellini
On Tue, 27 Feb 2024, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> Add the callbacks for mapping/unmapping guest memory via grants to the
> special grant memory region.
> 
> Signed-off-by: Juergen Gross 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/xen/xen-mapcache.c | 176 +-
>  system/physmem.c  |  11 ++-
>  2 files changed, 182 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 179b7e95b2..2e4c9b4947 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -9,6 +9,8 @@
>   */
>  
>  #include "qemu/osdep.h"
> +#include "qemu/queue.h"
> +#include "qemu/thread.h"
>  #include "qemu/units.h"
>  #include "qemu/error-report.h"
>  
> @@ -23,6 +25,8 @@
>  #include "sysemu/xen-mapcache.h"
>  #include "trace.h"
>  
> +#include 
> +#include 
>  
>  #if HOST_LONG_BITS == 32
>  #  define MCACHE_BUCKET_SHIFT 16
> @@ -377,7 +381,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_try(void *ptr)
>  {
>  MapCacheEntry *entry = NULL;
>  MapCacheRev *reventry;
> @@ -588,10 +592,179 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
>  return p;
>  }
>  
> +struct XENMappedGrantRegion {
> +void *addr;
> +unsigned int pages;
> +unsigned int refs;
> +unsigned int prot;
> +uint32_t idx;
> +QLIST_ENTRY(XENMappedGrantRegion) list;
> +};
> +
> +static xengnttab_handle *xen_region_gnttabdev;
> +static QLIST_HEAD(GrantRegionList, XENMappedGrantRegion) xen_grant_mappings =
> +QLIST_HEAD_INITIALIZER(xen_grant_mappings);
> +static QemuMutex xen_map_mutex;
> +
> +static void *xen_map_grant_dyn(MemoryRegion **mr, hwaddr addr, hwaddr *plen,
> +   bool is_write, MemTxAttrs attrs)
> +{
> +unsigned int page_off = addr & (XC_PAGE_SIZE - 1);
> +unsigned int i;
> +unsigned int total_grants = 0;
> +unsigned int nrefs = (page_off + *plen + XC_PAGE_SIZE - 1) >> 
> XC_PAGE_SHIFT;
> +uint32_t ref = (addr - XEN_GRANT_ADDR_OFF) >> XC_PAGE_SHIFT;
> +uint32_t *refs = NULL;
> +unsigned int prot = PROT_READ;
> +struct XENMappedGrantRegion *mgr = NULL;
> +
> +if (is_write) {
> +prot |= PROT_WRITE;
> +}
> +
> +qemu_mutex_lock(_map_mutex);
> +
> +QLIST_FOREACH(mgr, _grant_mappings, list) {
> +if (mgr->idx == ref &&
> +mgr->pages == nrefs &&
> +(mgr->prot & prot) == prot) {
> +break;
> +}
> +
> +total_grants += mgr->pages;
> +}
> +
> +if (!mgr) {
> +if (nrefs + total_grants >= XEN_MAX_VIRTIO_GRANTS) {
> +qemu_mutex_unlock(_map_mutex);
> +return NULL;
> +}
> +
> +mgr = g_new(struct XENMappedGrantRegion, 1);
> +
> +if (nrefs == 1) {
> +refs = 
> +} else {
> +refs = g_new(uint32_t, nrefs);
> +for (i = 0; i < nrefs; i++) {
> +refs[i] = ref + i;
> +}
> +}
> +mgr->addr = xengnttab_map_domain_grant_refs(xen_region_gnttabdev, 
> nrefs,
> +xen_domid, refs, prot);
> +if (mgr->addr) {
> +mgr->pages = nrefs;
> +mgr->refs = 1;
> +mgr->prot = prot;
> +mgr->idx = ref;
> +
> +QLIST_INSERT_HEAD(_grant_mappings, mgr, list);
> +} else {
> +g_free(mgr);
> +mgr = NULL;
> +}
> +} else {
> +mgr->refs++;
> +}
> +
> +qemu_mutex_unlock(_map_mutex);
> +
> +if (nrefs > 1) {
> +g_free(refs);
> +}
> +
> +return mgr ? mgr->addr + page_off : NULL;
> +}
> +
> +static void xen_unmap_grant_dyn(MemoryRegion *mr, void *buffer, ram_addr_t 
> addr,
> +hwaddr len, bool is_write, hwaddr access_len)
> +{
> +unsigned int page_off = (unsigned long)buffer & (XC_PAGE_SIZE - 1);
> +unsigned int nrefs = (page_off + len + XC_PAGE_SIZE - 1) >> 
> XC_PAGE_SHIFT;
> +unsigned int prot = PROT_READ;
> +struct XENMappedGrantRegion *mgr = NULL;
> +
> +if (is_write) {
> +prot |= PROT_WRITE;
> +}
> +
> +qemu_mutex_lock(_map_mutex);

Re: [QEMU][PATCH v3 5/7] memory: add MemoryRegion map and unmap callbacks

2024-02-29 Thread Stefano Stabellini
On Tue, 27 Feb 2024, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> In order to support mapping and unmapping guest memory dynamically to
> and from qemu during address_space_[un]map() operations add the map()
> and unmap() callbacks to MemoryRegionOps.
> 
> Those will be used e.g. for Xen grant mappings when performing guest
> I/Os.
> 
> Signed-off-by: Juergen Gross 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  include/exec/memory.h | 21 ++
>  system/physmem.c  | 50 +--
>  2 files changed, 60 insertions(+), 11 deletions(-)
> 
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 8626a355b3..9f7dfe59c7 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -282,6 +282,27 @@ struct MemoryRegionOps {
>  unsigned size,
>  MemTxAttrs attrs);
>  
> +/*
> + * Dynamically create mapping. @addr is the guest address to map; @plen
> + * is the pointer to the usable length of the buffer.
> + * @mr contents can be changed in case a new memory region is created for
> + * the mapping.
> + * Returns the buffer address for accessing the data.
> + */
> +void *(*map)(MemoryRegion **mr,
> + hwaddr addr,
> + hwaddr *plen,
> + bool is_write,
> + MemTxAttrs attrs);
> +
> +/* Unmap an area obtained via map() before. */
> +void (*unmap)(MemoryRegion *mr,
> +  void *buffer,
> +  ram_addr_t addr,
> +  hwaddr len,
> +  bool is_write,
> +  hwaddr access_len);
> +
>  enum device_endian endianness;
>  /* Guest-visible constraints: */
>  struct {
> diff --git a/system/physmem.c b/system/physmem.c
> index 949dcb20ba..d989e9fc1f 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -3141,6 +3141,7 @@ void *address_space_map(AddressSpace *as,
>  hwaddr len = *plen;
>  hwaddr l, xlat;
>  MemoryRegion *mr;
> +void *ptr = NULL;
>  FlatView *fv;
>  
>  if (len == 0) {
> @@ -3174,12 +3175,20 @@ void *address_space_map(AddressSpace *as,
>  return bounce.buffer;
>  }
>  
> -
>  memory_region_ref(mr);
> +
> +if (mr->ops && mr->ops->map) {
> +ptr = mr->ops->map(, addr, plen, is_write, attrs);
> +}
> +
>  *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);
> +if (ptr == NULL) {
> +ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true);
> +}
> +
> +return ptr;
>  }
>  
>  /* Unmaps a memory region previously mapped by address_space_map().
> @@ -3195,11 +3204,16 @@ void address_space_unmap(AddressSpace *as, void 
> *buffer, hwaddr len,
>  
>  mr = memory_region_from_host(buffer, );
>  assert(mr != NULL);
> -if (is_write) {
> -invalidate_and_set_dirty(mr, addr1, access_len);
> -}
> -if (xen_enabled()) {
> -xen_invalidate_map_cache_entry(buffer);
> +
> +if (mr->ops && mr->ops->unmap) {
> +mr->ops->unmap(mr, buffer, addr1, len, is_write, access_len);
> +} else {
> +if (is_write) {
> +invalidate_and_set_dirty(mr, addr1, access_len);
> +}
> +if (xen_enabled()) {
> +xen_invalidate_map_cache_entry(buffer);
> +}
>  }
>  memory_region_unref(mr);
>  return;
> @@ -3272,10 +3286,18 @@ int64_t address_space_cache_init(MemoryRegionCache 
> *cache,
>   * doing this if we found actual RAM, which behaves the same
>   * regardless of attributes; so UNSPECIFIED is fine.
>   */
> +if (mr->ops && mr->ops->map) {
> +cache->ptr = mr->ops->map(, addr, , is_write,
> +  MEMTXATTRS_UNSPECIFIED);
> +}
> +
>  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, , 
> true);
> +if (!cache->ptr) {
> +cache->ptr = qemu_ram_ptr_length(mr->ram_b

Re: [RFC QEMU PATCH v4 1/1] xen: Use gsi instead of irq for mapping pirq

2024-02-22 Thread Stefano Stabellini
On Fri, 5 Jan 2024, Jiqian Chen wrote:
> In PVH dom0, it uses the linux local interrupt mechanism,
> when it allocs irq for a gsi, it is dynamic, and follow
> the principle of applying first, distributing first. And
> the irq number is alloced from small to large, but the
> applying gsi number is not, may gsi 38 comes before gsi
> 28, that causes the irq number is not equal with the gsi
> number. And when passthrough a device, qemu wants to use
> gsi to map pirq, xen_pt_realize->xc_physdev_map_pirq, but
> the gsi number is got from file
> /sys/bus/pci/devices//irq in current code, so it
> will fail when mapping.
> 
> Add gsi into XenHostPCIDevice and use gsi number that
> read from gsi sysfs if it exists.
> 
> Co-developed-by: Huang Rui 
> Signed-off-by: Jiqian Chen 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/xen/xen-host-pci-device.c | 7 +++
>  hw/xen/xen-host-pci-device.h | 1 +
>  hw/xen/xen_pt.c  | 6 +-
>  3 files changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/xen/xen-host-pci-device.c b/hw/xen/xen-host-pci-device.c
> index 8c6e9a1716a2..5be3279aa25b 100644
> --- a/hw/xen/xen-host-pci-device.c
> +++ b/hw/xen/xen-host-pci-device.c
> @@ -370,6 +370,13 @@ void xen_host_pci_device_get(XenHostPCIDevice *d, 
> uint16_t domain,
>  }
>  d->irq = v;
>  
> +xen_host_pci_get_dec_value(d, "gsi", , errp);
> +if (*errp) {
> +d->gsi = -1;
> +} else {
> +d->gsi = v;
> +}
> +
>  xen_host_pci_get_hex_value(d, "class", , errp);
>  if (*errp) {
>  goto error;
> diff --git a/hw/xen/xen-host-pci-device.h b/hw/xen/xen-host-pci-device.h
> index 4d8d34ecb024..74c552bb5548 100644
> --- a/hw/xen/xen-host-pci-device.h
> +++ b/hw/xen/xen-host-pci-device.h
> @@ -27,6 +27,7 @@ typedef struct XenHostPCIDevice {
>  uint16_t device_id;
>  uint32_t class_code;
>  int irq;
> +int gsi;
>  
>  XenHostPCIIORegion io_regions[PCI_NUM_REGIONS - 1];
>  XenHostPCIIORegion rom;
> diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
> index 36e6f93c372f..d448f3a17306 100644
> --- a/hw/xen/xen_pt.c
> +++ b/hw/xen/xen_pt.c
> @@ -839,7 +839,11 @@ static void xen_pt_realize(PCIDevice *d, Error **errp)
>  goto out;
>  }
>  
> -machine_irq = s->real_device.irq;
> +if (s->real_device.gsi < 0) {
> +machine_irq = s->real_device.irq;
> +} else {
> +machine_irq = s->real_device.gsi;
> +}
>  if (machine_irq == 0) {
>  XEN_PT_LOG(d, "machine irq is 0\n");
>  cmd |= PCI_COMMAND_INTX_DISABLE;
> -- 
> 2.34.1
> 



Re: [PATCH V2] xen: Drop out of coroutine context xen_invalidate_map_cache_entry

2024-01-23 Thread Stefano Stabellini
On Wed, 24 Jan 2024, Peng Fan (OSS) wrote:
> From: Peng Fan 
> 
> xen_invalidate_map_cache_entry is not expected to run in a
> coroutine. Without this, there is crash:
> 
> signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
> threadid=) at pthread_kill.c:78
> at /usr/src/debug/glibc/2.38+git-r0/sysdeps/posix/raise.c:26
> fmt=0x9e1ca8a8 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n",
> assertion=assertion@entry=0xe0d25740 "!qemu_in_coroutine()",
> file=file@entry=0xe0d301a8 
> "../qemu-xen-dir-remote/block/graph-lock.c", line=line@entry=260,
> function=function@entry=0xe0e522c0 <__PRETTY_FUNCTION__.3> 
> "bdrv_graph_rdlock_main_loop") at assert.c:92
> assertion=assertion@entry=0xe0d25740 "!qemu_in_coroutine()",
> file=file@entry=0xe0d301a8 
> "../qemu-xen-dir-remote/block/graph-lock.c", line=line@entry=260,
> function=function@entry=0xe0e522c0 <__PRETTY_FUNCTION__.3> 
> "bdrv_graph_rdlock_main_loop") at assert.c:101
> at ../qemu-xen-dir-remote/block/graph-lock.c:260
> at 
> /home/Freenix/work/sw-stash/xen/upstream/tools/qemu-xen-dir-remote/include/block/graph-lock.h:259
> host=host@entry=0x742c8000, size=size@entry=2097152)
> at ../qemu-xen-dir-remote/block/io.c:3362
> host=0x742c8000, size=2097152)
> at ../qemu-xen-dir-remote/block/block-backend.c:2859
> host=, size=, max_size=)
> at ../qemu-xen-dir-remote/block/block-ram-registrar.c:33
> size=2097152, max_size=2097152)
> at ../qemu-xen-dir-remote/hw/core/numa.c:883
> buffer=buffer@entry=0x743c5000 "")
> at ../qemu-xen-dir-remote/hw/xen/xen-mapcache.c:475
> buffer=buffer@entry=0x743c5000 "")
> at ../qemu-xen-dir-remote/hw/xen/xen-mapcache.c:487
> as=as@entry=0xe1ca3ae8 , buffer=0x743c5000,
> len=, is_write=is_write@entry=true,
> access_len=access_len@entry=32768)
> at ../qemu-xen-dir-remote/system/physmem.c:3199
> dir=DMA_DIRECTION_FROM_DEVICE, len=,
> buffer=, as=0xe1ca3ae8 )
> at 
> /home/Freenix/work/sw-stash/xen/upstream/tools/qemu-xen-dir-remote/include/sysemu/dma.h:236
> elem=elem@entry=0xf620aa30, len=len@entry=32769)
> at ../qemu-xen-dir-remote/hw/virtio/virtio.c:758
> elem=elem@entry=0xf620aa30, len=len@entry=32769, idx=idx@entry=0)
> at ../qemu-xen-dir-remote/hw/virtio/virtio.c:919
> elem=elem@entry=0xf620aa30, len=32769)
> at ../qemu-xen-dir-remote/hw/virtio/virtio.c:994
> req=req@entry=0xf620aa30, status=status@entry=0 '\000')
> at ../qemu-xen-dir-remote/hw/block/virtio-blk.c:67
> ret=0) at ../qemu-xen-dir-remote/hw/block/virtio-blk.c:136
> at ../qemu-xen-dir-remote/block/block-backend.c:1559
> --Type  for more, q to quit, c to continue without paging--
> at ../qemu-xen-dir-remote/block/block-backend.c:1614
> i1=) at 
> ../qemu-xen-dir-remote/util/coroutine-ucontext.c:177
> at ../sysdeps/unix/sysv/linux/aarch64/setcontext.S:123
> 
> Signed-off-by: Peng Fan 

Reviewed-by: Stefano Stabellini 


> 
> V2:
>  Drop unused ret in XenMapCacheData (thanks Stefano)
> 
>  hw/xen/xen-mapcache.c | 30 --
>  1 file changed, 28 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index f7d974677d..8d62b3d2ed 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -481,11 +481,37 @@ static void 
> xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
>  g_free(entry);
>  }
>  
> -void xen_invalidate_map_cache_entry(uint8_t *buffer)
> +typedef struct XenMapCacheData {
> +Coroutine *co;
> +uint8_t *buffer;
> +} XenMapCacheData;
> +
> +static void xen_invalidate_map_cache_entry_bh(void *opaque)
>  {
> +XenMapCacheData *data = opaque;
> +
>  mapcache_lock();
> -xen_invalidate_map_cache_entry_unlocked(buffer);
> +xen_invalidate_map_cache_entry_unlocked(data->buffer);
>  mapcache_unlock();
> +
> +aio_co_wake(data->co);
> +}
> +
> +void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
> +{
> +if (qemu_in_coroutine()) {
> +XenMapCacheData data = {
> +.co = qemu_coroutine_self(),
> +.buffer = buffer,
> +};
> +aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
> +xen_invalidate_map_cache_entry_bh, );
> +qemu_coroutine_yield();
> +} else {
> +mapcache_lock();
> +xen_invalidate_map_cache_entry_unlocked(buffer);
> +mapcache_unlock();
> +}
>  }
>  
>  void xen_invalidate_map_cache(void)
> -- 
> 2.35.3
> 



Re: [PATCH] xen: Drop out of coroutine context xen_invalidate_map_cache_entry

2024-01-23 Thread Stefano Stabellini
On Tue, 16 Jan 2024, Peng Fan (OSS) wrote:
> From: Peng Fan 
> 
> xen_invalidate_map_cache_entry is not expected to run in a
> coroutine. Without this, there is crash:
> 
> signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
> threadid=) at pthread_kill.c:78
> at /usr/src/debug/glibc/2.38+git-r0/sysdeps/posix/raise.c:26
> fmt=0x9e1ca8a8 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n",
> assertion=assertion@entry=0xe0d25740 "!qemu_in_coroutine()",
> file=file@entry=0xe0d301a8 
> "../qemu-xen-dir-remote/block/graph-lock.c", line=line@entry=260,
> function=function@entry=0xe0e522c0 <__PRETTY_FUNCTION__.3> 
> "bdrv_graph_rdlock_main_loop") at assert.c:92
> assertion=assertion@entry=0xe0d25740 "!qemu_in_coroutine()",
> file=file@entry=0xe0d301a8 
> "../qemu-xen-dir-remote/block/graph-lock.c", line=line@entry=260,
> function=function@entry=0xe0e522c0 <__PRETTY_FUNCTION__.3> 
> "bdrv_graph_rdlock_main_loop") at assert.c:101
> at ../qemu-xen-dir-remote/block/graph-lock.c:260
> at 
> /home/Freenix/work/sw-stash/xen/upstream/tools/qemu-xen-dir-remote/include/block/graph-lock.h:259
> host=host@entry=0x742c8000, size=size@entry=2097152)
> at ../qemu-xen-dir-remote/block/io.c:3362
> host=0x742c8000, size=2097152)
> at ../qemu-xen-dir-remote/block/block-backend.c:2859
> host=, size=, max_size=)
> at ../qemu-xen-dir-remote/block/block-ram-registrar.c:33
> size=2097152, max_size=2097152)
> at ../qemu-xen-dir-remote/hw/core/numa.c:883
> buffer=buffer@entry=0x743c5000 "")
> at ../qemu-xen-dir-remote/hw/xen/xen-mapcache.c:475
> buffer=buffer@entry=0x743c5000 "")
> at ../qemu-xen-dir-remote/hw/xen/xen-mapcache.c:487
> as=as@entry=0xe1ca3ae8 , buffer=0x743c5000,
> len=, is_write=is_write@entry=true,
> access_len=access_len@entry=32768)
> at ../qemu-xen-dir-remote/system/physmem.c:3199
> dir=DMA_DIRECTION_FROM_DEVICE, len=,
> buffer=, as=0xe1ca3ae8 )
> at 
> /home/Freenix/work/sw-stash/xen/upstream/tools/qemu-xen-dir-remote/include/sysemu/dma.h:236
> elem=elem@entry=0xf620aa30, len=len@entry=32769)
> at ../qemu-xen-dir-remote/hw/virtio/virtio.c:758
> elem=elem@entry=0xf620aa30, len=len@entry=32769, idx=idx@entry=0)
> at ../qemu-xen-dir-remote/hw/virtio/virtio.c:919
> elem=elem@entry=0xf620aa30, len=32769)
> at ../qemu-xen-dir-remote/hw/virtio/virtio.c:994
> req=req@entry=0xf620aa30, status=status@entry=0 '\000')
> at ../qemu-xen-dir-remote/hw/block/virtio-blk.c:67
> ret=0) at ../qemu-xen-dir-remote/hw/block/virtio-blk.c:136
> at ../qemu-xen-dir-remote/block/block-backend.c:1559
> --Type  for more, q to quit, c to continue without paging--
> at ../qemu-xen-dir-remote/block/block-backend.c:1614
> i1=) at 
> ../qemu-xen-dir-remote/util/coroutine-ucontext.c:177
> at ../sysdeps/unix/sysv/linux/aarch64/setcontext.S:123
> 
> Signed-off-by: Peng Fan 

Hi Peng! Many thanks for the patch and for the investigation!

Only one minor question below


> ---
>  hw/xen/xen-mapcache.c | 31 +--
>  1 file changed, 29 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index f7d974677d..4e1bb665ee 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -481,11 +481,38 @@ static void 
> xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
>  g_free(entry);
>  }
>  
> -void xen_invalidate_map_cache_entry(uint8_t *buffer)
> +typedef struct XenMapCacheData {
> +Coroutine *co;
> +uint8_t *buffer;
> +int ret;

Do we need int ret? It doesn't look like we are using it.


> +} XenMapCacheData;
> +
> +static void xen_invalidate_map_cache_entry_bh(void *opaque)
>  {
> +XenMapCacheData *data = opaque;
> +
>  mapcache_lock();
> -xen_invalidate_map_cache_entry_unlocked(buffer);
> +xen_invalidate_map_cache_entry_unlocked(data->buffer);
>  mapcache_unlock();
> +
> +aio_co_wake(data->co);
> +}
> +
> +void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
> +{
> +if (qemu_in_coroutine()) {
> +XenMapCacheData data = {
> +.co = qemu_coroutine_self(),
> +.buffer = buffer,
> +};
> +aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
> +xen_invalidate_map_cache_entry_bh, );
> +qemu_coroutine_yield();
> +} else {
> +mapcache_lock();
> +xen_invalidate_map_cache_entry_unlocked(buffer);
> +mapcache_unlock();
> +}
>  }
>  
>  void xen_invalidate_map_cache(void)
> -- 
> 2.35.3
> 



Re: [PATCH] xen: fix condition for enabling the Xen accelerator

2023-12-11 Thread Stefano Stabellini
On Sat, 9 Dec 2023, Paolo Bonzini wrote:
> A misspelled condition in xen_native.h is hiding a bug in the enablement of
> Xen for qemu-system-aarch64.  The bug becomes apparent when building for
> Xen 4.18.
> 
> While the i386 emulator provides the xenpv machine type for multiple 
> architectures,
> and therefore can be compiled with Xen enabled even when the host is Arm, the
> opposite is not true: qemu-system-aarch64 can only be compiled with Xen 
> support
> enabled when the host is Arm.
> 
> Expand the computation of accelerator_targets['CONFIG_XEN'] similar to what is
> already there for KVM, and fix xen_native.h.
> 
> Cc: Stefano Stabellini 
> Cc: Richard W.M. Jones 
> Cc: Daniel P. Berrangé 
> Reported-by: Michael Young 
> Supersedes: 
> <277e21fc78b75ec459efc7f5fde628a0222c63b0.1701989261.git.m.a.yo...@durham.ac.uk>
> Signed-off-by: Paolo Bonzini 

Reviewed-by: Stefano Stabellini 


> ---
>  include/hw/xen/xen_native.h |  2 +-
>  meson.build | 17 ++---
>  2 files changed, 11 insertions(+), 8 deletions(-)
> 
> diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
> index 6f09c48823b..1a5ad693a4d 100644
> --- a/include/hw/xen/xen_native.h
> +++ b/include/hw/xen/xen_native.h
> @@ -532,7 +532,7 @@ static inline int 
> xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
>  }
>  #endif
>  
> -#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41700
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41700
>  #define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
>  #define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
>  #define GUEST_VIRTIO_MMIO_SPI_FIRST   33
> diff --git a/meson.build b/meson.build
> index ec01f8b138a..67f4ede8aea 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -123,21 +123,24 @@ if get_option('kvm').allowed() and targetos == 'linux'
>kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"'
>  endif
>  config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c)
> -
>  accelerator_targets = { 'CONFIG_KVM': kvm_targets }
>  
> +if cpu in ['x86', 'x86_64']
> +  xen_targets = ['i386-softmmu', 'x86_64-softmmu']
> +elif cpu in ['arm', 'aarch64']
> +  # i386 emulator provides xenpv machine type for multiple architectures
> +  xen_targets = ['i386-softmmu', 'x86_64-softmmu', 'aarch64-softmmu']
> +else
> +  xen_targets = []
> +endif
> +accelerator_targets += { 'CONFIG_XEN': xen_targets }
> +
>  if cpu in ['aarch64']
>accelerator_targets += {
>  'CONFIG_HVF': ['aarch64-softmmu']
>}
>  endif
>  
> -if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
> -  # i386 emulator provides xenpv machine type for multiple architectures
> -  accelerator_targets += {
> -'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu', 'aarch64-softmmu'],
> -  }
> -endif
>  if cpu in ['x86', 'x86_64']
>accelerator_targets += {
>  'CONFIG_HVF': ['x86_64-softmmu'],
> -- 
> 2.43.0
> 
> 

Re: [PATCH] fix qemu build with xen-4.18.0

2023-12-08 Thread Stefano Stabellini
On Fri, 8 Dec 2023, Daniel P. Berrangé wrote:
> CC'ing the Xen folks
> 
> On Thu, Dec 07, 2023 at 11:12:48PM +, Michael Young wrote:
> > Builds of qemu-8.2.0rc2 with xen-4.18.0 are currently failing
> > with errors like
> > ../hw/arm/xen_arm.c:74:5: error: ‘GUEST_VIRTIO_MMIO_SPI_LAST’ undeclared 
> > (first use in this function)
> >74 |(GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
> >   | ^~
> > 
> > as there is an incorrect comparision in include/hw/xen/xen_native.h
> > which means that settings like GUEST_VIRTIO_MMIO_SPI_LAST
> > aren't being defined for xen-4.18.0
> 
> The conditions in arch-arm.h for xen 4.18 show:
> 
> $ cppi arch-arm.h | grep -E '(#.*if)|MMIO'
> #ifndef __XEN_PUBLIC_ARCH_ARM_H__
> # if defined(__XEN__) || defined(__XEN_TOOLS__) || defined(__GNUC__)
> # endif
> # ifndef __ASSEMBLY__
> #  if defined(__XEN__) || defined(__XEN_TOOLS__)
> #   if defined(__GNUC__) && !defined(__STRICT_ANSI__)
> #   endif
> #  endif /* __XEN__ || __XEN_TOOLS__ */
> # endif
> # if defined(__XEN__) || defined(__XEN_TOOLS__)
> #  define PSR_MODE_BIT  0x10U /* Set iff AArch32 */
> /* Virtio MMIO mappings */
> #  define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
> #  define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
> #  define GUEST_VIRTIO_MMIO_SPI_FIRST   33
> #  define GUEST_VIRTIO_MMIO_SPI_LAST43
> # endif
> # ifndef __ASSEMBLY__
> # endif
> #endif /*  __XEN_PUBLIC_ARCH_ARM_H__ */
> 
> So the MMIO constants are available if __XEN__ or __XEN_TOOLS__
> are defined. This is no different to the condition that was
> present in Xen 4.17.
> 
> What you didn't mention was that the Fedora build failure is
> seen on an x86_64 host, when building the aarch64 target QEMU,
> and I think this is the key issue.

Hi Daniel, thanks for looking into it.

- you are building on a x86_64 host
- the target is aarch64
- the target is the aarch64 Xen PVH machine (xen_arm.c)

But is the resulting QEMU binary expected to be an x86 binary? Or are
you cross compiling ARM binaries on a x86 host?

In other word, is the resulting QEMU binary expected to run on ARM or
x86?


> Are we expecting to build Xen support for non-arch native QEMU
> system binaries or not ?

The ARM xenpvh machine (xen_arm.c) is meant to work with Xen on ARM, not
Xen on x86.  So this is only expected to work if you are
cross-compiling. But you can cross-compile both Xen and QEMU, and I am
pretty sure that Yocto is able to build Xen, Xen userspace tools, and
QEMU for Xen/ARM on an x86 host today.


> The constants are defined in arch-arm.h, which is only included
> under:
> 
>   #if defined(__i386__) || defined(__x86_64__)
>   #include "arch-x86/xen.h"
>   #elif defined(__arm__) || defined (__aarch64__)
>   #include "arch-arm.h"
>   #else
>   #error "Unsupported architecture"
>   #endif
> 
> 
> When we are building on an x86_64 host, we not going to get
> arch-arm.h included, even if we're trying to build the aarch64
> system emulator.
> 
> I don't know how this is supposed to work ?

It looks like a host vs. target architecture mismatch: the #if defined
(__aarch64__) check should pass I think.


The following is a guess. Maybe Xen gets enabled because you have x86
Xen installed, and you are building QEMU for an aarch64 target (aarch64
emulation, running on a x86 host). So this is not meant to work for
xen_arm.c and it would be better to disable xen_arm.c.

On the other hand if you are trying to cross-build a QEMU binary meant
to run on an aarch64 host, cross-building it on an x86_64 host, then yes
this is meant to work and we need to figure out why the #if defined
(__aarch64__) is not passing.



> > Signed-off-by: Michael Young 
> > ---
> >  include/hw/xen/xen_native.h | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
> > index 6f09c48823..04b1ef4d34 100644
> > --- a/include/hw/xen/xen_native.h
> > +++ b/include/hw/xen/xen_native.h
> > @@ -532,7 +532,7 @@ static inline int 
> > xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
> >  }
> >  #endif
> >  
> > -#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41700
> > +#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 41700
> 
> This change is not correct
> 
> We can see the upstream change was introduced in 4.17:
> 
>   $ git describe  2128143c114
>   4.16.0-rc4-967-g2128143c11
> 
> IOW, if we have 4.17 or newer these constants already
> exist. If we have 4.16 or older, then we need to define
> them to provide back compat.
> 
> >  #define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
> >  #define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
> >  #define GUEST_VIRTIO_MMIO_SPI_FIRST   33
> 
> With regards,
> Daniel
> -- 
> |: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org -o-https://fstop138.berrange.com :|
> |: https://entangle-photo.org-o-

Re: Adding MSI support for virtio-pci to QEMU as Xen backend on ARM

2023-12-08 Thread Stefano Stabellini
+Stewart

On Fri, 8 Dec 2023, Mykyta Poturai wrote:
> Hello everyone,
> 
> I am currently working on adding MSI support to virtio-pci on ARM with Xen.

Excellent!


> As far as I understand QEMU Xen ARM machine that is used for virtio-pci 
> device emulation does not initialize any interrupt controllers. And that 
> makes it somewhat unclear what is the best approach to adding the MSI 
> support. So, I would appreciate some thoughts on this.
> To trigger the MSI interrupt in Xen guests we basically need to call a single 
> DMOP, which I am also implementing.

You should be able to call xen_inject_msi


> So far, I have come up with 3 possible approaches:
> 1. Hooking up the existing GIC code to the Xen Arm machine and extending it 
> with the DMOP call.

No, I would rather avoid this for a couple of reasons. In reality, the
GIC is emulated by Xen, not QEMU. So letting QEMU think that QEMU is
emulating a GIC is more error prone than the alternatives and also it
would allocate resources needlessly.


> 2. Writing some new barebones GIC implementation with only the required 
> methods (something similar to xen_apic.c).
> 3. Just hooking up the DMOP call to the existing PCI code based on 
> xen_enabled() check.

I would rather not introduce any more if (xen_enabled()) checks beyond
the ones we already have unless it is the only option. So I would go
with option 2). Even better if we could reuse xen_apic.c. xen_apic.c is
just a stub, which is basically the same thing that we need here.



Re: [PATCH v2 4/6] xen_pvdev: Do not assume Dom0 when creating a directory

2023-11-22 Thread Stefano Stabellini
On Wed, 22 Nov 2023, David Woodhouse wrote:
> On Wed, 2023-11-22 at 15:09 -0800, Stefano Stabellini wrote:
> > On Wed, 22 Nov 2023, David Woodhouse wrote:
> > > On Wed, 2023-11-22 at 14:29 -0800, Stefano Stabellini wrote:
> > > > On Wed, 22 Nov 2023, Paul Durrant wrote:
> > > > > On 21/11/2023 22:10, Volodymyr Babchuk wrote:
> > > > > > From: Oleksandr Tyshchenko 
> > > > > > 
> > > > > > Instead of forcing the owner to domid 0, use XS_PRESERVE_OWNER to
> > > > > > inherit the owner of the directory.
> > > > > 
> > > > > Ah... so that's why the previous patch is there.
> > > > > 
> > > > > This is not the right way to fix it. The QEMU Xen support is 
> > > > > *assuming* that
> > > > > QEMU is either running in, or emulating, dom0. In the emulation case 
> > > > > this is
> > > > > probably fine, but the 'real Xen' case it should be using the correct 
> > > > > domid
> > > > > for node creation. I guess this could either be supplied on the 
> > > > > command line
> > > > > or discerned by reading the local domain 'domid' node.
> > > > 
> > > > yes, it should be passed as command line option to QEMU
> > > 
> > > I'm not sure I like the idea of a command line option for something
> > > which QEMU could discover for itself.
> > 
> > That's fine too. I meant to say "yes, as far as I know the toolstack
> > passes the domid to QEMU as a command line option today".
> 
> The -xen-domid argument on the QEMU command line today is the *guest*
> domain ID, not the domain ID in which QEMU itself is running.
> 
> Or were you thinking of something different?

Ops, you are right and I understand your comment better now. The backend
domid is not on the command line but it should be discoverable (on
xenstore if I remember right).



Re: [PATCH v2 4/6] xen_pvdev: Do not assume Dom0 when creating a directory

2023-11-22 Thread Stefano Stabellini
On Wed, 22 Nov 2023, David Woodhouse wrote:
> On Wed, 2023-11-22 at 14:29 -0800, Stefano Stabellini wrote:
> > On Wed, 22 Nov 2023, Paul Durrant wrote:
> > > On 21/11/2023 22:10, Volodymyr Babchuk wrote:
> > > > From: Oleksandr Tyshchenko 
> > > > 
> > > > Instead of forcing the owner to domid 0, use XS_PRESERVE_OWNER to
> > > > inherit the owner of the directory.
> > > 
> > > Ah... so that's why the previous patch is there.
> > > 
> > > This is not the right way to fix it. The QEMU Xen support is *assuming* 
> > > that
> > > QEMU is either running in, or emulating, dom0. In the emulation case this 
> > > is
> > > probably fine, but the 'real Xen' case it should be using the correct 
> > > domid
> > > for node creation. I guess this could either be supplied on the command 
> > > line
> > > or discerned by reading the local domain 'domid' node.
> > 
> > yes, it should be passed as command line option to QEMU
> 
> I'm not sure I like the idea of a command line option for something
> which QEMU could discover for itself.

That's fine too. I meant to say "yes, as far as I know the toolstack
passes the domid to QEMU as a command line option today".



Re: [PATCH v2 6/6] xen_arm: Add virtual PCIe host bridge support

2023-11-22 Thread Stefano Stabellini
+Vikram

On Tue, 21 Nov 2023, Volodymyr Babchuk wrote:
> From: Oleksandr Tyshchenko 
> 
> The bridge is needed for virtio-pci support, as QEMU can emulate the
> whole bridge with any virtio-pci devices connected to it.
> 
> This patch provides a flexible way to configure PCIe brige resources
> with xenstore. We made this for several reasons:
> 
> - We don't want to clash with vPCI devices, so we need information
>   from Xen toolstack on which PCI bus to use.
> - The guest memory layout that describes these resources is not stable
>   and may vary between guests, so we cannot rely on static resources
>   to be always the same for both ends.
> - Also the device-models which run in different domains and serve
>   virtio-pci devices for the same guest should use different host
>   bridge resources for Xen to distinguish. The rule for the guest
>   device-tree generation is one PCI host bridge per backend domain.
> 
> Signed-off-by: Oleksandr Tyshchenko 
> Signed-off-by: Volodymyr Babchuk 

There is still a discussion ongoing on xen-devel if / how to register a
PCI Root Complex or individual BDFs. In the meantime a couple of
comments.

Typically emulated devices are configured in QEMU via QEMU command line
parameters, not xenstore. If you are running QEMU in a domU (instead of
Dom0) you can always read config parameters from xenstore from a wrapper
bash script (using xenstore-read) and then pass the right command line
options to QEMU.

If you need help in adding new QEMU command line options, Vikram (CCed)
can help.


> ---
> 
> Changes from v1:
> 
>  - Renamed virtio_pci_host to pcie_host entries in XenStore, because
>  there is nothing specific to virtio-pci: any PCI device can be
>  emulated via this newly created bridge.
> ---
>  hw/arm/xen_arm.c| 186 
>  hw/xen/xen-hvm-common.c |   9 +-
>  include/hw/xen/xen_native.h |   8 +-
>  3 files changed, 200 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index b9c3ae14b6..d506d55d0f 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -22,6 +22,7 @@
>   */
>  
>  #include "qemu/osdep.h"
> +#include "qemu/cutils.h"
>  #include "qemu/error-report.h"
>  #include "qapi/qapi-commands-migration.h"
>  #include "qapi/visitor.h"
> @@ -34,6 +35,9 @@
>  #include "hw/xen/xen-hvm-common.h"
>  #include "sysemu/tpm.h"
>  #include "hw/xen/arch_hvm.h"
> +#include "exec/address-spaces.h"
> +#include "hw/pci-host/gpex.h"
> +#include "hw/virtio/virtio-pci.h"
>  
>  #define TYPE_XEN_ARM  MACHINE_TYPE_NAME("xenpvh")
>  OBJECT_DECLARE_SIMPLE_TYPE(XenArmState, XEN_ARM)
> @@ -58,6 +62,11 @@ struct XenArmState {
>  struct {
>  uint64_t tpm_base_addr;
>  } cfg;
> +
> +MemMapEntry pcie_mmio;
> +MemMapEntry pcie_ecam;
> +MemMapEntry pcie_mmio_high;
> +int pcie_irq;
>  };
>  
>  static MemoryRegion ram_lo, ram_hi;
> @@ -73,6 +82,7 @@ static MemoryRegion ram_lo, ram_hi;
>  #define NR_VIRTIO_MMIO_DEVICES   \
> (GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
>  
> +/* TODO It should be xendevicemodel_set_pci_intx_level() for PCI interrupts. 
> */
>  static void xen_set_irq(void *opaque, int irq, int level)
>  {
>  if (xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level)) {
> @@ -129,6 +139,176 @@ static void xen_init_ram(MachineState *machine)
>  }
>  }
>  
> +static void xen_create_pcie(XenArmState *xam)
> +{
> +MemoryRegion *mmio_alias, *mmio_alias_high, *mmio_reg;
> +MemoryRegion *ecam_alias, *ecam_reg;
> +DeviceState *dev;
> +int i;
> +
> +dev = qdev_new(TYPE_GPEX_HOST);
> +sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
> +
> +/* Map ECAM space */
> +ecam_alias = g_new0(MemoryRegion, 1);
> +ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> +memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
> + ecam_reg, 0, xam->pcie_ecam.size);
> +memory_region_add_subregion(get_system_memory(), xam->pcie_ecam.base,
> +ecam_alias);
> +
> +/* Map the MMIO space */
> +mmio_alias = g_new0(MemoryRegion, 1);
> +mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
> +memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
> + mmio_reg,
> + xam->pcie_mmio.base,
> + xam->pcie_mmio.size);
> +memory_region_add_subregion(get_system_memory(), xam->pcie_mmio.base,
> +mmio_alias);
> +
> +/* Map the MMIO_HIGH space */
> +mmio_alias_high = g_new0(MemoryRegion, 1);
> +memory_region_init_alias(mmio_alias_high, OBJECT(dev), "pcie-mmio-high",
> + mmio_reg,
> + xam->pcie_mmio_high.base,
> + xam->pcie_mmio_high.size);
> +memory_region_add_subregion(get_system_memory(), 
> 

Re: [PATCH v2 4/6] xen_pvdev: Do not assume Dom0 when creating a directory

2023-11-22 Thread Stefano Stabellini
On Wed, 22 Nov 2023, Paul Durrant wrote:
> On 21/11/2023 22:10, Volodymyr Babchuk wrote:
> > From: Oleksandr Tyshchenko 
> > 
> > Instead of forcing the owner to domid 0, use XS_PRESERVE_OWNER to
> > inherit the owner of the directory.
> 
> Ah... so that's why the previous patch is there.
> 
> This is not the right way to fix it. The QEMU Xen support is *assuming* that
> QEMU is either running in, or emulating, dom0. In the emulation case this is
> probably fine, but the 'real Xen' case it should be using the correct domid
> for node creation. I guess this could either be supplied on the command line
> or discerned by reading the local domain 'domid' node.

yes, it should be passed as command line option to QEMU

 
> > Note that for other than Dom0 domain (non toolstack domain) the
> > "driver_domain" property should be set in domain config file for the
> > toolstack to create required directories in advance.
> > 
> > Signed-off-by: Oleksandr Tyshchenko 
> > Signed-off-by: Volodymyr Babchuk 
> > ---
> >   hw/xen/xen_pvdev.c | 3 ++-
> >   1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/xen/xen_pvdev.c b/hw/xen/xen_pvdev.c
> > index c5ad71e8dc..42bdd4f6c8 100644
> > --- a/hw/xen/xen_pvdev.c
> > +++ b/hw/xen/xen_pvdev.c
> > @@ -60,7 +60,8 @@ void xen_config_cleanup(void)
> > int xenstore_mkdir(char *path, int p)
> >   {
> > -if (!qemu_xen_xs_create(xenstore, 0, 0, xen_domid, p, path)) {
> > +if (!qemu_xen_xs_create(xenstore, 0, XS_PRESERVE_OWNER,
> > +xen_domid, p, path)) {
> >   xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
> >   return -1;
> >   }
> 



Re: [PATCH v2 3/6] xen: xenstore: add possibility to preserve owner

2023-11-22 Thread Stefano Stabellini
On Wed, 22 Nov 2023, Paul Durrant wrote:
> On 21/11/2023 22:10, Volodymyr Babchuk wrote:
> > Add option to preserve owner when creating an entry in Xen Store. This
> > may be needed in cases when Qemu is working as device model in a
> 
> *may* be needed?
> 
> I don't undertstand why this patch is necessary and the commit comment isn't
> really helping me.
> 
> > domain that is Domain-0, e.g. in driver domain.

I think Volodymyr meant: 

domain that is *not* Domain-0

So I am guessing this patch is needed otherwise QEMU will run into
permissions errors doing xenstore operations



> > "owner" parameter for qemu_xen_xs_create() function can have special
> > value XS_PRESERVE_OWNER, which will make specific implementation to
> > get original owner of an entry and pass it back to
> > set_permissions() call.
> > 
> > Please note, that XenStore inherits permissions, so even if entry is
> > newly created by, it already has the owner set to match owner of entry
> > at previous level.
> > 
> > Signed-off-by: Volodymyr Babchuk 
> 



Re: [QEMU][PATCHv2 0/8] Xen: support grant mappings.

2023-11-14 Thread Stefano Stabellini
On Tue, 14 Nov 2023, Juergen Gross wrote:
> On 13.11.23 21:24, David Woodhouse wrote:
> > On Fri, 2023-10-27 at 07:27 +0200, Juergen Gross wrote:
> > > On 26.10.23 22:56, Stefano Stabellini wrote:
> > > > On Thu, 26 Oct 2023, David Woodhouse wrote:
> > > > > On Thu, 2023-10-26 at 13:36 -0700, Stefano Stabellini wrote:
> > > > > > 
> > > > > > > This seems like a lot of code to replace that simpler option... is
> > > > > > > there a massive performance win from doing it this way? Would we
> > > > > > > want
> > > > > > > to use this trick for the Xen PV backends (qdisk, qnic) *too*?
> > > > > > > Might it
> > > > > > > make sense to introduce the simple version and *then* the
> > > > > > > optimisation,
> > > > > > > with some clear benchmarking to show the win?
> > > > > > 
> > > > > > This is not done for performance but for safety (as in safety
> > > > > > certifications, ISO 26262, etc.). This is to enable unprivileged
> > > > > > virtio
> > > > > > backends running in a DomU. By unprivileged I mean a virtio backend
> > > > > > that
> > > > > > is unable to map arbitrary memory (the xenforeignmemory interface is
> > > > > > prohibited).
> > > > > > 
> > > > > > The goal is to run Xen on safety-critical systems such as cars,
> > > > > > industrial robots and more. In this configuration there is no
> > > > > > traditional Dom0 in the system at all. If you  would like to know
> > > > > > more:
> > > > > > https://www.youtube.com/watch?v=tisljY6Bqv0=PLYyw7IQjL-zHtpYtMpFR3KYdRn0rcp5Xn=8
> > > > > 
> > > > > Yeah, I understand why we're using grant mappings instead of just
> > > > > directly having access via foreignmem mappings. That wasn't what I was
> > > > > confused about.
> > > > > 
> > > > > What I haven't worked out is why we're implementing this through an
> > > > > automatically-populated MemoryRegion in QEMU, rather than just using
> > > > > grant mapping ops like we always have.
> > > > > 
> > > > > It seems like a lot of complexity just to avoid calling
> > > > > qemu_xen_gnttab_map_refs() from the virtio backend.
> > > > 
> > > > I think there are two questions here. One question is "Why do we need
> > > > all the new grant mapping code added to xen-mapcache.c in patch #7?
> > > > Can't we use qemu_xen_gnttab_map_refs() instead?"
> > > 
> > > The main motivation was to _avoid_ having to change all the backends.
> > > 
> > > My implementation enables _all_ qemu based virtio backends to use grant
> > > mappings. And if a new backend is added to qemu, there will be no change
> > > required to make it work with grants.
> > 
> > I'm not really convinced I buy that. This is a lot of complexity, and
> > don't backends need to call an appropriate mapping function to map via
> > an IOMMU if it's present anyway? Make then call a helper where you can
> > do this in one place directly instead of through a fake MemoryRegion,
> > and you're done, surely?
> 
> That was tested with unmodified block and net backends in qemu.
> 
> Maybe I missed something, but I think the IOMMU accesses are _not_ covering
> accesses to the virtio rings from qemu. And this is something you really
> want for driver domains.

Hi Juergen, David,

I don't think we should use the IOMMU accesses and I don't think we
should change the virtio backends.

My preference would be to either use the patch as is, or (better) to
reuse the original Xen hooks already in place (qemu_ram_ptr_length and
xen_invalidate_map_cache_entry, see
https://marc.info/?l=qemu-devel=169828434927778).

Juergen did a good job at adding new hooks in a clean way, but from my
point of view I would still prefer to only have the two existing hooks
instead of having 4 (2 old, 2 new).

[PULL 1/1] Xen: Fix xen_set_irq() and xendevicemodel_set_irq_level()

2023-11-07 Thread Stefano Stabellini
Remove '=' from 'if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500'.
Because xendevicemodel_set_irq_level() was introduced in 4.15 version.

Also, update xendevicemodel_set_irq_level() to return -1 for older versions.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
---
 hw/arm/xen_arm.c| 4 +++-
 include/hw/xen/xen_native.h | 4 ++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
index f83b983ec5..a5631529d0 100644
--- a/hw/arm/xen_arm.c
+++ b/hw/arm/xen_arm.c
@@ -75,7 +75,9 @@ static MemoryRegion ram_lo, ram_hi;
 
 static void xen_set_irq(void *opaque, int irq, int level)
 {
-xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level);
+if (xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level)) {
+error_report("xendevicemodel_set_irq_level failed");
+}
 }
 
 static void xen_create_virtio_mmio_devices(XenArmState *xam)
diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
index 5d2718261f..6f09c48823 100644
--- a/include/hw/xen/xen_native.h
+++ b/include/hw/xen/xen_native.h
@@ -523,12 +523,12 @@ static inline int xen_set_ioreq_server_state(domid_t dom,
  enable);
 }
 
-#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41500
 static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
domid_t domid, uint32_t irq,
unsigned int level)
 {
-return 0;
+return -1;
 }
 #endif
 
-- 
2.25.1




[PULL 0/1] xen-virtio-fix-1-tag

2023-11-07 Thread Stefano Stabellini
Minor bug fix for Virtio/Xen support


The following changes since commit 462ad017ed76889d46696a3581e1b52343f9b683:

  Merge tag 'xen-virtio-fix-1-tag' of https://gitlab.com/marcandre.lureau/qemu 
into staging (2023-11-07 19:00:03 +0800)

are available in the Git repository at:

  https://gitlab.com/sstabellini/qemu.git 

for you to fetch changes up to 01bb72afbb95003fb5562e341a592f583e27e280:

  Xen: Fix xen_set_irq() and xendevicemodel_set_irq_level() (2023-11-07 
13:03:19 -0800)


Vikram Garhwal (1):
  Xen: Fix xen_set_irq() and xendevicemodel_set_irq_level()

 hw/arm/xen_arm.c| 4 +++-
 include/hw/xen/xen_native.h | 4 ++--
 2 files changed, 5 insertions(+), 3 deletions(-)



Re: [QEMU][PATCH v1] Xen: Fix xen_set_irq() and xendevicemodel_set_irq_level()

2023-11-01 Thread Stefano Stabellini
On Wed, 1 Nov 2023, Vikram Garhwal wrote:
> Remove '=' from 'if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500'.
> Because xendevicemodel_set_irq_level() was introduced in 4.15 version.
> 
> Also, update xendevicemodel_set_irq_level() to return -1 for older versions.
> 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/arm/xen_arm.c| 4 +++-
>  include/hw/xen/xen_native.h | 4 ++--
>  2 files changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index f83b983ec5..a5631529d0 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -75,7 +75,9 @@ static MemoryRegion ram_lo, ram_hi;
>  
>  static void xen_set_irq(void *opaque, int irq, int level)
>  {
> -xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level);
> +if (xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level)) {
> +error_report("xendevicemodel_set_irq_level failed");
> +}
>  }
>  
>  static void xen_create_virtio_mmio_devices(XenArmState *xam)
> diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
> index 5d2718261f..6f09c48823 100644
> --- a/include/hw/xen/xen_native.h
> +++ b/include/hw/xen/xen_native.h
> @@ -523,12 +523,12 @@ static inline int xen_set_ioreq_server_state(domid_t 
> dom,
>   enable);
>  }
>  
> -#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41500
>  static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
> domid_t domid, uint32_t irq,
> unsigned int level)
>  {
> -return 0;
> +return -1;
>  }
>  #endif
>  
> -- 
> 2.17.1
> 



Re: [QEMU][PATCHv2 0/8] Xen: support grant mappings.

2023-10-26 Thread Stefano Stabellini
On Thu, 26 Oct 2023, David Woodhouse wrote:
> On Thu, 2023-10-26 at 13:36 -0700, Stefano Stabellini wrote:
> > 
> > > This seems like a lot of code to replace that simpler option... is
> > > there a massive performance win from doing it this way? Would we want
> > > to use this trick for the Xen PV backends (qdisk, qnic) *too*? Might it
> > > make sense to introduce the simple version and *then* the optimisation,
> > > with some clear benchmarking to show the win?
> > 
> > This is not done for performance but for safety (as in safety
> > certifications, ISO 26262, etc.). This is to enable unprivileged virtio
> > backends running in a DomU. By unprivileged I mean a virtio backend that
> > is unable to map arbitrary memory (the xenforeignmemory interface is
> > prohibited).
> > 
> > The goal is to run Xen on safety-critical systems such as cars,
> > industrial robots and more. In this configuration there is no
> > traditional Dom0 in the system at all. If you  would like to know more:
> > https://www.youtube.com/watch?v=tisljY6Bqv0=PLYyw7IQjL-zHtpYtMpFR3KYdRn0rcp5Xn=8
> 
> Yeah, I understand why we're using grant mappings instead of just
> directly having access via foreignmem mappings. That wasn't what I was
> confused about.
> 
> What I haven't worked out is why we're implementing this through an
> automatically-populated MemoryRegion in QEMU, rather than just using
> grant mapping ops like we always have.
> 
> It seems like a lot of complexity just to avoid calling
> qemu_xen_gnttab_map_refs() from the virtio backend.

I think there are two questions here. One question is "Why do we need
all the new grant mapping code added to xen-mapcache.c in patch #7?
Can't we use qemu_xen_gnttab_map_refs() instead?"

Good question, I'll let Juergen and Vikram comment as original authors.

And the second question is where to call the grant mapping from (whether
the new code or the old qemu_xen_gnttab_map_refs code it doesn't
matter). It could be even simpler than calling it from the virtio
backends: we could just call it from the existing qemu_ram_ptr_length()
hook. See this discussion:
https://marc.info/?l=qemu-devel=169828434927778

Re: [QEMU][PATCHv2 0/8] Xen: support grant mappings.

2023-10-26 Thread Stefano Stabellini
On Thu, 26 Oct 2023, David Woodhouse wrote:
> On Thu, 2023-10-26 at 11:07 -0700, Stefano Stabellini wrote:
> > On Thu, 26 Oct 2023, David Woodhouse wrote:
> > > On Wed, 2023-10-25 at 14:24 -0700, Vikram Garhwal wrote:
> > > > Hi,
> > > > This patch series add support for grant mappings as a pseudo RAM region 
> > > > for Xen.
> > > > 
> > > > Enabling grant mappings patches(first 6) are written by Juergen in 2021.
> > > > 
> > > > QEMU Virtio device provides an emulated backends for Virtio frontned 
> > > > devices
> > > > in Xen.
> > > > Please set "iommu_platform=on" option when invoking QEMU. As this will 
> > > > set
> > > > VIRTIO_F_ACCESS_PLATFORM feature which will be used by virtio frontend 
> > > > in Xen
> > > > to know whether backend supports grants or not.
> > > 
> > > I don't really understand what's going on here. The subject of the
> > > cover letter certainly doesn't help me, because we *already* support
> > > grant mappings under Xen, don't we?
> > > 
> > > I found
> > > https://static.linaro.org/connect/lvc21/presentations/lvc21-314.pdf but
> > > I think it's a bit out of date; the decision about how to handle grant
> > > mappings for virtio devices is still 'TBD'.
> > 
> > See this presentation:
> > https://www.youtube.com/watch?v=boRQ8UHc760
> > 
> > The patch series is for the guest (e.g. Linux) to use grants to share
> > memory with virtio devices. The plumbing was already done in Linux a
> > couple of years ago, but QEMU support for it is still missing.
> 
> Thanks.
> 
> > > Can you talk me through the process of what happens when a guest wants
> > > to a virtio device to initiate 'DMA' to one of its pages? I assume it
> > > starts by creating a grant mapping, and then taking the gntref and...
> > > then what?
> > 
> > First the guest gets a grant reference for the page, then it uses it as
> > "dma address" to pass to the virtio device. The top bit (1ULL << 63) is
> > used to signal that the address in question is a grant address.
> 
> OK, so the guest sets the top bit in the DMA address and that indicates
> that this is no longer actually a guest physical address, but instead,
> bits 62-12 are a (starting) grant ref. (And the address *within* the
> page is still bits 0-11, assuming 4KiB pages).
> 
> An alternative way of implementing this on the QEMU side would just be
> to teach the virtio mapping to recognise the "special" format with the
> top bit set, and call qemu_xen_gnttab_map_refs() directly to get the
> mapping?
> 
> This seems like a lot of code to replace that simpler option... is
> there a massive performance win from doing it this way? Would we want
> to use this trick for the Xen PV backends (qdisk, qnic) *too*? Might it
> make sense to introduce the simple version and *then* the optimisation,
> with some clear benchmarking to show the win?

This is not done for performance but for safety (as in safety
certifications, ISO 26262, etc.). This is to enable unprivileged virtio
backends running in a DomU. By unprivileged I mean a virtio backend that
is unable to map arbitrary memory (the xenforeignmemory interface is
prohibited).

The goal is to run Xen on safety-critical systems such as cars,
industrial robots and more. In this configuration there is no
traditional Dom0 in the system at all. If you  would like to know more:
https://www.youtube.com/watch?v=tisljY6Bqv0=PLYyw7IQjL-zHtpYtMpFR3KYdRn0rcp5Xn=8


> If we're just going to switch to grant mappings, why *aren't* we using
> Xen PV device models on Arm anyway?

I think you mean Xen PV drivers. Yes we have been using them for a
while. Now we would also like to add the option of running virtio
devices but we can only do that if the virtio backend is unprivileged as
we have no Dom0 in the system.

Re: [QEMU][PATCHv2 0/8] Xen: support grant mappings.

2023-10-26 Thread Stefano Stabellini
On Thu, 26 Oct 2023, David Woodhouse wrote:
> On Wed, 2023-10-25 at 14:24 -0700, Vikram Garhwal wrote:
> > Hi,
> > This patch series add support for grant mappings as a pseudo RAM region for 
> > Xen.
> > 
> > Enabling grant mappings patches(first 6) are written by Juergen in 2021.
> > 
> > QEMU Virtio device provides an emulated backends for Virtio frontned devices
> > in Xen.
> > Please set "iommu_platform=on" option when invoking QEMU. As this will set
> > VIRTIO_F_ACCESS_PLATFORM feature which will be used by virtio frontend in 
> > Xen
> > to know whether backend supports grants or not.
> 
> I don't really understand what's going on here. The subject of the
> cover letter certainly doesn't help me, because we *already* support
> grant mappings under Xen, don't we?
> 
> I found
> https://static.linaro.org/connect/lvc21/presentations/lvc21-314.pdf but
> I think it's a bit out of date; the decision about how to handle grant
> mappings for virtio devices is still 'TBD'.

See this presentation:
https://www.youtube.com/watch?v=boRQ8UHc760

The patch series is for the guest (e.g. Linux) to use grants to share
memory with virtio devices. The plumbing was already done in Linux a
couple of years ago, but QEMU support for it is still missing.


> Can you talk me through the process of what happens when a guest wants
> to a virtio device to initiate 'DMA' to one of its pages? I assume it
> starts by creating a grant mapping, and then taking the gntref and...
> then what?

First the guest gets a grant reference for the page, then it uses it as
"dma address" to pass to the virtio device. The top bit (1ULL << 63) is
used to signal that the address in question is a grant address.

See in Linux:
drivers/xen/grant-dma-ops.c grant_to_dma, dma_to_grant,
xen_grant_dma_alloc, etc.


> I don't see any changes to the virtio devices themselves in this
> series; are we doing something that will make it work by magic? If so,
> it might be useful to explain that magic...

Yes something like that :-)
https://marc.info/?l=xen-devel=165419780304962=2

Vikram, I think it would be a good idea to submit a separate patch to
xen.git to add a document under docs/ to capture this.



Re: [QEMU][PATCH v1 5/7] memory: add MemoryRegion map and unmap callbacks

2023-10-25 Thread Stefano Stabellini
On Wed, 11 Oct 2023, Juergen Gross wrote:
> On 10.10.23 02:17, Stefano Stabellini wrote:
> > On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> > > From: Juergen Gross 
> > > 
> > > In order to support mapping and unmapping guest memory dynamically to
> > > and from qemu during address_space_[un]map() operations add the map()
> > > and unmap() callbacks to MemoryRegionOps.
> > > 
> > > Those will be used e.g. for Xen grant mappings when performing guest
> > > I/Os.
> > > 
> > > Signed-off-by: Juergen Gross 
> > > Signed-off-by: Vikram Garhwal 
> > 
> > Can't we just use the existing Xen hooks in qemu_ram_ptr_length and
> > xen_invalidate_map_cache_entry? Do we really need new ones?
> 
> I tried your idea first and it didn't work out.
> 
> The existing hooks are invoked not only when explicitly [un]mapping memory
> regions, but in some other cases, too. Have a look for qemu_ram_ptr_length()
> call in flatview_write_continue().

Hi Juergen, thanks for the explanation and sorry for my late reply. I
missed your email when it came out.

If that is the only problem, it seems to me that it could be solved. The
call to qemu_ram_ptr_length() in flatview_write_continue is unlocked. It
should be also distinguishable by address (the grants have the top bit
set?)

So from qemu_ram_ptr_length() we could call xen_map_grant_dyn only when
locked. And in xen_map_grant_dyn we could also check that
XEN_GRANT_ADDR_OFF is set before continuing.

Do you see any other issues with it?



Re: [QEMU][PATCHv2 7/8] xen: add map and unmap callbacks for grant region

2023-10-25 Thread Stefano Stabellini
On Wed, 25 Oct 2023, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> Add the callbacks for mapping/unmapping guest memory via grants to the
> special grant memory region.
> 
> Signed-off-by: Juergen Gross 
> Signed-off-by: Vikram Garhwal 
> ---
>  hw/xen/xen-mapcache.c | 175 +-
>  system/physmem.c  |  11 ++-
>  2 files changed, 181 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 8a61c7dde6..feb4a3b886 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -9,6 +9,8 @@
>   */
>  
>  #include "qemu/osdep.h"
> +#include "qemu/queue.h"
> +#include "qemu/thread.h"
>  #include "qemu/units.h"
>  #include "qemu/error-report.h"
>  
> @@ -23,6 +25,8 @@
>  #include "sysemu/xen-mapcache.h"
>  #include "trace.h"
>  
> +#include 
> +#include 
>  
>  //#define MAPCACHE_DEBUG
>  
> @@ -385,7 +389,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_try(void *ptr)
>  {
>  MapCacheEntry *entry = NULL;
>  MapCacheRev *reventry;
> @@ -594,10 +598,178 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
>  return p;
>  }
>  
> +struct XENMappedGrantRegion {
> +void *addr;
> +unsigned int pages;
> +unsigned int refs;
> +unsigned int prot;
> +uint32_t idx;
> +QLIST_ENTRY(XENMappedGrantRegion) list;
> +};
> +
> +static xengnttab_handle *xen_region_gnttabdev;
> +static QLIST_HEAD(GrantRegionList, XENMappedGrantRegion) xen_grant_mappings =
> +QLIST_HEAD_INITIALIZER(xen_grant_mappings);
> +static QemuMutex xen_map_mutex;
> +
> +static void *xen_map_grant_dyn(MemoryRegion **mr, hwaddr addr, hwaddr *plen,
> +   bool is_write, MemTxAttrs attrs)
> +{
> +unsigned int page_off = addr & (XC_PAGE_SIZE - 1);
> +unsigned int i;
> +unsigned int total_grants = 0;
> +unsigned int nrefs = (page_off + *plen + XC_PAGE_SIZE - 1) >> 
> XC_PAGE_SHIFT;
> +uint32_t ref = (addr - XEN_GRANT_ADDR_OFF) >> XC_PAGE_SHIFT;
> +uint32_t *refs = NULL;
> +unsigned int prot = PROT_READ;
> +struct XENMappedGrantRegion *mgr = NULL;
> +
> +if (is_write) {
> +prot |= PROT_WRITE;
> +}
> +
> +qemu_mutex_lock(_map_mutex);
> +
> +QLIST_FOREACH(mgr, _grant_mappings, list) {
> +if (mgr->idx == ref &&
> +mgr->pages == nrefs &&
> +(mgr->prot & prot) == prot) {
> +break;
> +}
> +
> +total_grants += mgr->pages;
> +}
> +
> +if (!mgr) {
> +if (nrefs + total_grants >= XEN_MAX_VIRTIO_GRANTS) {
> +return NULL;

missing qemu_mutex_unlock


> +}
> +
> +mgr = g_new(struct XENMappedGrantRegion, 1);
> +
> +if (nrefs == 1) {
> +refs = 
> +} else {
> +refs = g_new(uint32_t, nrefs);
> +for (i = 0; i < nrefs; i++) {
> +refs[i] = ref + i;
> +}
> +}
> +mgr->addr = xengnttab_map_domain_grant_refs(xen_region_gnttabdev, 
> nrefs,
> +xen_domid, refs, prot);
> +if (mgr->addr) {
> +mgr->pages = nrefs;
> +mgr->refs = 1;
> +mgr->prot = prot;
> +mgr->idx = ref;
> +
> +QLIST_INSERT_HEAD(_grant_mappings, mgr, list);
> +} else {
> +g_free(mgr);
> +mgr = NULL;
> +}
> +} else {
> +mgr->refs++;
> +}
> +
> +qemu_mutex_unlock(_map_mutex);
> +
> +if (nrefs > 1) {
> +g_free(refs);
> +}
> +
> +return mgr ? mgr->addr + page_off : NULL;
> +}
> +
> +static void xen_unmap_grant_dyn(MemoryRegion *mr, void *buffer, ram_addr_t 
> addr,
> +hwaddr len, bool is_write, hwaddr access_len)
> +{
> +unsigned int page_off = (unsigned long)buffer & (XC_PAGE_SIZE - 1);
> +unsigned int nrefs = (page_off + len + XC_PAGE_SIZE - 1) >> 
> XC_PAGE_SHIFT;
> +unsigned int prot = PROT_READ;
> +struct XENMappedGrantRegion *mgr = NULL;
> +
> +if (is_write) {
> +prot |= PROT_WRITE;
> +}
> +
> +qemu_mutex_lock(_map_mutex);
> +
> +QLIST_FOREACH(mgr, _grant_mappings, list) {
> +if (mgr->addr == buffer - page_off &&
> +mgr->pages == nrefs &&
> +(mgr->prot & prot) == prot) {
> +break;
> +}
> +}
> +if (mgr) {
> +mgr->refs--;
> +if (!mgr->refs) {
> +xengnttab_unmap(xen_region_gnttabdev, mgr->addr, nrefs);
> +
> +QLIST_REMOVE(mgr, list);
> +g_free(mgr);
> +}
> +} else {
> +error_report("xen_unmap_grant_dyn() trying to unmap unknown buffer");
> +}
> +
> +qemu_mutex_unlock(_map_mutex);
> +}
> +
> +static ram_addr_t xen_ram_addr_from_grant_cache(void *ptr)
> +{
> +unsigned int 

Re: [QEMU][PATCHv2 4/8] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()

2023-10-25 Thread Stefano Stabellini
On Wed, 25 Oct 2023, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> 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 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  system/physmem.c | 58 +++-
>  1 file changed, 23 insertions(+), 35 deletions(-)
> 
> diff --git a/system/physmem.c b/system/physmem.c
> index 7a7f95b8b9..667a695078 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -2163,38 +2163,8 @@ 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 *ram_block, ram_addr_t addr)
> -{
> -RAMBlock *block = ram_block;
> -
> -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.
>   */
> @@ -2202,7 +2172,9 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, 
> ram_addr_t addr,
>   hwaddr *size, bool lock)
>  {
>  RAMBlock *block = ram_block;
> -if (*size == 0) {
> +hwaddr len = 0;
> +
> +if (size && *size == 0) {
>  return NULL;
>  }
>  
> @@ -2210,7 +2182,10 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_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
> @@ -2218,7 +2193,7 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_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);
> @@ -2227,6 +2202,19 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_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.17.1
> 



Re: [QEMU][PATCHv2 3/8] xen: add pseudo RAM region for grant mappings

2023-10-25 Thread Stefano Stabellini
On Wed, 25 Oct 2023, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> Add a memory region which can be used to automatically map granted
> memory. It is starting at 0x8000ULL in order to be able to
> distinguish it from normal RAM.
> 
> For this reason the xen.ram memory region is expanded, which has no
> further impact as it is used just as a container of the real RAM
> regions and now the grant region.
> 
> Signed-off-by: Juergen Gross 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/i386/xen/xen-hvm.c   |  3 +++
>  hw/xen/xen-hvm-common.c |  4 ++--
>  hw/xen/xen-mapcache.c   | 27 +++
>  include/hw/xen/xen-hvm-common.h |  2 ++
>  include/hw/xen/xen_pvdev.h  |  3 +++
>  include/sysemu/xen-mapcache.h   |  3 +++
>  6 files changed, 40 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> index f42621e674..67a8a6 100644
> --- a/hw/i386/xen/xen-hvm.c
> +++ b/hw/i386/xen/xen-hvm.c
> @@ -172,6 +172,9 @@ static void xen_ram_init(PCMachineState *pcms,
>   x86ms->above_4g_mem_size);
>  memory_region_add_subregion(sysmem, 0x1ULL, _hi);
>  }
> +
> +/* Add grant mappings as a pseudo RAM region. */
> +ram_grants = *xen_init_grant_ram();
>  }
>  
>  static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size)
> diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
> index 565dc39c8f..b7255977a5 100644
> --- a/hw/xen/xen-hvm-common.c
> +++ b/hw/xen/xen-hvm-common.c
> @@ -9,7 +9,7 @@
>  #include "hw/boards.h"
>  #include "hw/xen/arch_hvm.h"
>  
> -MemoryRegion ram_memory;
> +MemoryRegion ram_memory, ram_grants;
>  
>  void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
> Error **errp)
> @@ -26,7 +26,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, 
> MemoryRegion *mr,
>  return;
>  }
>  
> -if (mr == _memory) {
> +if (mr == _memory || mr == _grants) {
>  return;
>  }
>  
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index f7d974677d..8115c44c00 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -14,7 +14,9 @@
>  
>  #include 
>  
> +#include "hw/xen/xen-hvm-common.h"
>  #include "hw/xen/xen_native.h"
> +#include "hw/xen/xen_pvdev.h"
>  #include "qemu/bitmap.h"
>  
>  #include "sysemu/runstate.h"
> @@ -597,3 +599,28 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
>  mapcache_unlock();
>  return p;
>  }
> +
> +MemoryRegion *xen_init_grant_ram(void)
> +{
> +RAMBlock *block;
> +
> +memory_region_init(_grants, NULL, "xen.grants",
> +   XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE);
> +block = g_malloc0(sizeof(*block));
> +block->mr = _grants;
> +block->used_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE;
> +block->max_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE;
> +block->fd = -1;
> +block->page_size = XC_PAGE_SIZE;
> +block->host = (void *)XEN_GRANT_ADDR_OFF;
> +block->offset = XEN_GRANT_ADDR_OFF;
> +block->flags = RAM_PREALLOC;
> +ram_grants.ram_block = block;
> +ram_grants.ram = true;
> +ram_grants.terminates = true;
> +ram_block_add_list(block);
> +memory_region_add_subregion(get_system_memory(), XEN_GRANT_ADDR_OFF,
> +_grants);
> +
> +return _grants;
> +}
> diff --git a/include/hw/xen/xen-hvm-common.h b/include/hw/xen/xen-hvm-common.h
> index 4e9904f1a6..0d300ba898 100644
> --- a/include/hw/xen/xen-hvm-common.h
> +++ b/include/hw/xen/xen-hvm-common.h
> @@ -17,6 +17,8 @@
>  #include 
>  
>  extern MemoryRegion ram_memory;
> +
> +extern MemoryRegion ram_grants;
>  extern MemoryListener xen_io_listener;
>  extern DeviceListener xen_device_listener;
>  
> diff --git a/include/hw/xen/xen_pvdev.h b/include/hw/xen/xen_pvdev.h
> index ddad4b9f36..0f1b5edfa9 100644
> --- a/include/hw/xen/xen_pvdev.h
> +++ b/include/hw/xen/xen_pvdev.h
> @@ -80,4 +80,7 @@ int xen_pv_send_notify(struct XenLegacyDevice *xendev);
>  void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
> const char *fmt, ...)  G_GNUC_PRINTF(3, 4);
>  
> +#define XEN_GRANT_ADDR_OFF0x8000ULL
> +#define XEN_MAX_VIRTIO_GRANTS 65536
> +
>  #endif /* QEMU_HW_XEN_PVDEV_H */
> diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h
> index c8e7c2f6cf..f4

Re: [QEMU][PATCHv2 2/8] softmmu: physmem: Split ram_block_add()

2023-10-25 Thread Stefano Stabellini
On Wed, 25 Oct 2023, Vikram Garhwal wrote:
> Extract ram block list update to a new function ram_block_add_list(). This is
> done to support grant mappings which adds a memory region for granted memory 
> and
> updates the ram_block list.
> 
> Signed-off-by: Juergen Gross 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  include/exec/ram_addr.h |  1 +
>  system/physmem.c| 62 ++---
>  2 files changed, 40 insertions(+), 23 deletions(-)
> 
> diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
> index 90676093f5..c0b5f9a7d0 100644
> --- a/include/exec/ram_addr.h
> +++ b/include/exec/ram_addr.h
> @@ -139,6 +139,7 @@ void qemu_ram_free(RAMBlock *block);
>  int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp);
>  
>  void qemu_ram_msync(RAMBlock *block, ram_addr_t start, ram_addr_t length);
> +void ram_block_add_list(RAMBlock *new_block);
>  
>  /* Clear whole block of mem */
>  static inline void qemu_ram_block_writeback(RAMBlock *block)
> diff --git a/system/physmem.c b/system/physmem.c
> index fc2b0fee01..7a7f95b8b9 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -1803,12 +1803,47 @@ static void dirty_memory_extend(ram_addr_t 
> old_ram_size,
>  }
>  }
>  
> +static void ram_block_add_list_locked(RAMBlock *new_block)
> + {
> + RAMBlock *block;
> + RAMBlock *last_block = NULL;
> +
> +/*
> + * Keep the list sorted from biggest to smallest block.  Unlike QTAILQ,
> + * QLIST (which has an RCU-friendly variant) does not have insertion at
> + * tail, so save the last element in last_block.
> + */
> +RAMBLOCK_FOREACH(block) {
> +last_block = block;
> +if (block->max_length < new_block->max_length) {
> +break;
> +}
> +}
> +if (block) {
> +QLIST_INSERT_BEFORE_RCU(block, new_block, next);
> +} else if (last_block) {
> +QLIST_INSERT_AFTER_RCU(last_block, new_block, next);
> +} else { /* list is empty */
> +QLIST_INSERT_HEAD_RCU(_list.blocks, new_block, next);
> +}
> +ram_list.mru_block = NULL;
> +
> +/* Write list before version */
> +smp_wmb();
> +ram_list.version++;
> +}
> +
> +void ram_block_add_list(RAMBlock *new_block)
> +{
> +qemu_mutex_lock_ramlist();
> +ram_block_add_list_locked(new_block);
> +qemu_mutex_unlock_ramlist();
> +}
> +
>  static void ram_block_add(RAMBlock *new_block, Error **errp)
>  {
>  const bool noreserve = qemu_ram_is_noreserve(new_block);
>  const bool shared = qemu_ram_is_shared(new_block);
> -RAMBlock *block;
> -RAMBlock *last_block = NULL;
>  ram_addr_t old_ram_size, new_ram_size;
>  Error *err = NULL;
>  
> @@ -1846,28 +1881,9 @@ static void ram_block_add(RAMBlock *new_block, Error 
> **errp)
>  if (new_ram_size > old_ram_size) {
>  dirty_memory_extend(old_ram_size, new_ram_size);
>  }
> -/* Keep the list sorted from biggest to smallest block.  Unlike QTAILQ,
> - * QLIST (which has an RCU-friendly variant) does not have insertion at
> - * tail, so save the last element in last_block.
> - */
> -RAMBLOCK_FOREACH(block) {
> -last_block = block;
> -if (block->max_length < new_block->max_length) {
> -break;
> -}
> -}
> -if (block) {
> -QLIST_INSERT_BEFORE_RCU(block, new_block, next);
> -} else if (last_block) {
> -QLIST_INSERT_AFTER_RCU(last_block, new_block, next);
> -} else { /* list is empty */
> -QLIST_INSERT_HEAD_RCU(_list.blocks, new_block, next);
> -}
> -ram_list.mru_block = NULL;
>  
> -/* Write list before version */
> -smp_wmb();
> -ram_list.version++;
> +ram_block_add_list_locked(new_block);
> +
>  qemu_mutex_unlock_ramlist();
>  
>  cpu_physical_memory_set_dirty_range(new_block->offset,
> -- 
> 2.17.1
> 



Re: [QEMU][PATCHv2 1/8] xen: when unplugging emulated devices skip virtio devices

2023-10-25 Thread Stefano Stabellini
On Thu, 26 Oct 2023, David Woodhouse wrote:
> On Wed, 2023-10-25 at 14:24 -0700, Vikram Garhwal wrote:
> > From: Juergen Gross 
> > 
> > Virtio devices should never be unplugged at boot time, as they are
> > similar to pci passthrough devices.
> > 
> > Signed-off-by: Juergen Gross 
> > Signed-off-by: Vikram Garhwal 
> 
> Hm, do your virtio NICs still actually *work* after that? Or are they
> all disconnected from their netdev peers? 
> 
> I suspect you're going to want a variant of
> https://lore.kernel.org/qemu-devel/20231025145042.627381-19-dw...@infradead.org/T/#u
> which also leave the peers of your virtio devices intact?

Hi David, device unplug is an x86-only thing (see the definition of
xen_emul_unplug in Linux under arch/x86/xen/platform-pci-unplug.c) I
suspect Vikram who is working on ARM hasn't tested it.

Vikram, a simple option is to drop this patch if you don't need it.



Re: [QEMU][PATCH v1 2/7] xen: add pseudo RAM region for grant mappings

2023-10-10 Thread Stefano Stabellini
On Tue, 10 Oct 2023, Vikram Garhwal wrote:
> On Mon, Oct 09, 2023 at 05:02:14PM -0700, Stefano Stabellini wrote:
> > On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> > > From: Juergen Gross 
> > > 
> > > Add a memory region which can be used to automatically map granted
> > > memory. It is starting at 0x8000ULL in order to be able to
> > > distinguish it from normal RAM.
> > > 
> > > For this reason the xen.ram memory region is expanded, which has no
> > > further impact as it is used just as a container of the real RAM
> > > regions and now the grant region.
> > > 
> > > Signed-off-by: Juergen Gross 
> > > Signed-off-by: Vikram Garhwal 
> > 
> > This patch doesn't apply to staging anymore
> Will re-base it. I rebased it against master branch.
> > 
> > 
> > > ---
> > >  hw/i386/xen/xen-hvm.c   |  3 ++
> > >  hw/xen/xen-hvm-common.c |  4 +--
> > >  hw/xen/xen-mapcache.c   | 27 ++
> > >  include/exec/ram_addr.h |  1 +
> > >  include/hw/xen/xen-hvm-common.h |  2 ++
> > >  include/hw/xen/xen_pvdev.h  |  3 ++
> > >  include/sysemu/xen-mapcache.h   |  3 ++
> > >  softmmu/physmem.c   | 62 +
> > >  8 files changed, 80 insertions(+), 25 deletions(-)
> > > 
> > > diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> > > index f42621e674..67a8a6 100644
> > > --- a/hw/i386/xen/xen-hvm.c
> > > +++ b/hw/i386/xen/xen-hvm.c
> > > @@ -172,6 +172,9 @@ static void xen_ram_init(PCMachineState *pcms,
> > >   x86ms->above_4g_mem_size);
> > >  memory_region_add_subregion(sysmem, 0x1ULL, _hi);
> > >  }
> > > +
> > > +/* Add grant mappings as a pseudo RAM region. */
> > > +ram_grants = *xen_init_grant_ram();
> > >  }
> > >  
> > >  static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size)
> > > diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
> > > index 565dc39c8f..b7255977a5 100644
> > > --- a/hw/xen/xen-hvm-common.c
> > > +++ b/hw/xen/xen-hvm-common.c
> > > @@ -9,7 +9,7 @@
> > >  #include "hw/boards.h"
> > >  #include "hw/xen/arch_hvm.h"
> > >  
> > > -MemoryRegion ram_memory;
> > > +MemoryRegion ram_memory, ram_grants;
> > >  
> > >  void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion 
> > > *mr,
> > > Error **errp)
> > > @@ -26,7 +26,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t 
> > > size, MemoryRegion *mr,
> > >  return;
> > >  }
> > >  
> > > -if (mr == _memory) {
> > > +if (mr == _memory || mr == _grants) {
> > >  return;
> > >  }
> > >  
> > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > > index f7d974677d..8115c44c00 100644
> > > --- a/hw/xen/xen-mapcache.c
> > > +++ b/hw/xen/xen-mapcache.c
> > > @@ -14,7 +14,9 @@
> > >  
> > >  #include 
> > >  
> > > +#include "hw/xen/xen-hvm-common.h"
> > >  #include "hw/xen/xen_native.h"
> > > +#include "hw/xen/xen_pvdev.h"
> > >  #include "qemu/bitmap.h"
> > >  
> > >  #include "sysemu/runstate.h"
> > > @@ -597,3 +599,28 @@ uint8_t *xen_replace_cache_entry(hwaddr 
> > > old_phys_addr,
> > >  mapcache_unlock();
> > >  return p;
> > >  }
> > > +
> > > +MemoryRegion *xen_init_grant_ram(void)
> > > +{
> > > +RAMBlock *block;
> > > +
> > > +memory_region_init(_grants, NULL, "xen.grants",
> > > +   XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE);
> > > +block = g_malloc0(sizeof(*block));
> > > +block->mr = _grants;
> > > +block->used_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE;
> > > +block->max_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE;
> > > +block->fd = -1;
> > > +block->page_size = XC_PAGE_SIZE;
> > > +block->host = (void *)XEN_GRANT_ADDR_OFF;
> > > +block->offset = XEN_GRANT_ADDR_OFF;
> > > +block->flags = RAM_PREALLOC;
> > > +ram_grants.ram_block = block;
> > > +ram_grants.ram = true;
> > > +r

Re: [QEMU][PATCH v1 2/7] xen: add pseudo RAM region for grant mappings

2023-10-09 Thread Stefano Stabellini
On Mon, 9 Oct 2023, Stefano Stabellini wrote:
> On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> > From: Juergen Gross 
> > 
> > Add a memory region which can be used to automatically map granted
> > memory. It is starting at 0x8000ULL in order to be able to
> > distinguish it from normal RAM.
> > 
> > For this reason the xen.ram memory region is expanded, which has no
> > further impact as it is used just as a container of the real RAM
> > regions and now the grant region.
> > 
> > Signed-off-by: Juergen Gross 
> > Signed-off-by: Vikram Garhwal 
> 
> This patch doesn't apply to staging anymore
> 
> 
> > ---
> >  hw/i386/xen/xen-hvm.c   |  3 ++
> >  hw/xen/xen-hvm-common.c |  4 +--
> >  hw/xen/xen-mapcache.c   | 27 ++
> >  include/exec/ram_addr.h |  1 +
> >  include/hw/xen/xen-hvm-common.h |  2 ++
> >  include/hw/xen/xen_pvdev.h  |  3 ++
> >  include/sysemu/xen-mapcache.h   |  3 ++
> >  softmmu/physmem.c   | 62 +
> >  8 files changed, 80 insertions(+), 25 deletions(-)
> > 
> > diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> > index f42621e674..67a8a6 100644
> > --- a/hw/i386/xen/xen-hvm.c
> > +++ b/hw/i386/xen/xen-hvm.c
> > @@ -172,6 +172,9 @@ static void xen_ram_init(PCMachineState *pcms,
> >   x86ms->above_4g_mem_size);
> >  memory_region_add_subregion(sysmem, 0x1ULL, _hi);
> >  }
> > +
> > +/* Add grant mappings as a pseudo RAM region. */
> > +ram_grants = *xen_init_grant_ram();
> >  }
> >  
> >  static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size)
> > diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
> > index 565dc39c8f..b7255977a5 100644
> > --- a/hw/xen/xen-hvm-common.c
> > +++ b/hw/xen/xen-hvm-common.c
> > @@ -9,7 +9,7 @@
> >  #include "hw/boards.h"
> >  #include "hw/xen/arch_hvm.h"
> >  
> > -MemoryRegion ram_memory;
> > +MemoryRegion ram_memory, ram_grants;
> >  
> >  void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
> > Error **errp)
> > @@ -26,7 +26,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, 
> > MemoryRegion *mr,
> >  return;
> >  }
> >  
> > -if (mr == _memory) {
> > +if (mr == _memory || mr == _grants) {
> >  return;
> >  }
> >  
> > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> > index f7d974677d..8115c44c00 100644
> > --- a/hw/xen/xen-mapcache.c
> > +++ b/hw/xen/xen-mapcache.c
> > @@ -14,7 +14,9 @@
> >  
> >  #include 
> >  
> > +#include "hw/xen/xen-hvm-common.h"
> >  #include "hw/xen/xen_native.h"
> > +#include "hw/xen/xen_pvdev.h"
> >  #include "qemu/bitmap.h"
> >  
> >  #include "sysemu/runstate.h"
> > @@ -597,3 +599,28 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
> >  mapcache_unlock();
> >  return p;
> >  }
> > +
> > +MemoryRegion *xen_init_grant_ram(void)
> > +{
> > +RAMBlock *block;
> > +
> > +memory_region_init(_grants, NULL, "xen.grants",
> > +   XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE);
> > +block = g_malloc0(sizeof(*block));
> > +block->mr = _grants;
> > +block->used_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE;
> > +block->max_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE;
> > +block->fd = -1;
> > +block->page_size = XC_PAGE_SIZE;
> > +block->host = (void *)XEN_GRANT_ADDR_OFF;
> > +block->offset = XEN_GRANT_ADDR_OFF;
> > +block->flags = RAM_PREALLOC;
> > +ram_grants.ram_block = block;
> > +ram_grants.ram = true;
> > +ram_grants.terminates = true;
> > +ram_block_add_list(block);
> > +memory_region_add_subregion(get_system_memory(), XEN_GRANT_ADDR_OFF,
> > +_grants);
> > +
> > +return _grants;
> 
> It doesn't look like xen_init_grant_ram has anything to do with the
> mapcache. It should be in another file. Maybe ./hw/xen/xen-hvm-common.c
> or ./hw/i386/xen/xen-hvm.c (but this is x86 specific and we need grants
> on ARM too)

Now having seen all the other patches, it might be OK to keep this here.
I am OK with this patch once it is rebased on the latest staging. I
would still advise to split the physdev.c changes to a separate patch.



Re: [QEMU][PATCH v1 7/7] hw: arm: Add grant mapping.

2023-10-09 Thread Stefano Stabellini
On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> Enable grant ram mapping support for Xenpvh machine on ARM.
> 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/arm/xen_arm.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index f83b983ec5..553c289720 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -125,6 +125,9 @@ static void xen_init_ram(MachineState *machine)
>  DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n",
>  GUEST_RAM1_BASE, ram_size[1]);
>  }
> +
> +DPRINTF("init grant ram mapping for XEN\n");
> +ram_grants = *xen_init_grant_ram();
>  }
>  
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
> -- 
> 2.17.1
> 



Re: [QEMU][PATCH v1 6/7] xen: add map and unmap callbacks for grant region

2023-10-09 Thread Stefano Stabellini
On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> Add the callbacks for mapping/unmapping guest memory via grants to the
> special grant memory region.
> 
> Signed-off-by: Juergen Gross 
> Signed-off-by: Vikram Garhwal 

This looks good. We need to add a check to make sure we don't exceed
XEN_MAX_VIRTIO_GRANTS.



> ---
>  hw/xen/xen-mapcache.c | 167 +-
>  softmmu/physmem.c |  11 ++-
>  2 files changed, 173 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 8a61c7dde6..52844a6a9d 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -9,6 +9,8 @@
>   */
>  
>  #include "qemu/osdep.h"
> +#include "qemu/queue.h"
> +#include "qemu/thread.h"
>  #include "qemu/units.h"
>  #include "qemu/error-report.h"
>  
> @@ -23,6 +25,8 @@
>  #include "sysemu/xen-mapcache.h"
>  #include "trace.h"
>  
> +#include 
> +#include 
>  
>  //#define MAPCACHE_DEBUG
>  
> @@ -385,7 +389,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_try(void *ptr)
>  {
>  MapCacheEntry *entry = NULL;
>  MapCacheRev *reventry;
> @@ -594,10 +598,170 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
>  return p;
>  }
>  
> +struct XENMappedGrantRegion {
> +void *addr;
> +unsigned int pages;
> +unsigned int refs;
> +unsigned int prot;
> +uint32_t idx;
> +QLIST_ENTRY(XENMappedGrantRegion) list;
> +};
> +
> +static xengnttab_handle *xen_region_gnttabdev;
> +static QLIST_HEAD(GrantRegionList, XENMappedGrantRegion) xen_grant_mappings =
> +QLIST_HEAD_INITIALIZER(xen_grant_mappings);
> +static QemuMutex xen_map_mutex;
> +
> +static void *xen_map_grant_dyn(MemoryRegion **mr, hwaddr addr, hwaddr *plen,
> +   bool is_write, MemTxAttrs attrs)
> +{
> +unsigned int page_off = addr & (XC_PAGE_SIZE - 1);
> +unsigned int i;
> +unsigned int nrefs = (page_off + *plen + XC_PAGE_SIZE - 1) >> 
> XC_PAGE_SHIFT;
> +uint32_t ref = (addr - XEN_GRANT_ADDR_OFF) >> XC_PAGE_SHIFT;
> +uint32_t *refs = NULL;
> +unsigned int prot = PROT_READ;
> +struct XENMappedGrantRegion *mgr = NULL;
> +
> +if (is_write) {
> +prot |= PROT_WRITE;
> +}
> +
> +qemu_mutex_lock(_map_mutex);
> +
> +QLIST_FOREACH(mgr, _grant_mappings, list) {
> +if (mgr->idx == ref &&
> +mgr->pages == nrefs &&
> +(mgr->prot & prot) == prot) {
> +break;
> +}
> +}
> +if (!mgr) {
> +mgr = g_new(struct XENMappedGrantRegion, 1);
> +
> +if (nrefs == 1) {
> +refs = 
> +} else {
> +refs = g_new(uint32_t, nrefs);
> +for (i = 0; i < nrefs; i++) {
> +refs[i] = ref + i;
> +}
> +}
> +mgr->addr = xengnttab_map_domain_grant_refs(xen_region_gnttabdev, 
> nrefs,
> +xen_domid, refs, prot);
> +if (mgr->addr) {
> +mgr->pages = nrefs;
> +mgr->refs = 1;
> +mgr->prot = prot;
> +mgr->idx = ref;
> +
> +QLIST_INSERT_HEAD(_grant_mappings, mgr, list);
> +} else {
> +g_free(mgr);
> +mgr = NULL;
> +}
> +} else {
> +mgr->refs++;
> +}
> +
> +qemu_mutex_unlock(_map_mutex);
> +
> +if (nrefs > 1) {
> +g_free(refs);
> +}
> +
> +return mgr ? mgr->addr + page_off : NULL;
> +}
> +
> +static void xen_unmap_grant_dyn(MemoryRegion *mr, void *buffer, ram_addr_t 
> addr,
> +hwaddr len, bool is_write, hwaddr access_len)
> +{
> +unsigned int page_off = (unsigned long)buffer & (XC_PAGE_SIZE - 1);
> +unsigned int nrefs = (page_off + len + XC_PAGE_SIZE - 1) >> 
> XC_PAGE_SHIFT;
> +unsigned int prot = PROT_READ;
> +struct XENMappedGrantRegion *mgr = NULL;
> +
> +if (is_write) {
> +prot |= PROT_WRITE;
> +}
> +
> +qemu_mutex_lock(_map_mutex);
> +
> +QLIST_FOREACH(mgr, _grant_mappings, list) {
> +if (mgr->addr == buffer - page_off &&
> +mgr->pages == nrefs &&
> +(mgr->prot & prot) == prot) {
> +break;
> +}
> +}
> +if (mgr) {
> +mgr->refs--;
> +if (!mgr->refs) {
> +xengnttab_unmap(xen_region_gnttabdev, mgr->addr, nrefs);
> +
> +QLIST_REMOVE(mgr, list);
> +g_free(mgr);
> +}
> +} else {
> +error_report("xen_unmap_grant_dyn() trying to unmap unknown buffer");
> +}
> +
> +qemu_mutex_unlock(_map_mutex);
> +}
> +
> +static ram_addr_t xen_ram_addr_from_grant_cache(void *ptr)
> +{
> +unsigned int page_off = (unsigned long)ptr & (XC_PAGE_SIZE - 1);
> +struct XENMappedGrantRegion *mgr = NULL;
> +ram_addr_t raddr = 

Re: [QEMU][PATCH v1 5/7] memory: add MemoryRegion map and unmap callbacks

2023-10-09 Thread Stefano Stabellini
On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> In order to support mapping and unmapping guest memory dynamically to
> and from qemu during address_space_[un]map() operations add the map()
> and unmap() callbacks to MemoryRegionOps.
> 
> Those will be used e.g. for Xen grant mappings when performing guest
> I/Os.
> 
> Signed-off-by: Juergen Gross 
> Signed-off-by: Vikram Garhwal 

Can't we just use the existing Xen hooks in qemu_ram_ptr_length and
xen_invalidate_map_cache_entry? Do we really need new ones?


> ---
>  include/exec/memory.h | 21 ++
>  softmmu/physmem.c | 50 +--
>  2 files changed, 60 insertions(+), 11 deletions(-)
> 
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index c99842d2fc..f3c62d2883 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -280,6 +280,27 @@ struct MemoryRegionOps {
>  unsigned size,
>  MemTxAttrs attrs);
>  
> +/*
> + * Dynamically create mapping. @addr is the guest address to map; @plen
> + * is the pointer to the usable length of the buffer.
> + * @mr contents can be changed in case a new memory region is created for
> + * the mapping.
> + * Returns the buffer address for accessing the data.
> + */
> +void *(*map)(MemoryRegion **mr,
> + hwaddr addr,
> + hwaddr *plen,
> + bool is_write,
> + MemTxAttrs attrs);
> +
> +/* Unmap an area obtained via map() before. */
> +void (*unmap)(MemoryRegion *mr,
> +  void *buffer,
> +  ram_addr_t addr,
> +  hwaddr len,
> +  bool is_write,
> +  hwaddr access_len);
> +
>  enum device_endian endianness;
>  /* Guest-visible constraints: */
>  struct {
> diff --git a/softmmu/physmem.c b/softmmu/physmem.c
> index 6e5e379dd0..5f425bea1c 100644
> --- a/softmmu/physmem.c
> +++ b/softmmu/physmem.c
> @@ -3135,6 +3135,7 @@ void *address_space_map(AddressSpace *as,
>  hwaddr len = *plen;
>  hwaddr l, xlat;
>  MemoryRegion *mr;
> +void *ptr = NULL;
>  FlatView *fv;
>  
>  if (len == 0) {
> @@ -3168,12 +3169,20 @@ void *address_space_map(AddressSpace *as,
>  return bounce.buffer;
>  }
>  
> -
>  memory_region_ref(mr);
> +
> +if (mr->ops && mr->ops->map) {
> +ptr = mr->ops->map(, addr, plen, is_write, attrs);
> +}
> +
>  *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);
> +if (ptr == NULL) {
> +ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true);
> +}
> +
> +return ptr;
>  }
>  
>  /* Unmaps a memory region previously mapped by address_space_map().
> @@ -3189,11 +3198,16 @@ void address_space_unmap(AddressSpace *as, void 
> *buffer, hwaddr len,
>  
>  mr = memory_region_from_host(buffer, );
>  assert(mr != NULL);
> -if (is_write) {
> -invalidate_and_set_dirty(mr, addr1, access_len);
> -}
> -if (xen_enabled()) {
> -xen_invalidate_map_cache_entry(buffer);
> +
> +if (mr->ops && mr->ops->unmap) {
> +mr->ops->unmap(mr, buffer, addr1, len, is_write, access_len);
> +} else {
> +if (is_write) {
> +invalidate_and_set_dirty(mr, addr1, access_len);
> +}
> +if (xen_enabled()) {
> +xen_invalidate_map_cache_entry(buffer);
> +}
>  }
>  memory_region_unref(mr);
>  return;
> @@ -3266,10 +3280,18 @@ int64_t address_space_cache_init(MemoryRegionCache 
> *cache,
>   * doing this if we found actual RAM, which behaves the same
>   * regardless of attributes; so UNSPECIFIED is fine.
>   */
> +if (mr->ops && mr->ops->map) {
> +cache->ptr = mr->ops->map(, addr, , is_write,
> +  MEMTXATTRS_UNSPECIFIED);
> +}
> +
>  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, , 
> true);
> +if (!cache->ptr) {
> +cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, ,
> + true);
> +}
>  } else {
>  cache->ptr = NULL;
>  }
> @@ -3291,14 +3313,20 @@ void address_space_cache_invalidate(MemoryRegionCache 
> *cache,
>  
>  void address_space_cache_destroy(MemoryRegionCache *cache)
>  {
> -if (!cache->mrs.mr) {
> +MemoryRegion *mr = cache->mrs.mr;
> 

Re: [QEMU][PATCH v1 4/7] xen: let xen_ram_addr_from_mapcache() return -1 in case of not found entry

2023-10-09 Thread Stefano Stabellini
On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> 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 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/xen/xen-mapcache.c | 12 +++-
>  1 file changed, 3 insertions(+), 9 deletions(-)
> 
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index 8115c44c00..8a61c7dde6 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -404,13 +404,8 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>  }
>  }
>  if (!found) {
> -fprintf(stderr, "%s, could not find %p\n", __func__, ptr);
> -QTAILQ_FOREACH(reventry, >locked_entries, next) {
> -DPRINTF("   "HWADDR_FMT_plx" -> %p is present\n", 
> reventry->paddr_index,
> -reventry->vaddr_req);
> -}
> -abort();
> -return 0;
> +mapcache_unlock();
> +return RAM_ADDR_INVALID;
>  }
>  
>  entry = >entry[paddr_index % mapcache->nr_buckets];
> @@ -418,8 +413,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
>  entry = entry->next;
>  }
>  if (!entry) {
> -DPRINTF("Trying to find address %p that is not in the mapcache!\n", 
> ptr);
> -raddr = 0;
> +raddr = RAM_ADDR_INVALID;
>  } else {
>  raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
>   ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
> -- 
> 2.17.1
> 



Re: [QEMU][PATCH v1 3/7] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()

2023-10-09 Thread Stefano Stabellini
On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> 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 
> Signed-off-by: Vikram Garhwal 

This patch also doesn't apply due to code movement.

Other than that, the patch looks good to me


> ---
>  softmmu/physmem.c | 58 +++
>  1 file changed, 23 insertions(+), 35 deletions(-)
> 
> diff --git a/softmmu/physmem.c b/softmmu/physmem.c
> index e182a2fa07..6e5e379dd0 100644
> --- a/softmmu/physmem.c
> +++ b/softmmu/physmem.c
> @@ -2163,38 +2163,8 @@ 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 *ram_block, ram_addr_t addr)
> -{
> -RAMBlock *block = ram_block;
> -
> -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.
>   */
> @@ -2202,7 +2172,9 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, 
> ram_addr_t addr,
>   hwaddr *size, bool lock)
>  {
>  RAMBlock *block = ram_block;
> -if (*size == 0) {
> +hwaddr len = 0;
> +
> +if (size && *size == 0) {
>  return NULL;
>  }
>  
> @@ -2210,7 +2182,10 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_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
> @@ -2218,7 +2193,7 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_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);
> @@ -2227,6 +2202,19 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_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.17.1
> 



Re: [QEMU][PATCH v1 2/7] xen: add pseudo RAM region for grant mappings

2023-10-09 Thread Stefano Stabellini
On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> Add a memory region which can be used to automatically map granted
> memory. It is starting at 0x8000ULL in order to be able to
> distinguish it from normal RAM.
> 
> For this reason the xen.ram memory region is expanded, which has no
> further impact as it is used just as a container of the real RAM
> regions and now the grant region.
> 
> Signed-off-by: Juergen Gross 
> Signed-off-by: Vikram Garhwal 

This patch doesn't apply to staging anymore


> ---
>  hw/i386/xen/xen-hvm.c   |  3 ++
>  hw/xen/xen-hvm-common.c |  4 +--
>  hw/xen/xen-mapcache.c   | 27 ++
>  include/exec/ram_addr.h |  1 +
>  include/hw/xen/xen-hvm-common.h |  2 ++
>  include/hw/xen/xen_pvdev.h  |  3 ++
>  include/sysemu/xen-mapcache.h   |  3 ++
>  softmmu/physmem.c   | 62 +
>  8 files changed, 80 insertions(+), 25 deletions(-)
> 
> diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> index f42621e674..67a8a6 100644
> --- a/hw/i386/xen/xen-hvm.c
> +++ b/hw/i386/xen/xen-hvm.c
> @@ -172,6 +172,9 @@ static void xen_ram_init(PCMachineState *pcms,
>   x86ms->above_4g_mem_size);
>  memory_region_add_subregion(sysmem, 0x1ULL, _hi);
>  }
> +
> +/* Add grant mappings as a pseudo RAM region. */
> +ram_grants = *xen_init_grant_ram();
>  }
>  
>  static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size)
> diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
> index 565dc39c8f..b7255977a5 100644
> --- a/hw/xen/xen-hvm-common.c
> +++ b/hw/xen/xen-hvm-common.c
> @@ -9,7 +9,7 @@
>  #include "hw/boards.h"
>  #include "hw/xen/arch_hvm.h"
>  
> -MemoryRegion ram_memory;
> +MemoryRegion ram_memory, ram_grants;
>  
>  void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
> Error **errp)
> @@ -26,7 +26,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, 
> MemoryRegion *mr,
>  return;
>  }
>  
> -if (mr == _memory) {
> +if (mr == _memory || mr == _grants) {
>  return;
>  }
>  
> diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
> index f7d974677d..8115c44c00 100644
> --- a/hw/xen/xen-mapcache.c
> +++ b/hw/xen/xen-mapcache.c
> @@ -14,7 +14,9 @@
>  
>  #include 
>  
> +#include "hw/xen/xen-hvm-common.h"
>  #include "hw/xen/xen_native.h"
> +#include "hw/xen/xen_pvdev.h"
>  #include "qemu/bitmap.h"
>  
>  #include "sysemu/runstate.h"
> @@ -597,3 +599,28 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
>  mapcache_unlock();
>  return p;
>  }
> +
> +MemoryRegion *xen_init_grant_ram(void)
> +{
> +RAMBlock *block;
> +
> +memory_region_init(_grants, NULL, "xen.grants",
> +   XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE);
> +block = g_malloc0(sizeof(*block));
> +block->mr = _grants;
> +block->used_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE;
> +block->max_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE;
> +block->fd = -1;
> +block->page_size = XC_PAGE_SIZE;
> +block->host = (void *)XEN_GRANT_ADDR_OFF;
> +block->offset = XEN_GRANT_ADDR_OFF;
> +block->flags = RAM_PREALLOC;
> +ram_grants.ram_block = block;
> +ram_grants.ram = true;
> +ram_grants.terminates = true;
> +ram_block_add_list(block);
> +memory_region_add_subregion(get_system_memory(), XEN_GRANT_ADDR_OFF,
> +_grants);
> +
> +return _grants;

It doesn't look like xen_init_grant_ram has anything to do with the
mapcache. It should be in another file. Maybe ./hw/xen/xen-hvm-common.c
or ./hw/i386/xen/xen-hvm.c (but this is x86 specific and we need grants
on ARM too)


> +}
> diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
> index 90676093f5..c0b5f9a7d0 100644
> --- a/include/exec/ram_addr.h
> +++ b/include/exec/ram_addr.h
> @@ -139,6 +139,7 @@ void qemu_ram_free(RAMBlock *block);
>  int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp);
>  
>  void qemu_ram_msync(RAMBlock *block, ram_addr_t start, ram_addr_t length);
> +void ram_block_add_list(RAMBlock *new_block);
>  
>  /* Clear whole block of mem */
>  static inline void qemu_ram_block_writeback(RAMBlock *block)
> diff --git a/include/hw/xen/xen-hvm-common.h b/include/hw/xen/xen-hvm-common.h
> index 4e9904f1a6..0d300ba898 100644
> --- a/include/hw/xen/xen-hvm-common.h
> +++ b/include/hw/xen/xen-hvm-common.h
> @@ -17,6 +17,8 @@
>  #include 
>  
>  extern MemoryRegion ram_memory;
> +
> +extern MemoryRegion ram_grants;
>  extern MemoryListener xen_io_listener;
>  extern DeviceListener xen_device_listener;
>  
> diff --git a/include/hw/xen/xen_pvdev.h b/include/hw/xen/xen_pvdev.h
> index ddad4b9f36..0f1b5edfa9 100644
> --- a/include/hw/xen/xen_pvdev.h
> +++ b/include/hw/xen/xen_pvdev.h
> @@ -80,4 +80,7 @@ int xen_pv_send_notify(struct XenLegacyDevice 

Re: [QEMU][PATCH v1 1/7] xen: when unplugging emulated devices skip virtio devices

2023-10-09 Thread Stefano Stabellini
On Thu, 5 Oct 2023, Vikram Garhwal wrote:
> From: Juergen Gross 
> 
> Virtio devices should never be unplugged at boot time, as they are
> similar to pci passthrough devices.
> 
> Signed-off-by: Juergen Gross 
> Signed-off-by: Vikram Garhwal 
> ---
>  hw/i386/xen/xen_platform.c | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
> index 17457ff3de..3560eaf8c8 100644
> --- a/hw/i386/xen/xen_platform.c
> +++ b/hw/i386/xen/xen_platform.c
> @@ -28,6 +28,7 @@
>  #include "hw/ide/pci.h"
>  #include "hw/pci/pci.h"
>  #include "migration/vmstate.h"
> +#include "hw/virtio/virtio-bus.h"
>  #include "net/net.h"
>  #include "trace.h"
>  #include "sysemu/xen.h"
> @@ -132,7 +133,8 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
>  /* We have to ignore passthrough devices */
>  if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
>  PCI_CLASS_NETWORK_ETHERNET
> -&& !pci_device_is_passthrough(d)) {
> +&& !pci_device_is_passthrough(d)
> +&& !qdev_get_child_bus(>qdev, TYPE_VIRTIO_BUS)) {

Please update the in-code comment above to say "ignore passthrough
devices and virtio devices"


>  object_unparent(OBJECT(d));
>  }
>  }
> @@ -208,6 +210,10 @@ static void unplug_disks(PCIBus *b, PCIDevice *d, void 
> *opaque)
>  /* We have to ignore passthrough devices */
>  if (pci_device_is_passthrough(d))
>  return;
> +/* Ignore virtio devices */
> +if (qdev_get_child_bus(>qdev, TYPE_VIRTIO_BUS)) {
> +return;
> +}
>  
>  switch (pci_get_word(d->config + PCI_CLASS_DEVICE)) {
>  case PCI_CLASS_STORAGE_IDE:
> -- 
> 2.17.1
> 



[PULL v2 2/2] xen_arm: Initialize RAM and add hi/low memory regions

2023-08-30 Thread Stefano Stabellini
From: Oleksandr Tyshchenko 

In order to use virtio backends we need to initialize RAM for the
xen-mapcache (which is responsible for mapping guest memory using foreign
mapping) to work. Calculate and add hi/low memory regions based on
machine->ram_size.

Use the constants defined in public header arch-arm.h to be aligned with the xen
toolstack.

While using this machine, the toolstack should then pass real ram_size using
"-m" arg. If "-m" is not given, create a QEMU machine without IOREQ and other
emulated devices like TPM and VIRTIO. This is done to keep this QEMU machine
usable for /etc/init.d/xencommons.

Signed-off-by: Oleksandr Tyshchenko 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
Signed-off-by: Stefano Stabellini 
---
 hw/arm/xen_arm.c| 45 +
 include/hw/xen/xen_native.h |  8 +++
 2 files changed, 53 insertions(+)

diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
index 7393b37355..f83b983ec5 100644
--- a/hw/arm/xen_arm.c
+++ b/hw/arm/xen_arm.c
@@ -60,6 +60,8 @@ struct XenArmState {
 } cfg;
 };
 
+static MemoryRegion ram_lo, ram_hi;
+
 /*
  * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under Xen
  * repository.
@@ -92,6 +94,39 @@ static void xen_create_virtio_mmio_devices(XenArmState *xam)
 }
 }
 
+static void xen_init_ram(MachineState *machine)
+{
+MemoryRegion *sysmem = get_system_memory();
+ram_addr_t block_len, ram_size[GUEST_RAM_BANKS];
+
+if (machine->ram_size <= GUEST_RAM0_SIZE) {
+ram_size[0] = machine->ram_size;
+ram_size[1] = 0;
+block_len = GUEST_RAM0_BASE + ram_size[0];
+} else {
+ram_size[0] = GUEST_RAM0_SIZE;
+ram_size[1] = machine->ram_size - GUEST_RAM0_SIZE;
+block_len = GUEST_RAM1_BASE + ram_size[1];
+}
+
+memory_region_init_ram(_memory, NULL, "xen.ram", block_len,
+   _fatal);
+
+memory_region_init_alias(_lo, NULL, "xen.ram.lo", _memory,
+ GUEST_RAM0_BASE, ram_size[0]);
+memory_region_add_subregion(sysmem, GUEST_RAM0_BASE, _lo);
+DPRINTF("Initialized region xen.ram.lo: base 0x%llx size 0x%lx\n",
+GUEST_RAM0_BASE, ram_size[0]);
+
+if (ram_size[1] > 0) {
+memory_region_init_alias(_hi, NULL, "xen.ram.hi", _memory,
+ GUEST_RAM1_BASE, ram_size[1]);
+memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, _hi);
+DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n",
+GUEST_RAM1_BASE, ram_size[1]);
+}
+}
+
 void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
 {
 hw_error("Invalid ioreq type 0x%x\n", req->type);
@@ -141,6 +176,14 @@ static void xen_arm_init(MachineState *machine)
 
 xam->state =  g_new0(XenIOState, 1);
 
+if (machine->ram_size == 0) {
+DPRINTF("ram_size not specified. QEMU machine started without IOREQ"
+"(no emulated devices including Virtio)\n");
+return;
+}
+
+xen_init_ram(machine);
+
 xen_register_ioreq(xam->state, machine->smp.cpus, _memory_listener);
 
 xen_create_virtio_mmio_devices(xam);
@@ -188,6 +231,8 @@ static void xen_arm_machine_class_init(ObjectClass *oc, 
void *data)
 mc->init = xen_arm_init;
 mc->max_cpus = 1;
 mc->default_machine_opts = "accel=xen";
+/* Set explicitly here to make sure that real ram_size is passed */
+mc->default_ram_size = 0;
 
 #ifdef CONFIG_TPM
 object_class_property_add(oc, "tpm-base-addr", "uint64_t",
diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
index a4b1aa9e5d..5d2718261f 100644
--- a/include/hw/xen/xen_native.h
+++ b/include/hw/xen/xen_native.h
@@ -539,4 +539,12 @@ static inline int 
xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
 #define GUEST_VIRTIO_MMIO_SPI_LAST43
 #endif
 
+#if defined(__i386__) || defined(__x86_64__)
+#define GUEST_RAM_BANKS   2
+#define GUEST_RAM0_BASE   0x4000ULL /* 3GB of low RAM @ 1GB */
+#define GUEST_RAM0_SIZE   0xc000ULL
+#define GUEST_RAM1_BASE   0x02ULL /* 1016GB of RAM @ 8GB */
+#define GUEST_RAM1_SIZE   0xfeULL
+#endif
+
 #endif /* QEMU_HW_XEN_NATIVE_H */
-- 
2.25.1




[PULL v2 1/2] xen_arm: Create virtio-mmio devices during initialization

2023-08-30 Thread Stefano Stabellini
From: Oleksandr Tyshchenko 

In order to use virtio backends we need to allocate virtio-mmio
parameters (irq and base) and register corresponding buses.

Use the constants defined in public header arch-arm.h to be
aligned with the toolstack. So the number of current supported
virtio-mmio devices is 10.

For the interrupts triggering use already existing on Arm
device-model hypercall.

The toolstack should then insert the same amount of device nodes
into guest device-tree.

Signed-off-by: Oleksandr Tyshchenko 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
Signed-off-by: Stefano Stabellini 
---
 hw/arm/xen_arm.c| 35 +++
 include/hw/xen/xen_native.h | 16 
 2 files changed, 51 insertions(+)

diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
index 1d3e6d481a..7393b37355 100644
--- a/hw/arm/xen_arm.c
+++ b/hw/arm/xen_arm.c
@@ -26,6 +26,7 @@
 #include "qapi/qapi-commands-migration.h"
 #include "qapi/visitor.h"
 #include "hw/boards.h"
+#include "hw/irq.h"
 #include "hw/sysbus.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/tpm_backend.h"
@@ -59,6 +60,38 @@ struct XenArmState {
 } cfg;
 };
 
+/*
+ * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under Xen
+ * repository.
+ *
+ * Origin: git://xenbits.xen.org/xen.git 2128143c114c
+ */
+#define VIRTIO_MMIO_DEV_SIZE   0x200
+
+#define NR_VIRTIO_MMIO_DEVICES   \
+   (GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
+
+static void xen_set_irq(void *opaque, int irq, int level)
+{
+xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level);
+}
+
+static void xen_create_virtio_mmio_devices(XenArmState *xam)
+{
+int i;
+
+for (i = 0; i < NR_VIRTIO_MMIO_DEVICES; i++) {
+hwaddr base = GUEST_VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_DEV_SIZE;
+qemu_irq irq = qemu_allocate_irq(xen_set_irq, NULL,
+ GUEST_VIRTIO_MMIO_SPI_FIRST + i);
+
+sysbus_create_simple("virtio-mmio", base, irq);
+
+DPRINTF("Created virtio-mmio device %d: irq %d base 0x%lx\n",
+i, GUEST_VIRTIO_MMIO_SPI_FIRST + i, base);
+}
+}
+
 void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
 {
 hw_error("Invalid ioreq type 0x%x\n", req->type);
@@ -110,6 +143,8 @@ static void xen_arm_init(MachineState *machine)
 
 xen_register_ioreq(xam->state, machine->smp.cpus, _memory_listener);
 
+xen_create_virtio_mmio_devices(xam);
+
 #ifdef CONFIG_TPM
 if (xam->cfg.tpm_base_addr) {
 xen_enable_tpm(xam);
diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
index 4dce905fde..a4b1aa9e5d 100644
--- a/include/hw/xen/xen_native.h
+++ b/include/hw/xen/xen_native.h
@@ -523,4 +523,20 @@ static inline int xen_set_ioreq_server_state(domid_t dom,
  enable);
 }
 
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500
+static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
+   domid_t domid, uint32_t irq,
+   unsigned int level)
+{
+return 0;
+}
+#endif
+
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41700
+#define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
+#define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
+#define GUEST_VIRTIO_MMIO_SPI_FIRST   33
+#define GUEST_VIRTIO_MMIO_SPI_LAST43
+#endif
+
 #endif /* QEMU_HW_XEN_NATIVE_H */
-- 
2.25.1




[PULL v2 0/2] xen-virtio-2-tag

2023-08-30 Thread Stefano Stabellini
The following changes since commit 156618d9ea67f2f2e31d9dedd97f2dcccbe6808c:

  Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into 
staging (2023-08-30 09:20:27 -0400)

are available in the Git repository at:

  https://gitlab.com/sstabellini/qemu.git xen-virtio-2-tag

for you to fetch changes up to 560142190bc347fdd4511a795bdcff768799519d:

  xen_arm: Initialize RAM and add hi/low memory regions (2023-08-30 18:23:08 
-0700)


Oleksandr Tyshchenko (2):
  xen_arm: Create virtio-mmio devices during initialization
  xen_arm: Initialize RAM and add hi/low memory regions

 hw/arm/xen_arm.c| 80 +
 include/hw/xen/xen_native.h | 24 ++
 2 files changed, 104 insertions(+)



Re: [QEMU][PATCH v4 1/2] xen_arm: Create virtio-mmio devices during initialization

2023-08-30 Thread Stefano Stabellini
On Tue, 29 Aug 2023, Vikram Garhwal wrote:
> From: Oleksandr Tyshchenko 
> 
> In order to use virtio backends we need to allocate virtio-mmio
> parameters (irq and base) and register corresponding buses.
> 
> Use the constants defined in public header arch-arm.h to be
> aligned with the toolstack. So the number of current supported
> virtio-mmio devices is 10.
> 
> For the interrupts triggering use already existing on Arm
> device-model hypercall.
> 
> The toolstack should then insert the same amount of device nodes
> into guest device-tree.
> 
> Signed-off-by: Oleksandr Tyshchenko 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/arm/xen_arm.c| 35 +++
>  include/hw/xen/xen_native.h | 16 
>  2 files changed, 51 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index 1d3e6d481a..7393b37355 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -26,6 +26,7 @@
>  #include "qapi/qapi-commands-migration.h"
>  #include "qapi/visitor.h"
>  #include "hw/boards.h"
> +#include "hw/irq.h"
>  #include "hw/sysbus.h"
>  #include "sysemu/block-backend.h"
>  #include "sysemu/tpm_backend.h"
> @@ -59,6 +60,38 @@ struct XenArmState {
>  } cfg;
>  };
>  
> +/*
> + * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under 
> Xen
> + * repository.
> + *
> + * Origin: git://xenbits.xen.org/xen.git 2128143c114c
> + */
> +#define VIRTIO_MMIO_DEV_SIZE   0x200
> +
> +#define NR_VIRTIO_MMIO_DEVICES   \
> +   (GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
> +
> +static void xen_set_irq(void *opaque, int irq, int level)
> +{
> +xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level);
> +}
> +
> +static void xen_create_virtio_mmio_devices(XenArmState *xam)
> +{
> +int i;
> +
> +for (i = 0; i < NR_VIRTIO_MMIO_DEVICES; i++) {
> +hwaddr base = GUEST_VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_DEV_SIZE;
> +qemu_irq irq = qemu_allocate_irq(xen_set_irq, NULL,
> + GUEST_VIRTIO_MMIO_SPI_FIRST + i);
> +
> +sysbus_create_simple("virtio-mmio", base, irq);
> +
> +DPRINTF("Created virtio-mmio device %d: irq %d base 0x%lx\n",
> +i, GUEST_VIRTIO_MMIO_SPI_FIRST + i, base);
> +}
> +}
> +
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
>  {
>  hw_error("Invalid ioreq type 0x%x\n", req->type);
> @@ -110,6 +143,8 @@ static void xen_arm_init(MachineState *machine)
>  
>  xen_register_ioreq(xam->state, machine->smp.cpus, _memory_listener);
>  
> +xen_create_virtio_mmio_devices(xam);
> +
>  #ifdef CONFIG_TPM
>  if (xam->cfg.tpm_base_addr) {
>  xen_enable_tpm(xam);
> diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
> index 4dce905fde..a4b1aa9e5d 100644
> --- a/include/hw/xen/xen_native.h
> +++ b/include/hw/xen/xen_native.h
> @@ -523,4 +523,20 @@ static inline int xen_set_ioreq_server_state(domid_t dom,
>   enable);
>  }
>  
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500
> +static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
> +   domid_t domid, uint32_t irq,
> +   unsigned int level)
> +{
> +return 0;
> +}
> +#endif
> +
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41700
> +#define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
> +#define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
> +#define GUEST_VIRTIO_MMIO_SPI_FIRST   33
> +#define GUEST_VIRTIO_MMIO_SPI_LAST43
> +#endif
> +
>  #endif /* QEMU_HW_XEN_NATIVE_H */
> -- 
> 2.17.1
> 



Re: [QEMU][PATCH v4 2/2] xen_arm: Initialize RAM and add hi/low memory regions

2023-08-30 Thread Stefano Stabellini
On Tue, 29 Aug 2023, Vikram Garhwal wrote:
> From: Oleksandr Tyshchenko 
> 
> In order to use virtio backends we need to initialize RAM for the
> xen-mapcache (which is responsible for mapping guest memory using foreign
> mapping) to work. Calculate and add hi/low memory regions based on
> machine->ram_size.
> 
> Use the constants defined in public header arch-arm.h to be aligned with the 
> xen
> toolstack.
> 
> While using this machine, the toolstack should then pass real ram_size using
> "-m" arg. If "-m" is not given, create a QEMU machine without IOREQ and other
> emulated devices like TPM and VIRTIO. This is done to keep this QEMU machine
> usable for /etc/init.d/xencommons.
> 
> Signed-off-by: Oleksandr Tyshchenko 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/arm/xen_arm.c| 45 +
>  include/hw/xen/xen_native.h |  8 +++
>  2 files changed, 53 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index 7393b37355..f83b983ec5 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -60,6 +60,8 @@ struct XenArmState {
>  } cfg;
>  };
>  
> +static MemoryRegion ram_lo, ram_hi;
> +
>  /*
>   * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under 
> Xen
>   * repository.
> @@ -92,6 +94,39 @@ static void xen_create_virtio_mmio_devices(XenArmState 
> *xam)
>  }
>  }
>  
> +static void xen_init_ram(MachineState *machine)
> +{
> +MemoryRegion *sysmem = get_system_memory();
> +ram_addr_t block_len, ram_size[GUEST_RAM_BANKS];
> +
> +if (machine->ram_size <= GUEST_RAM0_SIZE) {
> +ram_size[0] = machine->ram_size;
> +ram_size[1] = 0;
> +block_len = GUEST_RAM0_BASE + ram_size[0];
> +} else {
> +ram_size[0] = GUEST_RAM0_SIZE;
> +ram_size[1] = machine->ram_size - GUEST_RAM0_SIZE;
> +block_len = GUEST_RAM1_BASE + ram_size[1];
> +}
> +
> +memory_region_init_ram(_memory, NULL, "xen.ram", block_len,
> +   _fatal);
> +
> +memory_region_init_alias(_lo, NULL, "xen.ram.lo", _memory,
> + GUEST_RAM0_BASE, ram_size[0]);
> +memory_region_add_subregion(sysmem, GUEST_RAM0_BASE, _lo);
> +DPRINTF("Initialized region xen.ram.lo: base 0x%llx size 0x%lx\n",
> +GUEST_RAM0_BASE, ram_size[0]);
> +
> +if (ram_size[1] > 0) {
> +memory_region_init_alias(_hi, NULL, "xen.ram.hi", _memory,
> + GUEST_RAM1_BASE, ram_size[1]);
> +memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, _hi);
> +DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n",
> +GUEST_RAM1_BASE, ram_size[1]);
> +}
> +}
> +
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
>  {
>  hw_error("Invalid ioreq type 0x%x\n", req->type);
> @@ -141,6 +176,14 @@ static void xen_arm_init(MachineState *machine)
>  
>  xam->state =  g_new0(XenIOState, 1);
>  
> +if (machine->ram_size == 0) {
> +DPRINTF("ram_size not specified. QEMU machine started without IOREQ"
> +"(no emulated devices including Virtio)\n");
> +return;
> +}
> +
> +xen_init_ram(machine);
> +
>  xen_register_ioreq(xam->state, machine->smp.cpus, _memory_listener);
>  
>  xen_create_virtio_mmio_devices(xam);
> @@ -188,6 +231,8 @@ static void xen_arm_machine_class_init(ObjectClass *oc, 
> void *data)
>  mc->init = xen_arm_init;
>  mc->max_cpus = 1;
>  mc->default_machine_opts = "accel=xen";
> +/* Set explicitly here to make sure that real ram_size is passed */
> +mc->default_ram_size = 0;
>  
>  #ifdef CONFIG_TPM
>  object_class_property_add(oc, "tpm-base-addr", "uint64_t",
> diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
> index a4b1aa9e5d..5d2718261f 100644
> --- a/include/hw/xen/xen_native.h
> +++ b/include/hw/xen/xen_native.h
> @@ -539,4 +539,12 @@ static inline int 
> xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
>  #define GUEST_VIRTIO_MMIO_SPI_LAST43
>  #endif
>  
> +#if defined(__i386__) || defined(__x86_64__)
> +#define GUEST_RAM_BANKS   2
> +#define GUEST_RAM0_BASE   0x4000ULL /* 3GB of low RAM @ 1GB */
> +#define GUEST_RAM0_SIZE   0xc000ULL
> +#define GUEST_RAM1_BASE   0x02ULL /* 1016GB of RAM @ 8GB */
> +#define GUEST_RAM1_SIZE   0xfeULL
> +#endif
> +
>  #endif /* QEMU_HW_XEN_NATIVE_H */
> -- 
> 2.17.1
> 



Re: QEMU features useful for Xen development?

2023-08-30 Thread Stefano Stabellini
Hi Alex,

Thanks for reaching out. QEMU is an important development tool for the
Xen community and we are using QEMU as part of our upstream gitlab-ci
testing, see automation/scripts/qemu-*.

As Xen is gaining R52 and R82 support, it would be great to be able to
use QEMU for development and testing there as well, but I don't think
QEMU can emulate EL2 properly for the Cortex-R architecture. We would
need EL2 support in the GIC/timer for R52/R82 as well.

On Cortex-As, in addition to a PCI root complex and an arbitrary PCI
device, SMMUv3 emulation (both stages) and GICv3 ITS are needed to be
able to test PCI Passthrough. However, if I recall correctly SMMUv3
emulation in QEMU might not be complete enough to enable us to use it.

For Virtio, using QEMU on target (not develpment/testing, but
production), it would greatly help if we could improve the build system
to only build what is strictly necessary for the xenpvh machine to run.

Cheers,

Stefano


On Wed, 30 Aug 2023, Alex Bennée wrote:
> Dear Xen community,
> 
> Linaro is significantly invested in QEMU development, with a special
> focus on Arm-related aspects. We recognize the value of QEMU as a
> readily available software reference platform for projects that need to
> test their software well before the availability of real hardware.
> 
> The primary focus of our effort is on adding core architectural elements
> to the CPU emulation. For an overview of the current feature set, please
> see:
> 
>   https://qemu.readthedocs.io/en/master/system/arm/emulation.html
> 
> Besides the -cpu max, providing an approximation of a v9.0 baseline CPU,
> we have also recently added several specific CPU types like the
> Neoverse-N1 and V1 processor types as well as numerous Cortex CPU
> models.
> 
> Our most utilized machine model is "virt", which is primarily designed
> for guest operation and therefore has minimal resemblance to actual
> hardware. "sbsa-ref" was implemented to more closely simulate a real
> machine that aligns with Arm's SBSA specification.
> 
> In our work on VirtIO, we often use QEMU. Most of our rust-vmm
> vhost-device backends, for instance, were initially tested on QEMU.
> 
> Now that everyone is up-to-date, I would welcome any feedback from the
> Xen community on features that would increase QEMU's usefulness as a
> development target.
> 
> Do you have interest in any upcoming Arm CPU features? For example, we
> recently added FEAT_RME support for Arm's new confidential computing,
> but currently do not implement FEAT_NV/NV2.
> 
> How about the HW emulation in QEMU? Is the PCI emulation reliable enough
> to ensure confidence while testing changes to Xen's PCI management? What
> about the few peripherals that the hypervisor accesses directly?
> 
> Are there other development features you consider essential? Have you
> noticed any limitations with gdbstub? Does anyone use the record/replay
> or reverse debug functions? Has anyone tried TCG plugins for analysing
> the behavior of the hypervisor?
> 
> While I cannot promise to implement every wish-list item (performance
> counter emulation, for example, as we are not a uArch simulator), I am
> eager to gather feedback on how QEMU could be improved to help the Xen
> community deliver it's roadmap faster.
> 
> Thank you for your time and I look forward to any feedback :-)
> 
> -- 
> Alex Bennée
> Virtualisation Tech Lead @ Linaro
> 

Re: [QEMU][PATCH v3 2/2] xen_arm: Initialize RAM and add hi/low memory regions

2023-08-28 Thread Stefano Stabellini
On Fri, 25 Aug 2023, Vikram Garhwal wrote:
> From: Oleksandr Tyshchenko 
> 
> In order to use virtio backends we need to initialize RAM for the
> xen-mapcache (which is responsible for mapping guest memory using foreign
> mapping) to work. Calculate and add hi/low memory regions based on
> machine->ram_size.
> 
> Use the constants defined in public header arch-arm.h to be aligned with the 
> xen
> toolstack.
> 
> While using this machine, the toolstack should then pass real ram_size using
> "-m" arg. If "-m" is not given, create a QEMU machine without IOREQ and other
> emulated devices like TPM and VIRTIO. This is done to keep this QEMU machine
> usable for /etc/init.d/xencommons.
> 
> Signed-off-by: Oleksandr Tyshchenko 
> Signed-off-by: Vikram Garhwal 
> ---
>  hw/arm/xen_arm.c | 53 
>  1 file changed, 53 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index d1e9f7b488..aa8b6171ad 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -60,6 +60,8 @@ struct XenArmState {
>  } cfg;
>  };
>  
> +static MemoryRegion ram_lo, ram_hi;
> +
>  /*
>   * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under 
> Xen
>   * repository.
> @@ -80,6 +82,14 @@ static int xendevicemodel_set_irq_level(
>  }
>  #endif
>  
> +#if defined(__i386__) || defined(__x86_64__)
> +#define GUEST_RAM_BANKS   2
> +#define GUEST_RAM0_BASE   0x4000ULL /* 3GB of low RAM @ 1GB */
> +#define GUEST_RAM0_SIZE   0xc000ULL
> +#define GUEST_RAM1_BASE   0x02ULL /* 1016GB of RAM @ 8GB */
> +#define GUEST_RAM1_SIZE   0xfeULL
> +#endif

Also here please move to include/hw/xen/xen_native.h


>  #if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41700
>  #define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
>  #define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
> @@ -108,6 +118,39 @@ static void xen_create_virtio_mmio_devices(XenArmState 
> *xam)
>  }
>  }
>  
> +static void xen_init_ram(MachineState *machine)
> +{
> +MemoryRegion *sysmem = get_system_memory();
> +ram_addr_t block_len, ram_size[GUEST_RAM_BANKS];
> +
> +if (machine->ram_size <= GUEST_RAM0_SIZE) {
> +ram_size[0] = machine->ram_size;
> +ram_size[1] = 0;
> +block_len = GUEST_RAM0_BASE + ram_size[0];
> +} else {
> +ram_size[0] = GUEST_RAM0_SIZE;
> +ram_size[1] = machine->ram_size - GUEST_RAM0_SIZE;
> +block_len = GUEST_RAM1_BASE + ram_size[1];
> +}
> +
> +memory_region_init_ram(_memory, NULL, "xen.ram", block_len,
> +   _fatal);
> +
> +memory_region_init_alias(_lo, NULL, "xen.ram.lo", _memory,
> + GUEST_RAM0_BASE, ram_size[0]);
> +memory_region_add_subregion(sysmem, GUEST_RAM0_BASE, _lo);
> +DPRINTF("Initialized region xen.ram.lo: base 0x%llx size 0x%lx\n",
> +GUEST_RAM0_BASE, ram_size[0]);
> +
> +if (ram_size[1] > 0) {
> +memory_region_init_alias(_hi, NULL, "xen.ram.hi", _memory,
> + GUEST_RAM1_BASE, ram_size[1]);
> +memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, _hi);
> +DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n",
> +GUEST_RAM1_BASE, ram_size[1]);
> +}
> +}
> +
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
>  {
>  hw_error("Invalid ioreq type 0x%x\n", req->type);
> @@ -157,6 +200,14 @@ static void xen_arm_init(MachineState *machine)
>  
>  xam->state =  g_new0(XenIOState, 1);
>  
> +if (machine->ram_size == 0) {
> +DPRINTF("ram_size not specified. QEMU machine started without IOREQ"
> +"(no emulated devices including Virtio)\n");
> +return;
> +}
> +
> +xen_init_ram(machine);
> +
>  xen_register_ioreq(xam->state, machine->smp.cpus, _memory_listener);
>  
>  xen_create_virtio_mmio_devices(xam);
> @@ -204,6 +255,8 @@ static void xen_arm_machine_class_init(ObjectClass *oc, 
> void *data)
>  mc->init = xen_arm_init;
>  mc->max_cpus = 1;
>  mc->default_machine_opts = "accel=xen";
> +/* Set explicitly here to make sure that real ram_size is passed */
> +mc->default_ram_size = 0;
>  
>  #ifdef CONFIG_TPM
>  object_class_property_add(oc, "tpm-base-addr", "uint64_t",
> -- 
> 2.17.1
> 



Re: [QEMU][PATCH v3 1/2] xen_arm: Create virtio-mmio devices during initialization

2023-08-28 Thread Stefano Stabellini
On Fri, 25 Aug 2023, Vikram Garhwal wrote:
> From: Oleksandr Tyshchenko 
> 
> In order to use virtio backends we need to allocate virtio-mmio
> parameters (irq and base) and register corresponding buses.
> 
> Use the constants defined in public header arch-arm.h to be
> aligned with the toolstack. So the number of current supported
> virtio-mmio devices is 10.
> 
> For the interrupts triggering use already existing on Arm
> device-model hypercall.
> 
> The toolstack should then insert the same amount of device nodes
> into guest device-tree.
> 
> Signed-off-by: Oleksandr Tyshchenko 
> Signed-off-by: Vikram Garhwal 
> ---
>  hw/arm/xen_arm.c | 51 
>  1 file changed, 51 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index 1d3e6d481a..d1e9f7b488 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -26,6 +26,7 @@
>  #include "qapi/qapi-commands-migration.h"
>  #include "qapi/visitor.h"
>  #include "hw/boards.h"
> +#include "hw/irq.h"
>  #include "hw/sysbus.h"
>  #include "sysemu/block-backend.h"
>  #include "sysemu/tpm_backend.h"
> @@ -59,6 +60,54 @@ struct XenArmState {
>  } cfg;
>  };
>  
> +/*
> + * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under 
> Xen
> + * repository.
> + *
> + * Origin: git://xenbits.xen.org/xen.git 2128143c114c
> + */
> +#define VIRTIO_MMIO_DEV_SIZE   0x200
> +
> +#define NR_VIRTIO_MMIO_DEVICES   \
> +   (GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
> +
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500
> +static int xendevicemodel_set_irq_level(
> +xendevicemodel_handle *dmod, domid_t domid, uint32_t irq,
> +unsigned int level)
> +{
> +return 0;
> +}
> +#endif
> +
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41700
> +#define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
> +#define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
> +#define GUEST_VIRTIO_MMIO_SPI_FIRST   33
> +#define GUEST_VIRTIO_MMIO_SPI_LAST43
> +#endif

Thanks Vikram. Please move this compat definitions to
include/hw/xen/xen_native.h


> +static void xen_set_irq(void *opaque, int irq, int level)
> +{
> +xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level);
> +}
> +
> +static void xen_create_virtio_mmio_devices(XenArmState *xam)
> +{
> +int i;
> +
> +for (i = 0; i < NR_VIRTIO_MMIO_DEVICES; i++) {
> +hwaddr base = GUEST_VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_DEV_SIZE;
> +qemu_irq irq = qemu_allocate_irq(xen_set_irq, NULL,
> + GUEST_VIRTIO_MMIO_SPI_FIRST + i);
> +
> +sysbus_create_simple("virtio-mmio", base, irq);
> +
> +DPRINTF("Created virtio-mmio device %d: irq %d base 0x%lx\n",
> +i, GUEST_VIRTIO_MMIO_SPI_FIRST + i, base);
> +}
> +}
> +
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
>  {
>  hw_error("Invalid ioreq type 0x%x\n", req->type);
> @@ -110,6 +159,8 @@ static void xen_arm_init(MachineState *machine)
>  
>  xen_register_ioreq(xam->state, machine->smp.cpus, _memory_listener);
>  
> +xen_create_virtio_mmio_devices(xam);
> +
>  #ifdef CONFIG_TPM
>  if (xam->cfg.tpm_base_addr) {
>  xen_enable_tpm(xam);
> -- 
> 2.17.1
> 



[PULL 1/2] xen_arm: Create virtio-mmio devices during initialization

2023-07-21 Thread Stefano Stabellini
From: Oleksandr Tyshchenko 

In order to use virtio backends we need to allocate virtio-mmio
parameters (irq and base) and register corresponding buses.

Use the constants defined in public header arch-arm.h to be
aligned with the toolstack. So the number of current supported
virtio-mmio devices is 10.

For the interrupts triggering use already existing on Arm
device-model hypercall.

The toolstack should then insert the same amount of device nodes
into guest device-tree.

Signed-off-by: Oleksandr Tyshchenko 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
---
 hw/arm/xen_arm.c | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
index 044093fec7..e700829654 100644
--- a/hw/arm/xen_arm.c
+++ b/hw/arm/xen_arm.c
@@ -26,6 +26,7 @@
 #include "qapi/qapi-commands-migration.h"
 #include "qapi/visitor.h"
 #include "hw/boards.h"
+#include "hw/irq.h"
 #include "hw/sysbus.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/tpm_backend.h"
@@ -59,6 +60,38 @@ struct XenArmState {
 } cfg;
 };
 
+/*
+ * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under Xen
+ * repository.
+ *
+ * Origin: git://xenbits.xen.org/xen.git 2128143c114c
+ */
+#define VIRTIO_MMIO_DEV_SIZE   0x200
+
+#define NR_VIRTIO_MMIO_DEVICES   \
+   (GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
+
+static void xen_set_irq(void *opaque, int irq, int level)
+{
+xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level);
+}
+
+static void xen_create_virtio_mmio_devices(XenArmState *xam)
+{
+int i;
+
+for (i = 0; i < NR_VIRTIO_MMIO_DEVICES; i++) {
+hwaddr base = GUEST_VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_DEV_SIZE;
+qemu_irq irq = qemu_allocate_irq(xen_set_irq, NULL,
+ GUEST_VIRTIO_MMIO_SPI_FIRST + i);
+
+sysbus_create_simple("virtio-mmio", base, irq);
+
+DPRINTF("Created virtio-mmio device %d: irq %d base 0x%lx\n",
+i, GUEST_VIRTIO_MMIO_SPI_FIRST + i, base);
+}
+}
+
 void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
 {
 hw_error("Invalid ioreq type 0x%x\n", req->type);
@@ -110,6 +143,8 @@ static void xen_arm_init(MachineState *machine)
 
 xen_register_ioreq(xam->state, machine->smp.cpus, xen_memory_listener);
 
+xen_create_virtio_mmio_devices(xam);
+
 #ifdef CONFIG_TPM
 if (xam->cfg.tpm_base_addr) {
 xen_enable_tpm(xam);
-- 
2.25.1




[PULL 2/2] xen_arm: Initialize RAM and add hi/low memory regions

2023-07-21 Thread Stefano Stabellini
From: Oleksandr Tyshchenko 

In order to use virtio backends we need to initialize RAM for the
xen-mapcache (which is responsible for mapping guest memory using foreign
mapping) to work. Calculate and add hi/low memory regions based on
machine->ram_size.

Use the constants defined in public header arch-arm.h to be aligned with the xen
toolstack.

While using this machine, the toolstack should then pass real ram_size using
"-m" arg. If "-m" is not given, create a QEMU machine without IOREQ and other
emulated devices like TPM and VIRTIO. This is done to keep this QEMU machine
usable for /etc/init.d/xencommons.

Signed-off-by: Oleksandr Tyshchenko 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
---
 hw/arm/xen_arm.c | 45 +
 1 file changed, 45 insertions(+)

diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
index e700829654..ec8de00cf5 100644
--- a/hw/arm/xen_arm.c
+++ b/hw/arm/xen_arm.c
@@ -60,6 +60,8 @@ struct XenArmState {
 } cfg;
 };
 
+static MemoryRegion ram_lo, ram_hi;
+
 /*
  * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under Xen
  * repository.
@@ -92,6 +94,39 @@ static void xen_create_virtio_mmio_devices(XenArmState *xam)
 }
 }
 
+static void xen_init_ram(MachineState *machine)
+{
+MemoryRegion *sysmem = get_system_memory();
+ram_addr_t block_len, ram_size[GUEST_RAM_BANKS];
+
+if (machine->ram_size <= GUEST_RAM0_SIZE) {
+ram_size[0] = machine->ram_size;
+ram_size[1] = 0;
+block_len = GUEST_RAM0_BASE + ram_size[0];
+} else {
+ram_size[0] = GUEST_RAM0_SIZE;
+ram_size[1] = machine->ram_size - GUEST_RAM0_SIZE;
+block_len = GUEST_RAM1_BASE + ram_size[1];
+}
+
+memory_region_init_ram(_memory, NULL, "xen.ram", block_len,
+   _fatal);
+
+memory_region_init_alias(_lo, NULL, "xen.ram.lo", _memory,
+ GUEST_RAM0_BASE, ram_size[0]);
+memory_region_add_subregion(sysmem, GUEST_RAM0_BASE, _lo);
+DPRINTF("Initialized region xen.ram.lo: base 0x%llx size 0x%lx\n",
+GUEST_RAM0_BASE, ram_size[0]);
+
+if (ram_size[1] > 0) {
+memory_region_init_alias(_hi, NULL, "xen.ram.hi", _memory,
+ GUEST_RAM1_BASE, ram_size[1]);
+memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, _hi);
+DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n",
+GUEST_RAM1_BASE, ram_size[1]);
+}
+}
+
 void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
 {
 hw_error("Invalid ioreq type 0x%x\n", req->type);
@@ -141,6 +176,14 @@ static void xen_arm_init(MachineState *machine)
 
 xam->state =  g_new0(XenIOState, 1);
 
+if (machine->ram_size == 0) {
+DPRINTF("ram_size not specified. QEMU machine started without IOREQ"
+"(no emulated devices including Virtio)\n");
+return;
+}
+
+xen_init_ram(machine);
+
 xen_register_ioreq(xam->state, machine->smp.cpus, xen_memory_listener);
 
 xen_create_virtio_mmio_devices(xam);
@@ -188,6 +231,8 @@ static void xen_arm_machine_class_init(ObjectClass *oc, 
void *data)
 mc->init = xen_arm_init;
 mc->max_cpus = 1;
 mc->default_machine_opts = "accel=xen";
+/* Set explicitly here to make sure that real ram_size is passed */
+mc->default_ram_size = 0;
 
 #ifdef CONFIG_TPM
 object_class_property_add(oc, "tpm-base-addr", "uint64_t",
-- 
2.25.1




[PULL 0/2] xen-virtio-1-tag

2023-07-21 Thread Stefano Stabellini
The following changes since commit d1181d29370a4318a9f11ea92065bea6bb159f83:

  Merge tag 'pull-nbd-2023-07-19' of https://repo.or.cz/qemu/ericb into staging 
(2023-07-20 09:54:07 +0100)

are available in the Git repository at:

  https://gitlab.com/sstabellini/qemu.git xen-virtio-1-tag

for you to fetch changes up to 6bb48c66946dfbd653f06ad5f3fc957972333b56:

  xen_arm: Initialize RAM and add hi/low memory regions (2023-07-21 18:00:29 
-0700)


Oleksandr Tyshchenko (2):
  xen_arm: Create virtio-mmio devices during initialization
  xen_arm: Initialize RAM and add hi/low memory regions

 hw/arm/xen_arm.c | 80 
 1 file changed, 80 insertions(+)



Re: [QEMU][PATCH v2 2/2] xen_arm: Initialize RAM and add hi/low memory regions

2023-07-07 Thread Stefano Stabellini
On Fri, 7 Jul 2023, Vikram Garhwal wrote:
> From: Oleksandr Tyshchenko 
> 
> In order to use virtio backends we need to initialize RAM for the
> xen-mapcache (which is responsible for mapping guest memory using foreign
> mapping) to work. Calculate and add hi/low memory regions based on
> machine->ram_size.
> 
> Use the constants defined in public header arch-arm.h to be aligned with the 
> xen
> toolstack.
> 
> While using this machine, the toolstack should then pass real ram_size using
> "-m" arg. If "-m" is not given, create a QEMU machine without IOREQ and other
> emulated devices like TPM and VIRTIO. This is done to keep this QEMU machine
> usable for /etc/init.d/xencommons.
> 
> Signed-off-by: Oleksandr Tyshchenko 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/arm/xen_arm.c | 45 +
>  1 file changed, 45 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index e700829654..ec8de00cf5 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -60,6 +60,8 @@ struct XenArmState {
>  } cfg;
>  };
>  
> +static MemoryRegion ram_lo, ram_hi;
> +
>  /*
>   * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under 
> Xen
>   * repository.
> @@ -92,6 +94,39 @@ static void xen_create_virtio_mmio_devices(XenArmState 
> *xam)
>  }
>  }
>  
> +static void xen_init_ram(MachineState *machine)
> +{
> +MemoryRegion *sysmem = get_system_memory();
> +ram_addr_t block_len, ram_size[GUEST_RAM_BANKS];
> +
> +if (machine->ram_size <= GUEST_RAM0_SIZE) {
> +ram_size[0] = machine->ram_size;
> +ram_size[1] = 0;
> +block_len = GUEST_RAM0_BASE + ram_size[0];
> +} else {
> +ram_size[0] = GUEST_RAM0_SIZE;
> +ram_size[1] = machine->ram_size - GUEST_RAM0_SIZE;
> +block_len = GUEST_RAM1_BASE + ram_size[1];
> +}
> +
> +memory_region_init_ram(_memory, NULL, "xen.ram", block_len,
> +   _fatal);
> +
> +memory_region_init_alias(_lo, NULL, "xen.ram.lo", _memory,
> + GUEST_RAM0_BASE, ram_size[0]);
> +memory_region_add_subregion(sysmem, GUEST_RAM0_BASE, _lo);
> +DPRINTF("Initialized region xen.ram.lo: base 0x%llx size 0x%lx\n",
> +GUEST_RAM0_BASE, ram_size[0]);
> +
> +if (ram_size[1] > 0) {
> +memory_region_init_alias(_hi, NULL, "xen.ram.hi", _memory,
> + GUEST_RAM1_BASE, ram_size[1]);
> +memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, _hi);
> +DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n",
> +GUEST_RAM1_BASE, ram_size[1]);
> +}
> +}
> +
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
>  {
>  hw_error("Invalid ioreq type 0x%x\n", req->type);
> @@ -141,6 +176,14 @@ static void xen_arm_init(MachineState *machine)
>  
>  xam->state =  g_new0(XenIOState, 1);
>  
> +if (machine->ram_size == 0) {
> +DPRINTF("ram_size not specified. QEMU machine started without IOREQ"
> +"(no emulated devices including Virtio)\n");
> +return;
> +}
> +
> +xen_init_ram(machine);
> +
>  xen_register_ioreq(xam->state, machine->smp.cpus, xen_memory_listener);
>  
>  xen_create_virtio_mmio_devices(xam);
> @@ -188,6 +231,8 @@ static void xen_arm_machine_class_init(ObjectClass *oc, 
> void *data)
>  mc->init = xen_arm_init;
>  mc->max_cpus = 1;
>  mc->default_machine_opts = "accel=xen";
> +/* Set explicitly here to make sure that real ram_size is passed */
> +mc->default_ram_size = 0;
>  
>  #ifdef CONFIG_TPM
>  object_class_property_add(oc, "tpm-base-addr", "uint64_t",
> -- 
> 2.25.1
> 



Re: [QEMU][PATCH v2 1/2] xen_arm: Create virtio-mmio devices during initialization

2023-07-07 Thread Stefano Stabellini
On Fri, 7 Jul 2023, Vikram Garhwal wrote:
> From: Oleksandr Tyshchenko 
> 
> In order to use virtio backends we need to allocate virtio-mmio
> parameters (irq and base) and register corresponding buses.
> 
> Use the constants defined in public header arch-arm.h to be
> aligned with the toolstack. So the number of current supported
> virtio-mmio devices is 10.
> 
> For the interrupts triggering use already existing on Arm
> device-model hypercall.
> 
> The toolstack should then insert the same amount of device nodes
> into guest device-tree.
> 
> Signed-off-by: Oleksandr Tyshchenko 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  hw/arm/xen_arm.c | 35 +++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index 044093fec7..e700829654 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -26,6 +26,7 @@
>  #include "qapi/qapi-commands-migration.h"
>  #include "qapi/visitor.h"
>  #include "hw/boards.h"
> +#include "hw/irq.h"
>  #include "hw/sysbus.h"
>  #include "sysemu/block-backend.h"
>  #include "sysemu/tpm_backend.h"
> @@ -59,6 +60,38 @@ struct XenArmState {
>  } cfg;
>  };
>  
> +/*
> + * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under 
> Xen
> + * repository.
> + *
> + * Origin: git://xenbits.xen.org/xen.git 2128143c114c
> + */
> +#define VIRTIO_MMIO_DEV_SIZE   0x200
> +
> +#define NR_VIRTIO_MMIO_DEVICES   \
> +   (GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
> +
> +static void xen_set_irq(void *opaque, int irq, int level)
> +{
> +xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level);
> +}
> +
> +static void xen_create_virtio_mmio_devices(XenArmState *xam)
> +{
> +int i;
> +
> +for (i = 0; i < NR_VIRTIO_MMIO_DEVICES; i++) {
> +hwaddr base = GUEST_VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_DEV_SIZE;
> +qemu_irq irq = qemu_allocate_irq(xen_set_irq, NULL,
> + GUEST_VIRTIO_MMIO_SPI_FIRST + i);
> +
> +sysbus_create_simple("virtio-mmio", base, irq);
> +
> +DPRINTF("Created virtio-mmio device %d: irq %d base 0x%lx\n",
> +i, GUEST_VIRTIO_MMIO_SPI_FIRST + i, base);
> +}
> +}
> +
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
>  {
>  hw_error("Invalid ioreq type 0x%x\n", req->type);
> @@ -110,6 +143,8 @@ static void xen_arm_init(MachineState *machine)
>  
>  xen_register_ioreq(xam->state, machine->smp.cpus, xen_memory_listener);
>  
> +xen_create_virtio_mmio_devices(xam);
> +
>  #ifdef CONFIG_TPM
>  if (xam->cfg.tpm_base_addr) {
>  xen_enable_tpm(xam);
> -- 
> 2.25.1
> 



Re: [RESEND][PATCH v1 2/2] xen_arm: Initialize RAM and add hi/low memory regions

2023-06-29 Thread Stefano Stabellini
On Thu, 29 Jun 2023, Vikram Garhwal wrote:
> From: Oleksandr Tyshchenko 
> 
> In order to use virtio backends we need to initialize RAM for the
> xen-mapcache (which is responsible for mapping guest memory using foreign
> mapping) to work. Calculate and add hi/low memory regions based on
> machine->ram_size.
> 
> Use the constants defined in public header arch-arm.h to be aligned with the 
> xen
> toolstack.
> 
> While using this machine, the toolstack should then pass real ram_size using
> "-m" arg. If "-m" is not given, create a QEMU machine without IOREQ, TPM and
> VIRTIO to keep it usable for /etc/init.d/xencommons.
> 
> Signed-off-by: Oleksandr Tyshchenko 
> Signed-off-by: Vikram Garhwal 
> ---
>  hw/arm/xen_arm.c | 45 +
>  1 file changed, 45 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index c0a93f2c9d..cc4dffee70 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -60,6 +60,8 @@ struct XenArmState {
>  } cfg;
>  };
>  
> +static MemoryRegion ram_lo, ram_hi;
> +
>  #define VIRTIO_MMIO_DEV_SIZE   0x200
>  
>  #define NR_VIRTIO_MMIO_DEVICES   \
> @@ -86,6 +88,39 @@ static void xen_create_virtio_mmio_devices(XenArmState 
> *xam)
>  }
>  }
>  
> +static void xen_init_ram(MachineState *machine)
> +{
> +MemoryRegion *sysmem = get_system_memory();
> +ram_addr_t block_len, ram_size[GUEST_RAM_BANKS];
> +
> +if (machine->ram_size <= GUEST_RAM0_SIZE) {
> +ram_size[0] = machine->ram_size;
> +ram_size[1] = 0;
> +block_len = GUEST_RAM0_BASE + ram_size[0];
> +} else {
> +ram_size[0] = GUEST_RAM0_SIZE;
> +ram_size[1] = machine->ram_size - GUEST_RAM0_SIZE;
> +block_len = GUEST_RAM1_BASE + ram_size[1];
> +}
> +
> +memory_region_init_ram(_memory, NULL, "xen.ram", block_len,
> +   _fatal);
> +
> +memory_region_init_alias(_lo, NULL, "xen.ram.lo", _memory,
> + GUEST_RAM0_BASE, ram_size[0]);
> +memory_region_add_subregion(sysmem, GUEST_RAM0_BASE, _lo);
> +DPRINTF("Initialized region xen.ram.lo: base 0x%llx size 0x%lx\n",
> +GUEST_RAM0_BASE, ram_size[0]);
> +
> +if (ram_size[1] > 0) {
> +memory_region_init_alias(_hi, NULL, "xen.ram.hi", _memory,
> + GUEST_RAM1_BASE, ram_size[1]);
> +memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, _hi);
> +DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n",
> +GUEST_RAM1_BASE, ram_size[1]);
> +}
> +}
> +
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
>  {
>  hw_error("Invalid ioreq type 0x%x\n", req->type);
> @@ -135,6 +170,14 @@ static void xen_arm_init(MachineState *machine)
>  
>  xam->state =  g_new0(XenIOState, 1);
>  
> +if (machine->ram_size == 0) {
> +DPRINTF("ram_size not specified. QEMU machine will be started 
> without"
> +" TPM, IOREQ and Virtio-MMIO backends\n");
> +return;
> +}

I would say "ram_size not specified. QEMU machine started without IOREQ
(no emulated devices including Virtio)."

We might add more devices in the future beyond Virtio and TPM. I don't
think we want to call out the whole list here.



> +xen_init_ram(machine);
> +
>  xen_register_ioreq(xam->state, machine->smp.cpus, xen_memory_listener);
>  
>  xen_create_virtio_mmio_devices(xam);
> @@ -182,6 +225,8 @@ static void xen_arm_machine_class_init(ObjectClass *oc, 
> void *data)
>  mc->init = xen_arm_init;
>  mc->max_cpus = 1;
>  mc->default_machine_opts = "accel=xen";
> +/* Set explicitly here to make sure that real ram_size is passed */
> +mc->default_ram_size = 0;
>  
>  printf("CHECK for NEW BUILD\n");
>  #ifdef CONFIG_TPM
> -- 
> 2.25.1
> 



Re: [RESEND][PATCH v1 1/2] xen_arm: Create virtio-mmio devices during initialization

2023-06-29 Thread Stefano Stabellini
On Thu, 29 Jun 2023, Vikram Garhwal wrote:
> From: Oleksandr Tyshchenko 
> 
> In order to use virtio backends we need to allocate virtio-mmio
> parameters (irq and base) and register corresponding buses.
> 
> Use the constants defined in public header arch-arm.h to be
> aligned with the toolstack. So the number of current supported
> virtio-mmio devices is 10.
> 
> For the interrupts triggering use already existing on Arm
> device-model hypercall.
> 
> The toolstack should then insert the same amount of device nodes
> into guest device-tree.
> 
> Signed-off-by: Oleksandr Tyshchenko 
> Signed-off-by: Vikram Garhwal 
> ---
>  hw/arm/xen_arm.c | 29 +
>  1 file changed, 29 insertions(+)
> 
> diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
> index 60dcd1bcc7..c0a93f2c9d 100644
> --- a/hw/arm/xen_arm.c
> +++ b/hw/arm/xen_arm.c
> @@ -26,6 +26,7 @@
>  #include "qapi/qapi-commands-migration.h"
>  #include "qapi/visitor.h"
>  #include "hw/boards.h"
> +#include "hw/irq.h"
>  #include "hw/sysbus.h"
>  #include "sysemu/block-backend.h"
>  #include "sysemu/tpm_backend.h"
> @@ -59,6 +60,32 @@ struct XenArmState {
>  } cfg;
>  };
>  
> +#define VIRTIO_MMIO_DEV_SIZE   0x200

Is this coming from QEMU? Or is it standard virtio?

Just asking to make sure that we don't run into a virtio device that
needs more than 0x200 of MMIO size.


> +#define NR_VIRTIO_MMIO_DEVICES   \
> +   (GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
> +
> +static void xen_set_irq(void *opaque, int irq, int level)
> +{
> +xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level);
> +}

Just a note: likely the xendevicemodel_set_irq_level call needs
privileges. Just something to keep in mind for when we try to run QEMU
in a domain other than Dom0. No need to do anything for now.

Everything looks good. If we can be sure 0x200 is the right MMIO size
for virtio devices then I would provide by Ack.


> +static void xen_create_virtio_mmio_devices(XenArmState *xam)
> +{
> +int i;
> +
> +for (i = 0; i < NR_VIRTIO_MMIO_DEVICES; i++) {
> +hwaddr base = GUEST_VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_DEV_SIZE;
> +qemu_irq irq = qemu_allocate_irq(xen_set_irq, NULL,
> + GUEST_VIRTIO_MMIO_SPI_FIRST + i);
> +
> +sysbus_create_simple("virtio-mmio", base, irq);
> +
> +DPRINTF("Created virtio-mmio device %d: irq %d base 0x%lx\n",
> +i, GUEST_VIRTIO_MMIO_SPI_FIRST + i, base);
> +}
> +}
> +
>  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
>  {
>  hw_error("Invalid ioreq type 0x%x\n", req->type);
> @@ -110,6 +137,8 @@ static void xen_arm_init(MachineState *machine)
>  
>  xen_register_ioreq(xam->state, machine->smp.cpus, xen_memory_listener);
>  
> +xen_create_virtio_mmio_devices(xam);
> +
>  #ifdef CONFIG_TPM
>  if (xam->cfg.tpm_base_addr) {
>  xen_enable_tpm(xam);
> -- 
> 2.25.1
> 



[PULL v5 10/11] meson.build: enable xenpv machine build for ARM

2023-06-15 Thread Stefano Stabellini
From: Vikram Garhwal 

Add CONFIG_XEN for aarch64 device to support build for ARM targets.

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Reviewed-by: Alex Bennée 
---
 meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/meson.build b/meson.build
index 481865bfa9..cfa98e9e25 100644
--- a/meson.build
+++ b/meson.build
@@ -136,7 +136,7 @@ endif
 if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
   # i386 emulator provides xenpv machine type for multiple architectures
   accelerator_targets += {
-'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
+'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu', 'aarch64-softmmu'],
   }
 endif
 if cpu in ['x86', 'x86_64']
-- 
2.25.1




[PULL v5 09/11] hw/arm: introduce xenpvh machine

2023-06-15 Thread Stefano Stabellini
From: Vikram Garhwal 

Add a new machine xenpvh which creates a IOREQ server to register/connect with
Xen Hypervisor.

Optional: When CONFIG_TPM is enabled, it also creates a tpm-tis-device, adds a
TPM emulator and connects to swtpm running on host machine via chardev socket
and support TPM functionalities for a guest domain.

Extra command line for aarch64 xenpvh QEMU to connect to swtpm:
-chardev socket,id=chrtpm,path=/tmp/myvtpm2/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-machine tpm-base-addr=0x0c00 \

swtpm implements a TPM software emulator(TPM 1.2 & TPM 2) built on libtpms and
provides access to TPM functionality over socket, chardev and CUSE interface.
Github repo: https://github.com/stefanberger/swtpm
Example for starting swtpm on host machine:
mkdir /tmp/vtpm2
swtpm socket --tpmstate dir=/tmp/vtpm2 \
--ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Reviewed-by: Stefano Stabellini 
---
 docs/system/arm/xenpvh.rst|  34 +++
 docs/system/target-arm.rst|   1 +
 hw/arm/meson.build|   2 +
 hw/arm/xen_arm.c  | 181 ++
 include/hw/arm/xen_arch_hvm.h |   9 ++
 include/hw/xen/arch_hvm.h |   2 +
 6 files changed, 229 insertions(+)
 create mode 100644 docs/system/arm/xenpvh.rst
 create mode 100644 hw/arm/xen_arm.c
 create mode 100644 include/hw/arm/xen_arch_hvm.h

diff --git a/docs/system/arm/xenpvh.rst b/docs/system/arm/xenpvh.rst
new file mode 100644
index 00..e1655c7ab8
--- /dev/null
+++ b/docs/system/arm/xenpvh.rst
@@ -0,0 +1,34 @@
+XENPVH (``xenpvh``)
+=
+This machine creates a IOREQ server to register/connect with Xen Hypervisor.
+
+When TPM is enabled, this machine also creates a tpm-tis-device at a user input
+tpm base address, adds a TPM emulator and connects to a swtpm application
+running on host machine via chardev socket. This enables xenpvh to support TPM
+functionalities for a guest domain.
+
+More information about TPM use and installing swtpm linux application can be
+found at: docs/specs/tpm.rst.
+
+Example for starting swtpm on host machine:
+.. code-block:: console
+
+mkdir /tmp/vtpm2
+swtpm socket --tpmstate dir=/tmp/vtpm2 \
+--ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &
+
+Sample QEMU xenpvh commands for running and connecting with Xen:
+.. code-block:: console
+
+qemu-system-aarch64 -xen-domid 1 \
+-chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
+-mon chardev=libxl-cmd,mode=control \
+-chardev socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off 
\
+-mon chardev=libxenstat-cmd,mode=control \
+-xen-attach -name guest0 -vnc none -display none -nographic \
+-machine xenpvh -m 1301 \
+-chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
+-tpmdev emulator,id=tpm0,chardev=chrtpm -machine tpm-base-addr=0x0C00
+
+In above QEMU command, last two lines are for connecting xenpvh QEMU to swtpm
+via chardev socket.
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index a12b6bca05..790ac1b8a2 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -107,6 +107,7 @@ undocumented; you can get a complete list by running
arm/stm32
arm/virt
arm/xlnx-versal-virt
+   arm/xenpvh
 
 Emulated CPU architecture support
 =
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 870ec67376..4f94f821b0 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -63,6 +63,8 @@ arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: 
files('fsl-imx7.c', 'mcimx7d-sabre.
 arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
 arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 
'mcimx6ul-evk.c'))
 arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
+arm_ss.add(when: 'CONFIG_XEN', if_true: files('xen_arm.c'))
+arm_ss.add_all(xen_ss)
 
 softmmu_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
 softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
new file mode 100644
index 00..19b1cb81ad
--- /dev/null
+++ b/hw/arm/xen_arm.c
@@ -0,0 +1,181 @@
+/*
+ * QEMU ARM Xen PVH Machine
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * TH

[PULL v5 03/11] hw/i386/xen/xen-hvm: move x86-specific fields out of XenIOState

2023-06-15 Thread Stefano Stabellini
From: Stefano Stabellini 

In preparation to moving most of xen-hvm code to an arch-neutral location, move:
- shared_vmport_page
- log_for_dirtybit
- dirty_bitmap
- suspend
- wakeup

out of XenIOState struct as these are only used on x86, especially the ones
related to dirty logging.
Updated XenIOState can be used for both aarch64 and x86.

Also, remove free_phys_offset as it was unused.

Signed-off-by: Stefano Stabellini 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Paul Durrant 
Reviewed-by: Alex Bennée 
---
 hw/i386/xen/xen-hvm.c | 58 ---
 1 file changed, 27 insertions(+), 31 deletions(-)

diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 7a7764240e..01bf947f1c 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -74,6 +74,7 @@ struct shared_vmport_iopage {
 };
 typedef struct shared_vmport_iopage shared_vmport_iopage_t;
 #endif
+static shared_vmport_iopage_t *shared_vmport_page;
 
 static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
 {
@@ -96,6 +97,11 @@ typedef struct XenPhysmap {
 } XenPhysmap;
 
 static QLIST_HEAD(, XenPhysmap) xen_physmap;
+static const XenPhysmap *log_for_dirtybit;
+/* Buffer used by xen_sync_dirty_bitmap */
+static unsigned long *dirty_bitmap;
+static Notifier suspend;
+static Notifier wakeup;
 
 typedef struct XenPciDevice {
 PCIDevice *pci_dev;
@@ -106,7 +112,6 @@ typedef struct XenPciDevice {
 typedef struct XenIOState {
 ioservid_t ioservid;
 shared_iopage_t *shared_page;
-shared_vmport_iopage_t *shared_vmport_page;
 buffered_iopage_t *buffered_io_page;
 xenforeignmemory_resource_handle *fres;
 QEMUTimer *buffered_io_timer;
@@ -126,14 +131,8 @@ typedef struct XenIOState {
 MemoryListener io_listener;
 QLIST_HEAD(, XenPciDevice) dev_list;
 DeviceListener device_listener;
-hwaddr free_phys_offset;
-const XenPhysmap *log_for_dirtybit;
-/* Buffer used by xen_sync_dirty_bitmap */
-unsigned long *dirty_bitmap;
 
 Notifier exit;
-Notifier suspend;
-Notifier wakeup;
 } XenIOState;
 
 /* Xen specific function for piix pci */
@@ -463,10 +462,10 @@ static int xen_remove_from_physmap(XenIOState *state,
 }
 
 QLIST_REMOVE(physmap, list);
-if (state->log_for_dirtybit == physmap) {
-state->log_for_dirtybit = NULL;
-g_free(state->dirty_bitmap);
-state->dirty_bitmap = NULL;
+if (log_for_dirtybit == physmap) {
+log_for_dirtybit = NULL;
+g_free(dirty_bitmap);
+dirty_bitmap = NULL;
 }
 g_free(physmap);
 
@@ -627,16 +626,16 @@ static void xen_sync_dirty_bitmap(XenIOState *state,
 return;
 }
 
-if (state->log_for_dirtybit == NULL) {
-state->log_for_dirtybit = physmap;
-state->dirty_bitmap = g_new(unsigned long, bitmap_size);
-} else if (state->log_for_dirtybit != physmap) {
+if (log_for_dirtybit == NULL) {
+log_for_dirtybit = physmap;
+dirty_bitmap = g_new(unsigned long, bitmap_size);
+} else if (log_for_dirtybit != physmap) {
 /* Only one range for dirty bitmap can be tracked. */
 return;
 }
 
 rc = xen_track_dirty_vram(xen_domid, start_addr >> TARGET_PAGE_BITS,
-  npages, state->dirty_bitmap);
+  npages, dirty_bitmap);
 if (rc < 0) {
 #ifndef ENODATA
 #define ENODATA  ENOENT
@@ -651,7 +650,7 @@ static void xen_sync_dirty_bitmap(XenIOState *state,
 }
 
 for (i = 0; i < bitmap_size; i++) {
-unsigned long map = state->dirty_bitmap[i];
+unsigned long map = dirty_bitmap[i];
 while (map != 0) {
 j = ctzl(map);
 map &= ~(1ul << j);
@@ -677,12 +676,10 @@ static void xen_log_start(MemoryListener *listener,
 static void xen_log_stop(MemoryListener *listener, MemoryRegionSection 
*section,
  int old, int new)
 {
-XenIOState *state = container_of(listener, XenIOState, memory_listener);
-
 if (old & ~new & (1 << DIRTY_MEMORY_VGA)) {
-state->log_for_dirtybit = NULL;
-g_free(state->dirty_bitmap);
-state->dirty_bitmap = NULL;
+log_for_dirtybit = NULL;
+g_free(dirty_bitmap);
+dirty_bitmap = NULL;
 /* Disable dirty bit tracking */
 xen_track_dirty_vram(xen_domid, 0, 0, NULL);
 }
@@ -1022,9 +1019,9 @@ static void handle_vmport_ioreq(XenIOState *state, 
ioreq_t *req)
 {
 vmware_regs_t *vmport_regs;
 
-assert(state->shared_vmport_page);
+assert(shared_vmport_page);
 vmport_regs =
->shared_vmport_page->vcpu_vmport_regs[state->send_vcpu];
+_vmport_page->vcpu_vmport_regs[state->send_vcpu];
 QEMU_BUILD_BUG_ON(sizeof(*req) < sizeof(*vmport_regs));
 
 current_cpu = state->cpu_by_vcpu_id[state->send_vcpu];
@@ -1472,7 +1469,6 @@ void xen_hvm_init_pc

[PULL v5 02/11] hw/i386/xen: rearrange xen_hvm_init_pc

2023-06-15 Thread Stefano Stabellini
From: Vikram Garhwal 

In preparation to moving most of xen-hvm code to an arch-neutral location,
move non IOREQ references to:
- xen_get_vmport_regs_pfn
- xen_suspend_notifier
- xen_wakeup_notifier
- xen_ram_init

towards the end of the xen_hvm_init_pc() function.

This is done to keep the common ioreq functions in one place which will be
moved to new function in next patch in order to make it common to both x86 and
aarch64 machines.

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 hw/i386/xen/xen-hvm.c | 49 ++-
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index ab8f1b61ee..7a7764240e 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -1419,12 +1419,6 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion 
**ram_memory)
 state->exit.notify = xen_exit_notifier;
 qemu_add_exit_notifier(>exit);
 
-state->suspend.notify = xen_suspend_notifier;
-qemu_register_suspend_notifier(>suspend);
-
-state->wakeup.notify = xen_wakeup_notifier;
-qemu_register_wakeup_notifier(>wakeup);
-
 /*
  * Register wake-up support in QMP query-current-machine API
  */
@@ -1435,23 +1429,6 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion 
**ram_memory)
 goto err;
 }
 
-rc = xen_get_vmport_regs_pfn(xen_xc, xen_domid, _pfn);
-if (!rc) {
-DPRINTF("shared vmport page at pfn %lx\n", ioreq_pfn);
-state->shared_vmport_page =
-xenforeignmemory_map(xen_fmem, xen_domid, PROT_READ|PROT_WRITE,
- 1, _pfn, NULL);
-if (state->shared_vmport_page == NULL) {
-error_report("map shared vmport IO page returned error %d 
handle=%p",
- errno, xen_xc);
-goto err;
-}
-} else if (rc != -ENOSYS) {
-error_report("get vmport regs pfn returned error %d, rc=%d",
- errno, rc);
-goto err;
-}
-
 /* Note: cpus is empty at this point in init */
 state->cpu_by_vcpu_id = g_new0(CPUState *, max_cpus);
 
@@ -1490,7 +1467,6 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion 
**ram_memory)
 #else
 xen_map_cache_init(NULL, state);
 #endif
-xen_ram_init(pcms, ms->ram_size, ram_memory);
 
 qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
 
@@ -1511,6 +1487,31 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion 
**ram_memory)
 QLIST_INIT(_physmap);
 xen_read_physmap(state);
 
+state->suspend.notify = xen_suspend_notifier;
+qemu_register_suspend_notifier(>suspend);
+
+state->wakeup.notify = xen_wakeup_notifier;
+qemu_register_wakeup_notifier(>wakeup);
+
+rc = xen_get_vmport_regs_pfn(xen_xc, xen_domid, _pfn);
+if (!rc) {
+DPRINTF("shared vmport page at pfn %lx\n", ioreq_pfn);
+state->shared_vmport_page =
+xenforeignmemory_map(xen_fmem, xen_domid, PROT_READ|PROT_WRITE,
+ 1, _pfn, NULL);
+if (state->shared_vmport_page == NULL) {
+error_report("map shared vmport IO page returned error %d 
handle=%p",
+ errno, xen_xc);
+goto err;
+}
+} else if (rc != -ENOSYS) {
+error_report("get vmport regs pfn returned error %d, rc=%d",
+ errno, rc);
+goto err;
+}
+
+xen_ram_init(pcms, ms->ram_size, ram_memory);
+
 /* Disable ACPI build because Xen handles it */
 pcms->acpi_build_enabled = false;
 
-- 
2.25.1




[PULL v5 05/11] include/hw/xen/xen_common: return error from xen_create_ioreq_server

2023-06-15 Thread Stefano Stabellini
From: Stefano Stabellini 

This is done to prepare for enabling xenpv support for ARM architecture.
On ARM it is possible to have a functioning xenpv machine with only the
PV backends and no IOREQ server. If the IOREQ server creation fails,
continue to the PV backends initialization.

Signed-off-by: Stefano Stabellini 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 include/hw/xen/xen_native.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
index f11eb423e3..4dce905fde 100644
--- a/include/hw/xen/xen_native.h
+++ b/include/hw/xen/xen_native.h
@@ -463,8 +463,8 @@ static inline void xen_unmap_pcidev(domid_t dom,
   PCI_FUNC(pci_dev->devfn));
 }
 
-static inline void xen_create_ioreq_server(domid_t dom,
-   ioservid_t *ioservid)
+static inline int xen_create_ioreq_server(domid_t dom,
+  ioservid_t *ioservid)
 {
 int rc = xendevicemodel_create_ioreq_server(xen_dmod, dom,
 HVM_IOREQSRV_BUFIOREQ_ATOMIC,
@@ -472,12 +472,14 @@ static inline void xen_create_ioreq_server(domid_t dom,
 
 if (rc == 0) {
 trace_xen_ioreq_server_create(*ioservid);
-return;
+return rc;
 }
 
 *ioservid = 0;
 use_default_ioreq_server = true;
 trace_xen_default_ioreq_server();
+
+return rc;
 }
 
 static inline void xen_destroy_ioreq_server(domid_t dom,
-- 
2.25.1




[PULL v5 06/11] hw/xen/xen-hvm-common: skip ioreq creation on ioreq registration failure

2023-06-15 Thread Stefano Stabellini
From: Stefano Stabellini 

On ARM it is possible to have a functioning xenpv machine with only the
PV backends and no IOREQ server. If the IOREQ server creation fails continue
to the PV backends initialization.

Also, moved the IOREQ registration and mapping subroutine to new function
xen_do_ioreq_register().

Signed-off-by: Stefano Stabellini 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 hw/xen/xen-hvm-common.c | 57 +++--
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index a31b067404..cb82f4b83d 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -764,27 +764,12 @@ void xen_shutdown_fatal_error(const char *fmt, ...)
 qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_ERROR);
 }
 
-void xen_register_ioreq(XenIOState *state, unsigned int max_cpus,
-MemoryListener xen_memory_listener)
+static void xen_do_ioreq_register(XenIOState *state,
+   unsigned int max_cpus,
+   MemoryListener xen_memory_listener)
 {
 int i, rc;
 
-setup_xen_backend_ops();
-
-state->xce_handle = qemu_xen_evtchn_open();
-if (state->xce_handle == NULL) {
-perror("xen: event channel open");
-goto err;
-}
-
-state->xenstore = xs_daemon_open();
-if (state->xenstore == NULL) {
-perror("xen: xenstore open");
-goto err;
-}
-
-xen_create_ioreq_server(xen_domid, >ioservid);
-
 state->exit.notify = xen_exit_notifier;
 qemu_add_exit_notifier(>exit);
 
@@ -849,12 +834,46 @@ void xen_register_ioreq(XenIOState *state, unsigned int 
max_cpus,
 QLIST_INIT(>dev_list);
 device_listener_register(>device_listener);
 
+return;
+
+err:
+error_report("xen hardware virtual machine initialisation failed");
+exit(1);
+}
+
+void xen_register_ioreq(XenIOState *state, unsigned int max_cpus,
+MemoryListener xen_memory_listener)
+{
+int rc;
+
+setup_xen_backend_ops();
+
+state->xce_handle = qemu_xen_evtchn_open();
+if (state->xce_handle == NULL) {
+perror("xen: event channel open");
+goto err;
+}
+
+state->xenstore = xs_daemon_open();
+if (state->xenstore == NULL) {
+perror("xen: xenstore open");
+goto err;
+}
+
+rc = xen_create_ioreq_server(xen_domid, >ioservid);
+if (!rc) {
+xen_do_ioreq_register(state, max_cpus, xen_memory_listener);
+} else {
+warn_report("xen: failed to create ioreq server");
+}
+
 xen_bus_init();
 
 xen_be_init();
 
 return;
+
 err:
-error_report("xen hardware virtual machine initialisation failed");
+error_report("xen hardware virtual machine backend registration failed");
 exit(1);
 }
-- 
2.25.1




[PULL v5 07/11] hw/xen/xen-hvm-common: Use g_new and error_report

2023-06-15 Thread Stefano Stabellini
From: Vikram Garhwal 

Replace g_malloc with g_new and perror with error_report.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 hw/xen/xen-hvm-common.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index cb82f4b83d..42339c96bd 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -33,7 +33,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, 
MemoryRegion *mr,
 trace_xen_ram_alloc(ram_addr, size);
 
 nr_pfn = size >> TARGET_PAGE_BITS;
-pfn_list = g_malloc(sizeof (*pfn_list) * nr_pfn);
+pfn_list = g_new(xen_pfn_t, nr_pfn);
 
 for (i = 0; i < nr_pfn; i++) {
 pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
@@ -730,7 +730,7 @@ void destroy_hvm_domain(bool reboot)
 return;
 }
 if (errno != ENOTTY /* old Xen */) {
-perror("xendevicemodel_shutdown failed");
+error_report("xendevicemodel_shutdown failed with error %d", 
errno);
 }
 /* well, try the old thing then */
 }
@@ -784,7 +784,7 @@ static void xen_do_ioreq_register(XenIOState *state,
 }
 
 /* Note: cpus is empty at this point in init */
-state->cpu_by_vcpu_id = g_malloc0(max_cpus * sizeof(CPUState *));
+state->cpu_by_vcpu_id = g_new0(CPUState *, max_cpus);
 
 rc = xen_set_ioreq_server_state(xen_domid, state->ioservid, true);
 if (rc < 0) {
@@ -793,7 +793,7 @@ static void xen_do_ioreq_register(XenIOState *state,
 goto err;
 }
 
-state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
+state->ioreq_local_port = g_new0(evtchn_port_t, max_cpus);
 
 /* FIXME: how about if we overflow the page here? */
 for (i = 0; i < max_cpus; i++) {
@@ -850,13 +850,13 @@ void xen_register_ioreq(XenIOState *state, unsigned int 
max_cpus,
 
 state->xce_handle = qemu_xen_evtchn_open();
 if (state->xce_handle == NULL) {
-perror("xen: event channel open");
+error_report("xen: event channel open failed with error %d", errno);
 goto err;
 }
 
 state->xenstore = xs_daemon_open();
 if (state->xenstore == NULL) {
-perror("xen: xenstore open");
+error_report("xen: xenstore open failed with error %d", errno);
 goto err;
 }
 
-- 
2.25.1




[PULL v5 11/11] test/qtest: add xepvh to skip list for qtest

2023-06-15 Thread Stefano Stabellini
From: Vikram Garhwal 

Like existing xen machines, xenpvh also cannot be used for qtest.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
---
 tests/qtest/libqtest.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index 77de16227f..de03ef5f60 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -1465,7 +1465,8 @@ void qtest_cb_for_every_machine(void (*cb)(const char 
*machine),
 for (i = 0; machines[i].name != NULL; i++) {
 /* Ignore machines that cannot be used for qtests */
 if (!strncmp("xenfv", machines[i].name, 5) ||
-g_str_equal("xenpv", machines[i].name)) {
+g_str_equal("xenpv", machines[i].name) ||
+g_str_equal("xenpvh", machines[i].name)) {
 continue;
 }
 if (!skip_old_versioned ||
-- 
2.25.1




[PULL v5 01/11] hw/i386/xen/: move xen-mapcache.c to hw/xen/

2023-06-15 Thread Stefano Stabellini
From: Vikram Garhwal 

xen-mapcache.c contains common functions which can be used for enabling Xen on
aarch64 with IOREQ handling. Moving it out from hw/i386/xen to hw/xen to make it
accessible for both aarch64 and x86.

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 hw/i386/meson.build  | 1 +
 hw/i386/xen/meson.build  | 1 -
 hw/i386/xen/trace-events | 5 -
 hw/xen/meson.build   | 4 
 hw/xen/trace-events  | 5 +
 hw/{i386 => }/xen/xen-mapcache.c | 0
 6 files changed, 10 insertions(+), 6 deletions(-)
 rename hw/{i386 => }/xen/xen-mapcache.c (100%)

diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 213e2e82b3..cfdbfdcbcb 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -33,5 +33,6 @@ subdir('kvm')
 subdir('xen')
 
 i386_ss.add_all(xenpv_ss)
+i386_ss.add_all(xen_ss)
 
 hw_arch += {'i386': i386_ss}
diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build
index 2e64a34e16..3dc4c4f106 100644
--- a/hw/i386/xen/meson.build
+++ b/hw/i386/xen/meson.build
@@ -1,6 +1,5 @@
 i386_ss.add(when: 'CONFIG_XEN', if_true: files(
   'xen-hvm.c',
-  'xen-mapcache.c',
   'xen_apic.c',
   'xen_pvdevice.c',
 ))
diff --git a/hw/i386/xen/trace-events b/hw/i386/xen/trace-events
index 5d6be61090..a0c89d91c4 100644
--- a/hw/i386/xen/trace-events
+++ b/hw/i386/xen/trace-events
@@ -21,8 +21,3 @@ xen_map_resource_ioreq(uint32_t id, void *addr) "id: %u addr: 
%p"
 cpu_ioreq_config_read(void *req, uint32_t sbdf, uint32_t reg, uint32_t size, 
uint32_t data) "I/O=%p sbdf=0x%x reg=%u size=%u data=0x%x"
 cpu_ioreq_config_write(void *req, uint32_t sbdf, uint32_t reg, uint32_t size, 
uint32_t data) "I/O=%p sbdf=0x%x reg=%u size=%u data=0x%x"
 
-# xen-mapcache.c
-xen_map_cache(uint64_t phys_addr) "want 0x%"PRIx64
-xen_remap_bucket(uint64_t index) "index 0x%"PRIx64
-xen_map_cache_return(void* ptr) "%p"
-
diff --git a/hw/xen/meson.build b/hw/xen/meson.build
index 19c6aabc7c..202752e557 100644
--- a/hw/xen/meson.build
+++ b/hw/xen/meson.build
@@ -26,3 +26,7 @@ else
 endif
 
 specific_ss.add_all(when: ['CONFIG_XEN', xen], if_true: xen_specific_ss)
+
+xen_ss = ss.source_set()
+
+xen_ss.add(when: 'CONFIG_XEN', if_true: files('xen-mapcache.c'))
diff --git a/hw/xen/trace-events b/hw/xen/trace-events
index 55c9e1df68..f977c7c8c6 100644
--- a/hw/xen/trace-events
+++ b/hw/xen/trace-events
@@ -41,3 +41,8 @@ xs_node_vprintf(char *path, char *value) "%s %s"
 xs_node_vscanf(char *path, char *value) "%s %s"
 xs_node_watch(char *path) "%s"
 xs_node_unwatch(char *path) "%s"
+
+# xen-mapcache.c
+xen_map_cache(uint64_t phys_addr) "want 0x%"PRIx64
+xen_remap_bucket(uint64_t index) "index 0x%"PRIx64
+xen_map_cache_return(void* ptr) "%p"
diff --git a/hw/i386/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
similarity index 100%
rename from hw/i386/xen/xen-mapcache.c
rename to hw/xen/xen-mapcache.c
-- 
2.25.1




[PULL v5 08/11] meson.build: do not set have_xen_pci_passthrough for aarch64 targets

2023-06-15 Thread Stefano Stabellini
From: Stefano Stabellini 

have_xen_pci_passthrough is only used for Xen x86 VMs.

Signed-off-by: Stefano Stabellini 
Reviewed-by: Alex Bennée 
---
 meson.build | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/meson.build b/meson.build
index 34306a6205..481865bfa9 100644
--- a/meson.build
+++ b/meson.build
@@ -1726,6 +1726,8 @@ have_xen_pci_passthrough = 
get_option('xen_pci_passthrough') \
error_message: 'Xen PCI passthrough requested but Xen not enabled') 
\
   .require(targetos == 'linux',
error_message: 'Xen PCI passthrough not available on this 
platform') \
+  .require(cpu == 'x86'  or cpu == 'x86_64',
+   error_message: 'Xen PCI passthrough not available on this 
platform') \
   .allowed()
 
 
-- 
2.25.1




[PULL v5 04/11] xen-hvm: reorganize xen-hvm and move common function to xen-hvm-common

2023-06-15 Thread Stefano Stabellini
From: Stefano Stabellini 

This patch does following:
1. creates arch_handle_ioreq() and arch_xen_set_memory(). This is done in
preparation for moving most of xen-hvm code to an arch-neutral location,
move the x86-specific portion of xen_set_memory to arch_xen_set_memory.
Also, move handle_vmport_ioreq to arch_handle_ioreq.

2. Pure code movement: move common functions to hw/xen/xen-hvm-common.c
Extract common functionalities from hw/i386/xen/xen-hvm.c and move them to
hw/xen/xen-hvm-common.c. These common functions are useful for creating
an IOREQ server.

xen_hvm_init_pc() contains the architecture independent code for creating
and mapping a IOREQ server, connecting memory and IO listeners, initializing
a xen bus and registering backends. Moved this common xen code to a new
function xen_register_ioreq() which can be used by both x86 and ARM 
machines.

Following functions are moved to hw/xen/xen-hvm-common.c:
xen_vcpu_eport(), xen_vcpu_ioreq(), xen_ram_alloc(), xen_set_memory(),
xen_region_add(), xen_region_del(), xen_io_add(), xen_io_del(),
xen_device_realize(), xen_device_unrealize(),
cpu_get_ioreq_from_shared_memory(), cpu_get_ioreq(), do_inp(),
do_outp(), rw_phys_req_item(), read_phys_req_item(),
write_phys_req_item(), cpu_ioreq_pio(), cpu_ioreq_move(),
cpu_ioreq_config(), handle_ioreq(), handle_buffered_iopage(),
handle_buffered_io(), cpu_handle_ioreq(), xen_main_loop_prepare(),
xen_hvm_change_state_handler(), xen_exit_notifier(),
xen_map_ioreq_server(), destroy_hvm_domain() and
xen_shutdown_fatal_error()

3. Removed static type from below functions:
1. xen_region_add()
2. xen_region_del()
3. xen_io_add()
4. xen_io_del()
5. xen_device_realize()
6. xen_device_unrealize()
7. xen_hvm_change_state_handler()
8. cpu_ioreq_pio()
9. xen_exit_notifier()

4. Replace TARGET_PAGE_SIZE with XC_PAGE_SIZE to match the page side with Xen.

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Acked-by: Stefano Stabellini 
---
 hw/i386/xen/trace-events|   14 -
 hw/i386/xen/xen-hvm.c   | 1016 ++-
 hw/xen/meson.build  |5 +-
 hw/xen/trace-events |   14 +
 hw/xen/xen-hvm-common.c |  860 ++
 include/hw/i386/xen_arch_hvm.h  |   11 +
 include/hw/xen/arch_hvm.h   |3 +
 include/hw/xen/xen-hvm-common.h |   99 +++
 8 files changed, 1054 insertions(+), 968 deletions(-)
 create mode 100644 hw/xen/xen-hvm-common.c
 create mode 100644 include/hw/i386/xen_arch_hvm.h
 create mode 100644 include/hw/xen/arch_hvm.h
 create mode 100644 include/hw/xen/xen-hvm-common.h

diff --git a/hw/i386/xen/trace-events b/hw/i386/xen/trace-events
index a0c89d91c4..5d0a8d6dcf 100644
--- a/hw/i386/xen/trace-events
+++ b/hw/i386/xen/trace-events
@@ -7,17 +7,3 @@ xen_platform_log(char *s) "xen platform: %s"
 xen_pv_mmio_read(uint64_t addr) "WARNING: read from Xen PV Device MMIO space 
(address 0x%"PRIx64")"
 xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space 
(address 0x%"PRIx64")"
 
-# xen-hvm.c
-xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: 0x%lx, 
size 0x%lx"
-xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) 
"0x%"PRIx64" size 0x%lx, log_dirty %i"
-handle_ioreq(void *req, uint32_t type, uint32_t dir, uint32_t df, uint32_t 
data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) 
"I/O=%p type=%d dir=%d df=%d ptr=%d port=0x%"PRIx64" data=0x%"PRIx64" count=%d 
size=%d"
-handle_ioreq_read(void *req, uint32_t type, uint32_t df, uint32_t data_is_ptr, 
uint64_t addr, uint64_t data, uint32_t count, uint32_t size) "I/O=%p read 
type=%d df=%d ptr=%d port=0x%"PRIx64" data=0x%"PRIx64" count=%d size=%d"
-handle_ioreq_write(void *req, uint32_t type, uint32_t df, uint32_t 
data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) 
"I/O=%p write type=%d df=%d ptr=%d port=0x%"PRIx64" data=0x%"PRIx64" count=%d 
size=%d"
-cpu_ioreq_pio(void *req, uint32_t dir, uint32_t df, uint32_t data_is_ptr, 
uint64_t addr, uint64_t data, uint32_t count, uint32_t size) "I/O=%p pio dir=%d 
df=%d ptr=%d port=0x%"PRIx64" data=0x%"PRIx64" count=%d size=%d"
-cpu_ioreq_pio_read_reg(void *req, uint64_t data, uint64_t addr, uint32_t size) 
"I/O=%p pio read reg data=0x%"PRIx64" port=0x%"PRIx64" size=%d"
-cpu_ioreq_pio_write_reg(void *req, uint64_t data, uint64_t addr, uint32_t 
size) "I/O=%p pio write reg data=0x%"PRIx64" port=0x%"PRIx64" size=%d"
-cpu_ioreq_move(void *req, uint32_t dir, uint32_t df, uint32_t data_is_ptr, 
uint64_t addr, 

[PULL v5 00/11] xenpvh5-tag

2023-06-15 Thread Stefano Stabellini
Hi Peter, Richard,

Vikram fixed the gitlab test problem yet again. I appended a tiny qtest
fix at the end of the series.

Cheers,

Stefano


The following changes since commit 7efd65423ab22e6f5890ca08ae40c84d6660242f:

  Merge tag 'pull-riscv-to-apply-20230614' of 
https://github.com/alistair23/qemu into staging (2023-06-14 05:28:51 +0200)

are available in the Git repository at:

  https://gitlab.com/sstabellini/qemu.git xenpvh5-tag

for you to fetch changes up to d8a714eba68cd7221d44a6acb6b8a69cf6f2f86b:

  test/qtest: add xepvh to skip list for qtest (2023-06-15 16:46:58 -0700)


Stefano Stabellini (5):
  hw/i386/xen/xen-hvm: move x86-specific fields out of XenIOState
  xen-hvm: reorganize xen-hvm and move common function to xen-hvm-common
  include/hw/xen/xen_common: return error from xen_create_ioreq_server
  hw/xen/xen-hvm-common: skip ioreq creation on ioreq registration failure
  meson.build: do not set have_xen_pci_passthrough for aarch64 targets

Vikram Garhwal (6):
  hw/i386/xen/: move xen-mapcache.c to hw/xen/
  hw/i386/xen: rearrange xen_hvm_init_pc
  hw/xen/xen-hvm-common: Use g_new and error_report
  hw/arm: introduce xenpvh machine
  meson.build: enable xenpv machine build for ARM
  test/qtest: add xepvh to skip list for qtest

 docs/system/arm/xenpvh.rst   |   34 ++
 docs/system/target-arm.rst   |1 +
 hw/arm/meson.build   |2 +
 hw/arm/xen_arm.c |  181 +++
 hw/i386/meson.build  |1 +
 hw/i386/xen/meson.build  |1 -
 hw/i386/xen/trace-events |   19 -
 hw/i386/xen/xen-hvm.c| 1075 --
 hw/xen/meson.build   |7 +
 hw/xen/trace-events  |   19 +
 hw/xen/xen-hvm-common.c  |  879 +++
 hw/{i386 => }/xen/xen-mapcache.c |0
 include/hw/arm/xen_arch_hvm.h|9 +
 include/hw/i386/xen_arch_hvm.h   |   11 +
 include/hw/xen/arch_hvm.h|5 +
 include/hw/xen/xen-hvm-common.h  |   99 
 include/hw/xen/xen_native.h  |8 +-
 meson.build  |4 +-
 tests/qtest/libqtest.c   |3 +-
 19 files changed, 1349 insertions(+), 1009 deletions(-)
 create mode 100644 docs/system/arm/xenpvh.rst
 create mode 100644 hw/arm/xen_arm.c
 create mode 100644 hw/xen/xen-hvm-common.c
 rename hw/{i386 => }/xen/xen-mapcache.c (100%)
 create mode 100644 include/hw/arm/xen_arch_hvm.h
 create mode 100644 include/hw/i386/xen_arch_hvm.h
 create mode 100644 include/hw/xen/arch_hvm.h
 create mode 100644 include/hw/xen/xen-hvm-common.h



Re: [QEMU][PATCH v8 11/11] test/qtest: add xepvh to skip list for qtest

2023-06-15 Thread Stefano Stabellini
On Wed, 14 Jun 2023, Vikram Garhwal wrote:
> Like existing xen machines, xenpvh also cannot be used for qtest.
> 
> Signed-off-by: Vikram Garhwal 

Reviewed-by: Stefano Stabellini 


> ---
>  tests/qtest/libqtest.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
> index 77de16227f..de03ef5f60 100644
> --- a/tests/qtest/libqtest.c
> +++ b/tests/qtest/libqtest.c
> @@ -1465,7 +1465,8 @@ void qtest_cb_for_every_machine(void (*cb)(const char 
> *machine),
>  for (i = 0; machines[i].name != NULL; i++) {
>  /* Ignore machines that cannot be used for qtests */
>  if (!strncmp("xenfv", machines[i].name, 5) ||
> -g_str_equal("xenpv", machines[i].name)) {
> +g_str_equal("xenpv", machines[i].name) ||
> +g_str_equal("xenpvh", machines[i].name)) {
>  continue;
>  }
>  if (!skip_old_versioned ||
> -- 
> 2.17.1
> 



[PULL v4 10/10] meson.build: enable xenpv machine build for ARM

2023-06-09 Thread Stefano Stabellini
From: Vikram Garhwal 

Add CONFIG_XEN for aarch64 device to support build for ARM targets.

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Reviewed-by: Alex Bennée 
---
 meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/meson.build b/meson.build
index 481865bfa9..cfa98e9e25 100644
--- a/meson.build
+++ b/meson.build
@@ -136,7 +136,7 @@ endif
 if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
   # i386 emulator provides xenpv machine type for multiple architectures
   accelerator_targets += {
-'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu'],
+'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu', 'aarch64-softmmu'],
   }
 endif
 if cpu in ['x86', 'x86_64']
-- 
2.25.1




[PULL v4 02/10] hw/i386/xen: rearrange xen_hvm_init_pc

2023-06-09 Thread Stefano Stabellini
From: Vikram Garhwal 

In preparation to moving most of xen-hvm code to an arch-neutral location,
move non IOREQ references to:
- xen_get_vmport_regs_pfn
- xen_suspend_notifier
- xen_wakeup_notifier
- xen_ram_init

towards the end of the xen_hvm_init_pc() function.

This is done to keep the common ioreq functions in one place which will be
moved to new function in next patch in order to make it common to both x86 and
aarch64 machines.

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 hw/i386/xen/xen-hvm.c | 49 ++-
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index ab8f1b61ee..7a7764240e 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -1419,12 +1419,6 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion 
**ram_memory)
 state->exit.notify = xen_exit_notifier;
 qemu_add_exit_notifier(>exit);
 
-state->suspend.notify = xen_suspend_notifier;
-qemu_register_suspend_notifier(>suspend);
-
-state->wakeup.notify = xen_wakeup_notifier;
-qemu_register_wakeup_notifier(>wakeup);
-
 /*
  * Register wake-up support in QMP query-current-machine API
  */
@@ -1435,23 +1429,6 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion 
**ram_memory)
 goto err;
 }
 
-rc = xen_get_vmport_regs_pfn(xen_xc, xen_domid, _pfn);
-if (!rc) {
-DPRINTF("shared vmport page at pfn %lx\n", ioreq_pfn);
-state->shared_vmport_page =
-xenforeignmemory_map(xen_fmem, xen_domid, PROT_READ|PROT_WRITE,
- 1, _pfn, NULL);
-if (state->shared_vmport_page == NULL) {
-error_report("map shared vmport IO page returned error %d 
handle=%p",
- errno, xen_xc);
-goto err;
-}
-} else if (rc != -ENOSYS) {
-error_report("get vmport regs pfn returned error %d, rc=%d",
- errno, rc);
-goto err;
-}
-
 /* Note: cpus is empty at this point in init */
 state->cpu_by_vcpu_id = g_new0(CPUState *, max_cpus);
 
@@ -1490,7 +1467,6 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion 
**ram_memory)
 #else
 xen_map_cache_init(NULL, state);
 #endif
-xen_ram_init(pcms, ms->ram_size, ram_memory);
 
 qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
 
@@ -1511,6 +1487,31 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion 
**ram_memory)
 QLIST_INIT(_physmap);
 xen_read_physmap(state);
 
+state->suspend.notify = xen_suspend_notifier;
+qemu_register_suspend_notifier(>suspend);
+
+state->wakeup.notify = xen_wakeup_notifier;
+qemu_register_wakeup_notifier(>wakeup);
+
+rc = xen_get_vmport_regs_pfn(xen_xc, xen_domid, _pfn);
+if (!rc) {
+DPRINTF("shared vmport page at pfn %lx\n", ioreq_pfn);
+state->shared_vmport_page =
+xenforeignmemory_map(xen_fmem, xen_domid, PROT_READ|PROT_WRITE,
+ 1, _pfn, NULL);
+if (state->shared_vmport_page == NULL) {
+error_report("map shared vmport IO page returned error %d 
handle=%p",
+ errno, xen_xc);
+goto err;
+}
+} else if (rc != -ENOSYS) {
+error_report("get vmport regs pfn returned error %d, rc=%d",
+ errno, rc);
+goto err;
+}
+
+xen_ram_init(pcms, ms->ram_size, ram_memory);
+
 /* Disable ACPI build because Xen handles it */
 pcms->acpi_build_enabled = false;
 
-- 
2.25.1




[PULL v4 06/10] hw/xen/xen-hvm-common: skip ioreq creation on ioreq registration failure

2023-06-09 Thread Stefano Stabellini
From: Stefano Stabellini 

On ARM it is possible to have a functioning xenpv machine with only the
PV backends and no IOREQ server. If the IOREQ server creation fails continue
to the PV backends initialization.

Also, moved the IOREQ registration and mapping subroutine to new function
xen_do_ioreq_register().

Signed-off-by: Stefano Stabellini 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 hw/xen/xen-hvm-common.c | 57 +++--
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index a31b067404..cb82f4b83d 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -764,27 +764,12 @@ void xen_shutdown_fatal_error(const char *fmt, ...)
 qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_ERROR);
 }
 
-void xen_register_ioreq(XenIOState *state, unsigned int max_cpus,
-MemoryListener xen_memory_listener)
+static void xen_do_ioreq_register(XenIOState *state,
+   unsigned int max_cpus,
+   MemoryListener xen_memory_listener)
 {
 int i, rc;
 
-setup_xen_backend_ops();
-
-state->xce_handle = qemu_xen_evtchn_open();
-if (state->xce_handle == NULL) {
-perror("xen: event channel open");
-goto err;
-}
-
-state->xenstore = xs_daemon_open();
-if (state->xenstore == NULL) {
-perror("xen: xenstore open");
-goto err;
-}
-
-xen_create_ioreq_server(xen_domid, >ioservid);
-
 state->exit.notify = xen_exit_notifier;
 qemu_add_exit_notifier(>exit);
 
@@ -849,12 +834,46 @@ void xen_register_ioreq(XenIOState *state, unsigned int 
max_cpus,
 QLIST_INIT(>dev_list);
 device_listener_register(>device_listener);
 
+return;
+
+err:
+error_report("xen hardware virtual machine initialisation failed");
+exit(1);
+}
+
+void xen_register_ioreq(XenIOState *state, unsigned int max_cpus,
+MemoryListener xen_memory_listener)
+{
+int rc;
+
+setup_xen_backend_ops();
+
+state->xce_handle = qemu_xen_evtchn_open();
+if (state->xce_handle == NULL) {
+perror("xen: event channel open");
+goto err;
+}
+
+state->xenstore = xs_daemon_open();
+if (state->xenstore == NULL) {
+perror("xen: xenstore open");
+goto err;
+}
+
+rc = xen_create_ioreq_server(xen_domid, >ioservid);
+if (!rc) {
+xen_do_ioreq_register(state, max_cpus, xen_memory_listener);
+} else {
+warn_report("xen: failed to create ioreq server");
+}
+
 xen_bus_init();
 
 xen_be_init();
 
 return;
+
 err:
-error_report("xen hardware virtual machine initialisation failed");
+error_report("xen hardware virtual machine backend registration failed");
 exit(1);
 }
-- 
2.25.1




[PULL v4 05/10] include/hw/xen/xen_common: return error from xen_create_ioreq_server

2023-06-09 Thread Stefano Stabellini
From: Stefano Stabellini 

From: Stefano Stabellini 

This is done to prepare for enabling xenpv support for ARM architecture.
On ARM it is possible to have a functioning xenpv machine with only the
PV backends and no IOREQ server. If the IOREQ server creation fails,
continue to the PV backends initialization.

Signed-off-by: Stefano Stabellini 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 include/hw/xen/xen_native.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
index f11eb423e3..4dce905fde 100644
--- a/include/hw/xen/xen_native.h
+++ b/include/hw/xen/xen_native.h
@@ -463,8 +463,8 @@ static inline void xen_unmap_pcidev(domid_t dom,
   PCI_FUNC(pci_dev->devfn));
 }
 
-static inline void xen_create_ioreq_server(domid_t dom,
-   ioservid_t *ioservid)
+static inline int xen_create_ioreq_server(domid_t dom,
+  ioservid_t *ioservid)
 {
 int rc = xendevicemodel_create_ioreq_server(xen_dmod, dom,
 HVM_IOREQSRV_BUFIOREQ_ATOMIC,
@@ -472,12 +472,14 @@ static inline void xen_create_ioreq_server(domid_t dom,
 
 if (rc == 0) {
 trace_xen_ioreq_server_create(*ioservid);
-return;
+return rc;
 }
 
 *ioservid = 0;
 use_default_ioreq_server = true;
 trace_xen_default_ioreq_server();
+
+return rc;
 }
 
 static inline void xen_destroy_ioreq_server(domid_t dom,
-- 
2.25.1




[PULL v4 09/10] hw/arm: introduce xenpvh machine

2023-06-09 Thread Stefano Stabellini
From: Vikram Garhwal 

Add a new machine xenpvh which creates a IOREQ server to register/connect with
Xen Hypervisor.

Optional: When CONFIG_TPM is enabled, it also creates a tpm-tis-device, adds a
TPM emulator and connects to swtpm running on host machine via chardev socket
and support TPM functionalities for a guest domain.

Extra command line for aarch64 xenpvh QEMU to connect to swtpm:
-chardev socket,id=chrtpm,path=/tmp/myvtpm2/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-machine tpm-base-addr=0x0c00 \

swtpm implements a TPM software emulator(TPM 1.2 & TPM 2) built on libtpms and
provides access to TPM functionality over socket, chardev and CUSE interface.
Github repo: https://github.com/stefanberger/swtpm
Example for starting swtpm on host machine:
mkdir /tmp/vtpm2
swtpm socket --tpmstate dir=/tmp/vtpm2 \
--ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Reviewed-by: Stefano Stabellini 
---
 docs/system/arm/xenpvh.rst|  34 +++
 docs/system/target-arm.rst|   1 +
 hw/arm/meson.build|   2 +
 hw/arm/xen_arm.c  | 181 ++
 include/hw/arm/xen_arch_hvm.h |   9 ++
 include/hw/xen/arch_hvm.h |   2 +
 6 files changed, 229 insertions(+)
 create mode 100644 docs/system/arm/xenpvh.rst
 create mode 100644 hw/arm/xen_arm.c
 create mode 100644 include/hw/arm/xen_arch_hvm.h

diff --git a/docs/system/arm/xenpvh.rst b/docs/system/arm/xenpvh.rst
new file mode 100644
index 00..e1655c7ab8
--- /dev/null
+++ b/docs/system/arm/xenpvh.rst
@@ -0,0 +1,34 @@
+XENPVH (``xenpvh``)
+=
+This machine creates a IOREQ server to register/connect with Xen Hypervisor.
+
+When TPM is enabled, this machine also creates a tpm-tis-device at a user input
+tpm base address, adds a TPM emulator and connects to a swtpm application
+running on host machine via chardev socket. This enables xenpvh to support TPM
+functionalities for a guest domain.
+
+More information about TPM use and installing swtpm linux application can be
+found at: docs/specs/tpm.rst.
+
+Example for starting swtpm on host machine:
+.. code-block:: console
+
+mkdir /tmp/vtpm2
+swtpm socket --tpmstate dir=/tmp/vtpm2 \
+--ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &
+
+Sample QEMU xenpvh commands for running and connecting with Xen:
+.. code-block:: console
+
+qemu-system-aarch64 -xen-domid 1 \
+-chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
+-mon chardev=libxl-cmd,mode=control \
+-chardev socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off 
\
+-mon chardev=libxenstat-cmd,mode=control \
+-xen-attach -name guest0 -vnc none -display none -nographic \
+-machine xenpvh -m 1301 \
+-chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
+-tpmdev emulator,id=tpm0,chardev=chrtpm -machine tpm-base-addr=0x0C00
+
+In above QEMU command, last two lines are for connecting xenpvh QEMU to swtpm
+via chardev socket.
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index a12b6bca05..790ac1b8a2 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -107,6 +107,7 @@ undocumented; you can get a complete list by running
arm/stm32
arm/virt
arm/xlnx-versal-virt
+   arm/xenpvh
 
 Emulated CPU architecture support
 =
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 870ec67376..4f94f821b0 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -63,6 +63,8 @@ arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: 
files('fsl-imx7.c', 'mcimx7d-sabre.
 arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
 arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 
'mcimx6ul-evk.c'))
 arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
+arm_ss.add(when: 'CONFIG_XEN', if_true: files('xen_arm.c'))
+arm_ss.add_all(xen_ss)
 
 softmmu_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
 softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
new file mode 100644
index 00..19b1cb81ad
--- /dev/null
+++ b/hw/arm/xen_arm.c
@@ -0,0 +1,181 @@
+/*
+ * QEMU ARM Xen PVH Machine
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * TH

[PULL v4 08/10] meson.build: do not set have_xen_pci_passthrough for aarch64 targets

2023-06-09 Thread Stefano Stabellini
From: Stefano Stabellini 

have_xen_pci_passthrough is only used for Xen x86 VMs.

Signed-off-by: Stefano Stabellini 
Reviewed-by: Alex Bennée 
---
 meson.build | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/meson.build b/meson.build
index 34306a6205..481865bfa9 100644
--- a/meson.build
+++ b/meson.build
@@ -1726,6 +1726,8 @@ have_xen_pci_passthrough = 
get_option('xen_pci_passthrough') \
error_message: 'Xen PCI passthrough requested but Xen not enabled') 
\
   .require(targetos == 'linux',
error_message: 'Xen PCI passthrough not available on this 
platform') \
+  .require(cpu == 'x86'  or cpu == 'x86_64',
+   error_message: 'Xen PCI passthrough not available on this 
platform') \
   .allowed()
 
 
-- 
2.25.1




[PULL v4 07/10] hw/xen/xen-hvm-common: Use g_new and error_report

2023-06-09 Thread Stefano Stabellini
From: Vikram Garhwal 

Replace g_malloc with g_new and perror with error_report.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 hw/xen/xen-hvm-common.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index cb82f4b83d..42339c96bd 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -33,7 +33,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, 
MemoryRegion *mr,
 trace_xen_ram_alloc(ram_addr, size);
 
 nr_pfn = size >> TARGET_PAGE_BITS;
-pfn_list = g_malloc(sizeof (*pfn_list) * nr_pfn);
+pfn_list = g_new(xen_pfn_t, nr_pfn);
 
 for (i = 0; i < nr_pfn; i++) {
 pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
@@ -730,7 +730,7 @@ void destroy_hvm_domain(bool reboot)
 return;
 }
 if (errno != ENOTTY /* old Xen */) {
-perror("xendevicemodel_shutdown failed");
+error_report("xendevicemodel_shutdown failed with error %d", 
errno);
 }
 /* well, try the old thing then */
 }
@@ -784,7 +784,7 @@ static void xen_do_ioreq_register(XenIOState *state,
 }
 
 /* Note: cpus is empty at this point in init */
-state->cpu_by_vcpu_id = g_malloc0(max_cpus * sizeof(CPUState *));
+state->cpu_by_vcpu_id = g_new0(CPUState *, max_cpus);
 
 rc = xen_set_ioreq_server_state(xen_domid, state->ioservid, true);
 if (rc < 0) {
@@ -793,7 +793,7 @@ static void xen_do_ioreq_register(XenIOState *state,
 goto err;
 }
 
-state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
+state->ioreq_local_port = g_new0(evtchn_port_t, max_cpus);
 
 /* FIXME: how about if we overflow the page here? */
 for (i = 0; i < max_cpus; i++) {
@@ -850,13 +850,13 @@ void xen_register_ioreq(XenIOState *state, unsigned int 
max_cpus,
 
 state->xce_handle = qemu_xen_evtchn_open();
 if (state->xce_handle == NULL) {
-perror("xen: event channel open");
+error_report("xen: event channel open failed with error %d", errno);
 goto err;
 }
 
 state->xenstore = xs_daemon_open();
 if (state->xenstore == NULL) {
-perror("xen: xenstore open");
+error_report("xen: xenstore open failed with error %d", errno);
 goto err;
 }
 
-- 
2.25.1




[PULL v4 04/10] xen-hvm: reorganize xen-hvm and move common function to xen-hvm-common

2023-06-09 Thread Stefano Stabellini
From: Stefano Stabellini 

This patch does following:
1. creates arch_handle_ioreq() and arch_xen_set_memory(). This is done in
preparation for moving most of xen-hvm code to an arch-neutral location,
move the x86-specific portion of xen_set_memory to arch_xen_set_memory.
Also, move handle_vmport_ioreq to arch_handle_ioreq.

2. Pure code movement: move common functions to hw/xen/xen-hvm-common.c
Extract common functionalities from hw/i386/xen/xen-hvm.c and move them to
hw/xen/xen-hvm-common.c. These common functions are useful for creating
an IOREQ server.

xen_hvm_init_pc() contains the architecture independent code for creating
and mapping a IOREQ server, connecting memory and IO listeners, initializing
a xen bus and registering backends. Moved this common xen code to a new
function xen_register_ioreq() which can be used by both x86 and ARM 
machines.

Following functions are moved to hw/xen/xen-hvm-common.c:
xen_vcpu_eport(), xen_vcpu_ioreq(), xen_ram_alloc(), xen_set_memory(),
xen_region_add(), xen_region_del(), xen_io_add(), xen_io_del(),
xen_device_realize(), xen_device_unrealize(),
cpu_get_ioreq_from_shared_memory(), cpu_get_ioreq(), do_inp(),
do_outp(), rw_phys_req_item(), read_phys_req_item(),
write_phys_req_item(), cpu_ioreq_pio(), cpu_ioreq_move(),
cpu_ioreq_config(), handle_ioreq(), handle_buffered_iopage(),
handle_buffered_io(), cpu_handle_ioreq(), xen_main_loop_prepare(),
xen_hvm_change_state_handler(), xen_exit_notifier(),
xen_map_ioreq_server(), destroy_hvm_domain() and
xen_shutdown_fatal_error()

3. Removed static type from below functions:
1. xen_region_add()
2. xen_region_del()
3. xen_io_add()
4. xen_io_del()
5. xen_device_realize()
6. xen_device_unrealize()
7. xen_hvm_change_state_handler()
8. cpu_ioreq_pio()
9. xen_exit_notifier()

4. Replace TARGET_PAGE_SIZE with XC_PAGE_SIZE to match the page side with Xen.

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Acked-by: Stefano Stabellini 
---
 hw/i386/xen/trace-events|   14 -
 hw/i386/xen/xen-hvm.c   | 1016 ++-
 hw/xen/meson.build  |5 +-
 hw/xen/trace-events |   14 +
 hw/xen/xen-hvm-common.c |  860 ++
 include/hw/i386/xen_arch_hvm.h  |   11 +
 include/hw/xen/arch_hvm.h   |3 +
 include/hw/xen/xen-hvm-common.h |   99 +++
 8 files changed, 1054 insertions(+), 968 deletions(-)
 create mode 100644 hw/xen/xen-hvm-common.c
 create mode 100644 include/hw/i386/xen_arch_hvm.h
 create mode 100644 include/hw/xen/arch_hvm.h
 create mode 100644 include/hw/xen/xen-hvm-common.h

diff --git a/hw/i386/xen/trace-events b/hw/i386/xen/trace-events
index a0c89d91c4..5d0a8d6dcf 100644
--- a/hw/i386/xen/trace-events
+++ b/hw/i386/xen/trace-events
@@ -7,17 +7,3 @@ xen_platform_log(char *s) "xen platform: %s"
 xen_pv_mmio_read(uint64_t addr) "WARNING: read from Xen PV Device MMIO space 
(address 0x%"PRIx64")"
 xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space 
(address 0x%"PRIx64")"
 
-# xen-hvm.c
-xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: 0x%lx, 
size 0x%lx"
-xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) 
"0x%"PRIx64" size 0x%lx, log_dirty %i"
-handle_ioreq(void *req, uint32_t type, uint32_t dir, uint32_t df, uint32_t 
data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) 
"I/O=%p type=%d dir=%d df=%d ptr=%d port=0x%"PRIx64" data=0x%"PRIx64" count=%d 
size=%d"
-handle_ioreq_read(void *req, uint32_t type, uint32_t df, uint32_t data_is_ptr, 
uint64_t addr, uint64_t data, uint32_t count, uint32_t size) "I/O=%p read 
type=%d df=%d ptr=%d port=0x%"PRIx64" data=0x%"PRIx64" count=%d size=%d"
-handle_ioreq_write(void *req, uint32_t type, uint32_t df, uint32_t 
data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) 
"I/O=%p write type=%d df=%d ptr=%d port=0x%"PRIx64" data=0x%"PRIx64" count=%d 
size=%d"
-cpu_ioreq_pio(void *req, uint32_t dir, uint32_t df, uint32_t data_is_ptr, 
uint64_t addr, uint64_t data, uint32_t count, uint32_t size) "I/O=%p pio dir=%d 
df=%d ptr=%d port=0x%"PRIx64" data=0x%"PRIx64" count=%d size=%d"
-cpu_ioreq_pio_read_reg(void *req, uint64_t data, uint64_t addr, uint32_t size) 
"I/O=%p pio read reg data=0x%"PRIx64" port=0x%"PRIx64" size=%d"
-cpu_ioreq_pio_write_reg(void *req, uint64_t data, uint64_t addr, uint32_t 
size) "I/O=%p pio write reg data=0x%"PRIx64" port=0x%"PRIx64" size=%d"
-cpu_ioreq_move(void *req, uint32_t dir, uint32_t df, uint32_t data_is_ptr, 
uint64_t addr, 

[PULL v4 01/10] hw/i386/xen/: move xen-mapcache.c to hw/xen/

2023-06-09 Thread Stefano Stabellini
From: Vikram Garhwal 

xen-mapcache.c contains common functions which can be used for enabling Xen on
aarch64 with IOREQ handling. Moving it out from hw/i386/xen to hw/xen to make it
accessible for both aarch64 and x86.

Signed-off-by: Vikram Garhwal 
Signed-off-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 hw/i386/meson.build  | 1 +
 hw/i386/xen/meson.build  | 1 -
 hw/i386/xen/trace-events | 5 -
 hw/xen/meson.build   | 4 
 hw/xen/trace-events  | 5 +
 hw/{i386 => }/xen/xen-mapcache.c | 0
 6 files changed, 10 insertions(+), 6 deletions(-)
 rename hw/{i386 => }/xen/xen-mapcache.c (100%)

diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 213e2e82b3..cfdbfdcbcb 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -33,5 +33,6 @@ subdir('kvm')
 subdir('xen')
 
 i386_ss.add_all(xenpv_ss)
+i386_ss.add_all(xen_ss)
 
 hw_arch += {'i386': i386_ss}
diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build
index 2e64a34e16..3dc4c4f106 100644
--- a/hw/i386/xen/meson.build
+++ b/hw/i386/xen/meson.build
@@ -1,6 +1,5 @@
 i386_ss.add(when: 'CONFIG_XEN', if_true: files(
   'xen-hvm.c',
-  'xen-mapcache.c',
   'xen_apic.c',
   'xen_pvdevice.c',
 ))
diff --git a/hw/i386/xen/trace-events b/hw/i386/xen/trace-events
index 5d6be61090..a0c89d91c4 100644
--- a/hw/i386/xen/trace-events
+++ b/hw/i386/xen/trace-events
@@ -21,8 +21,3 @@ xen_map_resource_ioreq(uint32_t id, void *addr) "id: %u addr: 
%p"
 cpu_ioreq_config_read(void *req, uint32_t sbdf, uint32_t reg, uint32_t size, 
uint32_t data) "I/O=%p sbdf=0x%x reg=%u size=%u data=0x%x"
 cpu_ioreq_config_write(void *req, uint32_t sbdf, uint32_t reg, uint32_t size, 
uint32_t data) "I/O=%p sbdf=0x%x reg=%u size=%u data=0x%x"
 
-# xen-mapcache.c
-xen_map_cache(uint64_t phys_addr) "want 0x%"PRIx64
-xen_remap_bucket(uint64_t index) "index 0x%"PRIx64
-xen_map_cache_return(void* ptr) "%p"
-
diff --git a/hw/xen/meson.build b/hw/xen/meson.build
index 19c6aabc7c..202752e557 100644
--- a/hw/xen/meson.build
+++ b/hw/xen/meson.build
@@ -26,3 +26,7 @@ else
 endif
 
 specific_ss.add_all(when: ['CONFIG_XEN', xen], if_true: xen_specific_ss)
+
+xen_ss = ss.source_set()
+
+xen_ss.add(when: 'CONFIG_XEN', if_true: files('xen-mapcache.c'))
diff --git a/hw/xen/trace-events b/hw/xen/trace-events
index 55c9e1df68..f977c7c8c6 100644
--- a/hw/xen/trace-events
+++ b/hw/xen/trace-events
@@ -41,3 +41,8 @@ xs_node_vprintf(char *path, char *value) "%s %s"
 xs_node_vscanf(char *path, char *value) "%s %s"
 xs_node_watch(char *path) "%s"
 xs_node_unwatch(char *path) "%s"
+
+# xen-mapcache.c
+xen_map_cache(uint64_t phys_addr) "want 0x%"PRIx64
+xen_remap_bucket(uint64_t index) "index 0x%"PRIx64
+xen_map_cache_return(void* ptr) "%p"
diff --git a/hw/i386/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
similarity index 100%
rename from hw/i386/xen/xen-mapcache.c
rename to hw/xen/xen-mapcache.c
-- 
2.25.1




[PULL v4 03/10] hw/i386/xen/xen-hvm: move x86-specific fields out of XenIOState

2023-06-09 Thread Stefano Stabellini
From: Stefano Stabellini 

In preparation to moving most of xen-hvm code to an arch-neutral location, move:
- shared_vmport_page
- log_for_dirtybit
- dirty_bitmap
- suspend
- wakeup

out of XenIOState struct as these are only used on x86, especially the ones
related to dirty logging.
Updated XenIOState can be used for both aarch64 and x86.

Also, remove free_phys_offset as it was unused.

Signed-off-by: Stefano Stabellini 
Signed-off-by: Vikram Garhwal 
Reviewed-by: Paul Durrant 
Reviewed-by: Alex Bennée 
---
 hw/i386/xen/xen-hvm.c | 58 ---
 1 file changed, 27 insertions(+), 31 deletions(-)

diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 7a7764240e..01bf947f1c 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -74,6 +74,7 @@ struct shared_vmport_iopage {
 };
 typedef struct shared_vmport_iopage shared_vmport_iopage_t;
 #endif
+static shared_vmport_iopage_t *shared_vmport_page;
 
 static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
 {
@@ -96,6 +97,11 @@ typedef struct XenPhysmap {
 } XenPhysmap;
 
 static QLIST_HEAD(, XenPhysmap) xen_physmap;
+static const XenPhysmap *log_for_dirtybit;
+/* Buffer used by xen_sync_dirty_bitmap */
+static unsigned long *dirty_bitmap;
+static Notifier suspend;
+static Notifier wakeup;
 
 typedef struct XenPciDevice {
 PCIDevice *pci_dev;
@@ -106,7 +112,6 @@ typedef struct XenPciDevice {
 typedef struct XenIOState {
 ioservid_t ioservid;
 shared_iopage_t *shared_page;
-shared_vmport_iopage_t *shared_vmport_page;
 buffered_iopage_t *buffered_io_page;
 xenforeignmemory_resource_handle *fres;
 QEMUTimer *buffered_io_timer;
@@ -126,14 +131,8 @@ typedef struct XenIOState {
 MemoryListener io_listener;
 QLIST_HEAD(, XenPciDevice) dev_list;
 DeviceListener device_listener;
-hwaddr free_phys_offset;
-const XenPhysmap *log_for_dirtybit;
-/* Buffer used by xen_sync_dirty_bitmap */
-unsigned long *dirty_bitmap;
 
 Notifier exit;
-Notifier suspend;
-Notifier wakeup;
 } XenIOState;
 
 /* Xen specific function for piix pci */
@@ -463,10 +462,10 @@ static int xen_remove_from_physmap(XenIOState *state,
 }
 
 QLIST_REMOVE(physmap, list);
-if (state->log_for_dirtybit == physmap) {
-state->log_for_dirtybit = NULL;
-g_free(state->dirty_bitmap);
-state->dirty_bitmap = NULL;
+if (log_for_dirtybit == physmap) {
+log_for_dirtybit = NULL;
+g_free(dirty_bitmap);
+dirty_bitmap = NULL;
 }
 g_free(physmap);
 
@@ -627,16 +626,16 @@ static void xen_sync_dirty_bitmap(XenIOState *state,
 return;
 }
 
-if (state->log_for_dirtybit == NULL) {
-state->log_for_dirtybit = physmap;
-state->dirty_bitmap = g_new(unsigned long, bitmap_size);
-} else if (state->log_for_dirtybit != physmap) {
+if (log_for_dirtybit == NULL) {
+log_for_dirtybit = physmap;
+dirty_bitmap = g_new(unsigned long, bitmap_size);
+} else if (log_for_dirtybit != physmap) {
 /* Only one range for dirty bitmap can be tracked. */
 return;
 }
 
 rc = xen_track_dirty_vram(xen_domid, start_addr >> TARGET_PAGE_BITS,
-  npages, state->dirty_bitmap);
+  npages, dirty_bitmap);
 if (rc < 0) {
 #ifndef ENODATA
 #define ENODATA  ENOENT
@@ -651,7 +650,7 @@ static void xen_sync_dirty_bitmap(XenIOState *state,
 }
 
 for (i = 0; i < bitmap_size; i++) {
-unsigned long map = state->dirty_bitmap[i];
+unsigned long map = dirty_bitmap[i];
 while (map != 0) {
 j = ctzl(map);
 map &= ~(1ul << j);
@@ -677,12 +676,10 @@ static void xen_log_start(MemoryListener *listener,
 static void xen_log_stop(MemoryListener *listener, MemoryRegionSection 
*section,
  int old, int new)
 {
-XenIOState *state = container_of(listener, XenIOState, memory_listener);
-
 if (old & ~new & (1 << DIRTY_MEMORY_VGA)) {
-state->log_for_dirtybit = NULL;
-g_free(state->dirty_bitmap);
-state->dirty_bitmap = NULL;
+log_for_dirtybit = NULL;
+g_free(dirty_bitmap);
+dirty_bitmap = NULL;
 /* Disable dirty bit tracking */
 xen_track_dirty_vram(xen_domid, 0, 0, NULL);
 }
@@ -1022,9 +1019,9 @@ static void handle_vmport_ioreq(XenIOState *state, 
ioreq_t *req)
 {
 vmware_regs_t *vmport_regs;
 
-assert(state->shared_vmport_page);
+assert(shared_vmport_page);
 vmport_regs =
->shared_vmport_page->vcpu_vmport_regs[state->send_vcpu];
+_vmport_page->vcpu_vmport_regs[state->send_vcpu];
 QEMU_BUILD_BUG_ON(sizeof(*req) < sizeof(*vmport_regs));
 
 current_cpu = state->cpu_by_vcpu_id[state->send_vcpu];
@@ -1472,7 +1469,6 @@ void xen_hvm_init_pc

[PULL v4 0/10] xenpvh4-tag

2023-06-09 Thread Stefano Stabellini
Hi Peter,

Vikram fixed the gitlab test problem again. This time I am providing
proof that it is not introducing build regressions:

baseline: https://gitlab.com/sstabellini/qemu/-/pipelines/894578994
with new commits: https://gitlab.com/sstabellini/qemu/-/pipelines/894471770

Cheers,

Stefano


The following changes since commit 5f9dd6a8ce3961db4ce47411ed2097ad88bdf5fc:

  Merge tag 'pull-9p-20230608' of https://github.com/cschoenebeck/qemu into 
staging (2023-06-08 08:47:35 -0700)

are available in the Git repository at:

  https://gitlab.com/sstabellini/qemu xenpvh4-tag

for you to fetch changes up to 236c27fd61dd0961631076a56286dd108fe5ef1f:

  meson.build: enable xenpv machine build for ARM (2023-06-08 16:54:31 -0700)


Stefano Stabellini (5):
  hw/i386/xen/xen-hvm: move x86-specific fields out of XenIOState
  xen-hvm: reorganize xen-hvm and move common function to xen-hvm-common
  include/hw/xen/xen_common: return error from xen_create_ioreq_server
  hw/xen/xen-hvm-common: skip ioreq creation on ioreq registration failure
  meson.build: do not set have_xen_pci_passthrough for aarch64 targets

Vikram Garhwal (5):
  hw/i386/xen/: move xen-mapcache.c to hw/xen/
  hw/i386/xen: rearrange xen_hvm_init_pc
  hw/xen/xen-hvm-common: Use g_new and error_report
  hw/arm: introduce xenpvh machine
  meson.build: enable xenpv machine build for ARM

 docs/system/arm/xenpvh.rst   |   34 ++
 docs/system/target-arm.rst   |1 +
 hw/arm/meson.build   |2 +
 hw/arm/xen_arm.c |  181 +++
 hw/i386/meson.build  |1 +
 hw/i386/xen/meson.build  |1 -
 hw/i386/xen/trace-events |   19 -
 hw/i386/xen/xen-hvm.c| 1075 --
 hw/xen/meson.build   |7 +
 hw/xen/trace-events  |   19 +
 hw/xen/xen-hvm-common.c  |  879 +++
 hw/{i386 => }/xen/xen-mapcache.c |0
 include/hw/arm/xen_arch_hvm.h|9 +
 include/hw/i386/xen_arch_hvm.h   |   11 +
 include/hw/xen/arch_hvm.h|5 +
 include/hw/xen/xen-hvm-common.h  |   99 
 include/hw/xen/xen_native.h  |8 +-
 meson.build  |4 +-
 18 files changed, 1347 insertions(+), 1008 deletions(-)
 create mode 100644 docs/system/arm/xenpvh.rst
 create mode 100644 hw/arm/xen_arm.c
 create mode 100644 hw/xen/xen-hvm-common.c
 rename hw/{i386 => }/xen/xen-mapcache.c (100%)
 create mode 100644 include/hw/arm/xen_arch_hvm.h
 create mode 100644 include/hw/i386/xen_arch_hvm.h
 create mode 100644 include/hw/xen/arch_hvm.h
 create mode 100644 include/hw/xen/xen-hvm-common.h



Re: [PATCH v4 0/7] Resolve TYPE_PIIX3_XEN_DEVICE

2023-06-08 Thread Stefano Stabellini
On Thu, 8 Jun 2023, Stefano Stabellini wrote:
> On Mon, 5 Jun 2023, Bernhard Beschow wrote:
> > Am 22. Mai 2023 15:42:03 UTC schrieb Bernhard Beschow :
> > >
> > >
> > >Am 15. Mai 2023 20:52:40 UTC schrieb Stefano Stabellini 
> > >:
> > >>On Sat, 13 May 2023, Bernhard Beschow wrote:
> > >>> Am 21. April 2023 07:38:10 UTC schrieb "Michael S. Tsirkin" 
> > >>> :
> > >>> >On Mon, Apr 03, 2023 at 09:41:17AM +0200, Bernhard Beschow wrote:
> > >>> >> There is currently a dedicated PIIX3 device model for use under Xen. 
> > >>> >> By reusing
> > >>> >> existing PCI API during initialization this device model can be 
> > >>> >> eliminated and
> > >>> >> the plain PIIX3 device model can be used instead.
> > >>> >> 
> > >>> >> Resolving TYPE_PIIX3_XEN_DEVICE results in less code while also 
> > >>> >> making Xen
> > >>> >> agnostic towards the precise south bridge being used in the PC 
> > >>> >> machine. The
> > >>> >> latter might become particularily interesting once PIIX4 becomes 
> > >>> >> usable in the
> > >>> >> PC machine, avoiding the "Frankenstein" use of PIIX4_ACPI in PIIX3.
> > >>> >
> > >>> >xen stuff so I assume that tree?
> > >>> 
> > >>> Ping
> > >>
> > >>I am OK either way. Michael, what do you prefer?
> > >>
> > >>Normally I would suggest for you to pick up the patches. But as it
> > >>happens I'll have to likely send another pull request in a week or two
> > >>and I can add these patches to it.
> > >>
> > >>Let me know your preference and I am happy to follow it.
> > >
> > >Hi Stefano,
> > >
> > >Michael's PR was merged last week. How about including this series into 
> > >your PR then?
> > 
> > Ping
> 
> Sorry for the late reply, it looks like patch #3 breaks the build:

I noticed now that this patch series got committed (the right version
without the build failure), thanks Anthony for sending the pull request!



Re: [PATCH v4 0/7] Resolve TYPE_PIIX3_XEN_DEVICE

2023-06-08 Thread Stefano Stabellini
On Mon, 5 Jun 2023, Bernhard Beschow wrote:
> Am 22. Mai 2023 15:42:03 UTC schrieb Bernhard Beschow :
> >
> >
> >Am 15. Mai 2023 20:52:40 UTC schrieb Stefano Stabellini 
> >:
> >>On Sat, 13 May 2023, Bernhard Beschow wrote:
> >>> Am 21. April 2023 07:38:10 UTC schrieb "Michael S. Tsirkin" 
> >>> :
> >>> >On Mon, Apr 03, 2023 at 09:41:17AM +0200, Bernhard Beschow wrote:
> >>> >> There is currently a dedicated PIIX3 device model for use under Xen. 
> >>> >> By reusing
> >>> >> existing PCI API during initialization this device model can be 
> >>> >> eliminated and
> >>> >> the plain PIIX3 device model can be used instead.
> >>> >> 
> >>> >> Resolving TYPE_PIIX3_XEN_DEVICE results in less code while also making 
> >>> >> Xen
> >>> >> agnostic towards the precise south bridge being used in the PC 
> >>> >> machine. The
> >>> >> latter might become particularily interesting once PIIX4 becomes 
> >>> >> usable in the
> >>> >> PC machine, avoiding the "Frankenstein" use of PIIX4_ACPI in PIIX3.
> >>> >
> >>> >xen stuff so I assume that tree?
> >>> 
> >>> Ping
> >>
> >>I am OK either way. Michael, what do you prefer?
> >>
> >>Normally I would suggest for you to pick up the patches. But as it
> >>happens I'll have to likely send another pull request in a week or two
> >>and I can add these patches to it.
> >>
> >>Let me know your preference and I am happy to follow it.
> >
> >Hi Stefano,
> >
> >Michael's PR was merged last week. How about including this series into your 
> >PR then?
> 
> Ping

Sorry for the late reply, it looks like patch #3 breaks the build:

[1888/4025] Compiling C object libcommon.fa.p/hw_isa_piix3.c.o
FAILED: libcommon.fa.p/hw_isa_piix3.c.o 
cc -m64 -mcx16 -Ilibcommon.fa.p -Iui -I../ui -I/usr/include/capstone 
-I/usr/include/pixman-1 -I/usr/include/libpng16 -I/usr/include/spice-server 
-I/usr/include/spice-1 -I/usr/include/p11-kit-1 -I/usr/include/libusb-1.0 
-I/usr/include/SDL2 -I/usr/include/glib-2.0 
-I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/libmount 
-I/usr/include/blkid -I/usr/include/gio-unix-2.0 -I/usr/include/slirp 
-I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz 
-I/usr/include/freetype2 -I/usr/include/fribidi -I/usr/include/uuid 
-I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/atk-1.0 
-I/usr/include/at-spi2-atk/2.0 -I/usr/include/dbus-1.0 
-I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/usr/include/at-spi-2.0 
-I/usr/include/vte-2.91 -I/usr/include/virgl -I/usr/include/cacard 
-I/usr/include/nss -I/usr/include/nspr -I/usr/include/PCSC 
-fdiagnostics-color=auto -Wall -Winvalid-pch -Werror -std=gnu11 -O2 -g 
-fstack-protector-strong -U_FORTIFY_SOURCE -D_FORTIFY_SOURC
 E=2 -Wundef -Wwrite-strings -Wmissing-prototypes -Wstrict-prototypes 
-Wredundant-decls -Wold-style-declaration -Wold-style-definition -Wtype-limits 
-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wempty-body 
-Wnested-externs -Wendif-labels -Wexpansion-to-defined -Wimplicit-fallthrough=2 
-Wmissing-format-attribute -Wno-missing-include-dirs -Wno-shift-negative-value 
-Wno-psabi -isystem /builds/Vikram.garhwal/qemu-ioreq/linux-headers -isystem 
linux-headers -iquote . -iquote /builds/Vikram.garhwal/qemu-ioreq -iquote 
/builds/Vikram.garhwal/qemu-ioreq/include -iquote 
/builds/Vikram.garhwal/qemu-ioreq/host/include/x86_64 -iquote 
/builds/Vikram.garhwal/qemu-ioreq/host/include/generic -iquote 
/builds/Vikram.garhwal/qemu-ioreq/tcg/i386 -pthread -D_GNU_SOURCE 
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing -fno-common 
-fwrapv -fPIE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DNCURSES_WIDECHAR=1 
-D_REENTRANT -Wno-undef -DSTRUCT_IOVEC_DEFINED -MD -MQ libcommon.fa.p/hw
 _isa_piix3.c.o -MF libcommon.fa.p/hw_isa_piix3.c.o.d -o 
libcommon.fa.p/hw_isa_piix3.c.o -c ../hw/isa/piix3.c
../hw/isa/piix3.c:265:13: error: ‘pci_piix3_realize’ defined but not used 
[-Werror=unused-function]
  265 | static void pci_piix3_realize(PCIDevice *dev, Error **errp)
  | ^
cc1: all warnings being treated as errors


  1   2   3   4   5   6   7   8   9   10   >