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

2024-03-06 Thread Vikram Garhwal
On Fri, Mar 01, 2024 at 05:04:54PM +, Alex Bennée wrote:
> Vikram Garhwal  writes:
> 
> > 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 | 56 
> >  1 file changed, 23 insertions(+), 33 deletions(-)
> >
> 
> > -
> > -/* 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.
> >   */
> 
> If you end up re-spinning it would be nice to kdoc this function and at
> least call out size as a return by ref and optional. 
Will do if re-spinning is needed.
> 
> >  static void *qemu_ram_ptr_length(RAMBlock *block, ram_addr_t addr,
> >   hwaddr *size, bool lock)
> >  {
> > -if (*size == 0) {
> > +hwaddr len = 0;
> > +
> > +if (size && *size == 0) {
> >  return NULL;
> >  }
> >  
> > @@ -2207,7 +2181,10 @@ static void *qemu_ram_ptr_length(RAMBlock *block, 
> > ram_addr_t addr,
> >  block = qemu_get_ram_block(addr);
> >  addr -= block->offset;
> >  }
> > -*size = MIN(*size, block->max_length - addr);
> > +if (size) {
> > +*size = MIN(*size, block->max_length - addr);
> > +len = *size;
> > +}
> >  
> >  if (xen_enabled() && block->host == NULL) {
> >  /* We need to check if the requested address is in the RAM
> > @@ -2215,7 +2192,7 @@ static void *qemu_ram_ptr_length(RAMBlock *block, 
> > ram_addr_t addr,
> >   * In that case just map the requested area.
> >   */
> >  if (block->offset == 0) {
> > -return xen_map_cache(addr, *size, lock, lock);
> > +return xen_map_cache(addr, len, lock, lock);
> 
> I did wonder if len == 0 will confuse things but it seems xen_map_cache
> will default to XC_PAGE_SIZE in that case.
> 
> Anyway:
> 
> Reviewed-by: Alex Bennée 
> 
> -- 
> Alex Bennée
> Virtualisation Tech Lead @ Linaro



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

2024-03-06 Thread Vikram Garhwal
Hi Alex,
On Fri, Mar 01, 2024 at 05:10:28PM +, Alex Bennée wrote:
> Vikram Garhwal  writes:
> 
> > 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 32776d94df..b5993ef2a6 100644
> > --- a/hw/arm/xen_arm.c
> > +++ b/hw/arm/xen_arm.c
> > @@ -125,6 +125,9 @@ static void xen_init_ram(MachineState *machine)
> >   GUEST_RAM1_BASE, ram_size[1]);
> >  memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, _hi);
> >  }
> > +
> > +DPRINTF("init grant ram mapping for XEN\n");
> 
> I don't think we need the DPRINTF here (there others where recently
> converted to trace-points although I suspect a memory_region tracepoint
> would be a better place to capture this).
May be drop the print? As it's not providing much information anyways.
> 
> > +ram_grants = *xen_init_grant_ram();
> >  }
> >  
> >  void arch_handle_ioreq(XenIOState *state, ioreq_t *req)
> 
> -- 
> Alex Bennée
> Virtualisation Tech Lead @ Linaro



Re: [QEMU][PATCH v3 0/7] Xen: support grant mappings.

2024-02-28 Thread Vikram Garhwal
Hi Manos,
On Wed, Feb 28, 2024 at 03:27:12PM +0200, Manos Pitsidianakis wrote:
> Hello Vikram,
> 
> Series doesn't apply on master. Can you rebase and also provide a
> base-commit with --base= when you use git-format-patch? This
> will help git rebase if there are any conflicts found locally.
I rebased it with latest master and it works fine. Series is based on following
commit: bfe8020c814a30479a4241aaa78b63960655962b.

For v4, I will send a version with base-commit id.

Can you please share what is base-commit id on your side?

Thanks!
> 
> Thanks,
> 
> On Wed, 28 Feb 2024 00:34, 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.
> > 
> > Changelog:
> > v2->v3:
> >Drop patch 1/7. This was done because device unplug is an x86-only case.
> >Add missing qemu_mutex_unlock() before return.
> > v1->v2:
> >Split patch 2/7 to keep phymem.c changes in a separate.
> >In patch "xen: add map and unmap callbacks for grant" add check for total
> >allowed grant < XEN_MAX_VIRTIO_GRANTS.
> >Fix formatting issues and re-based with master latest.
> > 
> > Regards,
> > Vikram
> > 
> > Juergen Gross (5):
> >  xen: add pseudo RAM region for grant mappings
> >  softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
> >  xen: let xen_ram_addr_from_mapcache() return -1 in case of not found
> >entry
> >  memory: add MemoryRegion map and unmap callbacks
> >  xen: add map and unmap callbacks for grant region
> > 
> > Vikram Garhwal (2):
> >  softmmu: physmem: Split ram_block_add()
> >  hw: arm: Add grant mapping.
> > 
> > hw/arm/xen_arm.c|   3 +
> > hw/i386/xen/xen-hvm.c   |   3 +
> > hw/xen/xen-hvm-common.c |   4 +-
> > hw/xen/xen-mapcache.c   | 214 ++--
> > include/exec/memory.h   |  21 
> > 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 +
> > system/physmem.c| 179 +++---
> > 10 files changed, 351 insertions(+), 82 deletions(-)
> > 
> > -- 
> > 2.17.1
> > 
> > 



[QEMU][PATCH v3 0/7] Xen: support grant mappings.

2024-02-27 Thread Vikram Garhwal
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.

Changelog:
v2->v3:
Drop patch 1/7. This was done because device unplug is an x86-only case.
Add missing qemu_mutex_unlock() before return.
v1->v2:
Split patch 2/7 to keep phymem.c changes in a separate.
In patch "xen: add map and unmap callbacks for grant" add check for total
allowed grant < XEN_MAX_VIRTIO_GRANTS.
Fix formatting issues and re-based with master latest.

Regards,
Vikram

Juergen Gross (5):
  xen: add pseudo RAM region for grant mappings
  softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
  xen: let xen_ram_addr_from_mapcache() return -1 in case of not found
entry
  memory: add MemoryRegion map and unmap callbacks
  xen: add map and unmap callbacks for grant region

Vikram Garhwal (2):
  softmmu: physmem: Split ram_block_add()
  hw: arm: Add grant mapping.

 hw/arm/xen_arm.c|   3 +
 hw/i386/xen/xen-hvm.c   |   3 +
 hw/xen/xen-hvm-common.c |   4 +-
 hw/xen/xen-mapcache.c   | 214 ++--
 include/exec/memory.h   |  21 
 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 +
 system/physmem.c| 179 +++---
 10 files changed, 351 insertions(+), 82 deletions(-)

-- 
2.17.1




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

2024-02-27 Thread Vikram Garhwal
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 32776d94df..b5993ef2a6 100644
--- a/hw/arm/xen_arm.c
+++ b/hw/arm/xen_arm.c
@@ -125,6 +125,9 @@ static void xen_init_ram(MachineState *machine)
  GUEST_RAM1_BASE, ram_size[1]);
 memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, _hi);
 }
+
+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




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

2024-02-27 Thread Vikram Garhwal
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 baa1adb9f2..6e53d3bf81 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 4f956d048e..dfc412d138 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"
@@ -590,3 +592,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 4b1d728f35..8deeff6bcf 100644
--- a/include/hw/xen/xen-hvm-common.h
+++ b/include/hw/xen/xen-hvm-common.h
@@ -16,6 +16,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..f4bedb1c11 100644
--- a/include/sysemu/xen-mapcache.h
+++ b/include/sysemu/xen-mapcache.h
@@ -10,6 +10,7 @@
 #define XEN_MAPCACHE_H
 
 #include "exec/cpu-common.h"
+#include "exec/ram_addr.h"
 
 typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
  ram_addr_t size);
@@ -25,6 +26,8 @@ void xen_invalidate_map_cache(void);
 uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
  hwaddr new_phys_addr,
  hwaddr size);
+MemoryRegion *xen_init_grant_ram(void);
+
 #else
 
 static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
-- 
2.17.1




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

2024-02-27 Thread Vikram Garhwal
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 | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

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




[QEMU][PATCH v3 1/7] softmmu: physmem: Split ram_block_add()

2024-02-27 Thread Vikram Garhwal
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 e3ebc19eef..84f3022099 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




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

2024-02-27 Thread Vikram Garhwal
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 | 56 
 1 file changed, 23 insertions(+), 33 deletions(-)

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




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

2024-02-27 Thread Vikram Garhwal
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 | 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);
+
+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 = RAM_AD

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

2024-02-27 Thread Vikram Garhwal
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 
---
 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_block, cache->xlat, ,
+ true);
+}
 } else {
 cache->ptr = NULL;
 }
@@ -3297,14 +3319,20 @@ void address_space_cache_invalidate(MemoryRegionCache 
*cache,
 
 void address_space_cache_destroy(MemoryRegionCache *cache)
 {
-if (!cache->mrs.mr) {
+MemoryRegion *mr = cache->mrs.mr;
+
+if (!mr) {
 return;
 }
 
-if (xen_enabled()) {
+if (mr->ops && mr->ops->unmap) {
+mr->ops->unmap(mr, cache->ptr, cache->xlat, cache->len,
+   cache->is_write, cache->len);
+} else if (xen_enabled()) {
 xen_invalidate

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

2023-11-22 Thread Vikram Garhwal
Hi Volodymyr,
Thank you sharing this patch. I have few comments below
On Wed, Nov 22, 2023 at 02:39:46PM -0800, Stefano Stabellini wrote:
> +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.
> 
> 
I agree with Stefano here. Setting properties would be better and easier.

I have one questions here:
1. If there are multiple QEMU backends, which means xen tools will end up
creating lot of entries in xenstore and we need to remove those xenstore
entries when backend goes away. Is this already handled in Xen tools?

Regards,
Vikram

> > ---
> > 
> > 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);
> > +

Re: [PATCH-for-8.2 v2 1/2] hw/net/can/xlnx-zynqmp: Avoid underflow while popping TX FIFOs

2023-11-22 Thread Vikram Garhwal
Hi,
On Sun, Nov 19, 2023 at 11:51:01PM +0100, Philippe Mathieu-Daudé wrote:
> Per https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm/Message-Format
> 
>   Message Format
> 
>   The same message format is used for RXFIFO, TXFIFO, and TXHPB.
>   Each message includes four words (16 bytes). Software must read
>   and write all four words regardless of the actual number of data
>   bytes and valid fields in the message.
> 
> There is no mention in this reference manual about what the
> hardware does when not all four words are written. To fix the
> reported underflow behavior when DATA2 register is written,
> I choose to fill the data with the previous content of the
> ID / DLC / DATA1 registers, which is how I expect hardware
> would do.
> 
> Note there is no hardware flag raised under such condition.
> 
> Reported-by: Qiang Liu 
> Fixes: 98e5d7a2b7 ("hw/net/can: Introduce Xilinx ZynqMP CAN controller")
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1425
> Signed-off-by: Philippe Mathieu-Daudé 
> Francisco Iglesias 
> ---
>  hw/net/can/xlnx-zynqmp-can.c | 49 +---
>  1 file changed, 46 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
> index e93e6c5e19..58938b574e 100644
> --- a/hw/net/can/xlnx-zynqmp-can.c
> +++ b/hw/net/can/xlnx-zynqmp-can.c
> @@ -434,6 +434,51 @@ static bool tx_ready_check(XlnxZynqMPCANState *s)
>  return true;
>  }
>  
> +static void read_tx_frame(XlnxZynqMPCANState *s, Fifo32 *fifo, uint32_t 
> *data)
> +{
> +unsigned used = fifo32_num_used(fifo);
> +bool is_txhpb = fifo == >txhpb_fifo;
> +
> +assert(used > 0);
> +used %= CAN_FRAME_SIZE;
> +
> +/*
> + * Frame Message Format
> + *
> + * Each frame includes four words (16 bytes). Software must read and 
> write
> + * all four words regardless of the actual number of data bytes and valid
> + * fields in the message.
> + * If software misbehave (not writting all four words), we use the 
> previous
%s/writting/writing
> + * registers content to initialize each missing word.
> + */
> +if (used > 0) {
> +/* ID, DLC, DATA1 missing */
Code is correct but i feel This comment is confusing. ID is missing for sure
if user > 0 but same is not the case for DLC and DATA1.

> +data[0] = s->regs[is_txhpb ? R_TXHPB_ID : R_TXFIFO_ID];
> +} else {
> +data[0] = fifo32_pop(fifo);
> +}
> +if (used == 1 || used == 2) {
> +/* DLC, DATA1 missing */
Same here DLC is missing for sure but DATA1 is not for used == 2.
> +data[1] = s->regs[is_txhpb ? R_TXHPB_DLC : R_TXFIFO_DLC];
> +} else {
> +data[1] = fifo32_pop(fifo);
> +}
> +if (used == 1) {
> +/* DATA1 missing */
May be we remove all these individual comments and write a common comment before
the first check(if(used > 0)). Something like this:
/*
 * If used is 1 then ID, DLC and DATA1 are missing.
 *
 * if used is 2 then ID and DLC are missing.
 *
 * if used is 3 then only ID is missing.
 */

Code looks correct to me. So, With above minor changes in code comments:

Reviewed-by: Vikram Garhwal 

> +data[2] = s->regs[is_txhpb ? R_TXHPB_DATA1 : R_TXFIFO_DATA1];
> +} else {
> +data[2] = fifo32_pop(fifo);
> +}
> +/* DATA2 triggered the transfer thus is always available */
> +data[3] = fifo32_pop(fifo);
> +
> +if (used) {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "%s: Incomplete CAN frame (only %u/%u slots used)\n",
> +  TYPE_XLNX_ZYNQMP_CAN, used, CAN_FRAME_SIZE);
> +}
> +}
> +
>  static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
>  {
>  qemu_can_frame frame;
> @@ -451,9 +496,7 @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 
> *fifo)
>  }
>  
>  while (!fifo32_is_empty(fifo)) {
> -for (i = 0; i < CAN_FRAME_SIZE; i++) {
> -data[i] = fifo32_pop(fifo);
> -}
> +read_tx_frame(s, fifo, data);
>  
>  if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
>  /*
> -- 
> 2.41.0
> 



Re: [PATCH-for-8.2 v2 2/2] hw/net/can/xlnx-zynqmp: Avoid underflow while popping RX FIFO

2023-11-22 Thread Vikram Garhwal
On Wed, Nov 22, 2023 at 08:45:56PM +0100, Francisco Iglesias wrote:
> On Sun, Nov 19, 2023 at 11:51:02PM +0100, Philippe Mathieu-Daudé wrote:
> > Per 
> > https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm/Message-Format
> > 
> >   Message Format
> > 
> >   The same message format is used for RXFIFO, TXFIFO, and TXHPB.
> >   Each message includes four words (16 bytes). Software must read
> >   and write all four words regardless of the actual number of data
> >   bytes and valid fields in the message.
> > 
> > There is no mention in this reference manual about what the
> > hardware does when not all four words are read. To fix the
> > reported underflow behavior, I choose to fill the 4 frame data
> > registers when the first register (ID) is accessed, which is how
> > I expect hardware would do.
> > 
> > Reported-by: Qiang Liu 
> > Fixes: 98e5d7a2b7 ("hw/net/can: Introduce Xilinx ZynqMP CAN controller")
> > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1427
> > Signed-off-by: Philippe Mathieu-Daudé 
> 
> Reviewed-by: Francisco Iglesias 
Reviewed-by: Vikram Garhwal 

> 
> 
> > ---
> >  hw/net/can/xlnx-zynqmp-can.c | 17 +
> >  1 file changed, 9 insertions(+), 8 deletions(-)
> > 
> > diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
> > index 58938b574e..c63fb4a83c 100644
> > --- a/hw/net/can/xlnx-zynqmp-can.c
> > +++ b/hw/net/can/xlnx-zynqmp-can.c
> > @@ -777,14 +777,18 @@ static void update_rx_fifo(XlnxZynqMPCANState *s, 
> > const qemu_can_frame *frame)
> >  }
> >  }
> >  
> > -static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
> > +static uint64_t can_rxfifo_post_read_id(RegisterInfo *reg, uint64_t val)
> >  {
> >  XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
> > +unsigned used = fifo32_num_used(>rx_fifo);
> >  
> > -if (!fifo32_is_empty(>rx_fifo)) {
> > -val = fifo32_pop(>rx_fifo);
> > -} else {
> > +if (used < CAN_FRAME_SIZE) {
> >  ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
> > +} else {
> > +val = s->regs[R_RXFIFO_ID] = fifo32_pop(>rx_fifo);
> > +s->regs[R_RXFIFO_DLC] = fifo32_pop(>rx_fifo);
> > +s->regs[R_RXFIFO_DATA1] = fifo32_pop(>rx_fifo);
> > +s->regs[R_RXFIFO_DATA2] = fifo32_pop(>rx_fifo);
> >  }
> >  
> >  can_update_irq(s);
> > @@ -945,14 +949,11 @@ static const RegisterAccessInfo can_regs_info[] = {
> >  .post_write = can_tx_post_write,
> >  },{ .name = "RXFIFO_ID",  .addr = A_RXFIFO_ID,
> >  .ro = 0x,
> > -.post_read = can_rxfifo_pre_read,
> > +.post_read = can_rxfifo_post_read_id,
> >  },{ .name = "RXFIFO_DLC",  .addr = A_RXFIFO_DLC,
> >  .rsvd = 0xfff,
> > -.post_read = can_rxfifo_pre_read,
> >  },{ .name = "RXFIFO_DATA1",  .addr = A_RXFIFO_DATA1,
> > -.post_read = can_rxfifo_pre_read,
> >  },{ .name = "RXFIFO_DATA2",  .addr = A_RXFIFO_DATA2,
> > -.post_read = can_rxfifo_pre_read,
> >  },{ .name = "AFR",  .addr = A_AFR,
> >  .rsvd = 0xfff0,
> >  .post_write = can_filter_enable_post_write,
> > -- 
> > 2.41.0
> > 



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

2023-11-01 Thread Vikram Garhwal
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 
---
 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: intermittent qtest-aarch64/xlnx-canfd-test test failure

2023-10-31 Thread Vikram Garhwal
Hi Michael & Cedric,
On Mon, Oct 30, 2023 at 05:19:38PM +0100, Cédric Le Goater wrote:
> On 9/21/23 09:51, Michael Tokarev wrote:
> > Hi!
> > 
> > While doing stable-8.1.1 preparation, I've a CI failure of 
> > ubuntu-20.04-s390x-all here:
> > 
> > https://gitlab.com/qemu-project/qemu/-/jobs/5132720046
> > 
> > ▶ ERROR:../tests/qtest/xlnx-canfd-test.c:265:match_rx_tx_data: \
> >    assertion failed ((buf_rx[size] & DLC_FD_BIT_MASK) == (buf_tx[size] & 
> > DLC_FD_BIT_MASK)): (2281701376 == 2147483648)
> > 
> >   qemu:qtest+qtest-aarch64 / qtest-aarch64/xlnx-canfd-test  \
> >     ERROR   0.77s   killed by signal 6 SIGABRT
> > 
> > Re-run of this test went successfully.  However, the assert looks
> > a bit scary, and the fact that it does not fail in a reliable way
> > is a bit troubling too.  Is it a flaky test or there's something
> > else in qemu with concurrent threads?
> > 
> > I don't see this assert in previous test runs.  But ubuntu-20.04-s390x-all
> > test fails quite often due to other reasons, so it isn't conclusive.
> > 
> > Should something be done with this?
> > 
> > The testing is done for commit f2fc49c302036315db6e8c9f74592decc3be0476,
> > which is in staging-8.1 branch only temporarily.
> > 
I tried with staging-8.1 and didn't see this error. I ran it with 
registry.gitlab.com/legoater/qemu/qemu/fedora-i386-cross:latest on a x86 host 
machine. Can you please share more about how you are running
the testes? It will be greatly helpful to me in reproducing the issue and fixing
it.
> > Thanks,
> > 
> > /mjt
> > 
> 
> I had the same CI error in job 
> https://gitlab.com/legoater/qemu/-/jobs/5416150239
> ▶ 170/258 ERROR:../tests/qtest/xlnx-canfd-test.c:265:match_rx_tx_data: 
> assertion failed ((buf_rx[size] & DLC_FD_BIT_MASK) == (buf_tx[size] & 
> DLC_FD_BIT_MASK)): (2281701376 == 2147483648) ERROR
> 170/258 qemu:qtest+qtest-aarch64 / qtest-aarch64/xlnx-canfd-test   
> ERROR   0.49s   killed by signal 6 SIGABRT
> > > > QTEST_QEMU_BINARY=./qemu-system-aarch64 
> > > > PYTHON=/builds/legoater/qemu/build/pyvenv/bin/python3 
> > > > MALLOC_PERTURB_=60 
> > > > G_TEST_DBUS_DAEMON=/builds/legoater/qemu/tests/dbus-vmstate-daemon.sh 
> > > > /builds/legoater/qemu/build/tests/qtest/xlnx-canfd-test --tap -k
> ― ✀  ―
> stderr:
> **
> ERROR:../tests/qtest/xlnx-canfd-test.c:265:match_rx_tx_data: assertion failed 
> ((buf_rx[size] & DLC_FD_BIT_MASK) == (buf_tx[size] & DLC_FD_BIT_MASK)): 
> (2281701376 == 2147483648)
> (test program exited with status code -6)
> 
> I could reproduce on PPC64 and s390x systems.
> 
> C.
> 



Re: [PATCH] MAINTAINERS: Add the can documenation file to the CAN section

2023-10-27 Thread Vikram Garhwal
On Fri, Oct 27, 2023 at 10:44:35AM +0200, Philippe Mathieu-Daudé wrote:
> CAUTION: This message has originated from an External Source. Please use 
> proper judgment and caution when opening attachments, clicking links, or 
> responding to this email.
> 
> 
> On 27/10/23 08:09, Thomas Huth wrote:
> > Add can.rst to the corresponding section in MAINTAINERS, so that
> > the maintainers get CC:-ed on corresponding patches.
> > 
> > Signed-off-by: Thomas Huth 
> > ---
> >   MAINTAINERS | 1 +
> >   1 file changed, 1 insertion(+)
> 
> Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Vikram Garhwal 
> 



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

2023-10-26 Thread Vikram Garhwal
On Thu, Oct 26, 2023 at 04:45:21PM +0100, David Woodhouse wrote:
> On Wed, 2023-10-25 at 18:23 -0700, Stefano Stabellini wrote:
> > 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.
> 
> Ah, I had assumed there was something else coming along later which
> would make it actually get used. 
> 
> > Vikram, a simple option is to drop this patch if you don't need it.
> 
> That works. Although I may revive it in that case. 
> 
Hopefully, Juergen is also okay with dropping the patch. Then, i will remove it
from v3.

Thanks David & Stefano!





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

2023-10-25 Thread Vikram Garhwal
On Wed, Oct 25, 2023 at 06:32:26PM -0700, Stefano Stabellini wrote:
> 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
Oops, thanks for catching this! Will fix it in v3.
> 
> 
> > +}
> > +
> > +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)

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

2023-10-25 Thread Vikram Garhwal
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 
---
 docs/system/i386/xen.rst   |  3 ---
 hw/i386/xen/xen_platform.c | 10 --
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/docs/system/i386/xen.rst b/docs/system/i386/xen.rst
index f06765e88c..b86d57af6e 100644
--- a/docs/system/i386/xen.rst
+++ b/docs/system/i386/xen.rst
@@ -52,9 +52,6 @@ It is necessary to use the pc machine type, as the q35 
machine uses AHCI instead
 of legacy IDE, and AHCI disks are not unplugged through the Xen PV unplug
 mechanism.
 
-VirtIO devices can also be used; Linux guests may need to be dissuaded from
-umplugging them by adding 'xen_emul_unplug=never' on their command line.
-
 Properties
 --
 
diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
index 17457ff3de..0187b73eeb 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"
@@ -129,10 +130,11 @@ static bool pci_device_is_passthrough(PCIDevice *d)
 
 static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
 {
-/* We have to ignore passthrough devices */
+/* We have to ignore passthrough devices  and virtio 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)) {
 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




[QEMU][PATCHv2 8/8] hw: arm: Add grant mapping.

2023-10-25 Thread Vikram Garhwal
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




[QEMU][PATCHv2 5/8] xen: let xen_ram_addr_from_mapcache() return -1 in case of not found entry

2023-10-25 Thread Vikram Garhwal
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




[QEMU][PATCHv2 6/8] memory: add MemoryRegion map and unmap callbacks

2023-10-25 Thread Vikram Garhwal
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 
---
 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 9087d02769..7c5444d46f 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 667a695078..5db1b32823 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -3120,6 +3120,7 @@ void *address_space_map(AddressSpace *as,
 hwaddr len = *plen;
 hwaddr l, xlat;
 MemoryRegion *mr;
+void *ptr = NULL;
 FlatView *fv;
 
 if (len == 0) {
@@ -3153,12 +3154,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().
@@ -3174,11 +3183,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;
@@ -3251,10 +3265,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;
 }
@@ -3276,14 +3298,20 @@ void address_space_cache_invalidate(MemoryRegionCache 
*cache,
 
 void address_space_cache_destroy(MemoryRegionCache *cache)
 {
-if (!cache->mrs.mr) {
+MemoryRegion *mr = cache->mrs.mr;
+
+if (!mr) {
 return;
 }
 
-if (xen_enabled()) {
+if (mr->ops && mr->ops->unmap) {
+mr->ops->unmap(mr, cache->ptr, cache->xlat, cache->len,
+   cache->is_write, cache->len);
+} else if (xen_enabled()) {
 xen_invalidate

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

2023-10-25 Thread Vikram Garhwal
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 
---
 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




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

2023-10-25 Thread Vikram Garhwal
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;
+}
+
+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 = RAM_ADDR_INVALID;
+
+qemu_mutex_lock(_map_mutex);
+
+QLIST_F

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

2023-10-25 Thread Vikram Garhwal
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 
---
 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




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

2023-10-25 Thread Vikram Garhwal
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.

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

Regards,
Vikram
Juergen Gross (6):
  xen: when unplugging emulated devices skip virtio devices
  xen: add pseudo RAM region for grant mappings
  softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
  xen: let xen_ram_addr_from_mapcache() return -1 in case of not found
entry
  memory: add MemoryRegion map and unmap callbacks
  xen: add map and unmap callbacks for grant region

Vikram Garhwal (2):
  softmmu: physmem: Split ram_block_add()
  hw: arm: Add grant mapping.

 docs/system/i386/xen.rst|   3 -
 hw/arm/xen_arm.c|   3 +
 hw/i386/xen/xen-hvm.c   |   3 +
 hw/i386/xen/xen_platform.c  |  10 +-
 hw/xen/xen-hvm-common.c |   4 +-
 hw/xen/xen-mapcache.c   | 214 ++--
 include/exec/memory.h   |  21 
 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 +
 system/physmem.c| 181 ---
 12 files changed, 358 insertions(+), 90 deletions(-)

-- 
2.17.1




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

2023-10-25 Thread Vikram Garhwal
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 
---
 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..f4bedb1c11 100644
--- a/include/sysemu/xen-mapcache.h
+++ b/include/sysemu/xen-mapcache.h
@@ -10,6 +10,7 @@
 #define XEN_MAPCACHE_H
 
 #include "exec/cpu-common.h"
+#include "exec/ram_addr.h"
 
 typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
  ram_addr_t size);
@@ -25,6 +26,8 @@ void xen_invalidate_map_cache(void);
 uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
  hwaddr new_phys_addr,
  hwaddr size);
+MemoryRegion *xen_init_grant_ram(void);
+
 #else
 
 static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
-- 
2.17.1




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

2023-10-11 Thread Vikram Garhwal
Hi Anthony,
On Thu, Oct 05, 2023 at 11:40:57AM +0100, Anthony PERARD wrote:
> Hi Vikram,
> 
> This patch prevent QEMU from been build with Xen 4.15. See comments.
> 
> Also, why didn't you CC all the maintainers of
> include/hw/xen/xen_native.h?
I missed it. Initial version didn't have this file change and i missed updating
my cc list.
> 
> On Tue, Aug 29, 2023 at 09:35:17PM -0700, Vikram Garhwal wrote:
> > 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
> 
> xendevicemodel_set_irq_level() was introduced in Xen 4.15, so this
> should say '<' and not '<=', otherwise, we have:
> include/hw/xen/xen_native.h:527:19: error: static declaration of 
> ‘xendevicemodel_set_irq_level’ follows non-static declaration
Thanks for spotting this.
I will create a fix and gitlab-ci for the patch.
> 
> > +static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
> > +   domid_t domid, uint32_t irq,
> > +   unsigned int level)
> > +{
> > +return 0;
> 
> Shouldn't this return something like -ENOSYS, instead of returning a
> success?
Changed return to -ENOSYS for older version.
> 
> > 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
> > +
> > +static void xen_set_irq(void *opaque, int irq, int level)
> > +{
> > +xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level);
> 
> So, you just ignore the return value here. Shouldn't there be some kind
> of error check?
> 
> And is it OK to create a virtio-mmio device without an error, even when
> we could find out that it never going to work (e.g. on Xen 4.14)?
This is something Oleksandr can answer better as it was written by him. But
I think we can print an error "virtio init failed" and exit the
machine init. Does that aligns with your thinking?
> 
> Cheers,
> 
> -- 
> Anthony PERARD



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

2023-10-10 Thread Vikram Garhwal
On Mon, Oct 09, 2023 at 05:10:43PM -0700, Stefano Stabellini wrote:
> 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.
Will rebase it.
> 
> 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-10 Thread Vikram Garhwal
Hi Stefano,
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;
> > +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)
Do you mean to move all grant related functions? As moving this alone will not
be suf

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

2023-10-10 Thread Vikram Garhwal
Hi Stefano,
On Mon, Oct 09, 2023 at 04:51:53PM -0700, Stefano Stabellini wrote:
> 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"
Sounds good. Will update in the code comment in v2.
> 
> 
> >  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
> > 



[QEMU][PATCH v1 0/7] Xen: support grant mappings.

2023-10-05 Thread Vikram Garhwal
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.

Regards,
Vikram

Juergen Gross (6):
  xen: when unplugging emulated devices skip virtio devices
  xen: add pseudo RAM region for grant mappings
  softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
  xen: let xen_ram_addr_from_mapcache() return -1 in case of not found
entry
  memory: add MemoryRegion map and unmap callbacks
  xen: add map and unmap callbacks for grant region

Vikram Garhwal (1):
  hw: arm: Add grant mapping.

 hw/arm/xen_arm.c|   3 +
 hw/i386/xen/xen-hvm.c   |   3 +
 hw/i386/xen/xen_platform.c  |   8 +-
 hw/xen/xen-hvm-common.c |   4 +-
 hw/xen/xen-mapcache.c   | 206 ++--
 include/exec/memory.h   |  21 
 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   | 181 +---
 11 files changed, 349 insertions(+), 86 deletions(-)

-- 
2.17.1




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

2023-10-05 Thread Vikram Garhwal
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)) {
 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




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

2023-10-05 Thread Vikram Garhwal
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 
---
 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




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

2023-10-05 Thread Vikram Garhwal
Enable grant ram mapping support for Xenpvh machine on ARM.

Signed-off-by: Vikram Garhwal 
---
 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




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

2023-10-05 Thread Vikram Garhwal
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 
---
 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;
+}
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 *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..f4bedb1c11 100644
--- a/include/sysemu/xen-mapcache.h
+++ b/include/sysemu/xen-mapcache.h
@@ -10,6 +10

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

2023-10-05 Thread Vikram Garhwal
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 | 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 = RAM_ADDR_INVALID;
+
+qemu_mutex_lock(_map_mutex);
+
+QLIST_FOREACH(mgr, _grant_mappings, list) {
+if (mgr->addr == ptr - page_off) {
+break;
+}
+}
+
+if (mgr) {
+raddr = (mgr->idx << XC_PAGE_SHIFT) + page

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

2023-10-05 Thread Vikram Garhwal
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 
---
 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




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

2023-10-05 Thread Vikram Garhwal
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 
---
 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;
+
+if (!mr) {
 return;
 }
 
-if (xen_enabled()) {
+if (mr->ops && mr->ops->unmap) {
+mr->ops->unmap(mr, cache->ptr, cache->xlat, cache->len,
+   cache->is_write, cache->len);
+} else if (xen_enabled()) {
 xen_invalidate

[QEMU][PATCH v4 0/2] Add Virtio support to Xenpvh machine for arm

2023-08-29 Thread Vikram Garhwal
Hi,
We added virtio-mmio support in xenpvh machine. Now, it can support upto
10 virtio mmio.

Changelog:
v3->v4:
Moved the defs to xen_native.h

v2->v3:
Define GUEST_VIRTIO_*, GUEST_RAM* and xendevicemodel_set_irq() manually
for old xen version. This was done to avoid build failures in gitlab-ci
v1->v2:
Add reference for VIRTIO_MMIO_DEV_SIZE.
Update ram_size=0 print statement.

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(+)

-- 
2.17.1




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

2023-08-29 Thread Vikram Garhwal
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| 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




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

2023-08-29 Thread Vikram Garhwal
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| 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




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

2023-08-25 Thread Vikram Garhwal
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
+
 #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




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

2023-08-25 Thread Vikram Garhwal
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
+
+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




[QEMU][PATCH v3 0/2] Add Virtio support to Xenpvh machine for arm

2023-08-25 Thread Vikram Garhwal
Hi,
We added virtio-mmio support in xenpvh machine. Now, it can support upto
10 virtio mmio.

Changelog:
v2->v3:
Define GUEST_VIRTIO_*, GUEST_RAM* and xendevicemodel_set_irq() manually
for old xen version. This was done to avoid build failures in gitlab-ci
v1->v2:
Add reference for VIRTIO_MMIO_DEV_SIZE.
Update ram_size=0 print statement.

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 | 104 +++
 1 file changed, 104 insertions(+)

-- 
2.17.1




[QEMU][PATCH v2 0/2] Add Virtio support to Xenpvh machine for arm

2023-07-07 Thread Vikram Garhwal
Hi,
We added virtio-mmio support in xenpvh machine. Now, it can support upto
10 virtio mmio.

Changelog:
   v1->v2:
Add reference for VIRTIO_MMIO_DEV_SIZE.
Update ram_size=0 print statement.

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(+)

-- 
2.25.1




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

2023-07-07 Thread Vikram Garhwal
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 | 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




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

2023-07-07 Thread Vikram Garhwal
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 | 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: [PATCH v1 2/2] xen_arm: Initialize RAM and add hi/low memory regions

2023-07-05 Thread Vikram Garhwal

HI Leo,

On 7/2/23 11:14 PM, Leo Yan wrote:

Hi Vikram,

On Thu, Jun 29, 2023 at 10:43:10AM -0700, Oleksandr Tyshchenko wrote:

[...]


  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;
+}
+
+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;

This patch fails to apply on my side on QEMU 8.0.0.


  printf("CHECK for NEW BUILD\n");

The printf sentence is introduced unexpectly, right?

I will rebase it with latest and resend v2.
Thank you!


Thanks,
Leo


  #ifdef CONFIG_TPM
--
2.25.1





[RESEND][PATCH v1 0/2] Add Virtio support to Xenpvh machine for arm

2023-06-29 Thread Vikram Garhwal
Hi,
We added virtio-mmio support in xenpvh machine. Now, it can support upto
10 virtio mmio.

I think none of previous patches were delivered to mailing list so Resending 
this series.

Regards,
Vikram

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 | 74 
 1 file changed, 74 insertions(+)

-- 
2.25.1




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

2023-06-29 Thread Vikram Garhwal
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;
+}
+
+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




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

2023-06-29 Thread Vikram Garhwal
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
+
+#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 +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




[QEMU][PATCH v1] tests/qtest: xlnx-canfd-test: Fix code coverity issues

2023-06-28 Thread Vikram Garhwal
Following are done to fix the coverity issues:
1. Change read_data to fix the CID 1512899: Out-of-bounds access (OVERRUN)
2. Fix match_rx_tx_data to fix CID 1512900: Logically dead code (DEADCODE)
3. Replace rand() in generate_random_data() with g_rand_int()

Signed-off-by: Vikram Garhwal 
---
 tests/qtest/xlnx-canfd-test.c | 33 +++--
 1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/tests/qtest/xlnx-canfd-test.c b/tests/qtest/xlnx-canfd-test.c
index 76ee106d4f..78ec9ef2a7 100644
--- a/tests/qtest/xlnx-canfd-test.c
+++ b/tests/qtest/xlnx-canfd-test.c
@@ -170,23 +170,23 @@ static void generate_random_data(uint32_t *buf_tx, bool 
is_canfd_frame)
 /* Generate random TX data for CANFD frame. */
 if (is_canfd_frame) {
 for (int i = 0; i < CANFD_FRAME_SIZE - 2; i++) {
-buf_tx[2 + i] = rand();
+buf_tx[2 + i] = g_random_int();
 }
 } else {
 /* Generate random TX data for CAN frame. */
 for (int i = 0; i < CAN_FRAME_SIZE - 2; i++) {
-buf_tx[2 + i] = rand();
+buf_tx[2 + i] = g_random_int();
 }
 }
 }
 
-static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t 
*buf_rx)
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t 
*buf_rx,
+  uint32_t frame_size)
 {
 uint32_t int_status;
 uint32_t fifo_status_reg_value;
 /* At which RX FIFO the received data is stored. */
 uint8_t store_ind = 0;
-bool is_canfd_frame = false;
 
 /* Read the interrupt on CANFD rx. */
 int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
@@ -207,16 +207,9 @@ static void read_data(QTestState *qts, uint64_t 
can_base_addr, uint32_t *buf_rx)
 buf_rx[0] = qtest_readl(qts, can_base_addr + R_RX0_ID_OFFSET);
 buf_rx[1] = qtest_readl(qts, can_base_addr + R_RX0_DLC_OFFSET);
 
-is_canfd_frame = (buf_rx[1] >> DLC_FD_BIT_SHIFT) & 1;
-
-if (is_canfd_frame) {
-for (int i = 0; i < CANFD_FRAME_SIZE - 2; i++) {
-buf_rx[i + 2] = qtest_readl(qts,
-can_base_addr + R_RX0_DATA1_OFFSET + 4 * 
i);
-}
-} else {
-buf_rx[2] = qtest_readl(qts, can_base_addr + R_RX0_DATA1_OFFSET);
-buf_rx[3] = qtest_readl(qts, can_base_addr + R_RX0_DATA2_OFFSET);
+for (int i = 0; i < frame_size - 2; i++) {
+buf_rx[i + 2] = qtest_readl(qts,
+can_base_addr + R_RX0_DATA1_OFFSET + 4 * i);
 }
 
 /* Clear the RX interrupt. */
@@ -272,10 +265,6 @@ static void match_rx_tx_data(const uint32_t *buf_tx, const 
uint32_t *buf_rx,
 g_assert_cmpint((buf_rx[size] & DLC_FD_BIT_MASK), ==,
 (buf_tx[size] & DLC_FD_BIT_MASK));
 } else {
-if (!is_canfd_frame && size == 4) {
-break;
-}
-
 g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
 }
 
@@ -318,7 +307,7 @@ static void test_can_data_transfer(void)
 write_data(qts, CANFD0_BASE_ADDR, buf_tx, false);
 
 send_data(qts, CANFD0_BASE_ADDR);
-read_data(qts, CANFD1_BASE_ADDR, buf_rx);
+read_data(qts, CANFD1_BASE_ADDR, buf_rx, CAN_FRAME_SIZE);
 match_rx_tx_data(buf_tx, buf_rx, false);
 
 qtest_quit(qts);
@@ -358,7 +347,7 @@ static void test_canfd_data_transfer(void)
 write_data(qts, CANFD0_BASE_ADDR, buf_tx, true);
 
 send_data(qts, CANFD0_BASE_ADDR);
-read_data(qts, CANFD1_BASE_ADDR, buf_rx);
+read_data(qts, CANFD1_BASE_ADDR, buf_rx, CANFD_FRAME_SIZE);
 match_rx_tx_data(buf_tx, buf_rx, true);
 
 qtest_quit(qts);
@@ -397,7 +386,7 @@ static void test_can_loopback(void)
 write_data(qts, CANFD0_BASE_ADDR, buf_tx, true);
 
 send_data(qts, CANFD0_BASE_ADDR);
-read_data(qts, CANFD0_BASE_ADDR, buf_rx);
+read_data(qts, CANFD0_BASE_ADDR, buf_rx, CANFD_FRAME_SIZE);
 match_rx_tx_data(buf_tx, buf_rx, true);
 
 generate_random_data(buf_tx, true);
@@ -405,7 +394,7 @@ static void test_can_loopback(void)
 write_data(qts, CANFD1_BASE_ADDR, buf_tx, true);
 
 send_data(qts, CANFD1_BASE_ADDR);
-read_data(qts, CANFD1_BASE_ADDR, buf_rx);
+read_data(qts, CANFD1_BASE_ADDR, buf_rx, CANFD_FRAME_SIZE);
 match_rx_tx_data(buf_tx, buf_rx, true);
 
 qtest_quit(qts);
-- 
2.30.2




[QEMU][PATCH v8 00/11] Introduce xenpvh machine for arm architecture

2023-06-14 Thread Vikram Garhwal
Hi,
Rebased and resending the series with latest QEMU as it's been quite sometime.
There is one line code change in patch 04/10. Rest is just rebased with latest.

This series add xenpvh machine for aarch64. Motivation behind creating xenpvh
machine with IOREQ and TPM was to enable each guest on Xen aarch64 to have it's
own unique and emulated TPM.

This series does following:
1. Moved common xen functionalities from hw/i386/xen to hw/xen/ so those can
   be used for aarch64.
2. We added a minimal xenpvh arm machine which creates an IOREQ server and
   support TPM.

Also, checkpatch.pl fails for 03/12 and 06/12. These fails are due to
moving old code to new place which was not QEMU code style compatible.
No new add code was added.

Regards,
Vikram

ChangeLog:
v7 -> v8:
Add new patch 11/11 for "xenpvh exception for qtests".

v5->v7:
Change in PATCH 04/10:
Fix build error for cross compile case by adding
"#include "qemu/error-report.h" in include/hw/xen/xen-hvm-common.h
v4->v5:
Fix missing 3 lines of codes in xen_exit_notifier() due to rebase.
Fix 07/10 patch subject.

v3->v4:
Removed the out of series 04/12 patch.

v2->v3:
1. Change machine name to xenpvh as per Jurgen's input.
2. Add docs/system/xenpvh.rst documentation.
3. Removed GUEST_TPM_BASE and added tpm_base_address as property.
4. Correct CONFIG_TPM related issues.
5. Added xen_register_backend() function call to xen_register_ioreq().
6. Added Oleksandr's suggestion i.e. removed extra interface opening and
   used accel=xen option

v1 -> v2
Merged patch 05 and 06.
04/12: xen-hvm-common.c:
1. Moved xen_be_init() and xen_be_register_common() from
xen_register_ioreq() to xen_register_backend().
2. Changed g_malloc to g_new and perror -> error_setg_errno.
3. Created a local subroutine function for Xen_IOREQ_register.
4. Fixed build issues with inclusion of xenstore.h.
5. Fixed minor errors.


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

-- 
2.17.1




[QEMU][PATCH v8 06/11] hw/xen/xen-hvm-common: skip ioreq creation on ioreq registration failure

2023-06-14 Thread Vikram Garhwal
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.17.1




[QEMU][PATCH v8 09/11] hw/arm: introduce xenpvh machine

2023-06-14 Thread 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.
+ *
+ * THE SOFTWARE IS PRO

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

2023-06-14 Thread Vikram Garhwal
Like existing xen machines, xenpvh also cannot be used for qtest.

Signed-off-by: Vikram Garhwal 
---
 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




[QEMU][PATCH v8 04/11] xen-hvm: reorganize xen-hvm and move common function to xen-hvm-common

2023-06-14 Thread Vikram Garhwal
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, 

[QEMU][PATCH v8 05/11] include/hw/xen/xen_common: return error from xen_create_ioreq_server

2023-06-14 Thread Vikram Garhwal
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.17.1




[QEMU][PATCH v8 10/11] meson.build: enable xenpv machine build for ARM

2023-06-14 Thread 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.17.1




[QEMU][PATCH v8 08/11] meson.build: do not set have_xen_pci_passthrough for aarch64 targets

2023-06-14 Thread Vikram Garhwal
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.17.1




[QEMU][PATCH v8 03/11] hw/i386/xen/xen-hvm: move x86-specific fields out of XenIOState

2023-06-14 Thread Vikram Garhwal
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

[QEMU][PATCH v8 07/11] hw/xen/xen-hvm-common: Use g_new and error_report

2023-06-14 Thread 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.17.1




[QEMU][PATCH v8 02/11] hw/i386/xen: rearrange xen_hvm_init_pc

2023-06-14 Thread 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.17.1




[QEMU][PATCH v8 01/11] hw/i386/xen/: move xen-mapcache.c to hw/xen/

2023-06-14 Thread 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.17.1




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

2023-06-11 Thread Vikram Garhwal

Hi Richard,

On 6/9/23 3:59 PM, Richard Henderson wrote:

On 6/9/23 10:07, Stefano Stabellini wrote:

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


Fails testing.

Summary of Failures:
 10/423 qemu:qtest+qtest-aarch64 / 
qtest-aarch64/test-hmp  ERROR 161.45s   killed by 
signal 6 SIGABRT
210/423 qemu:qtest+qtest-aarch64 / 
qtest-aarch64/qom-test  ERROR 327.56s   killed by 
signal 6 SIGABRT


# starting QEMU: exec ./qemu-system-aarch64 -qtest 
unix:/tmp/qtest-669817.sock -qtest-log /dev/null -chardev 
socket,path=/tmp/qtest-669817.qmp,id=char0 -mon 
chardev=char0,mode=control -display none -machine xenpvh -accel qtest
qemu-system-aarch64: The -accel and "-machine accel=" options are 
incompatible

socket_accept failed: Resource temporarily unavailable
**
ERROR:../src/tests/qtest/libqtest.c:474:qtest_init_without_qmp_handshake: 
assertion failed: (s->fd >= 0 && s->qmp_fd >= 0)
Bail out! 
ERROR:../src/tests/qtest/libqtest.c:474:qtest_init_without_qmp_handshake: 
assertion failed: (s->fd >= 0 && s->qmp_fd >= 0)
../src/tests/qtest/libqtest.c:186: kill_qemu() tried to terminate QEMU 
process but encountered exit status 1 (expected 0)



Found the fix. QTest adds 'accel = qtest' and xen machines already have 
"accel = xen" option by default. Adding this xenpvh machine to skip 
fixed the issue, other xen machines are already in skip list. I am 
running the gitlab-ci locally to see if there are other fails/


i checked your pipeline and can see there are other failure but 
unrelated to Xen. To make sure, are there any others failures related to 
my patches?


Also, I am not an expert on gitlab ci flow. What i do to run gitlab-ci 
is this: Create a new gitlab pipeline with QEMU_CI = 2 and this runs 
around 120+ jobs. Is this enough or there any other variable setting needed?


Regards,
Vikram

r~





Re: [QEMU][PATCH v6 4/4] tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

2023-06-08 Thread Vikram Garhwal

Hi Peter,
Thanks for sharing the details. I will fix these and send a follow up 
patch soon.


On 6/8/23 2:42 AM, Peter Maydell wrote:

On Tue, 30 May 2023 at 22:23, Vikram Garhwal  wrote:

The QTests perform three tests on the Xilinx VERSAL CANFD controller:
 Tests the CANFD controllers in loopback.
 Tests the CANFD controllers in normal mode with CAN frame.
 Tests the CANFD controllers in normal mode with CANFD frame.

Signed-off-by: Vikram Garhwal 
Acked-by: Thomas Huth 
Reviewed-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 

Hi; Coverity has spotted some issues with this test code; could
you investigate and send followup patches, please ?



+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
+ bool is_canfd_frame)
+{
+uint16_t size = 0;
+uint8_t len = CAN_FRAME_SIZE;
+
+if (is_canfd_frame) {
+len = CANFD_FRAME_SIZE;
+}

Here len is either 4 (if !is_canfd_frame) or 18 (if is_canfd_frame)...


+
+while (size < len) {

...and we loop with size always less than len...


+if (R_RX0_ID_OFFSET + 4 * size == R_RX0_DLC_OFFSET)  {
+g_assert_cmpint((buf_rx[size] & DLC_FD_BIT_MASK), ==,
+(buf_tx[size] & DLC_FD_BIT_MASK));
+} else {
+if (!is_canfd_frame && size == 4) {

...so here this condition can never be true: if !is_canfd_frame
then we know size is less than 4.

What was the intention here ?

(CID 1512900)


+break;
+}
+
+g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
+}
+
+size++;
+}
+}
+/*
+ * Xilinx CANFD supports both CAN and CANFD frames. This test will be
+ * transferring CAN frame i.e. 8 bytes of data from CANFD0 and CANFD1 through
+ * canbus. CANFD0 initiate the data transfer to can-bus, CANFD1 receives the
+ * data. Test compares the can frame data sent from CANFD0 and received on
+ * CANFD1.
+ */
+static void test_can_data_transfer(void)
+{
+uint32_t buf_tx[CAN_FRAME_SIZE] = { 0x5a5bb9a4, 0x8000,
+0x12345678, 0x87654321 };
+uint32_t buf_rx[CAN_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 };

The buf_rx[] array here is only 4 bytes long...


+uint32_t status = 0;
+
+generate_random_data(buf_tx, false);
+
+QTestState *qts = qtest_init("-machine xlnx-versal-virt"
+" -object can-bus,id=canbus"
+" -machine canbus0=canbus"
+" -machine canbus1=canbus"
+);
+
+configure_canfd(qts, MSR_NORMAL_MODE);
+
+/* Check if CANFD0 and CANFD1 are in Normal mode. */
+status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
+status = status & STATUS_REG_MASK;
+g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
+
+status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
+status = status & STATUS_REG_MASK;
+g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
+
+write_data(qts, CANFD0_BASE_ADDR, buf_tx, false);
+
+send_data(qts, CANFD0_BASE_ADDR);
+read_data(qts, CANFD1_BASE_ADDR, buf_rx);

...but read_data() will write up to 17 bytes of data to the buffer,
if the incoming data from the device claims it to be a canfd frame.
The device shouldn't really do that, but the point of a test is
that the device might not be functioning correctly, so we should
size buf_rx[] large enough to fit whatever read_data() writes to it.

(CID 1512899)


+match_rx_tx_data(buf_tx, buf_rx, false);
+
+qtest_quit(qts);
+}

thanks
-- PMM





[QEMU][PATCH v7 09/10] hw/arm: introduce xenpvh machine

2023-06-07 Thread 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 91ebc26c6d..af8d7c77d6 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -106,6 +106,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 b545ba0e4f..1b2a01a005 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -62,6 +62,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.
+ *
+ * THE SOFTWARE IS PRO

[QEMU][PATCH v7 07/10] hw/xen/xen-hvm-common: Use g_new and error_report

2023-06-07 Thread 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.17.1




[QEMU][PATCH v7 06/10] hw/xen/xen-hvm-common: skip ioreq creation on ioreq registration failure

2023-06-07 Thread Vikram Garhwal
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.17.1




[QEMU][PATCH v7 10/10] meson.build: enable xenpv machine build for ARM

2023-06-07 Thread 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 786c69b06d..afba3b6441 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.17.1




[QEMU][PATCH v7 08/10] meson.build: do not set have_xen_pci_passthrough for aarch64 targets

2023-06-07 Thread Vikram Garhwal
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 a61d3e9b06..786c69b06d 100644
--- a/meson.build
+++ b/meson.build
@@ -1737,6 +1737,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.17.1




[QEMU][PATCH v7 04/10] xen-hvm: reorganize xen-hvm and move common function to xen-hvm-common

2023-06-07 Thread Vikram Garhwal
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 
---
 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, uint64_t data, uint32_t count, 

[QEMU][PATCH v7 01/10] hw/i386/xen/: move xen-mapcache.c to hw/xen/

2023-06-07 Thread 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.17.1




[QEMU][PATCH v7 05/10] include/hw/xen/xen_common: return error from xen_create_ioreq_server

2023-06-07 Thread Vikram Garhwal
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 | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
index 6bcc83baf9..8b01b071e5 100644
--- a/include/hw/xen/xen_native.h
+++ b/include/hw/xen/xen_native.h
@@ -433,9 +433,10 @@ static inline void xen_unmap_pcidev(domid_t dom,
 {
 }
 
-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)
 {
+return 0;
 }
 
 static inline void xen_destroy_ioreq_server(domid_t dom,
@@ -566,8 +567,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,
@@ -575,12 +576,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.17.1




[QEMU][PATCH v7 03/10] hw/i386/xen/xen-hvm: move x86-specific fields out of XenIOState

2023-06-07 Thread Vikram Garhwal
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 5403ac4b89..6be5a250a8 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

[QEMU][PATCH v7 00/10] Introduce xenpvh machine for arm architecture

2023-06-07 Thread Vikram Garhwal
Hi,
Rebased and resending the series with latest QEMU as it's been quite sometime.
There is one line code change in patch 04/10. Rest is just rebased with latest.

Also, this series has dependency on following gitlab-ci
patch: https://lists.nongnu.org/archive/html/qemu-devel/2023-06/msg01471.html.

I ran gitlab-ci and here are the successful build logs:
https://gitlab.com/Vikram.garhwal/qemu-ioreq/-/pipelines/891635328/

This series add xenpvh machine for aarch64. Motivation behind creating xenpvh
machine with IOREQ and TPM was to enable each guest on Xen aarch64 to have it's
own unique and emulated TPM.

This series does following:
1. Moved common xen functionalities from hw/i386/xen to hw/xen/ so those can
   be used for aarch64.
2. We added a minimal xenpvh arm machine which creates an IOREQ server and
   support TPM.

Also, checkpatch.pl fails for 03/12 and 06/12. These fails are due to
moving old code to new place which was not QEMU code style compatible.
No new add code was added.

Regards,
Vikram

ChangeLog:
v5->v7:
Change in PATCH 04/10:
Fix build error for cross compile case by adding
"#include "qemu/error-report.h" in include/hw/xen/xen-hvm-common.h
v4->v5:
Fix missing 3 lines of codes in xen_exit_notifier() due to rebase.
Fix 07/10 patch subject.

v3->v4:
Removed the out of series 04/12 patch.

v2->v3:
1. Change machine name to xenpvh as per Jurgen's input.
2. Add docs/system/xenpvh.rst documentation.
3. Removed GUEST_TPM_BASE and added tpm_base_address as property.
4. Correct CONFIG_TPM related issues.
5. Added xen_register_backend() function call to xen_register_ioreq().
6. Added Oleksandr's suggestion i.e. removed extra interface opening and
   used accel=xen option

v1 -> v2
Merged patch 05 and 06.
04/12: xen-hvm-common.c:
1. Moved xen_be_init() and xen_be_register_common() from
xen_register_ioreq() to xen_register_backend().
2. Changed g_malloc to g_new and perror -> error_setg_errno.
3. Created a local subroutine function for Xen_IOREQ_register.
4. Fixed build issues with inclusion of xenstore.h.
5. Fixed minor errors.

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  |   13 +-
 meson.build  |4 +-
 18 files changed, 1350 insertions(+), 1010 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

-- 
2.17.1




[QEMU][PATCH v7 02/10] hw/i386/xen: rearrange xen_hvm_init_pc

2023-06-07 Thread 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 56641a550e..5403ac4b89 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.17.1




Re: [PULL v3 0/10] xenpvh3-tag

2023-06-06 Thread Vikram Garhwal




On 6/6/23 3:50 PM, Richard Henderson wrote:

On 6/6/23 11:51, Garhwal, Vikram wrote:

Hi Richard,

I fixed the tsan-build issue but now seeing another issue with 
“—disable-tcg” option for cross builds xen. Here is the build failure 
message:
"include/tcg/oversized-guest.h:10:10: fatal error: 
tcg-target-reg-bits.h: No such file or directory


10 | #include "tcg-target-reg-bits.h”



Full log for build fail: 
https://gitlab.com/Vikram.garhwal/qemu-ioreq/-/jobs/4416773231 
.


This is my last patch which enables xen build for ARM: 
https://gitlab.com/Vikram.garhwal/qemu-ioreq/-/commit/6f6667217bfc14ff5504ee5fdee23a948d60fb7f 
. 



This seems something missing in disable-tcg config for ARM builds. 
Any hints on what might be causing this TCG issue?


Thanks in advance for your help!


I meant to cc you, but fix here:

https://patchew.org/QEMU/20230606224609.208550-1-richard.hender...@linaro.org/ 



Thanks, Richard. This helps a lot. I will rebase my patches on this 
series and re-test gitlab ci.


r~





[QEMU][PATCH v6 4/4] tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

2023-05-30 Thread Vikram Garhwal
The QTests perform three tests on the Xilinx VERSAL CANFD controller:
Tests the CANFD controllers in loopback.
Tests the CANFD controllers in normal mode with CAN frame.
Tests the CANFD controllers in normal mode with CANFD frame.

Signed-off-by: Vikram Garhwal 
Acked-by: Thomas Huth 
Reviewed-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 tests/qtest/meson.build   |   1 +
 tests/qtest/xlnx-canfd-test.c | 423 ++
 2 files changed, 424 insertions(+)
 create mode 100644 tests/qtest/xlnx-canfd-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 087f2dc9d7..fd434069b7 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -215,6 +215,7 @@ qtests_aarch64 = \
   (config_all.has_key('CONFIG_TCG') and 
config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?\
 ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) +   
  \
   (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 
'fuzz-xlnx-dp-test'] : []) + \
+  (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : 
[]) + \
   (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) +  \
   (config_all.has_key('CONFIG_TCG') and
\
config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : 
[]) + \
diff --git a/tests/qtest/xlnx-canfd-test.c b/tests/qtest/xlnx-canfd-test.c
new file mode 100644
index 00..76ee106d4f
--- /dev/null
+++ b/tests/qtest/xlnx-canfd-test.c
@@ -0,0 +1,423 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * QTests for the Xilinx Versal CANFD controller.
+ *
+ * Copyright (c) 2022 AMD Inc.
+ *
+ * Written-by: Vikram Garhwal
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+/* Base address. */
+#define CANFD0_BASE_ADDR0xff06
+#define CANFD1_BASE_ADDR0xff07
+
+/* Register addresses. */
+#define R_SRR_OFFSET0x00
+#define R_MSR_OFFSET0x04
+#define R_FILTER_CONTROL_REGISTER   0xe0
+#define R_SR_OFFSET 0x18
+#define R_ISR_OFFSET0x1c
+#define R_IER_OFFSET0x20
+#define R_ICR_OFFSET0x24
+#define R_TX_READY_REQ_REGISTER 0x90
+#define RX_FIFO_STATUS_REGISTER 0xe8
+#define R_TXID_OFFSET   0x100
+#define R_TXDLC_OFFSET  0x104
+#define R_TXDATA1_OFFSET0x108
+#define R_TXDATA2_OFFSET0x10c
+#define R_AFMR_REGISTER00xa00
+#define R_AFIR_REGISTER00xa04
+#define R_RX0_ID_OFFSET 0x2100
+#define R_RX0_DLC_OFFSET0x2104
+#define R_RX0_DATA1_OFFSET  0x2108
+#define R_RX0_DATA2_OFFSET  0x210c
+
+/* CANFD modes. */
+#define SRR_CONFIG_MODE 0x00
+#define MSR_NORMAL_MODE 0x00
+#define MSR_LOOPBACK_MODE   (1 << 1)
+#define ENABLE_CANFD(1 << 1)
+
+/* CANFD status. */
+#define STATUS_CONFIG_MODE  (1 << 0)
+#define STATUS_NORMAL_MODE  (1 << 3)
+#define STATUS_LOOPBACK_MODE(1 << 1)
+#define ISR_TXOK(1 << 1)
+#define ISR_RXOK(1 << 4)
+
+#define ENABLE_ALL_FILTERS  0x
+#define ENABLE_ALL_INTERRUPTS   0x
+
+/* We are sending one canfd message. */
+#define TX_READY_REG_VAL0x1
+
+#define FIRST_RX_STORE_INDEX0x1
+#define STATUS_REG_MASK 0xf
+#define DLC_FD_BIT_SHIFT0x1b
+#define DLC_FD_BIT_MASK 0xf800
+#define FIFO_STATUS_READ_INDEX_MASK 0x3f
+#define FIFO_STATUS_F

[QEMU][PATCH v6 0/4] Introduce Xilinx Versal CANFD

2023-05-30 Thread Vikram Garhwal
Hi,
This patch implements CANFD controller for xlnx-versal-virt machine. There are
two controllers CANFD0@0xFF06_ and CANFD1@0xFF07_ are connected to the
machine.

Also, added basic qtests for data exchange between both the controllers in
various supported configs.

Changelog:
v5->v6:
Add formatting related comments from Francisco.
Add "review-by" for all remaining patches.
v4->v5:
Fix Linux dtb connections for CANFD.
Address feedback from Francisco for xlnx-versal-canfd.c file.
v3->v4:
Address formatting related feedback from Peter.
Correct dlc byte data storing if dlc is not a multiple of 4.
Remove unnecessary LOG_GUEST_ERROR.
Remove instance_finalize(canfd_finalize) function.
Remove unused member of struct XlnxVersalCANFDState.

v2->v3:
Corrected reg2frame().
Added assert to prevent out of bound cases.
Replace tx_id link list with GSList and removed sorting function.
Replaced PTIMER_POLICY_LEGACY with proper timer policies.
Corrected minor code format issues.

v1->v2
Update xlnx-versal-virt.rst with CANFD examples and add this in 03/05 patch.
Addressed comments for patch 02/05 and 03/05.
Add reviewed-by tags for patch 01/05, 04/05 and 05/05.
Change commit message for patch 02/05.
Add SPDX license for Qtest.

Regards,
Vikram

Vikram Garhwal (4):
  MAINTAINERS: Include canfd tests under Xilinx CAN
  hw/net/can: Introduce Xilinx Versal CANFD controller
  xlnx-versal: Connect Xilinx VERSAL CANFD controllers
  tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

 MAINTAINERS  |2 +-
 docs/system/arm/xlnx-versal-virt.rst |   31 +
 hw/arm/xlnx-versal-virt.c|   53 +
 hw/arm/xlnx-versal.c |   37 +
 hw/net/can/meson.build   |1 +
 hw/net/can/trace-events  |7 +
 hw/net/can/xlnx-versal-canfd.c   | 2107 ++
 include/hw/arm/xlnx-versal.h |   12 +
 include/hw/net/xlnx-versal-canfd.h   |   87 ++
 tests/qtest/meson.build  |1 +
 tests/qtest/xlnx-canfd-test.c|  423 ++
 11 files changed, 2760 insertions(+), 1 deletion(-)
 create mode 100644 hw/net/can/xlnx-versal-canfd.c
 create mode 100644 include/hw/net/xlnx-versal-canfd.h
 create mode 100644 tests/qtest/xlnx-canfd-test.c

-- 
2.17.1




[QEMU][PATCH v6 3/4] xlnx-versal: Connect Xilinx VERSAL CANFD controllers

2023-05-30 Thread Vikram Garhwal
Connect CANFD0 and CANFD1 on the Versal-virt machine and update xlnx-versal-virt
document with CANFD command line examples.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Peter Maydell 
Reviewed-by: Francisco Iglesias 
---
 docs/system/arm/xlnx-versal-virt.rst | 31 
 hw/arm/xlnx-versal-virt.c| 53 
 hw/arm/xlnx-versal.c | 37 +++
 include/hw/arm/xlnx-versal.h | 12 +++
 4 files changed, 133 insertions(+)

diff --git a/docs/system/arm/xlnx-versal-virt.rst 
b/docs/system/arm/xlnx-versal-virt.rst
index 92ad10d2da..d2d1b26692 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -34,6 +34,7 @@ Implemented devices:
 - DDR memory
 - BBRAM (36 bytes of Battery-backed RAM)
 - eFUSE (3072 bytes of one-time field-programmable bit array)
+- 2 CANFDs
 
 QEMU does not yet model any other devices, including the PL and the AI Engine.
 
@@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, add:
 
   Better yet, do not use actual product data when running guest image
   on this Xilinx Versal Virt board.
+
+Using CANFDs for Versal Virt
+""""""""""""""""""""""""""""
+Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
+implementation. Bus connection and socketCAN connection for each CAN module
+can be set through command lines.
+
+To connect both CANFD0 and CANFD1 on the same bus:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
+
+To connect CANFD0 and CANFD1 to separate buses:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
+-machine canbus0=canbus0 -machine canbus1=canbus1
+
+The SocketCAN interface can connect to a Physical or a Virtual CAN interfaces 
on
+the host machine. Please check this document to learn about CAN interface on
+Linux: docs/system/devices/can.rst
+
+To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
+-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 668a9d65a4..1ee2b8697f 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -40,9 +40,11 @@ struct VersalVirt {
 uint32_t clk_25Mhz;
 uint32_t usb;
 uint32_t dwc;
+uint32_t canfd[2];
 } phandle;
 struct arm_boot_info binfo;
 
+CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
 struct {
 bool secure;
 } cfg;
@@ -235,6 +237,38 @@ static void fdt_add_uart_nodes(VersalVirt *s)
 }
 }
 
+static void fdt_add_canfd_nodes(VersalVirt *s)
+{
+uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
+uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
+unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
+const char clocknames[] = "can_clk\0s_axi_aclk";
+int i;
+
+/* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
+for (i = 0; i < ARRAY_SIZE(addrs); i++) {
+char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
+qemu_fdt_add_subnode(s->fdt, name);
+
+qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40);
+qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20);
+
+qemu_fdt_setprop_cells(s->fdt, name, "clocks",
+   s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
+qemu_fdt_setprop(s->fdt, name, "clock-names",
+ clocknames, sizeof(clocknames));
+qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
+   GIC_FDT_IRQ_TYPE_SPI, irqs[i],
+   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+ 2, addrs[i], 2, size[i]);
+qemu_fdt_setprop_string(s->fdt, name, "compatible",
+"xlnx,canfd-2.0");
+
+g_free(name);
+}
+}
+
 static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
  uint32_t phandle)
 {
@@ -639,12 +673,17 @@ static void versal_virt_init(MachineState *machine)
 TYPE_XLNX_VERSAL);
 object_property_set_link(OBJECT(>soc), "ddr", OBJECT(machine->ram),
  _abort);
+object_property_set_link(OBJECT(>soc), "canbus0", OBJECT(s->canbus[0]),
+ _abort);
+object_property_set_link(OBJECT(>soc), "canbus1", OBJECT(s->canbus[1]),
+  

[QEMU][PATCH v6 2/4] hw/net/can: Introduce Xilinx Versal CANFD controller

2023-05-30 Thread Vikram Garhwal
The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN bus
implementation. Bus connection and socketCAN connection for each CAN module
can be set through command lines.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Francisco Iglesias 
---
 hw/net/can/meson.build |1 +
 hw/net/can/trace-events|7 +
 hw/net/can/xlnx-versal-canfd.c | 2107 
 include/hw/net/xlnx-versal-canfd.h |   87 ++
 4 files changed, 2202 insertions(+)
 create mode 100644 hw/net/can/xlnx-versal-canfd.c
 create mode 100644 include/hw/net/xlnx-versal-canfd.h

diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
index 8fabbd9ee6..8d85201cb0 100644
--- a/hw/net/can/meson.build
+++ b/hw/net/can/meson.build
@@ -5,3 +5,4 @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: 
files('can_mioe3680_pci.c'))
 softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
 softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
 softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-canfd.c'))
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
index 8346a98ab5..de64ac1b31 100644
--- a/hw/net/can/trace-events
+++ b/hw/net/can/trace-events
@@ -7,3 +7,10 @@ xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t 
value) "Filter%d MAS
 xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t 
db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: 
ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 
0x%02x"
 xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t 
db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: 
ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 
0x%02x"
 xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus 
communication. Status Register: 0x%08x"
+
+# xlnx-versal-canfd.c
+xlnx_canfd_update_irq(char *path, uint32_t isr, uint32_t ier, uint32_t irq) 
"%s: ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
+xlnx_canfd_rx_fifo_filter_reject(char *path, uint32_t id, uint8_t dlc) "%s: 
Frame: ID: 0x%08x DLC: 0x%02x"
+xlnx_canfd_rx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flags) "%s: 
Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
+xlnx_canfd_tx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flgas) "%s: 
Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
+xlnx_canfd_reset(char *path, uint32_t val) "%s: Resetting controller with 
value = 0x%08x"
diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
new file mode 100644
index 00..5b8ce0a285
--- /dev/null
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -0,0 +1,2107 @@
+/*
+ * QEMU model of the Xilinx Versal CANFD device.
+ *
+ * This implementation is based on the following datasheet:
+ * https://docs.xilinx.com/v/u/2.0-English/pg223-canfd
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ *
+ * Written-by: Vikram Garhwal 
+ *
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
+ * Pavel Pisa
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/register.h"
+#include "qapi/error.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/cutils.h"
+#include "qemu/event_notifier.h"
+#include "hw/qdev-properties.h"
+#include "qom/object_interfaces.h"
+#include "migration/vmstate.h"
+#include "hw/net/xlnx-versal-canfd.h"
+#include "trace.h"
+
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
+  

[QEMU][PATCH v6 1/4] MAINTAINERS: Include canfd tests under Xilinx CAN

2023-05-30 Thread Vikram Garhwal
Signed-off-by: Vikram Garhwal 
Reviewed-by: Peter Maydell 
Reviewed-by: Francisco Iglesias 
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 4b025a7b63..1d73f182c6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1817,7 +1817,7 @@ M: Francisco Iglesias 
 S: Maintained
 F: hw/net/can/xlnx-*
 F: include/hw/net/xlnx-*
-F: tests/qtest/xlnx-can-test*
+F: tests/qtest/xlnx-can*-test*
 
 EDU
 M: Jiri Slaby 
-- 
2.17.1




[QEMU][PATCH v5 0/4] Introduce Xilinx Versal CANFD

2023-05-19 Thread Vikram Garhwal
Hi,
This patch implements CANFD controller for xlnx-versal-virt machine. There are
two controllers CANFD0@0xFF06_ and CANFD1@0xFF07_ are connected to the
machine.

Also, added basic qtests for data exchange between both the controllers in
various supported configs.

Changelog:
v4->v5:
Fix Linux dtb connections for CANFD.
Address feedback from Francisco for xlnx-versal-canfd.c file.
v3->v4:
Address formatting related feedback from Peter.
Correct dlc byte data storing if dlc is not a multiple of 4.
Remove unnecessary LOG_GUEST_ERROR.
Remove instance_finalize(canfd_finalize) function.
Remove unused member of struct XlnxVersalCANFDState.

v2->v3:
Corrected reg2frame().
Added assert to prevent out of bound cases.
Replace tx_id link list with GSList and removed sorting function.
Replaced PTIMER_POLICY_LEGACY with proper timer policies.
Corrected minor code format issues.

v1->v2
Update xlnx-versal-virt.rst with CANFD examples and add this in 03/05 patch.
Addressed comments for patch 02/05 and 03/05.
Add reviewed-by tags for patch 01/05, 04/05 and 05/05.
Change commit message for patch 02/05.
Add SPDX license for Qtest.

Regards,
Vikram


Vikram Garhwal (4):
  MAINTAINERS: Include canfd tests under Xilinx CAN
  hw/net/can: Introduce Xilinx Versal CANFD controller
  xlnx-versal: Connect Xilinx VERSAL CANFD controllers
  tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

 MAINTAINERS  |2 +-
 docs/system/arm/xlnx-versal-virt.rst |   31 +
 hw/arm/xlnx-versal-virt.c|   53 +
 hw/arm/xlnx-versal.c |   37 +
 hw/net/can/meson.build   |1 +
 hw/net/can/trace-events  |7 +
 hw/net/can/xlnx-versal-canfd.c   | 2107 ++
 include/hw/arm/xlnx-versal.h |   12 +
 include/hw/net/xlnx-versal-canfd.h   |   87 ++
 tests/qtest/meson.build  |1 +
 tests/qtest/xlnx-canfd-test.c|  423 ++
 11 files changed, 2760 insertions(+), 1 deletion(-)
 create mode 100644 hw/net/can/xlnx-versal-canfd.c
 create mode 100644 include/hw/net/xlnx-versal-canfd.h
 create mode 100644 tests/qtest/xlnx-canfd-test.c

-- 
2.17.1




[QEMU][PATCH v5 4/4] tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

2023-05-19 Thread Vikram Garhwal
The QTests perform three tests on the Xilinx VERSAL CANFD controller:
Tests the CANFD controllers in loopback.
Tests the CANFD controllers in normal mode with CAN frame.
Tests the CANFD controllers in normal mode with CANFD frame.

Signed-off-by: Vikram Garhwal 
Acked-by: Thomas Huth 
Reviewed-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 tests/qtest/meson.build   |   1 +
 tests/qtest/xlnx-canfd-test.c | 423 ++
 2 files changed, 424 insertions(+)
 create mode 100644 tests/qtest/xlnx-canfd-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index ab422772d3..045007c34c 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -212,6 +212,7 @@ qtests_aarch64 = \
   (config_all.has_key('CONFIG_TCG') and 
config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?\
 ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) +   
  \
   (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 
'fuzz-xlnx-dp-test'] : []) + \
+  (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : 
[]) + \
   (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) +  \
   (config_all.has_key('CONFIG_TCG') and
\
config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : 
[]) + \
diff --git a/tests/qtest/xlnx-canfd-test.c b/tests/qtest/xlnx-canfd-test.c
new file mode 100644
index 00..76ee106d4f
--- /dev/null
+++ b/tests/qtest/xlnx-canfd-test.c
@@ -0,0 +1,423 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * QTests for the Xilinx Versal CANFD controller.
+ *
+ * Copyright (c) 2022 AMD Inc.
+ *
+ * Written-by: Vikram Garhwal
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+/* Base address. */
+#define CANFD0_BASE_ADDR0xff06
+#define CANFD1_BASE_ADDR0xff07
+
+/* Register addresses. */
+#define R_SRR_OFFSET0x00
+#define R_MSR_OFFSET0x04
+#define R_FILTER_CONTROL_REGISTER   0xe0
+#define R_SR_OFFSET 0x18
+#define R_ISR_OFFSET0x1c
+#define R_IER_OFFSET0x20
+#define R_ICR_OFFSET0x24
+#define R_TX_READY_REQ_REGISTER 0x90
+#define RX_FIFO_STATUS_REGISTER 0xe8
+#define R_TXID_OFFSET   0x100
+#define R_TXDLC_OFFSET  0x104
+#define R_TXDATA1_OFFSET0x108
+#define R_TXDATA2_OFFSET0x10c
+#define R_AFMR_REGISTER00xa00
+#define R_AFIR_REGISTER00xa04
+#define R_RX0_ID_OFFSET 0x2100
+#define R_RX0_DLC_OFFSET0x2104
+#define R_RX0_DATA1_OFFSET  0x2108
+#define R_RX0_DATA2_OFFSET  0x210c
+
+/* CANFD modes. */
+#define SRR_CONFIG_MODE 0x00
+#define MSR_NORMAL_MODE 0x00
+#define MSR_LOOPBACK_MODE   (1 << 1)
+#define ENABLE_CANFD(1 << 1)
+
+/* CANFD status. */
+#define STATUS_CONFIG_MODE  (1 << 0)
+#define STATUS_NORMAL_MODE  (1 << 3)
+#define STATUS_LOOPBACK_MODE(1 << 1)
+#define ISR_TXOK(1 << 1)
+#define ISR_RXOK(1 << 4)
+
+#define ENABLE_ALL_FILTERS  0x
+#define ENABLE_ALL_INTERRUPTS   0x
+
+/* We are sending one canfd message. */
+#define TX_READY_REG_VAL0x1
+
+#define FIRST_RX_STORE_INDEX0x1
+#define STATUS_REG_MASK 0xf
+#define DLC_FD_BIT_SHIFT0x1b
+#define DLC_FD_BIT_MASK 0xf800
+#define FIFO_STATUS_READ_INDEX_MASK 0x3f
+#define FIFO_STATUS_F

[QEMU][PATCH v5 2/4] hw/net/can: Introduce Xilinx Versal CANFD controller

2023-05-19 Thread Vikram Garhwal
The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN bus
implementation. Bus connection and socketCAN connection for each CAN module
can be set through command lines.

Signed-off-by: Vikram Garhwal 
---
 hw/net/can/meson.build |1 +
 hw/net/can/trace-events|7 +
 hw/net/can/xlnx-versal-canfd.c | 2107 
 include/hw/net/xlnx-versal-canfd.h |   87 ++
 4 files changed, 2202 insertions(+)
 create mode 100644 hw/net/can/xlnx-versal-canfd.c
 create mode 100644 include/hw/net/xlnx-versal-canfd.h

diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
index 8fabbd9ee6..8d85201cb0 100644
--- a/hw/net/can/meson.build
+++ b/hw/net/can/meson.build
@@ -5,3 +5,4 @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: 
files('can_mioe3680_pci.c'))
 softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
 softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
 softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-canfd.c'))
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
index 8346a98ab5..de64ac1b31 100644
--- a/hw/net/can/trace-events
+++ b/hw/net/can/trace-events
@@ -7,3 +7,10 @@ xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t 
value) "Filter%d MAS
 xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t 
db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: 
ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 
0x%02x"
 xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t 
db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: 
ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 
0x%02x"
 xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus 
communication. Status Register: 0x%08x"
+
+# xlnx-versal-canfd.c
+xlnx_canfd_update_irq(char *path, uint32_t isr, uint32_t ier, uint32_t irq) 
"%s: ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
+xlnx_canfd_rx_fifo_filter_reject(char *path, uint32_t id, uint8_t dlc) "%s: 
Frame: ID: 0x%08x DLC: 0x%02x"
+xlnx_canfd_rx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flags) "%s: 
Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
+xlnx_canfd_tx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flgas) "%s: 
Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
+xlnx_canfd_reset(char *path, uint32_t val) "%s: Resetting controller with 
value = 0x%08x"
diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
new file mode 100644
index 00..bb86b3a9cf
--- /dev/null
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -0,0 +1,2107 @@
+/*
+ * QEMU model of the Xilinx Versal CANFD device.
+ *
+ * This implementation is based on the following datasheet:
+ * https://docs.xilinx.com/v/u/2.0-English/pg223-canfd
+ *
+ * Copyright (c) 2022 AMD Inc.
+ *
+ * Written-by: Vikram Garhwal 
+ *
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
+ * Pavel Pisa
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/register.h"
+#include "qapi/error.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/cutils.h"
+#include "qemu/event_notifier.h"
+#include "hw/qdev-properties.h"
+#include "qom/object_interfaces.h"
+#include "migration/vmstate.h"
+#include "hw/net/xlnx-versal-canfd.h"
+#include "trace.h"
+
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
+FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
+FIELD(S

[QEMU][PATCH v5 1/4] MAINTAINERS: Include canfd tests under Xilinx CAN

2023-05-19 Thread Vikram Garhwal
Signed-off-by: Vikram Garhwal 
Reviewed-by: Peter Maydell 
Reviewed-by: Francisco Iglesias 
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index d0e604c725..e636bb5df8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1813,7 +1813,7 @@ M: Francisco Iglesias 
 S: Maintained
 F: hw/net/can/xlnx-*
 F: include/hw/net/xlnx-*
-F: tests/qtest/xlnx-can-test*
+F: tests/qtest/xlnx-can*-test*
 
 EDU
 M: Jiri Slaby 
-- 
2.17.1




[QEMU][PATCH v5 3/4] xlnx-versal: Connect Xilinx VERSAL CANFD controllers

2023-05-19 Thread Vikram Garhwal
Connect CANFD0 and CANFD1 on the Versal-virt machine and update xlnx-versal-virt
document with CANFD command line examples.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Peter Maydell 
---
 docs/system/arm/xlnx-versal-virt.rst | 31 
 hw/arm/xlnx-versal-virt.c| 53 
 hw/arm/xlnx-versal.c | 37 +++
 include/hw/arm/xlnx-versal.h | 12 +++
 4 files changed, 133 insertions(+)

diff --git a/docs/system/arm/xlnx-versal-virt.rst 
b/docs/system/arm/xlnx-versal-virt.rst
index 92ad10d2da..d2d1b26692 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -34,6 +34,7 @@ Implemented devices:
 - DDR memory
 - BBRAM (36 bytes of Battery-backed RAM)
 - eFUSE (3072 bytes of one-time field-programmable bit array)
+- 2 CANFDs
 
 QEMU does not yet model any other devices, including the PL and the AI Engine.
 
@@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, add:
 
   Better yet, do not use actual product data when running guest image
   on this Xilinx Versal Virt board.
+
+Using CANFDs for Versal Virt
+""""""""""""""""""""""""""""
+Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
+implementation. Bus connection and socketCAN connection for each CAN module
+can be set through command lines.
+
+To connect both CANFD0 and CANFD1 on the same bus:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
+
+To connect CANFD0 and CANFD1 to separate buses:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
+-machine canbus0=canbus0 -machine canbus1=canbus1
+
+The SocketCAN interface can connect to a Physical or a Virtual CAN interfaces 
on
+the host machine. Please check this document to learn about CAN interface on
+Linux: docs/system/devices/can.rst
+
+To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
+-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 668a9d65a4..1ee2b8697f 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -40,9 +40,11 @@ struct VersalVirt {
 uint32_t clk_25Mhz;
 uint32_t usb;
 uint32_t dwc;
+uint32_t canfd[2];
 } phandle;
 struct arm_boot_info binfo;
 
+CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
 struct {
 bool secure;
 } cfg;
@@ -235,6 +237,38 @@ static void fdt_add_uart_nodes(VersalVirt *s)
 }
 }
 
+static void fdt_add_canfd_nodes(VersalVirt *s)
+{
+uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
+uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
+unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
+const char clocknames[] = "can_clk\0s_axi_aclk";
+int i;
+
+/* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
+for (i = 0; i < ARRAY_SIZE(addrs); i++) {
+char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
+qemu_fdt_add_subnode(s->fdt, name);
+
+qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40);
+qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20);
+
+qemu_fdt_setprop_cells(s->fdt, name, "clocks",
+   s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
+qemu_fdt_setprop(s->fdt, name, "clock-names",
+ clocknames, sizeof(clocknames));
+qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
+   GIC_FDT_IRQ_TYPE_SPI, irqs[i],
+   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+ 2, addrs[i], 2, size[i]);
+qemu_fdt_setprop_string(s->fdt, name, "compatible",
+"xlnx,canfd-2.0");
+
+g_free(name);
+}
+}
+
 static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
  uint32_t phandle)
 {
@@ -639,12 +673,17 @@ static void versal_virt_init(MachineState *machine)
 TYPE_XLNX_VERSAL);
 object_property_set_link(OBJECT(>soc), "ddr", OBJECT(machine->ram),
  _abort);
+object_property_set_link(OBJECT(>soc), "canbus0", OBJECT(s->canbus[0]),
+ _abort);
+object_property_set_link(OBJECT(>soc), "canbus1", OBJECT(s->canbus[1]),
+ _abort);

Re: [PULL v3 0/10] xenpvh3-tag

2023-05-03 Thread Vikram Garhwal

Hi Richard,

On 5/3/23 12:47 AM, Richard Henderson wrote:

On 5/3/23 01:12, Stefano Stabellini wrote:

Hi Peter,

Vikram fixed the gitlab test problem, so now all the tests should
succeed. There were no changes to the QEMU code. I am resending the pull
request (I rebased it on staging, no conflicts.)

For reference this was the previous pull request:
https://marc.info/?l=qemu-devel=167641819725964

Cheers,

Stefano


The following changes since commit 
4ebc33f3f3b656ebf62112daca6aa0f8019b4891:


   Merge tag 'pull-tcg-20230502-2' of https://gitlab.com/rth7680/qemu 
into staging (2023-05-02 21:18:45 +0100)


are available in the Git repository at:

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

for you to fetch changes up to bc618c54318cbc2fcb9decf9d4c193cc336a0dbc:

   meson.build: enable xenpv machine build for ARM (2023-05-02 
17:04:54 -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


Errors in CI:

https://gitlab.com/qemu-project/qemu/-/jobs/4216392008#L2381

../hw/i386/xen/xen-hvm.c:303:9: error: implicit declaration of 
function 'error_report' is invalid in C99 
[-Werror,-Wimplicit-function-declaration]

    error_report("relocate_memory %lu pages from GFN %"HWADDR_PRIx
Thanks for notifying this. I am not sure why this particular build is 
failing. error_report() is defined in "|qemu/error-report.h" and the 
header should be included as |||it builds fine for other configs.

|Also, the same tsan-build passed when we sent the PULL for v2.

I am not sure why it's failing for this config. W||ill try to fix 
this. Meanwhile, any hints on how to fix/debug this?


Regards,
Vikram
|

^


r~





[QEMU][PATCH v4 0/4] Introduce Xilinx Versal CANFD

2023-04-25 Thread Vikram Garhwal
Hi,
This patch implements CANFD controller for xlnx-versal-virt machine. There are
two controllers CANFD0@0xFF06_ and CANFD1@0xFF07_ are connected to the
machine.

Also, added basic qtests for data exchange between both the controllers in
various supported configs.

Changelog:
v3->v4:
Address formatting related feedback from Peter.
Correct dlc byte data storing if dlc is not a multiple of 4.
Remove unnecessary LOG_GUEST_ERROR.
Remove instance_finalize(canfd_finalize) function.
Remove unused member of struct XlnxVersalCANFDState.

v2->v3:
Corrected reg2frame().
Added assert to prevent out of bound cases.
Replace tx_id link list with GSList and removed sorting function.
Replaced PTIMER_POLICY_LEGACY with proper timer policies.
Corrected minor code format issues.

v1->v2
Update xlnx-versal-virt.rst with CANFD examples and add this in 03/05 patch.
Addressed comments for patch 02/05 and 03/05.
Add reviewed-by tags for patch 01/05, 04/05 and 05/05.
Change commit message for patch 02/05.
Add SPDX license for Qtest.

Regards,
Vikram

Vikram Garhwal (4):
  MAINTAINERS: Include canfd tests under Xilinx CAN
  hw/net/can: Introduce Xilinx Versal CANFD controller
  xlnx-versal: Connect Xilinx VERSAL CANFD controllers
  tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

 MAINTAINERS  |2 +-
 docs/system/arm/xlnx-versal-virt.rst |   31 +
 hw/arm/xlnx-versal-virt.c|   48 +
 hw/arm/xlnx-versal.c |   37 +
 hw/net/can/meson.build   |1 +
 hw/net/can/trace-events  |7 +
 hw/net/can/xlnx-versal-canfd.c   | 2115 ++
 include/hw/arm/xlnx-versal.h |   12 +
 include/hw/net/xlnx-versal-canfd.h   |   87 ++
 tests/qtest/meson.build  |1 +
 tests/qtest/xlnx-canfd-test.c|  423 ++
 11 files changed, 2763 insertions(+), 1 deletion(-)
 create mode 100644 hw/net/can/xlnx-versal-canfd.c
 create mode 100644 include/hw/net/xlnx-versal-canfd.h
 create mode 100644 tests/qtest/xlnx-canfd-test.c

-- 
2.17.1




[QEMU][PATCH v4 4/4] tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

2023-04-25 Thread Vikram Garhwal
The QTests perform three tests on the Xilinx VERSAL CANFD controller:
Tests the CANFD controllers in loopback.
Tests the CANFD controllers in normal mode with CAN frame.
Tests the CANFD controllers in normal mode with CANFD frame.

Signed-off-by: Vikram Garhwal 
Acked-by: Thomas Huth 
Reviewed-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 tests/qtest/meson.build   |   1 +
 tests/qtest/xlnx-canfd-test.c | 423 ++
 2 files changed, 424 insertions(+)
 create mode 100644 tests/qtest/xlnx-canfd-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index cfc66ade6f..268ededfd5 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -212,6 +212,7 @@ qtests_aarch64 = \
   (config_all.has_key('CONFIG_TCG') and 
config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?\
 ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) +   
  \
   (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 
'fuzz-xlnx-dp-test'] : []) + \
+  (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : 
[]) + \
   (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) +  \
   (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : 
[]) + \
   ['arm-cpu-features',
diff --git a/tests/qtest/xlnx-canfd-test.c b/tests/qtest/xlnx-canfd-test.c
new file mode 100644
index 00..76ee106d4f
--- /dev/null
+++ b/tests/qtest/xlnx-canfd-test.c
@@ -0,0 +1,423 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * QTests for the Xilinx Versal CANFD controller.
+ *
+ * Copyright (c) 2022 AMD Inc.
+ *
+ * Written-by: Vikram Garhwal
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+/* Base address. */
+#define CANFD0_BASE_ADDR0xff06
+#define CANFD1_BASE_ADDR0xff07
+
+/* Register addresses. */
+#define R_SRR_OFFSET0x00
+#define R_MSR_OFFSET0x04
+#define R_FILTER_CONTROL_REGISTER   0xe0
+#define R_SR_OFFSET 0x18
+#define R_ISR_OFFSET0x1c
+#define R_IER_OFFSET0x20
+#define R_ICR_OFFSET0x24
+#define R_TX_READY_REQ_REGISTER 0x90
+#define RX_FIFO_STATUS_REGISTER 0xe8
+#define R_TXID_OFFSET   0x100
+#define R_TXDLC_OFFSET  0x104
+#define R_TXDATA1_OFFSET0x108
+#define R_TXDATA2_OFFSET0x10c
+#define R_AFMR_REGISTER00xa00
+#define R_AFIR_REGISTER00xa04
+#define R_RX0_ID_OFFSET 0x2100
+#define R_RX0_DLC_OFFSET0x2104
+#define R_RX0_DATA1_OFFSET  0x2108
+#define R_RX0_DATA2_OFFSET  0x210c
+
+/* CANFD modes. */
+#define SRR_CONFIG_MODE 0x00
+#define MSR_NORMAL_MODE 0x00
+#define MSR_LOOPBACK_MODE   (1 << 1)
+#define ENABLE_CANFD(1 << 1)
+
+/* CANFD status. */
+#define STATUS_CONFIG_MODE  (1 << 0)
+#define STATUS_NORMAL_MODE  (1 << 3)
+#define STATUS_LOOPBACK_MODE(1 << 1)
+#define ISR_TXOK(1 << 1)
+#define ISR_RXOK(1 << 4)
+
+#define ENABLE_ALL_FILTERS  0x
+#define ENABLE_ALL_INTERRUPTS   0x
+
+/* We are sending one canfd message. */
+#define TX_READY_REG_VAL0x1
+
+#define FIRST_RX_STORE_INDEX0x1
+#define STATUS_REG_MASK 0xf
+#define DLC_FD_BIT_SHIFT0x1b
+#define DLC_FD_BIT_MASK 0xf800
+#define FIFO_STATUS_READ_INDEX_MASK 0x3f
+#define FIFO_STATUS_FILL_LEVEL_MASK 0x7f00
+#define FILL_LEVEL_SHI

[QEMU][PATCH v4 3/4] xlnx-versal: Connect Xilinx VERSAL CANFD controllers

2023-04-25 Thread Vikram Garhwal
Connect CANFD0 and CANFD1 on the Versal-virt machine and update xlnx-versal-virt
document with CANFD command line examples.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Peter Maydell 
---
 docs/system/arm/xlnx-versal-virt.rst | 31 ++
 hw/arm/xlnx-versal-virt.c| 48 
 hw/arm/xlnx-versal.c | 37 +
 include/hw/arm/xlnx-versal.h | 12 +++
 4 files changed, 128 insertions(+)

diff --git a/docs/system/arm/xlnx-versal-virt.rst 
b/docs/system/arm/xlnx-versal-virt.rst
index 92ad10d2da..d2d1b26692 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -34,6 +34,7 @@ Implemented devices:
 - DDR memory
 - BBRAM (36 bytes of Battery-backed RAM)
 - eFUSE (3072 bytes of one-time field-programmable bit array)
+- 2 CANFDs
 
 QEMU does not yet model any other devices, including the PL and the AI Engine.
 
@@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, add:
 
   Better yet, do not use actual product data when running guest image
   on this Xilinx Versal Virt board.
+
+Using CANFDs for Versal Virt
+""""""""""""""""""""""""""""
+Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
+implementation. Bus connection and socketCAN connection for each CAN module
+can be set through command lines.
+
+To connect both CANFD0 and CANFD1 on the same bus:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
+
+To connect CANFD0 and CANFD1 to separate buses:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
+-machine canbus0=canbus0 -machine canbus1=canbus1
+
+The SocketCAN interface can connect to a Physical or a Virtual CAN interfaces 
on
+the host machine. Please check this document to learn about CAN interface on
+Linux: docs/system/devices/can.rst
+
+To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
+-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 668a9d65a4..52c93a590d 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -40,9 +40,11 @@ struct VersalVirt {
 uint32_t clk_25Mhz;
 uint32_t usb;
 uint32_t dwc;
+uint32_t canfd[2];
 } phandle;
 struct arm_boot_info binfo;
 
+CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
 struct {
 bool secure;
 } cfg;
@@ -235,6 +237,33 @@ static void fdt_add_uart_nodes(VersalVirt *s)
 }
 }
 
+static void fdt_add_canfd_nodes(VersalVirt *s)
+{
+uint64_t addrs[] = { MM_CANFD0, MM_CANFD1 };
+uint32_t size[] = { MM_CANFD0_SIZE, MM_CANFD1_SIZE };
+unsigned int irqs[] = { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0 };
+int i;
+
+/* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
+for (i = 0; i < ARRAY_SIZE(addrs); i++) {
+char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
+qemu_fdt_add_subnode(s->fdt, name);
+qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo0", 0x40);
+qemu_fdt_setprop_cell(s->fdt, name, "enable-rx-fifo1", 0x1);
+qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo1", 0x40);
+
+qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
+   GIC_FDT_IRQ_TYPE_SPI, irqs[i],
+   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+ 2, addrs[i], 2, size[i]);
+qemu_fdt_setprop_string(s->fdt, name, "compatible",
+"xlnx,versal-canfd");
+
+g_free(name);
+}
+}
+
 static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
  uint32_t phandle)
 {
@@ -639,12 +668,17 @@ static void versal_virt_init(MachineState *machine)
 TYPE_XLNX_VERSAL);
 object_property_set_link(OBJECT(>soc), "ddr", OBJECT(machine->ram),
  _abort);
+object_property_set_link(OBJECT(>soc), "canbus0", OBJECT(s->canbus[0]),
+ _abort);
+object_property_set_link(OBJECT(>soc), "canbus1", OBJECT(s->canbus[1]),
+ _abort);
 sysbus_realize(SYS_BUS_DEVICE(>soc), _fatal);
 
 fdt_create(s);
 create_virtio_regions(s);
 fdt_add_gem_nodes(s);
 fdt_add_uart_nodes(s);
+fdt_add_canfd_nodes(s);
 fdt_add_gic_nodes(s);
 fdt_add_timer_nodes(s);
 fdt_add_zd

[QEMU][PATCH v4 2/4] hw/net/can: Introduce Xilinx Versal CANFD controller

2023-04-25 Thread Vikram Garhwal
The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN bus
implementation. Bus connection and socketCAN connection for each CAN module
can be set through command lines.

Signed-off-by: Vikram Garhwal 
---
 hw/net/can/meson.build |1 +
 hw/net/can/trace-events|7 +
 hw/net/can/xlnx-versal-canfd.c | 2115 
 include/hw/net/xlnx-versal-canfd.h |   87 ++
 4 files changed, 2210 insertions(+)
 create mode 100644 hw/net/can/xlnx-versal-canfd.c
 create mode 100644 include/hw/net/xlnx-versal-canfd.h

diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
index 8fabbd9ee6..8d85201cb0 100644
--- a/hw/net/can/meson.build
+++ b/hw/net/can/meson.build
@@ -5,3 +5,4 @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: 
files('can_mioe3680_pci.c'))
 softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
 softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
 softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-canfd.c'))
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
index 8346a98ab5..de64ac1b31 100644
--- a/hw/net/can/trace-events
+++ b/hw/net/can/trace-events
@@ -7,3 +7,10 @@ xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t 
value) "Filter%d MAS
 xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t 
db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: 
ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 
0x%02x"
 xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t 
db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: 
ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 
0x%02x"
 xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus 
communication. Status Register: 0x%08x"
+
+# xlnx-versal-canfd.c
+xlnx_canfd_update_irq(char *path, uint32_t isr, uint32_t ier, uint32_t irq) 
"%s: ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
+xlnx_canfd_rx_fifo_filter_reject(char *path, uint32_t id, uint8_t dlc) "%s: 
Frame: ID: 0x%08x DLC: 0x%02x"
+xlnx_canfd_rx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flags) "%s: 
Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
+xlnx_canfd_tx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flgas) "%s: 
Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
+xlnx_canfd_reset(char *path, uint32_t val) "%s: Resetting controller with 
value = 0x%08x"
diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
new file mode 100644
index 00..fb6fa54698
--- /dev/null
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -0,0 +1,2115 @@
+/*
+ * QEMU model of the Xilinx Versal CANFD device.
+ *
+ * This implementation is based on the following datasheet:
+ * https://docs.xilinx.com/v/u/2.0-English/pg223-canfd
+ *
+ * Copyright (c) 2022 AMD Inc.
+ *
+ * Written-by: Vikram Garhwal 
+ *
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
+ * Pavel Pisa
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/register.h"
+#include "qapi/error.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/cutils.h"
+#include "qemu/event_notifier.h"
+#include "hw/qdev-properties.h"
+#include "qom/object_interfaces.h"
+#include "migration/vmstate.h"
+#include "hw/net/xlnx-versal-canfd.h"
+#include "trace.h"
+
+/*
+ * This is done to avoid the build issues on Windows machines. The ERROR field
+ * of 

[QEMU][PATCH v4 1/4] MAINTAINERS: Include canfd tests under Xilinx CAN

2023-04-25 Thread Vikram Garhwal
Signed-off-by: Vikram Garhwal 
Reviewed-by: Peter Maydell 
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 24154f5721..c3dbacb615 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1809,7 +1809,7 @@ M: Francisco Iglesias 
 S: Maintained
 F: hw/net/can/xlnx-*
 F: include/hw/net/xlnx-*
-F: tests/qtest/xlnx-can-test*
+F: tests/qtest/xlnx-can*-test*
 
 EDU
 M: Jiri Slaby 
-- 
2.17.1




Re: [QEMU][PATCH v3 2/4] hw/net/can: Introduce Xilinx Versal CANFD controller

2023-04-14 Thread Vikram Garhwal

Hi Peter & Francisco,

Apologies for long delay with next version i.e. v4. I was on family 
leave and resumed work two weeks back.


Please see my comments below.

On 12/19/22 8:11 AM, Peter Maydell wrote:

On Wed, 7 Dec 2022 at 02:13, Vikram Garhwal  wrote:

The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN bus
implementation. Bus connection and socketCAN connection for each CAN module
can be set through command lines.

Signed-off-by: Vikram Garhwal
---
  hw/net/can/meson.build |1 +
  hw/net/can/trace-events|7 +
  hw/net/can/xlnx-versal-canfd.c | 2121 
  include/hw/net/xlnx-versal-canfd.h |   90 ++
  4 files changed, 2219 insertions(+)
  create mode 100644 hw/net/can/xlnx-versal-canfd.c
  create mode 100644 include/hw/net/xlnx-versal-canfd.h




@@ -0,0 +1,2121 @@
+/*
+ * QEMU model of the Xilinx Versal CANFD device.
+ *
+ * This implementation is based on the following datasheet:
+ *https://docs.xilinx.com/v/u/2.0-English/pg223-canfd
+ *
+ * Copyright (c) 2022 AMD Inc.
+ *
+ * Written-by: Vikram Garhwal

Missing space before '<'.


+static void canfd_config_reset(XlnxVersalCANFDState *s)
+{
+
+unsigned int i;
+
+/* Reset all the configuration register. */

"registers"


+for (i = 0; i < R_RX_FIFO_WATERMARK_REGISTER; ++i) {
+register_reset(>reg_info[i]);
+}
+
+canfd_update_irq(s);
+}
+static void store_rx_sequential(XlnxVersalCANFDState *s,
+const qemu_can_frame *frame,
+uint32_t fill_level, uint32_t read_index,
+uint32_t store_location, uint8_t rx_fifo,
+bool rx_fifo_id, uint8_t filter_index)
+{
+int i;
+bool is_canfd_frame;
+uint8_t dlc = frame->can_dlc;
+uint32_t dlc_reg_val = 0;
+uint32_t data_reg_val = 0;
+
+/* Getting RX0/1 fill level */
+if ((fill_level) > rx_fifo - 1) {
+g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+qemu_log_mask(LOG_GUEST_ERROR, "%s: RX%d Buffer is full. Discarding 
the"
+  " message\n", path, rx_fifo_id);
+
+/* Set the corresponding RF buffer overflow interrupt. */
+if (rx_fifo_id == 0) {
+ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW, 1);
+} else {
+ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 1);
+}
+} else {
+uint16_t rx_timestamp = CANFD_TIMER_MAX -
+ptimer_get_count(s->canfd_timer);
+
+if (rx_timestamp == 0x) {
+ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TSCNT_OFLW, 
1);
+} else {
+ARRAY_FIELD_DP32(s->regs, TIMESTAMP_REGISTER, TIMESTAMP_CNT,
+ rx_timestamp);
+}
+
+if (rx_fifo_id == 0) {
+ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL,
+ fill_level + 1);
+assert(store_location <=
+  R_RB_ID_REGISTER + (s->cfg.rx0_fifo *
+  NUM_REGS_PER_MSG_SPACE));
+} else {
+ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1,
+ fill_level + 1);
+assert(store_location <=
+  R_RB_ID_REGISTER_1 + (s->cfg.rx1_fifo *
+NUM_REGS_PER_MSG_SPACE));
+}
+
+s->regs[store_location] = frame->can_id;
+
+if (frame->flags == QEMU_CAN_FRMF_TYPE_FD) {
+is_canfd_frame = true;
+
+for (i = 0; i < ARRAY_SIZE(canfd_dlc_array); i++) {
+if (canfd_dlc_array[i] == frame->can_dlc) {
+dlc = 8 + i;
+}
+
+dlc_reg_val = FIELD_DP32(0, RB_DLC_REGISTER, DLC, dlc);
+}
+} else {
+is_canfd_frame = false;
+if (frame->can_dlc > 8) {
+dlc = 8;
+}
+
+dlc_reg_val = FIELD_DP32(0, RB_DLC_REGISTER, DLC, frame->can_dlc);
+}
+
+dlc_reg_val |= FIELD_DP32(0, RB_DLC_REGISTER, FDF, is_canfd_frame);
+dlc_reg_val |= FIELD_DP32(0, RB_DLC_REGISTER, TIMESTAMP, rx_timestamp);
+dlc_reg_val |= FIELD_DP32(0, RB_DLC_REGISTER, MATCHED_FILTER_INDEX,
+  filter_index);
+s->regs[store_location + 1] = dlc_reg_val;
+
+for (i = 0; i <= dlc; i++) {
+data_reg_val = FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES3,
+  frame->data[4 * i]);
+data_reg_val |= FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES2,
+   frame->data[4 * i + 1]);
+dat

Re: [QEMU][PATCH] gitlab-ci.d/crossbuilds: Drop the '--disable-tcg' configuration for xen

2023-04-12 Thread Vikram Garhwal

Hi all,

Yes, gdbstub build issue is only for for aarch64-softmmu target and that 
was the reason for this patch. x86 targets build fine with 
''disable-tcg" option.


Thanks Fabiano & Philippe for sharing the existing patch series for this.

Regards,

Vikram



On 4/12/23 5:51 AM, Fabiano Rosas wrote:

Alex Bennée  writes:


Vikram Garhwal  writes:


Xen is supported for aarch64 via xenpvh machine. disable-tcg option fails the
build for aarch64 target.

Link for xen on arm patch series: 
https://mail.gnu.org/archive/html/qemu-devel/2023-02/msg03979.html

Signed-off-by: Vikram Garhwal 
---
  .gitlab-ci.d/crossbuilds.yml | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml
index 61b8ac86ee..6867839248 100644
--- a/.gitlab-ci.d/crossbuilds.yml
+++ b/.gitlab-ci.d/crossbuilds.yml
@@ -186,7 +186,7 @@ cross-amd64-xen-only:
variables:
  IMAGE: debian-amd64-cross
  ACCEL: xen
-EXTRA_CONFIGURE_OPTS: --disable-tcg --disable-kvm
+EXTRA_CONFIGURE_OPTS: --disable-kvm

x86 should handle --disable-tcg fine.

  
  cross-arm64-xen-only:

extends: .cross_accel_build_job
@@ -195,4 +195,4 @@ cross-arm64-xen-only:
variables:
  IMAGE: debian-arm64-cross
  ACCEL: xen
-EXTRA_CONFIGURE_OPTS: --disable-tcg --disable-kvm
+EXTRA_CONFIGURE_OPTS: --disable-kvm

Currently this builds qemu-system-i386, but with your changes and the
work Fabiano is doing:

   Message-Id: <20230313151058.19645-1-faro...@suse.de>
   Date: Mon, 13 Mar 2023 12:10:48 -0300
   Subject: [PATCH v9 00/10] target/arm: Allow CONFIG_TCG=n builds
   From: Fabiano Rosas 

We should be able to have a qemu-system-aarch64 supporting Xen without TCG

The build should already be working on current master after Philippe
fixed the gdbstub issues. My remaining patches fix tests and general
runtime issues. I just sent v10 to the list.





[QEMU][PATCH v6 06/10] hw/xen/xen-hvm-common: skip ioreq creation on ioreq registration failure

2023-04-11 Thread Vikram Garhwal
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.17.0




[QEMU][PATCH v6 04/10] xen-hvm: reorganize xen-hvm and move common function to xen-hvm-common

2023-04-11 Thread Vikram Garhwal
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 
Reviewed-by: Stefano Stabellini 
Reviewed-by: Paul Durrant 
---
 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 

  1   2   3   >