Re: [PATCH v2 07/21] include/exec/memattrs: Add two bits of space to MemTxAttrs

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 00:26, Richard Henderson wrote:

We will need 2 bits to represent ARMSecurityState.

Do not attempt to replace or widen secure, even though it
logically overlaps the new field -- there are uses within
e.g. hw/block/pflash_cfi01.c, which don't know anything
specific about ARM.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
  include/exec/memattrs.h | 9 -
  1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
index 9fb98bc1ef..d04170aa27 100644
--- a/include/exec/memattrs.h
+++ b/include/exec/memattrs.h
@@ -29,10 +29,17 @@ typedef struct MemTxAttrs {
   * "didn't specify" if necessary.
   */
  unsigned int unspecified:1;
-/* ARM/AMBA: TrustZone Secure access
+/*
+ * ARM/AMBA: TrustZone Secure access
   * x86: System Management Mode access
   */
  unsigned int secure:1;
+/*
+ * ARM: ArmSecuritySpace.  This partially overlaps secure, but it is
+ * easier to have both fields to assist code that does not understand
+ * ARMv9 RME, or no specific knowledge of ARM at all (e.g. pflash).
+ */
+unsigned int space:2;
  /* Memory access is usermode (unprivileged) */
  unsigned int user:1;


'secure' & 'user' seem mutually exclusive. If we get short in bits,
they could be shared.



Re: [PATCH 2/2] qga/win32: Use rundll for VSS installation

2023-02-20 Thread Yan Vugenfirer
Reviewed-by: Yan Vugenfirer 


On Mon, Feb 20, 2023 at 7:41 PM Konstantin Kostiuk  wrote:
>
> Add specific an entry points for rundll which is
> just a wrapper for COMRegister/COMUnregister functions.
>
> resolves: rhbz#2167436
> fixes: CVE-2023-0664
>
> Signed-off-by: Konstantin Kostiuk 
> ---
>  qga/installer/qemu-ga.wxs | 10 +-
>  qga/vss-win32/install.cpp |  9 +
>  qga/vss-win32/qga-vss.def |  2 ++
>  3 files changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs
> index feb629ec47..46ae9e7a13 100644
> --- a/qga/installer/qemu-ga.wxs
> +++ b/qga/installer/qemu-ga.wxs
> @@ -127,22 +127,22 @@
>
>  
>
> -
> +
>  
>
>  
>   -  ExeCommand='/c "[qemu_ga_directory]qemu-ga.exe" -s vss-install'
> +  ExeCommand='"[qemu_ga_directory]qga-vss.dll",DLLCOMRegister'
>Execute="deferred"
> -  Property="cmd"
> +  Property="rundll"
>Impersonate="no"
>Return="check"
>>
>  
>   -  ExeCommand='/c "[qemu_ga_directory]qemu-ga.exe" -s 
> vss-uninstall'
> +  ExeCommand='"[qemu_ga_directory]qga-vss.dll",DLLCOMUnregister'
>Execute="deferred"
> -  Property="cmd"
> +  Property="rundll"
>Impersonate="no"
>Return="check"
>>
> diff --git a/qga/vss-win32/install.cpp b/qga/vss-win32/install.cpp
> index b57508fbe0..68662a6dfc 100644
> --- a/qga/vss-win32/install.cpp
> +++ b/qga/vss-win32/install.cpp
> @@ -357,6 +357,15 @@ out:
>  return hr;
>  }
>
> +STDAPI_(void) CALLBACK DLLCOMRegister(HWND, HINSTANCE, LPSTR, int)
> +{
> +COMRegister();
> +}
> +
> +STDAPI_(void) CALLBACK DLLCOMUnregister(HWND, HINSTANCE, LPSTR, int)
> +{
> +COMUnregister();
> +}
>
>  static BOOL CreateRegistryKey(LPCTSTR key, LPCTSTR value, LPCTSTR data)
>  {
> diff --git a/qga/vss-win32/qga-vss.def b/qga/vss-win32/qga-vss.def
> index 927782c31b..ee97a81427 100644
> --- a/qga/vss-win32/qga-vss.def
> +++ b/qga/vss-win32/qga-vss.def
> @@ -1,6 +1,8 @@
>  LIBRARY  "QGA-PROVIDER.DLL"
>
>  EXPORTS
> +   DLLCOMRegister
> +   DLLCOMUnregister
> COMRegister PRIVATE
> COMUnregister   PRIVATE
> DllCanUnloadNow PRIVATE
> --
> 2.25.1
>




Re: [PATCH 1/2] qga/win32: Remove change action from MSI installer

2023-02-20 Thread Yan Vugenfirer
Reviewed-by: Yan Vugenfirer 

On Mon, Feb 20, 2023 at 7:41 PM Konstantin Kostiuk  wrote:
>
> resolves: rhbz#2167436
> fixes: CVE-2023-0664
>
> Signed-off-by: Konstantin Kostiuk 
> ---
>  qga/installer/qemu-ga.wxs | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs
> index 51340f7ecc..feb629ec47 100644
> --- a/qga/installer/qemu-ga.wxs
> +++ b/qga/installer/qemu-ga.wxs
> @@ -31,6 +31,7 @@
>/>
>   EmbedCab="yes" />
>  1
> +
>  DowngradeErrorMessage="Error: A newer version of QEMU guest agent is 
> already installed."
>/>
> --
> 2.25.1
>




Re: [PATCH v3 2/6] configure: Add courtesy hint to Python version failure message

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 02:24, John Snow wrote:

If we begin requiring Python 3.7+, a few platforms are going to need to
install an additional Python interpreter package.

As a courtesy to the user, suggest the optional package they might need
to install. This will hopefully minimize any downtime caused by the
change in Python dependency.

Signed-off-by: John Snow 
---
  configure | 5 -
  1 file changed, 4 insertions(+), 1 deletion(-)


Reviewed-by: Philippe Mathieu-Daudé 





Re: [PATCH v2 14/14] target/arm: Implement gdbstub m-profile systemreg and secext

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 03:19, Richard Henderson wrote:

The upstream gdb xml only implements {MSP,PSP}{,_NS,S}, but
go ahead and implement the other system registers as well.

Since there is significant overlap between the two, implement
them with common code.  The only exception is the systemreg
view of CONTROL, which merges the banked bits as per MRS.

Signed-off-by: David Reiss 
[rth: Substatial rewrite using enumerator and shared code.]
Signed-off-by: Richard Henderson 
---
  target/arm/cpu.h |   2 +
  target/arm/gdbstub.c | 194 +++
  2 files changed, 196 insertions(+)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v2 13/14] target/arm: Export arm_v7m_get_sp_ptr

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 03:19, Richard Henderson wrote:

From: David Reiss 

Allow the function to be used outside of m_helper.c.
Move to be outside of ifndef CONFIG_USER_ONLY block.
Rename from get_v7m_sp_ptr.

Reviewed-by: Peter Maydell 
Signed-off-by: David Reiss 
[rth: Split out of a larger patch]
Signed-off-by: Richard Henderson 
---
  target/arm/internals.h | 10 +
  target/arm/m_helper.c  | 84 +-
  2 files changed, 51 insertions(+), 43 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v2 12/14] target/arm: Export arm_v7m_mrs_control

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 03:19, Richard Henderson wrote:

From: David Reiss 

Allow the function to be used outside of m_helper.c.
Rename with an "arm_" prefix.

Reviewed-by: Peter Maydell 
Signed-off-by: David Reiss 
[rth: Split out of a larger patch]
Signed-off-by: Richard Henderson 
---
  target/arm/internals.h | 3 +++
  target/arm/m_helper.c  | 6 +++---
  2 files changed, 6 insertions(+), 3 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v2 08/14] target/arm: Add name argument to output_vector_union_type

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 03:19, Richard Henderson wrote:

This will make the function usable between SVE and SME.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
  target/arm/gdbstub64.c | 28 ++--
  1 file changed, 14 insertions(+), 14 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v2 06/14] target/arm: Hoist pred_width in arm_gen_dynamic_svereg_xml

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 03:19, Richard Henderson wrote:

Reviewed-by: Fabiano Rosas 
Signed-off-by: Richard Henderson 
---
  target/arm/gdbstub64.c | 5 +++--
  1 file changed, 3 insertions(+), 2 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v2 05/14] target/arm: Simplify register counting in arm_gen_dynamic_svereg_xml

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 03:19, Richard Henderson wrote:

Rather than increment base_reg and num, compute num
from the change to base_reg at the end.  Clean up some
nearby comments.

Signed-off-by: Richard Henderson 
---
  target/arm/gdbstub64.c | 27 ---
  1 file changed, 16 insertions(+), 11 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v11 0/9] support subsets of code size reduction extension

2023-02-20 Thread liweiwei

Hi,  any  new comments for this patchset?

Regards,

Weiwei Li

On 2023/2/9 12:13, Weiwei Li wrote:

This patchset implements RISC-V Zc* extension v1.0.2-1 version instructions.

Specification:
https://github.com/riscv/riscv-code-size-reduction/tree/main/Zc-specification

The port is available here:
https://github.com/plctlab/plct-qemu/tree/plct-zce-upstream-v11

To test Zc* implementation, specify cpu argument with 'x-zca=true,x-zcb=true,x-zcf=true,f=true" and 
"x-zcd=true,d=true" (or "x-zcmp=true,x-zcmt=true" with c or d=false) to enable 
Zca/Zcb/Zcf and Zcd(or Zcmp,Zcmt) extensions support.


This implementation can pass the basic zc tests from 
https://github.com/yulong-plct/zc-test

v11
* update format and field name based on the latest spec in patch 5, 6, 7 
(without other functional changes)
* rebase on riscv-to-apply.next

v10:
* rebase on Daniel's series(riscv-to-apply.next) and adjust riscv-tests to test 
on sifive related CPUs

v9:
* rebase on riscv-to-apply.next

v8:
* improve disas support in Patch 9

v7:
* Fix description for Zca

v6:
* fix base address for jump table in Patch 7
* rebase on riscv-to-apply.next

v5:
* fix exception unwind problem for cpu_ld*_code in helper of cm_jalt

v4:
* improve Zcmp suggested by Richard
* fix stateen related check for Zcmt

v3:
* update the solution for Zcf to the way of Zcd
* update Zcb to reuse gen_load/store
* use trans function instead of helper for push/pop

v2:
* add check for relationship between Zca/Zcf/Zcd with C/F/D based on related 
discussion in review of Zc* spec
* separate c.fld{sp}/fsd{sp} with fld{sp}/fsd{sp} before support of zcmp/zcmt

Weiwei Li (9):
   target/riscv: add cfg properties for Zc* extension
   target/riscv: add support for Zca extension
   target/riscv: add support for Zcf extension
   target/riscv: add support for Zcd extension
   target/riscv: add support for Zcb extension
   target/riscv: add support for Zcmp extension
   target/riscv: add support for Zcmt extension
   target/riscv: expose properties for Zc* extension
   disas/riscv.c: add disasm support for Zc*

  disas/riscv.c | 228 +++-
  target/riscv/cpu.c|  56 
  target/riscv/cpu.h|  10 +
  target/riscv/cpu_bits.h   |   7 +
  target/riscv/csr.c|  38 ++-
  target/riscv/helper.h |   3 +
  target/riscv/insn16.decode|  62 -
  target/riscv/insn_trans/trans_rvd.c.inc   |  18 ++
  target/riscv/insn_trans/trans_rvf.c.inc   |  18 ++
  target/riscv/insn_trans/trans_rvi.c.inc   |   4 +-
  target/riscv/insn_trans/trans_rvzce.c.inc | 313 ++
  target/riscv/machine.c|  19 ++
  target/riscv/meson.build  |   3 +-
  target/riscv/translate.c  |  15 +-
  target/riscv/zce_helper.c |  55 
  15 files changed, 833 insertions(+), 16 deletions(-)
  create mode 100644 target/riscv/insn_trans/trans_rvzce.c.inc
  create mode 100644 target/riscv/zce_helper.c






Re: [PATCH v2 02/14] target/arm: Unexport arm_gen_dynamic_sysreg_xml

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 03:19, Richard Henderson wrote:

This function is not used outside gdbstub.c.

Reviewed-by: Fabiano Rosas 
Signed-off-by: Richard Henderson 
---
  target/arm/cpu.h | 1 -
  target/arm/gdbstub.c | 2 +-
  2 files changed, 1 insertion(+), 2 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v2 03/14] target/arm: Move arm_gen_dynamic_svereg_xml to gdbstub64.c

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 03:19, Richard Henderson wrote:

The function is only used for aarch64, so move it to the
file that has the other aarch64 gdbstub stuff.  Move the
declaration to internals.h.

Reviewed-by: Fabiano Rosas 
Signed-off-by: Richard Henderson 
---
  target/arm/cpu.h   |   6 ---
  target/arm/internals.h |   1 +
  target/arm/gdbstub.c   | 120 -
  target/arm/gdbstub64.c | 118 
  4 files changed, 119 insertions(+), 126 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v2 01/14] target/arm: Normalize aarch64 gdbstub get/set function names

2023-02-20 Thread Philippe Mathieu-Daudé

On 21/2/23 03:19, Richard Henderson wrote:

Make the form of the function names between fp and sve the same:
   - arm_gdb_*_svereg -> aarch64_gdb_*_sve_reg.
   - aarch64_fpu_gdb_*_reg -> aarch64_gdb_*_fpu_reg.

Reviewed-by: Fabiano Rosas 
Signed-off-by: Richard Henderson 
---
  target/arm/internals.h | 8 
  target/arm/gdbstub.c   | 9 +
  target/arm/gdbstub64.c | 8 
  3 files changed, 13 insertions(+), 12 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v3 6/6] Python: Drop support for Python 3.6

2023-02-20 Thread Markus Armbruster
John Snow  writes:

> Python 3.6 was EOL 2021-12-31. Newer versions of upstream libraries have
> been dropping support for this version and it is becoming more
> cumbersome to support. Avocado-framework and qemu.qmp each have their
> own reasons for wanting to drop Python 3.6, but won't until QEMU does.

I'd prefer more thorough rationale.  I can dig it out of v2's review if
you like.  Might be best to wait for the rebase on Paolo's work, so we
know the context.

> Versions of Python available in our supported build platforms as of today,
> with optional versions available in parentheses:
>
> openSUSE Leap 15.4: 3.6.15 (3.9.10, 3.10.2)
> CentOS Stream 8:3.6.8  (3.8.13, 3.9.16)
> CentOS Stream 9:3.9.13
> Fedora 36:  3.10
> Fedora 37:  3.11
> Debian 11:  3.9.2
> Alpine 3.14, 3.15:  3.9.16
> Alpine 3.16, 3.17:  3.10.10
> Ubuntu 20.04 LTS:   3.8.10
> Ubuntu 22.04 LTS:   3.10.4
> NetBSD 9.3: 3.9.13*
> FreeBSD 12.4:   3.9.16
> FreeBSD 13.1:   3.9.16
> OpenBSD 7.2:3.9.16
>
> Note: Our VM tests install 3.7 specifically for freebsd and netbsd; the
> default for "python" or "python3" in FreeBSD is 3.9.16. NetBSD does not
> appear to have a default meta-package, but offers several options, the
> lowest of which is 3.7.15. "python39" appears to be a pre-requisite to
> one of the other packages we request in tests/vm/netbsd.
>
> Since it is safe under our supported platform policy, bump our minimum
> supported version of Python to 3.7.
>
> Signed-off-by: John Snow 




Re: [PATCH v2 04/13] vdpa: move vhost reset after get vring base

2023-02-20 Thread Eugenio Perez Martin
On Tue, Feb 21, 2023 at 6:36 AM Jason Wang  wrote:
>
>
> 在 2023/2/8 17:42, Eugenio Pérez 写道:
> > The function vhost.c:vhost_dev_stop calls vhost operation
> > vhost_dev_start(false). In the case of vdpa it totally reset and wipes
> > the device, making the fetching of the vring base (virtqueue state) totally
> > useless.
> >
> > The kernel backend does not use vhost_dev_start vhost op callback, but
> > vhost-user do. A patch to make vhost_user_dev_start more similar to vdpa
> > is desirable, but it can be added on top.
> >
> > Signed-off-by: Eugenio Pérez 
> > ---
> >   include/hw/virtio/vhost-backend.h |  4 
> >   hw/virtio/vhost-vdpa.c| 22 --
> >   hw/virtio/vhost.c |  3 +++
> >   3 files changed, 23 insertions(+), 6 deletions(-)
> >
> > diff --git a/include/hw/virtio/vhost-backend.h 
> > b/include/hw/virtio/vhost-backend.h
> > index c5ab49051e..ec3fbae58d 100644
> > --- a/include/hw/virtio/vhost-backend.h
> > +++ b/include/hw/virtio/vhost-backend.h
> > @@ -130,6 +130,9 @@ typedef bool (*vhost_force_iommu_op)(struct vhost_dev 
> > *dev);
> >
> >   typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev,
> >  int fd);
> > +
> > +typedef void (*vhost_reset_status_op)(struct vhost_dev *dev);
> > +
> >   typedef struct VhostOps {
> >   VhostBackendType backend_type;
> >   vhost_backend_init vhost_backend_init;
> > @@ -177,6 +180,7 @@ typedef struct VhostOps {
> >   vhost_get_device_id_op vhost_get_device_id;
> >   vhost_force_iommu_op vhost_force_iommu;
> >   vhost_set_config_call_op vhost_set_config_call;
> > +vhost_reset_status_op vhost_reset_status;
> >   } VhostOps;
> >
> >   int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
> > diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> > index cbbe92ffe8..26e38a6aab 100644
> > --- a/hw/virtio/vhost-vdpa.c
> > +++ b/hw/virtio/vhost-vdpa.c
> > @@ -1152,14 +1152,23 @@ static int vhost_vdpa_dev_start(struct vhost_dev 
> > *dev, bool started)
> >   if (started) {
> >   memory_listener_register(&v->listener, &address_space_memory);
> >   return vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
> > -} else {
> > -vhost_vdpa_reset_device(dev);
> > -vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
> > -   VIRTIO_CONFIG_S_DRIVER);
> > -memory_listener_unregister(&v->listener);
> > +}
> >
> > -return 0;
> > +return 0;
> > +}
> > +
> > +static void vhost_vdpa_reset_status(struct vhost_dev *dev)
> > +{
> > +struct vhost_vdpa *v = dev->opaque;
> > +
> > +if (dev->vq_index + dev->nvqs != dev->vq_index_end) {
> > +return;
> >   }
> > +
> > +vhost_vdpa_reset_device(dev);
> > +vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
> > +VIRTIO_CONFIG_S_DRIVER);
> > +memory_listener_unregister(&v->listener);
> >   }
> >
> >   static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base,
> > @@ -1346,4 +1355,5 @@ const VhostOps vdpa_ops = {
> >   .vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
> >   .vhost_force_iommu = vhost_vdpa_force_iommu,
> >   .vhost_set_config_call = vhost_vdpa_set_config_call,
> > +.vhost_reset_status = vhost_vdpa_reset_status,
> >   };
> > diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> > index eb8c4c378c..a266396576 100644
> > --- a/hw/virtio/vhost.c
> > +++ b/hw/virtio/vhost.c
> > @@ -2049,6 +2049,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, 
> > VirtIODevice *vdev, bool vrings)
> >hdev->vqs + i,
> >hdev->vq_index + i);
> >   }
> > +if (hdev->vhost_ops->vhost_reset_status) {
> > +hdev->vhost_ops->vhost_reset_status(hdev);
> > +}
>
>
> This looks racy, if we don't suspend/reset the device, device can move
> last_avail_idx even after get_vring_base()?
>
> Instead of doing things like this, should we fallback to
> virtio_queue_restore_last_avail_idx() in this case?
>

Right, we can track if the device is suspended / SVQ and then return
an error in vring_get_base if it is not. Would that work?

Thanks!

> Thanks
>
>
> >
> >   if (vhost_dev_has_iommu(hdev)) {
> >   if (hdev->vhost_ops->vhost_set_iotlb_callback) {
>




Re: [PATCH v2 03/13] vdpa: add vhost_vdpa_suspend

2023-02-20 Thread Eugenio Perez Martin
On Tue, Feb 21, 2023 at 6:33 AM Jason Wang  wrote:
>
>
> 在 2023/2/21 13:27, Jason Wang 写道:
> >
> > 在 2023/2/8 17:42, Eugenio Pérez 写道:
> >> The function vhost.c:vhost_dev_stop fetches the vring base so the vq
> >> state can be migrated to other devices.  However, this is unreliable in
> >> vdpa, since we didn't signal the device to suspend the queues, making
> >> the value fetched useless.
> >>
> >> Suspend the device if possible before fetching first and subsequent
> >> vring bases.
> >>
> >> Moreover, vdpa totally reset and wipes the device at the last device
> >> before fetch its vrings base, making that operation useless in the last
> >> device. This will be fixed in later patches of this series.
> >
> >
> > It would be better not introduce a bug first and fix it in the
> > following patch.
> >
> >
> >>
> >> Signed-off-by: Eugenio Pérez 
> >> ---
> >>   hw/virtio/vhost-vdpa.c | 19 +++
> >>   hw/virtio/trace-events |  1 +
> >>   2 files changed, 20 insertions(+)
> >>
> >> diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> >> index 2e79fbe4b2..cbbe92ffe8 100644
> >> --- a/hw/virtio/vhost-vdpa.c
> >> +++ b/hw/virtio/vhost-vdpa.c
> >> @@ -1108,6 +1108,24 @@ static void vhost_vdpa_svqs_stop(struct
> >> vhost_dev *dev)
> >>   }
> >>   }
> >>   +static void vhost_vdpa_suspend(struct vhost_dev *dev)
> >> +{
> >> +struct vhost_vdpa *v = dev->opaque;
> >> +int r;
> >> +
> >> +if (!vhost_vdpa_first_dev(dev) ||
> >
> >
> > Any reason we need to use vhost_vdpa_first_dev() instead of replacing the
> >
> > if (started) {
> > } else {
> > vhost_vdpa_reset_device(dev);
> > 
> > }

I can also move the check to vhost_vdpa_dev_start, for sure.

>
> Ok, I think I kind of understand, so I think we need re-order the
> patches, at least patch 4 should come before this patch?
>

I think it is doable, yes. I'll check and come back to you.

Thanks!

> Thanks
>
>
> >
> >
> > We check
> >
> > if (dev->vq_index + dev->nvqs != dev->vq_index_end) in
> > vhost_vdpa_dev_start() but vhost_vdpa_first_dev() inside
> > vhost_vdpa_suspend(). This will result code that is hard to maintain.
> >
> > Thanks
> >
> >
> >> +!(dev->backend_cap & BIT_ULL(VHOST_BACKEND_F_SUSPEND))) {
> >> +return;
> >> +}
> >> +
> >> +trace_vhost_vdpa_suspend(dev);
> >> +r = ioctl(v->device_fd, VHOST_VDPA_SUSPEND);
> >> +if (unlikely(r)) {
> >> +error_report("Cannot suspend: %s(%d)", g_strerror(errno),
> >> errno);
> >> +/* Not aborting since we're called from stop context */
> >> +}
> >> +}
> >> +
> >>   static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
> >>   {
> >>   struct vhost_vdpa *v = dev->opaque;
> >> @@ -1122,6 +1140,7 @@ static int vhost_vdpa_dev_start(struct
> >> vhost_dev *dev, bool started)
> >>   }
> >>   vhost_vdpa_set_vring_ready(dev);
> >>   } else {
> >> +vhost_vdpa_suspend(dev);
> >>   vhost_vdpa_svqs_stop(dev);
> >>   vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
> >>   }
> >> diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> >> index a87c5f39a2..8f8d05cf9b 100644
> >> --- a/hw/virtio/trace-events
> >> +++ b/hw/virtio/trace-events
> >> @@ -50,6 +50,7 @@ vhost_vdpa_set_vring_ready(void *dev) "dev: %p"
> >>   vhost_vdpa_dump_config(void *dev, const char *line) "dev: %p %s"
> >>   vhost_vdpa_set_config(void *dev, uint32_t offset, uint32_t size,
> >> uint32_t flags) "dev: %p offset: %"PRIu32" size: %"PRIu32" flags:
> >> 0x%"PRIx32
> >>   vhost_vdpa_get_config(void *dev, void *config, uint32_t config_len)
> >> "dev: %p config: %p config_len: %"PRIu32
> >> +vhost_vdpa_suspend(void *dev) "dev: %p"
> >>   vhost_vdpa_dev_start(void *dev, bool started) "dev: %p started: %d"
> >>   vhost_vdpa_set_log_base(void *dev, uint64_t base, unsigned long
> >> long size, int refcnt, int fd, void *log) "dev: %p base: 0x%"PRIx64"
> >> size: %llu refcnt: %d fd: %d log: %p"
> >>   vhost_vdpa_set_vring_addr(void *dev, unsigned int index, unsigned
> >> int flags, uint64_t desc_user_addr, uint64_t used_user_addr, uint64_t
> >> avail_user_addr, uint64_t log_guest_addr) "dev: %p index: %u flags:
> >> 0x%x desc_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64"
> >> avail_user_addr: 0x%"PRIx64" log_guest_addr: 0x%"PRIx64
>




Re: [PATCH v3 0/6] Python: Drop support for Python 3.6

2023-02-20 Thread Markus Armbruster
John Snow  writes:

> CI: https://gitlab.com/jsnow/qemu/-/pipelines/783612696
> [Updated for v3, still all green.]
> GL: https://gitlab.com/jsnow/qemu/-/commits/python-require-37
>
> Hi, discussion about this series is ongoing. This series (v3) is not
> meant to address all of that discussion, but rather is an updated
> baseline for what we are capable of right now, today, without much
> additional engineering. It's meant to serve as a reference for further
> discussion.

Misses the RFC tag then :)

> To my knowledge, the inconveniences caused by this patchset as currently
> written are:
>
> (1) Users of CentOS 8 and OpenSUSE 15.4 would need to install an
> additional python package that will exist side-by-side with their
> base platform's Python 3.6 package.
>
> "zypper install python39" or "dnf install python38" is enough;
> configure will do the rest of the work.
>
> It's my understanding that this is largely a non-issue.
>
> (2) Due to our Sphinx plugin that imports QAPI code from the tree,

I can read this as "Due to our Sphinx plugin (which by the way imports
some QAPI code)" or as "Due to out Sphinx plugin importing QAPI code".
The former is more accurate.  We need a newer Sphinx because we use a
plugin, the plugin is written in Python, so our new Python requirement
applies.  Fine print: the code the plugin imports from QAPI is going to
break first.

> distro-provided versions of Sphinx that are installed and tied to
> Python 3.6 will no longer be suitable. Users may forego building
> docs or install a suitable sphinx using "pip".
>
> It's my understanding that this one is "kind of a bummer".
>
> I feel that the inconvenience caused by (1) is minimized as is possible;
> the inconvenience caused by (2) is slightly worse and I concede the
> workaround has some complexities that I would otherwise seek to avoid.
>
> As far as I am aware, the way forward is to work with Paolo to implement
> a proper venv solution for the build tree that will help mitigate the
> fallout from (2) by automating the use of a pip-provided Sphinx in the
> cases where the distro-provided version is insufficient.

So, your current plan is to rebase this series less its DO-NOT-MERGE
parts, on top of Paolo's.  Correct?

> OK, seeya later!




Re: [PATCH v3 5/6] meson: prefer 'sphinx-build' to 'sphinx-build-3'

2023-02-20 Thread Markus Armbruster
John Snow  writes:

> Once upon a time, "sphinx-build" on certain RPM platforms invoked
> specifically a Python 2.x version, while "sphinx-build-3" was a distro
> shim for the Python 3.x version.
>
> These days, none of our supported platforms utilize a 2.x version, so it
> should be safe to search for 'sphinx-build' prior to 'sphinx-build-3',
> which will prefer pip/venv installed versions of sphinx if they're
> available.
>
> This adds an extremely convenient ability to test document building
> ability in QEMU across multiple versions of Sphinx for the purposes of
> compatibility testing.
>
> Signed-off-by: John Snow 
> ---
>  docs/meson.build | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/docs/meson.build b/docs/meson.build
> index 9136fed3b73..906034f9a87 100644
> --- a/docs/meson.build
> +++ b/docs/meson.build
> @@ -1,5 +1,5 @@
>  if get_option('sphinx_build') == ''
> -  sphinx_build = find_program(['sphinx-build-3', 'sphinx-build'],
> +  sphinx_build = find_program(['sphinx-build', 'sphinx-build-3'],
>required: get_option('docs'))
>  else
>sphinx_build = find_program(get_option('sphinx_build'),

Do we still need to check for sphinx-build-3?  Or asked differently, is
there any supported build host that provides only sphinx-build-3?




Re: [PATCH v4 0/6] qapi: static typing conversion, pt5c

2023-02-20 Thread Markus Armbruster
John Snow  writes:

> On Wed, Feb 15, 2023 at 8:39 AM Markus Armbruster  wrote:
>>
>> I had a few suggestions, but none of them requires a respin.  Let's
>> discuss them, and then I merge.
>
> Hiya, I lost track of things a little due to the other Python
> discussion. Who is waiting for whom?

Just two questions remain:

* PATCH 3: Dumb down check_keys() argument all the way to List[str]?

* PATCH 4: Suggested commit message addition okay?

We settle them, and then I'll take it from there.




Re: online blockdev-backup, a clarification (was: Summary on new backup interfaces in QEMU)

2023-02-20 Thread Vladimir Sementsov-Ogievskiy

On 20.02.23 18:18, John Maline wrote:

As a qemu newcomer I had a related question and confusion from reading existing 
docs. Searching qemu-block, this seemed related to my question so I’ll ask…



On Mar 15, 2022, at 12:57 PM, Vladimir Sementsov-Ogievskiy 
 wrote:

Hi all!

Here I want to summarize new interfaces and use cases for backup in QEMU.

TODO for me: convert this into good rst documentation in docs/.


The existing docs I found at 
https://qemu.readthedocs.io/en/latest/interop/live-block-operations.html#live-disk-backup-blockdev-backup-and-the-deprecated-drive-backup
 are confusing me. This, if I’m understanding, seem clearer.




OK, let's begin.

First, note that drive-backup qmp command is deprecated.

Next, some terminology:

push backup: the whole process is inside QEMU process, also may be called "internal 
backup"

pull backup: QEMU only exports a kind of snapshot (for example by NBD), and third party 
software reads this export and stores it somehow, also called "external backup"

copy-before-write operations: We usually do backup of active disk, guest is 
running and may write to the disk during the process of backup. When guest 
wants to rewrite data region which is not backed up yet, we must stop this 
guest write, and copy original data to somewhere before continuing guest write. 
That's a copy-before-write operation.

image-fleecing: the technique that allows to export a "snapshotted" state of the active disk with help of 
copy-before-write operations. We create a temporary image - target for copy-before-write operations, and provide an 
interface to the user to read the "snapshotted" state. And for read, we do read from temporary image the data 
which is already changed in original active disk, and we read unchanged data directly from active disk. The temporary 
image itself is also called "reverse delta" or "reversed delta".



== Simple push backup ==

Just use blockdev-backup, nothing new here. I just note some technical details, 
that are relatively new:

1. First, backup job inserts copy-before-write filter above source disk, to do 
copy-before-write operation.
2. Created copy-before-write filter shares internal block-copy state with 
backup job, so they work in collaboration, to not copy same things twice.


The simple case I’m aiming for matches a push backup. I’m OK w/ a snapshot.

Environment - macos 12.6 on arm processor, guest is aarch64 centos linux using 
hvf accelerator. Qemu 7.2.

I assume what you describe w/ copy-before-write is behavior in qemu 7.2. I’m 
fine if the Linux client needs to do a bit of log replay if I revert to a 
backup.

In the docs I link above it talks as if a VM shutdown is recommended after the 
job completes. Seems to ruin the whole point of an online backup. I tried 
instead finishing w/ a blockdev-del and I see the backup file closed by qemu. 
I’m guessing that’s an appropriate way to flush/complete the backup. In an 
experiment, it seemed the generated backup worked as expected.


Yes, shutdown is unrelated. Also, block-jobs do flush target on finish, so it's 
really synced after block-job completion event. Still, blockdev-del(target) is 
right thing to do.



I’m hoping for confirmation or correction on my approach.

Specifically I’m doing the following QMP commands.

{"execute": "qmp_capabilities"}

{"execute":"blockdev-add",
  "arguments":{"node-name":"backup-node", "driver":"qcow2", "file":{"driver":"file", 
"filename":"backups/backup1.img"}}
}

{"execute":"blockdev-backup",
  "arguments":{"device":"drive0", "job-id":"job0", "target":"backup-node", 
"sync":"full"}
}

... watch many job state change events ...


The last one should be BLOCK_JOB_COMPLETED, you wait for it, and check "error" 
field - if it exist the job is failed.

You also can poll with query-block-jobs command.



{"execute":"blockdev-del",
  "arguments": {"node-name":"backup-node"}
}



Yes your approach is correct. Note that ideally, you also should do fs-freeze / 
fs-thaw in guest around blockdev-backup command call, to be sure that the 
moment in time when we start the backup (the final target image will correspond 
to this moment in time) is consistent and we'll be able to boot from the backup 
image later.

--
Best regards,
Vladimir




[PATCH] hw/riscv: Skip re-generating DT nodes for a given DTB

2023-02-20 Thread Bin Meng
Lanuch qemu-system-riscv64 with a given dtb for 'sifive_u' and 'virt'
machines, QEMU complains:

  qemu_fdt_add_subnode: Failed to create subnode /soc: FDT_ERR_EXISTS

The whole DT generation logic should be skipped when a given DTB is
present.

Fixes: b1f19f238cae ("hw/riscv: write bootargs 'chosen' FDT after 
riscv_load_kernel()")
Signed-off-by: Bin Meng 
---

 hw/riscv/sifive_u.c | 1 +
 hw/riscv/virt.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index ad3bb35b34..76db5ed3dd 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -118,6 +118,7 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 error_report("load_device_tree() failed");
 exit(1);
 }
+return;
 } else {
 fdt = ms->fdt = create_device_tree(&fdt_size);
 if (!fdt) {
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 86c4adc0c9..0c7b4a1e46 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1014,6 +1014,7 @@ static void create_fdt(RISCVVirtState *s, const 
MemMapEntry *memmap)
 error_report("load_device_tree() failed");
 exit(1);
 }
+return;
 } else {
 ms->fdt = create_device_tree(&s->fdt_size);
 if (!ms->fdt) {
-- 
2.25.1




Re: [PATCH v2 05/13] vdpa: rewind at get_base, not set_base

2023-02-20 Thread Jason Wang



在 2023/2/8 17:42, Eugenio Pérez 写道:

At this moment it is only possible to migrate to a vdpa device running
with x-svq=on. As a protective measure, the rewind of the inflight
descriptors was done at the destination. That way if the source sent a
virtqueue with inuse descriptors they are always discarded.

Since this series allows to migrate also to passthrough devices with no
SVQ, the right thing to do is to rewind at the source so the base of
vrings are correct.

Support for inflight descriptors may be added in the future.

Signed-off-by: Eugenio Pérez 



Acked-by: Jason Wang 

Thanks



---
  hw/virtio/vhost-vdpa.c | 24 +---
  1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 26e38a6aab..d99db0bd03 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1211,18 +1211,7 @@ static int vhost_vdpa_set_vring_base(struct vhost_dev 
*dev,
 struct vhost_vring_state *ring)
  {
  struct vhost_vdpa *v = dev->opaque;
-VirtQueue *vq = virtio_get_queue(dev->vdev, ring->index);
  
-/*

- * vhost-vdpa devices does not support in-flight requests. Set all of them
- * as available.
- *
- * TODO: This is ok for networking, but other kinds of devices might
- * have problems with these retransmissions.
- */
-while (virtqueue_rewind(vq, 1)) {
-continue;
-}
  if (v->shadow_vqs_enabled) {
  /*
   * Device vring base was set at device start. SVQ base is handled by
@@ -1241,6 +1230,19 @@ static int vhost_vdpa_get_vring_base(struct vhost_dev 
*dev,
  int ret;
  
  if (v->shadow_vqs_enabled) {

+VirtQueue *vq = virtio_get_queue(dev->vdev, ring->index);
+
+/*
+ * vhost-vdpa devices does not support in-flight requests. Set all of
+ * them as available.
+ *
+ * TODO: This is ok for networking, but other kinds of devices might
+ * have problems with these retransmissions.
+ */
+while (virtqueue_rewind(vq, 1)) {
+continue;
+}
+
  ring->num = virtio_queue_get_last_avail_idx(dev->vdev, ring->index);
  return 0;
  }





Re: [PATCH v2 04/13] vdpa: move vhost reset after get vring base

2023-02-20 Thread Jason Wang



在 2023/2/8 17:42, Eugenio Pérez 写道:

The function vhost.c:vhost_dev_stop calls vhost operation
vhost_dev_start(false). In the case of vdpa it totally reset and wipes
the device, making the fetching of the vring base (virtqueue state) totally
useless.

The kernel backend does not use vhost_dev_start vhost op callback, but
vhost-user do. A patch to make vhost_user_dev_start more similar to vdpa
is desirable, but it can be added on top.

Signed-off-by: Eugenio Pérez 
---
  include/hw/virtio/vhost-backend.h |  4 
  hw/virtio/vhost-vdpa.c| 22 --
  hw/virtio/vhost.c |  3 +++
  3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/include/hw/virtio/vhost-backend.h 
b/include/hw/virtio/vhost-backend.h
index c5ab49051e..ec3fbae58d 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -130,6 +130,9 @@ typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev);
  
  typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev,

 int fd);
+
+typedef void (*vhost_reset_status_op)(struct vhost_dev *dev);
+
  typedef struct VhostOps {
  VhostBackendType backend_type;
  vhost_backend_init vhost_backend_init;
@@ -177,6 +180,7 @@ typedef struct VhostOps {
  vhost_get_device_id_op vhost_get_device_id;
  vhost_force_iommu_op vhost_force_iommu;
  vhost_set_config_call_op vhost_set_config_call;
+vhost_reset_status_op vhost_reset_status;
  } VhostOps;
  
  int vhost_backend_update_device_iotlb(struct vhost_dev *dev,

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index cbbe92ffe8..26e38a6aab 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1152,14 +1152,23 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, 
bool started)
  if (started) {
  memory_listener_register(&v->listener, &address_space_memory);
  return vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
-} else {
-vhost_vdpa_reset_device(dev);
-vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
-   VIRTIO_CONFIG_S_DRIVER);
-memory_listener_unregister(&v->listener);
+}
  
-return 0;

+return 0;
+}
+
+static void vhost_vdpa_reset_status(struct vhost_dev *dev)
+{
+struct vhost_vdpa *v = dev->opaque;
+
+if (dev->vq_index + dev->nvqs != dev->vq_index_end) {
+return;
  }
+
+vhost_vdpa_reset_device(dev);
+vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+VIRTIO_CONFIG_S_DRIVER);
+memory_listener_unregister(&v->listener);
  }
  
  static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base,

@@ -1346,4 +1355,5 @@ const VhostOps vdpa_ops = {
  .vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
  .vhost_force_iommu = vhost_vdpa_force_iommu,
  .vhost_set_config_call = vhost_vdpa_set_config_call,
+.vhost_reset_status = vhost_vdpa_reset_status,
  };
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index eb8c4c378c..a266396576 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -2049,6 +2049,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice 
*vdev, bool vrings)
   hdev->vqs + i,
   hdev->vq_index + i);
  }
+if (hdev->vhost_ops->vhost_reset_status) {
+hdev->vhost_ops->vhost_reset_status(hdev);
+}



This looks racy, if we don't suspend/reset the device, device can move 
last_avail_idx even after get_vring_base()?


Instead of doing things like this, should we fallback to 
virtio_queue_restore_last_avail_idx() in this case?


Thanks


  
  if (vhost_dev_has_iommu(hdev)) {

  if (hdev->vhost_ops->vhost_set_iotlb_callback) {





Re: [PATCH v2 03/13] vdpa: add vhost_vdpa_suspend

2023-02-20 Thread Jason Wang



在 2023/2/21 13:27, Jason Wang 写道:


在 2023/2/8 17:42, Eugenio Pérez 写道:

The function vhost.c:vhost_dev_stop fetches the vring base so the vq
state can be migrated to other devices.  However, this is unreliable in
vdpa, since we didn't signal the device to suspend the queues, making
the value fetched useless.

Suspend the device if possible before fetching first and subsequent
vring bases.

Moreover, vdpa totally reset and wipes the device at the last device
before fetch its vrings base, making that operation useless in the last
device. This will be fixed in later patches of this series.



It would be better not introduce a bug first and fix it in the 
following patch.





Signed-off-by: Eugenio Pérez 
---
  hw/virtio/vhost-vdpa.c | 19 +++
  hw/virtio/trace-events |  1 +
  2 files changed, 20 insertions(+)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 2e79fbe4b2..cbbe92ffe8 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1108,6 +1108,24 @@ static void vhost_vdpa_svqs_stop(struct 
vhost_dev *dev)

  }
  }
  +static void vhost_vdpa_suspend(struct vhost_dev *dev)
+{
+    struct vhost_vdpa *v = dev->opaque;
+    int r;
+
+    if (!vhost_vdpa_first_dev(dev) ||



Any reason we need to use vhost_vdpa_first_dev() instead of replacing the

if (started) {
} else {
    vhost_vdpa_reset_device(dev);
    
}



Ok, I think I kind of understand, so I think we need re-order the 
patches, at least patch 4 should come before this patch?


Thanks





We check

if (dev->vq_index + dev->nvqs != dev->vq_index_end) in 
vhost_vdpa_dev_start() but vhost_vdpa_first_dev() inside 
vhost_vdpa_suspend(). This will result code that is hard to maintain.


Thanks



+    !(dev->backend_cap & BIT_ULL(VHOST_BACKEND_F_SUSPEND))) {
+    return;
+    }
+
+    trace_vhost_vdpa_suspend(dev);
+    r = ioctl(v->device_fd, VHOST_VDPA_SUSPEND);
+    if (unlikely(r)) {
+    error_report("Cannot suspend: %s(%d)", g_strerror(errno), 
errno);

+    /* Not aborting since we're called from stop context */
+    }
+}
+
  static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
  {
  struct vhost_vdpa *v = dev->opaque;
@@ -1122,6 +1140,7 @@ static int vhost_vdpa_dev_start(struct 
vhost_dev *dev, bool started)

  }
  vhost_vdpa_set_vring_ready(dev);
  } else {
+    vhost_vdpa_suspend(dev);
  vhost_vdpa_svqs_stop(dev);
  vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
  }
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index a87c5f39a2..8f8d05cf9b 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -50,6 +50,7 @@ vhost_vdpa_set_vring_ready(void *dev) "dev: %p"
  vhost_vdpa_dump_config(void *dev, const char *line) "dev: %p %s"
  vhost_vdpa_set_config(void *dev, uint32_t offset, uint32_t size, 
uint32_t flags) "dev: %p offset: %"PRIu32" size: %"PRIu32" flags: 
0x%"PRIx32
  vhost_vdpa_get_config(void *dev, void *config, uint32_t config_len) 
"dev: %p config: %p config_len: %"PRIu32

+vhost_vdpa_suspend(void *dev) "dev: %p"
  vhost_vdpa_dev_start(void *dev, bool started) "dev: %p started: %d"
  vhost_vdpa_set_log_base(void *dev, uint64_t base, unsigned long 
long size, int refcnt, int fd, void *log) "dev: %p base: 0x%"PRIx64" 
size: %llu refcnt: %d fd: %d log: %p"
  vhost_vdpa_set_vring_addr(void *dev, unsigned int index, unsigned 
int flags, uint64_t desc_user_addr, uint64_t used_user_addr, uint64_t 
avail_user_addr, uint64_t log_guest_addr) "dev: %p index: %u flags: 
0x%x desc_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64" 
avail_user_addr: 0x%"PRIx64" log_guest_addr: 0x%"PRIx64





Re: [PATCH v2 03/13] vdpa: add vhost_vdpa_suspend

2023-02-20 Thread Jason Wang



在 2023/2/8 17:42, Eugenio Pérez 写道:

The function vhost.c:vhost_dev_stop fetches the vring base so the vq
state can be migrated to other devices.  However, this is unreliable in
vdpa, since we didn't signal the device to suspend the queues, making
the value fetched useless.

Suspend the device if possible before fetching first and subsequent
vring bases.

Moreover, vdpa totally reset and wipes the device at the last device
before fetch its vrings base, making that operation useless in the last
device. This will be fixed in later patches of this series.



It would be better not introduce a bug first and fix it in the following 
patch.





Signed-off-by: Eugenio Pérez 
---
  hw/virtio/vhost-vdpa.c | 19 +++
  hw/virtio/trace-events |  1 +
  2 files changed, 20 insertions(+)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 2e79fbe4b2..cbbe92ffe8 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1108,6 +1108,24 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev)
  }
  }
  
+static void vhost_vdpa_suspend(struct vhost_dev *dev)

+{
+struct vhost_vdpa *v = dev->opaque;
+int r;
+
+if (!vhost_vdpa_first_dev(dev) ||



Any reason we need to use vhost_vdpa_first_dev() instead of replacing the

if (started) {
} else {
    vhost_vdpa_reset_device(dev);
    
}


We check

if (dev->vq_index + dev->nvqs != dev->vq_index_end) in 
vhost_vdpa_dev_start() but vhost_vdpa_first_dev() inside 
vhost_vdpa_suspend(). This will result code that is hard to maintain.


Thanks



+!(dev->backend_cap & BIT_ULL(VHOST_BACKEND_F_SUSPEND))) {
+return;
+}
+
+trace_vhost_vdpa_suspend(dev);
+r = ioctl(v->device_fd, VHOST_VDPA_SUSPEND);
+if (unlikely(r)) {
+error_report("Cannot suspend: %s(%d)", g_strerror(errno), errno);
+/* Not aborting since we're called from stop context */
+}
+}
+
  static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
  {
  struct vhost_vdpa *v = dev->opaque;
@@ -1122,6 +1140,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, 
bool started)
  }
  vhost_vdpa_set_vring_ready(dev);
  } else {
+vhost_vdpa_suspend(dev);
  vhost_vdpa_svqs_stop(dev);
  vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
  }
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index a87c5f39a2..8f8d05cf9b 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -50,6 +50,7 @@ vhost_vdpa_set_vring_ready(void *dev) "dev: %p"
  vhost_vdpa_dump_config(void *dev, const char *line) "dev: %p %s"
  vhost_vdpa_set_config(void *dev, uint32_t offset, uint32_t size, uint32_t flags) "dev: %p offset: 
%"PRIu32" size: %"PRIu32" flags: 0x%"PRIx32
  vhost_vdpa_get_config(void *dev, void *config, uint32_t config_len) "dev: %p 
config: %p config_len: %"PRIu32
+vhost_vdpa_suspend(void *dev) "dev: %p"
  vhost_vdpa_dev_start(void *dev, bool started) "dev: %p started: %d"
  vhost_vdpa_set_log_base(void *dev, uint64_t base, unsigned long long size, int refcnt, int fd, 
void *log) "dev: %p base: 0x%"PRIx64" size: %llu refcnt: %d fd: %d log: %p"
  vhost_vdpa_set_vring_addr(void *dev, unsigned int index, unsigned int flags, uint64_t desc_user_addr, uint64_t 
used_user_addr, uint64_t avail_user_addr, uint64_t log_guest_addr) "dev: %p index: %u flags: 0x%x desc_user_addr: 
0x%"PRIx64" used_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" log_guest_addr: 
0x%"PRIx64





Re: [PATCH v3 6/8] target/i386/intel-pt: Enable host pass through of Intel PT

2023-02-20 Thread Wang, Lei


On 12/8/2022 2:25 PM, Xiaoyao Li wrote:
> commit e37a5c7fa459 ("i386: Add Intel Processor Trace feature support")
> added the support of Intel PT by making CPUID[14] of PT as fixed feature
> set (from ICX) for any CPU model on any host. This truly breaks the PT
> exposure on Intel SPR platform because SPR has less supported bitmap of
> CPUID(0x14,1):EBX[15:0] than ICX.
> 
> To fix the problem, enable pass through of host's PT capabilities for
> the cases "-cpu host/max" that it won't use default fixed PT feature set
> of ICX but expand automatically based on get_supported_cpuid reported by
> host. Meanwhile, it needs to ensure named CPU model still has the fixed
> PT feature set to not break the live migration case of
> "-cpu named_cpu_model,+intel-pt"
> 
> Introduces env->use_default_intel_pt flag.
>  - True means it's old CPU model that uses fixed PT feature set of ICX.
>  - False means the named CPU model has its own PT feature set.
> 
> Besides, to keep the same behavior for old CPU models that validate PT
> feature set against default fixed PT feature set of ICX in addition to
> validate from host's capabilities (via get_supported_cpuid) in
> x86_cpu_filter_features().
> 
> In the future, new named CPU model, e.g., Sapphire Rapids, can define
> its own PT feature set by setting @has_specific_intel_pt_feature_set to
> true and defines it's own FEAT_14_0_EBX, FEAT_14_0_ECX, FEAT_14_1_EAX
> and FEAT_14_1_EBX.
> 
> Signed-off-by: Xiaoyao Li 
> ---
>  target/i386/cpu.c | 71 ++-
>  target/i386/cpu.h |  1 +
>  2 files changed, 40 insertions(+), 32 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index e302cbbebfc5..24f3c7b06698 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -5194,6 +5194,21 @@ static void x86_cpu_load_model(X86CPU *cpu, 
> X86CPUModel *model)
>  env->features[w] = def->features[w];
>  }
>  
> +/*
> + * All (old) named CPU models have the same default values for INTEL_PT_*
> + *
> + * Assign the default value here since we don't want to manually 
> copy/paste
> + * it to all entries in builtin_x86_defs.
> + */
> +if (!env->features[FEAT_14_0_EBX] && !env->features[FEAT_14_0_ECX] &&
> +!env->features[FEAT_14_1_EAX] && !env->features[FEAT_14_1_EBX]) {
> +env->use_default_intel_pt = true;
> +env->features[FEAT_14_0_EBX] = INTEL_PT_DEFAULT_0_EBX;
> +env->features[FEAT_14_0_ECX] = INTEL_PT_DEFAULT_0_ECX;
> +env->features[FEAT_14_1_EAX] = INTEL_PT_DEFAULT_1_EAX;
> +env->features[FEAT_14_1_EBX] = INTEL_PT_DEFAULT_1_EBX;
> +}
> +
>  /* legacy-cache defaults to 'off' if CPU model provides cache info */
>  cpu->legacy_cache = !def->cache_info;
>  
> @@ -5716,14 +5731,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
> uint32_t count,
>  
>  if (count == 0) {
>  *eax = INTEL_PT_MAX_SUBLEAF;
> -*ebx = INTEL_PT_DEFAULT_0_EBX;
> -*ecx = INTEL_PT_DEFAULT_0_ECX;
> -if (env->features[FEAT_14_0_ECX] & CPUID_14_0_ECX_LIP) {
> -*ecx |= CPUID_14_0_ECX_LIP;
> -}
> +*ebx = env->features[FEAT_14_0_EBX];
> +*ecx = env->features[FEAT_14_0_ECX];
>  } else if (count == 1) {
> -*eax = INTEL_PT_DEFAULT_1_EAX;
> -*ebx = INTEL_PT_DEFAULT_1_EBX;
> +*eax = env->features[FEAT_14_1_EAX];
> +*ebx = env->features[FEAT_14_1_EBX];
>  }
>  break;
>  }
> @@ -6425,6 +6437,7 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool 
> verbose)
>  CPUX86State *env = &cpu->env;
>  FeatureWord w;
>  const char *prefix = NULL;
> +uint64_t host_feat;
>  
>  if (verbose) {
>  prefix = accel_uses_host_cpuid()
> @@ -6433,8 +6446,7 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool 
> verbose)
>  }
>  
>  for (w = 0; w < FEATURE_WORDS; w++) {
> -uint64_t host_feat =
> -x86_cpu_get_supported_feature_word(w, false);
> +host_feat = x86_cpu_get_supported_feature_word(w, false);
>  uint64_t requested_features = env->features[w];
>  uint64_t unavailable_features;
>  
> @@ -6458,31 +6470,26 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool 
> verbose)
>  mark_unavailable_features(cpu, w, unavailable_features, prefix);
>  }
>  
> -if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) &&
> -kvm_enabled()) {
> -KVMState *s = CPU(cpu)->kvm_state;
> -uint32_t eax_0 = kvm_arch_get_supported_cpuid(s, 0x14, 0, R_EAX);
> -uint32_t ebx_0 = kvm_arch_get_supported_cpuid(s, 0x14, 0, R_EBX);
> -uint32_t ecx_0 = kvm_arch_get_supported_cpuid(s, 0x14, 0, R_ECX);
> -uint32_t eax_1 = kvm_arch_get_supported_cpuid(s, 0x14, 1, R_EAX);
> -uint32_t ebx_1 = kvm_arch_get_supported_cpuid(s, 0x14, 1, R_EBX);
> -
> -if (!eax_0 ||
> - 

[PATCH 2/2] target/arm: Fix arm_cpu_get_phys_page_attrs_debug for m-profile

2023-02-20 Thread Richard Henderson
M-profile is not supported by arm_is_secure, so using it as
a replacement when bypassing get_phys_addr was incorrect.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1421
Fixes: 4a35855682ce ("target/arm: Plumb debug into S1Translate")
Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index cb073ac477..057cc9f641 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -2974,9 +2974,10 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, 
vaddr addr,
 {
 ARMCPU *cpu = ARM_CPU(cs);
 CPUARMState *env = &cpu->env;
+ARMMMUIdx mmu_idx = arm_mmu_idx(env);
 S1Translate ptw = {
-.in_mmu_idx = arm_mmu_idx(env),
-.in_secure = arm_is_secure(env),
+.in_mmu_idx = mmu_idx,
+.in_secure = regime_is_secure(env, mmu_idx),
 .in_debug = true,
 };
 GetPhysAddrResult res = {};
-- 
2.34.1




[PATCH 1/2] Revert "target/arm: Merge regime_is_secure into get_phys_addr"

2023-02-20 Thread Richard Henderson
This reverts commit 03bea66e7fa3af42976ceafb20512c59abf2e699,
but restore into ptw.c instead of internals.h.

Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 2b125fff44..cb073ac477 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -2926,12 +2926,9 @@ bool get_phys_addr_with_secure(CPUARMState *env, 
target_ulong address,
  result, fi);
 }
 
-bool get_phys_addr(CPUARMState *env, target_ulong address,
-   MMUAccessType access_type, ARMMMUIdx mmu_idx,
-   GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
+/* Return true if this address translation regime is secure */
+static bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
-bool is_secure;
-
 switch (mmu_idx) {
 case ARMMMUIdx_E10_0:
 case ARMMMUIdx_E10_1:
@@ -2943,16 +2940,14 @@ bool get_phys_addr(CPUARMState *env, target_ulong 
address,
 case ARMMMUIdx_Stage1_E1:
 case ARMMMUIdx_Stage1_E1_PAN:
 case ARMMMUIdx_E2:
-is_secure = arm_is_secure_below_el3(env);
-break;
+return arm_is_secure_below_el3(env);
 case ARMMMUIdx_Stage2:
 case ARMMMUIdx_Phys_NS:
 case ARMMMUIdx_MPrivNegPri:
 case ARMMMUIdx_MUserNegPri:
 case ARMMMUIdx_MPriv:
 case ARMMMUIdx_MUser:
-is_secure = false;
-break;
+return false;
 case ARMMMUIdx_E3:
 case ARMMMUIdx_Stage2_S:
 case ARMMMUIdx_Phys_S:
@@ -2960,13 +2955,18 @@ bool get_phys_addr(CPUARMState *env, target_ulong 
address,
 case ARMMMUIdx_MSUserNegPri:
 case ARMMMUIdx_MSPriv:
 case ARMMMUIdx_MSUser:
-is_secure = true;
-break;
-default:
-g_assert_not_reached();
+return true;
 }
+g_assert_not_reached();
+}
+
+bool get_phys_addr(CPUARMState *env, target_ulong address,
+   MMUAccessType access_type, ARMMMUIdx mmu_idx,
+   GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
+{
 return get_phys_addr_with_secure(env, address, access_type, mmu_idx,
- is_secure, result, fi);
+ regime_is_secure(env, mmu_idx),
+ result, fi);
 }
 
 hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
-- 
2.34.1




[PATCH 0/2] target/arm: Fix gdbstub for m-profile (#1421)

2023-02-20 Thread Richard Henderson
This will conflict with FEAT_RME patches; I'll fix that up later.


r~


Richard Henderson (2):
  Revert "target/arm: Merge regime_is_secure into get_phys_addr"
  target/arm: Fix arm_cpu_get_phys_page_attrs_debug for m-profile

 target/arm/ptw.c | 33 +
 1 file changed, 17 insertions(+), 16 deletions(-)

-- 
2.34.1




Re: [PATCH v5 21/29] hw/net/net_tx_pkt: Automatically determine if virtio-net header is used

2023-02-20 Thread Jason Wang



在 2023/2/1 11:35, Akihiko Odaki 写道:

The new function qemu_get_using_vnet_hdr() allows to automatically
determine if virtio-net header is used.

Signed-off-by: Akihiko Odaki 
---
  hw/net/e1000e_core.c |  3 +--
  hw/net/net_tx_pkt.c  | 19 ++-
  hw/net/net_tx_pkt.h  |  3 +--
  hw/net/vmxnet3.c |  6 ++
  4 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 38d374fba3..954a007151 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -3376,8 +3376,7 @@ e1000e_core_pci_realize(E1000ECore *core,
  qemu_add_vm_change_state_handler(e1000e_vm_state_change, core);
  
  for (i = 0; i < E1000E_NUM_QUEUES; i++) {

-net_tx_pkt_init(&core->tx[i].tx_pkt, core->owner,
-E1000E_MAX_TX_FRAGS, core->has_vnet);
+net_tx_pkt_init(&core->tx[i].tx_pkt, core->owner, E1000E_MAX_TX_FRAGS);
  }
  
  net_rx_pkt_init(&core->rx_pkt, core->has_vnet);

diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index 8a23899a4d..cf46c8457f 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -35,7 +35,6 @@ struct NetTxPkt {
  PCIDevice *pci_dev;
  
  struct virtio_net_hdr virt_hdr;

-bool has_virt_hdr;



So this requires implicit coupling of NetTxPkt and a NetClientState (not 
self contained). This may work now but probably not the future e.g when 
two packets were queued in a list when one packet has a vnet header but 
another doesn't?


Thanks


  
  struct iovec *raw;

  uint32_t raw_frags;
@@ -59,7 +58,7 @@ struct NetTxPkt {
  };
  
  void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev,

-uint32_t max_frags, bool has_virt_hdr)
+uint32_t max_frags)
  {
  struct NetTxPkt *p = g_malloc0(sizeof *p);
  
@@ -71,10 +70,8 @@ void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev,
  
  p->max_payload_frags = max_frags;

  p->max_raw_frags = max_frags;
-p->has_virt_hdr = has_virt_hdr;
  p->vec[NET_TX_PKT_VHDR_FRAG].iov_base = &p->virt_hdr;
-p->vec[NET_TX_PKT_VHDR_FRAG].iov_len =
-p->has_virt_hdr ? sizeof p->virt_hdr : 0;
+p->vec[NET_TX_PKT_VHDR_FRAG].iov_len = sizeof p->virt_hdr;
  p->vec[NET_TX_PKT_L2HDR_FRAG].iov_base = &p->l2_hdr;
  p->vec[NET_TX_PKT_L3HDR_FRAG].iov_base = &p->l3_hdr;
  
@@ -617,9 +614,11 @@ static bool net_tx_pkt_do_sw_fragmentation(struct NetTxPkt *pkt,
  
  bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState *nc)

  {
+bool using_vnet_hdr = qemu_get_using_vnet_hdr(nc->peer);
+
  assert(pkt);
  
-if (!pkt->has_virt_hdr &&

+if (!using_vnet_hdr &&
  pkt->virt_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
  net_tx_pkt_do_sw_csum(pkt);
  }
@@ -636,11 +635,13 @@ bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState 
*nc)
  }
  }
  
-if (pkt->has_virt_hdr ||

+if (using_vnet_hdr ||
  pkt->virt_hdr.gso_type == VIRTIO_NET_HDR_GSO_NONE) {
+int index = using_vnet_hdr ?
+NET_TX_PKT_VHDR_FRAG : NET_TX_PKT_L2HDR_FRAG;
  net_tx_pkt_fix_ip6_payload_len(pkt);
-net_tx_pkt_sendv(pkt, nc, pkt->vec,
-pkt->payload_frags + NET_TX_PKT_PL_START_FRAG);
+net_tx_pkt_sendv(pkt, nc, pkt->vec + index,
+pkt->payload_frags + NET_TX_PKT_PL_START_FRAG - index);
  return true;
  }
  
diff --git a/hw/net/net_tx_pkt.h b/hw/net/net_tx_pkt.h

index 2e38a5fa69..8d3faa42fb 100644
--- a/hw/net/net_tx_pkt.h
+++ b/hw/net/net_tx_pkt.h
@@ -32,10 +32,9 @@ struct NetTxPkt;
   * @pkt:packet pointer
   * @pci_dev:PCI device processing this packet
   * @max_frags:  max tx ip fragments
- * @has_virt_hdr:   device uses virtio header.
   */
  void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev,
-uint32_t max_frags, bool has_virt_hdr);
+uint32_t max_frags);
  
  /**

   * Clean all tx packet resources.
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index c63bbb59bd..8c3f5d6e14 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -1521,8 +1521,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
  
  /* Preallocate TX packet wrapper */

  VMW_CFPRN("Max TX fragments is %u", s->max_tx_frags);
-net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s),
-s->max_tx_frags, s->peer_has_vhdr);
+net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s), s->max_tx_frags);
  net_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
  
  /* Read rings memory locations for RX queues */

@@ -2402,8 +2401,7 @@ static int vmxnet3_post_load(void *opaque, int version_id)
  {
  VMXNET3State *s = opaque;
  
-net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s),

-s->max_tx_frags, s->peer_has_vhdr);
+net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s), s->max_tx_frags);
  net_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
  
  if (s->msix_used) {





Re: [RFC v5 0/3] migration: reduce time of loading non-iterable vmstate

2023-02-20 Thread Chuang Xu

Hi, Peter

It seems that there is a problem with the code format in my last email.
I adjusted the format and resend this to you. Hope the format of this
email won't be wrong again..  :)

On 2023/2/17 下午11:52, Peter Xu wrote:

Hello, Chuang,

On Fri, Feb 17, 2023 at 04:11:19PM +0800, Chuang Xu wrote:

Error 1 was triggered by our sanity check. I try to add RCU_READ_LOCK_GUARD()
in address_space_init() and it works. But I'm not sure if this code change is
appropriate. If this change is not appropriate, we may need to consider other
sanity check.

I'd suggest not adding RCU locks without a good reason.

address_space_init() is definitely a special context because the AS is
exclusively owned by the caller before it returns.  It means no RCU
protection needed at all because no one else is touching it; neither do we
need qatomic_rcu_read() when read.

So I suggest we directly reference current_map, even though that'll need a
rich comment:

  static void address_space_set_flatview(AddressSpace *as)
  {
-FlatView *old_view = address_space_to_flatview(as);
+/*
+ * NOTE: we don't use RCU flavoured of address_space_to_flatview()
+ * because we exclusively own as->current_map here: it's either during
+ * init of an address space, or during commit() with BQL held.
+ */
+FlatView *old_view = as->current_map;

We can have address_space_to_flatview_raw() but since we'll directly modify
as->current_map very soon in the same function, so may not even bother.

I agree with you.

But now I am facing a new problem. Our sanity check is not as reliable 
as we think.


Although my current code can pass all the tests that Juan told me in the 
email.
But if I configure with nothing and run 'make check', My patch triggers 
error

in ahci migrate test:

G_TEST_DBUS_DAEMON=/data00/migration/qemu-open/tests/dbus-vmstate-daemon.sh
QTEST_QEMU_BINARY=./qemu-system-x86_64 QTEST_QEMU_IMG=./qemu-img
MALLOC_PERTURB_=1
QTEST_QEMU_STORAGE_DAEMON_BINARY=./storage-daemon/qemu-storage-daemon
/data00/migration/qemu-open/build/tests/qtest/ahci-test --tap -k
 


✀
 


stderr:
qemu-system-x86_64: AHCI: Failed to start FIS receive engine: bad FIS
receive buffer address
qemu-system-x86_64: Failed to load ich9_ahci:ahci
qemu-system-x86_64: error while loading state for instance 0x0 of device
':00:1f.2/ich9_ahci'
qemu-system-x86_64: load of migration failed: Operation not permitted
Migration did not complete, status: failed

It seems that ahci_state_post_load() will call memory_access_is_direct()
and access mr->ram. Due to mr transaction delay, this value doesn't meet
expectations. And Here is the call chain for you to read the code:
->ahci_state_post_load
->ahci_cond_start_engines
->ahci_map_fis_address
->map_page
->dma_memory_map
->address_space_map
->memory_access_is_direct


I think we need a memory_region_transaction_commit_force() to force commit
some transactions when load vmstate. This function is designed like this:

/*
 * memory_region_transaction_commit_force() is desgined to
 * force the mr transaction to be commited in the process
 * of loading vmstate.
 */
void memory_region_transaction_commit_force(void)
{
    AddressSpace *as;
    unsigned int memory_region_transaction_depth_copy = 
memory_region_transaction_depth;


    /*
 * Temporarily replace memory_region_transaction_depth with 0 to 
prevent
 * memory_region_transaction_commit_force() and 
address_space_to_flatview()

 * call each other recursively.
 */
    memory_region_transaction_depth = 0;

    assert(qemu_mutex_iothread_locked());


    if (memory_region_update_pending) {
    flatviews_reset();

    MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);

    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
    address_space_set_flatview(as);
    address_space_update_ioeventfds(as);
    }
    memory_region_update_pending = false;
    ioeventfd_update_pending = false;
    MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
    } else if (ioeventfd_update_pending) {
    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
    address_space_update_ioeventfds(as);
    }
    ioeventfd_update_pending = false;
    }

    /* recover memory_region_transaction_depth */
    memory_region_transaction_depth = 
memory_region_transaction_depth_copy;

}

Now there are two options to use this function:
1. call it in address_space_to_flatview():

static inline FlatView *address_space_to_flatview(AddressSpace *as)
{
    /*
 * Before using any flatview, check whether we're during a memory
 * region transaction. If so, force commit the memory region 
transaction.

 */
    if (memory_region_transaction_in_progress())
    memory_region_transaction_commit_force();
    return qatomic_rcu_read(&as->

[PATCH v2 10/14] target/arm: Create pauth_ptr_mask

2023-02-20 Thread Richard Henderson
Keep the logic for pauth within pauth_helper.c, and expose
a helper function for use with the gdbstub pac extension.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/internals.h| 10 ++
 target/arm/pauth_helper.c | 26 ++
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 32b8562cbf..370655061e 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1350,6 +1350,16 @@ int exception_target_el(CPUARMState *env);
 bool arm_singlestep_active(CPUARMState *env);
 bool arm_generate_debug_exceptions(CPUARMState *env);
 
+/**
+ * pauth_ptr_mask:
+ * @env: cpu context
+ * @ptr: selects between TTBR0 and TTBR1
+ * @data: selects between TBI and TBID
+ *
+ * Return a mask of the bits of @ptr that contain the authentication code.
+ */
+uint64_t pauth_ptr_mask(CPUARMState *env, uint64_t ptr, bool data);
+
 /* Add the cpreg definitions for debug related system registers */
 void define_debug_regs(ARMCPU *cpu);
 
diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c
index d0483bf051..20f347332d 100644
--- a/target/arm/pauth_helper.c
+++ b/target/arm/pauth_helper.c
@@ -339,14 +339,32 @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t 
ptr, uint64_t modifier,
 return pac | ext | ptr;
 }
 
-static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param)
+static uint64_t pauth_ptr_mask_internal(ARMVAParameters param)
 {
-/* Note that bit 55 is used whether or not the regime has 2 ranges. */
-uint64_t extfield = sextract64(ptr, 55, 1);
 int bot_pac_bit = 64 - param.tsz;
 int top_pac_bit = 64 - 8 * param.tbi;
 
-return deposit64(ptr, bot_pac_bit, top_pac_bit - bot_pac_bit, extfield);
+return MAKE_64BIT_MASK(bot_pac_bit, top_pac_bit - bot_pac_bit);
+}
+
+static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param)
+{
+uint64_t mask = pauth_ptr_mask_internal(param);
+
+/* Note that bit 55 is used whether or not the regime has 2 ranges. */
+if (extract64(ptr, 55, 1)) {
+return ptr | mask;
+} else {
+return ptr & ~mask;
+}
+}
+
+uint64_t pauth_ptr_mask(CPUARMState *env, uint64_t ptr, bool data)
+{
+ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
+ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data);
+
+return pauth_ptr_mask_internal(param);
 }
 
 static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
-- 
2.34.1




[PATCH v2 11/14] target/arm: Implement gdbstub pauth extension

2023-02-20 Thread Richard Henderson
The extension is primarily defined by the Linux kernel NT_ARM_PAC_MASK
ptrace register set.

The original gdb feature consists of two masks, data and code, which are
used to mask out the authentication code within a pointer.  Following
discussion with Luis Machado, add two more masks in order to support
pointers within the high half of the address space (i.e. TTBR1 vs TTBR0).

Cc: Luis Machado 
Cc: Thiago Jung Bauermann 
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1105
Signed-off-by: Richard Henderson 
---
 configs/targets/aarch64-linux-user.mak|  2 +-
 configs/targets/aarch64-softmmu.mak   |  2 +-
 configs/targets/aarch64_be-linux-user.mak |  2 +-
 target/arm/internals.h|  2 ++
 target/arm/gdbstub.c  |  5 
 target/arm/gdbstub64.c| 34 +++
 gdb-xml/aarch64-pauth.xml | 15 ++
 7 files changed, 59 insertions(+), 3 deletions(-)
 create mode 100644 gdb-xml/aarch64-pauth.xml

diff --git a/configs/targets/aarch64-linux-user.mak 
b/configs/targets/aarch64-linux-user.mak
index db552f1839..ba8bc5fe3f 100644
--- a/configs/targets/aarch64-linux-user.mak
+++ b/configs/targets/aarch64-linux-user.mak
@@ -1,6 +1,6 @@
 TARGET_ARCH=aarch64
 TARGET_BASE_ARCH=arm
-TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
+TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml 
gdb-xml/aarch64-pauth.xml
 TARGET_HAS_BFLT=y
 CONFIG_SEMIHOSTING=y
 CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
diff --git a/configs/targets/aarch64-softmmu.mak 
b/configs/targets/aarch64-softmmu.mak
index d489e6da83..b4338e9568 100644
--- a/configs/targets/aarch64-softmmu.mak
+++ b/configs/targets/aarch64-softmmu.mak
@@ -1,5 +1,5 @@
 TARGET_ARCH=aarch64
 TARGET_BASE_ARCH=arm
 TARGET_SUPPORTS_MTTCG=y
-TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml 
gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml 
gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml 
gdb-xml/arm-m-profile-mve.xml
+TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml 
gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml 
gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml 
gdb-xml/arm-m-profile-mve.xml gdb-xml/aarch64-pauth.xml
 TARGET_NEED_FDT=y
diff --git a/configs/targets/aarch64_be-linux-user.mak 
b/configs/targets/aarch64_be-linux-user.mak
index dc78044fb1..acb5620cdb 100644
--- a/configs/targets/aarch64_be-linux-user.mak
+++ b/configs/targets/aarch64_be-linux-user.mak
@@ -1,7 +1,7 @@
 TARGET_ARCH=aarch64
 TARGET_BASE_ARCH=arm
 TARGET_BIG_ENDIAN=y
-TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
+TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml 
gdb-xml/aarch64-pauth.xml
 TARGET_HAS_BFLT=y
 CONFIG_SEMIHOSTING=y
 CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 370655061e..fb88b16579 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1331,6 +1331,8 @@ int aarch64_gdb_get_sve_reg(CPUARMState *env, GByteArray 
*buf, int reg);
 int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, int reg);
 int aarch64_gdb_get_fpu_reg(CPUARMState *env, GByteArray *buf, int reg);
 int aarch64_gdb_set_fpu_reg(CPUARMState *env, uint8_t *buf, int reg);
+int aarch64_gdb_get_pauth_reg(CPUARMState *env, GByteArray *buf, int reg);
+int aarch64_gdb_set_pauth_reg(CPUARMState *env, uint8_t *buf, int reg);
 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index bf8aff7824..062c8d447a 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -355,6 +355,11 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
  aarch64_gdb_set_fpu_reg,
  34, "aarch64-fpu.xml", 0);
 }
+if (isar_feature_aa64_pauth(&cpu->isar)) {
+gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg,
+ aarch64_gdb_set_pauth_reg,
+ 4, "aarch64-pauth.xml", 0);
+}
 #endif
 } else {
 if (arm_feature(env, ARM_FEATURE_NEON)) {
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 3d9e9e97c8..3bee892fb7 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -210,6 +210,40 @@ int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t 
*buf, int reg)
 return 0;
 }
 
+int aarch64_gdb_get_pauth_reg(CPUARMState *env, GByteArray *buf, int reg)
+{
+switch (reg) {
+case 0: /* pauth_dmask */
+case 1: /* pauth_cmask */
+case 2: /* pauth_dmask_high */
+case 3: /* pauth_cmask_high */
+/*
+ * Note that older versions of this feature only contained
+ * pauth_{d,c}mask, for use with 

[PATCH v2 06/14] target/arm: Hoist pred_width in arm_gen_dynamic_svereg_xml

2023-02-20 Thread Richard Henderson
Reviewed-by: Fabiano Rosas 
Signed-off-by: Richard Henderson 
---
 target/arm/gdbstub64.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 070ba20d99..895e19f084 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -283,6 +283,7 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int 
orig_base_reg)
 GString *s = g_string_new(NULL);
 DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
 int reg_width = cpu->sve_max_vq * 128;
+int pred_width = cpu->sve_max_vq * 16;
 int base_reg = orig_base_reg;
 int i;
 
@@ -319,13 +320,13 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int 
orig_base_reg)
 g_string_append_printf(s,
"",
-   i, cpu->sve_max_vq * 16, base_reg++);
+   i, pred_width, base_reg++);
 }
 g_string_append_printf(s,
"",
-   cpu->sve_max_vq * 16, base_reg++);
+   pred_width, base_reg++);
 
 /* Define the vector length pseudo-register. */
 g_string_append_printf(s,
-- 
2.34.1




[PATCH v2 01/14] target/arm: Normalize aarch64 gdbstub get/set function names

2023-02-20 Thread Richard Henderson
Make the form of the function names between fp and sve the same:
  - arm_gdb_*_svereg -> aarch64_gdb_*_sve_reg.
  - aarch64_fpu_gdb_*_reg -> aarch64_gdb_*_fpu_reg.

Reviewed-by: Fabiano Rosas 
Signed-off-by: Richard Henderson 
---
 target/arm/internals.h | 8 
 target/arm/gdbstub.c   | 9 +
 target/arm/gdbstub64.c | 8 
 3 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 759b70c646..121ecd420b 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1326,10 +1326,10 @@ static inline uint64_t pmu_counter_mask(CPUARMState 
*env)
 }
 
 #ifdef TARGET_AARCH64
-int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg);
-int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg);
-int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg);
-int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg);
+int aarch64_gdb_get_sve_reg(CPUARMState *env, GByteArray *buf, int reg);
+int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, int reg);
+int aarch64_gdb_get_fpu_reg(CPUARMState *env, GByteArray *buf, int reg);
+int aarch64_gdb_set_fpu_reg(CPUARMState *env, uint8_t *buf, int reg);
 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 2f806512d0..cf1c01e3cf 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -466,12 +466,13 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
  */
 #ifdef TARGET_AARCH64
 if (isar_feature_aa64_sve(&cpu->isar)) {
-gdb_register_coprocessor(cs, arm_gdb_get_svereg, 
arm_gdb_set_svereg,
- arm_gen_dynamic_svereg_xml(cs, 
cs->gdb_num_regs),
+int nreg = arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs);
+gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
+ aarch64_gdb_set_sve_reg, nreg,
  "sve-registers.xml", 0);
 } else {
-gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
- aarch64_fpu_gdb_set_reg,
+gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg,
+ aarch64_gdb_set_fpu_reg,
  34, "aarch64-fpu.xml", 0);
 }
 #endif
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 07a6746944..c598cb0375 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -72,7 +72,7 @@ int aarch64_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 return 0;
 }
 
-int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
+int aarch64_gdb_get_fpu_reg(CPUARMState *env, GByteArray *buf, int reg)
 {
 switch (reg) {
 case 0 ... 31:
@@ -92,7 +92,7 @@ int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray 
*buf, int reg)
 }
 }
 
-int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
+int aarch64_gdb_set_fpu_reg(CPUARMState *env, uint8_t *buf, int reg)
 {
 switch (reg) {
 case 0 ... 31:
@@ -116,7 +116,7 @@ int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, 
int reg)
 }
 }
 
-int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg)
+int aarch64_gdb_get_sve_reg(CPUARMState *env, GByteArray *buf, int reg)
 {
 ARMCPU *cpu = env_archcpu(env);
 
@@ -164,7 +164,7 @@ int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, 
int reg)
 return 0;
 }
 
-int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg)
+int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, int reg)
 {
 ARMCPU *cpu = env_archcpu(env);
 
-- 
2.34.1




[PATCH v2 09/14] target/arm: Simplify iteration over bit widths

2023-02-20 Thread Richard Henderson
Order suf[] by the log8 of the width.
Use ARRAY_SIZE instead of hard-coding 128.

This changes the order of the union definitions,
but retains the order of the union-of-union members.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/gdbstub64.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 36166bf81e..3d9e9e97c8 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -240,8 +240,8 @@ static void output_vector_union_type(GString *s, int 
reg_width,
 { "int8", 8, 'b', 's' },
 };
 
-static const char suf[] = { 'q', 'd', 's', 'h', 'b' };
-int i, j, bits;
+static const char suf[] = { 'b', 'h', 's', 'd', 'q' };
+int i, j;
 
 /* First define types and totals in a whole VL */
 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
@@ -256,7 +256,9 @@ static void output_vector_union_type(GString *s, int 
reg_width,
  * signed and potentially float versions of each size from 128 to
  * 8 bits.
  */
-for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
+for (i = 0; i < ARRAY_SIZE(suf); i++) {
+int bits = 8 << i;
+
 g_string_append_printf(s, "", name, suf[i]);
 for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) {
 if (vec_lanes[j].size == bits) {
@@ -270,7 +272,7 @@ static void output_vector_union_type(GString *s, int 
reg_width,
 
 /* And now the final union of unions */
 g_string_append_printf(s, "", name);
-for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
+for (i = ARRAY_SIZE(suf) - 1; i >= 0; i--) {
 g_string_append_printf(s, "",
suf[i], name, suf[i]);
 }
-- 
2.34.1




[PATCH v2 14/14] target/arm: Implement gdbstub m-profile systemreg and secext

2023-02-20 Thread Richard Henderson
The upstream gdb xml only implements {MSP,PSP}{,_NS,S}, but
go ahead and implement the other system registers as well.

Since there is significant overlap between the two, implement
them with common code.  The only exception is the systemreg
view of CONTROL, which merges the banked bits as per MRS.

Signed-off-by: David Reiss 
[rth: Substatial rewrite using enumerator and shared code.]
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h |   2 +
 target/arm/gdbstub.c | 194 +++
 2 files changed, 196 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 059fe62eaa..6e97a256fb 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -869,6 +869,8 @@ struct ArchCPU {
 
 DynamicGDBXMLInfo dyn_sysreg_xml;
 DynamicGDBXMLInfo dyn_svereg_xml;
+DynamicGDBXMLInfo dyn_m_systemreg_xml;
+DynamicGDBXMLInfo dyn_m_secextreg_xml;
 
 /* Timers used by the generic (architected) timer */
 QEMUTimer *gt_timer[NUM_GTIMERS];
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 062c8d447a..fef53e4ef5 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -322,6 +322,180 @@ static int arm_gen_dynamic_sysreg_xml(CPUState *cs, int 
base_reg)
 return cpu->dyn_sysreg_xml.num;
 }
 
+typedef enum {
+M_SYSREG_MSP,
+M_SYSREG_PSP,
+M_SYSREG_PRIMASK,
+M_SYSREG_CONTROL,
+M_SYSREG_BASEPRI,
+M_SYSREG_FAULTMASK,
+M_SYSREG_MSPLIM,
+M_SYSREG_PSPLIM,
+} MProfileSysreg;
+
+static const struct {
+const char *name;
+int feature;
+} m_sysreg_def[] = {
+[M_SYSREG_MSP] = { "msp", ARM_FEATURE_M },
+[M_SYSREG_PSP] = { "psp", ARM_FEATURE_M },
+[M_SYSREG_PRIMASK] = { "primask", ARM_FEATURE_M },
+[M_SYSREG_CONTROL] = { "control", ARM_FEATURE_M },
+[M_SYSREG_BASEPRI] = { "basepri", ARM_FEATURE_M_MAIN },
+[M_SYSREG_FAULTMASK] = { "faultmask", ARM_FEATURE_M_MAIN },
+[M_SYSREG_MSPLIM] = { "msplim", ARM_FEATURE_V8 },
+[M_SYSREG_PSPLIM] = { "psplim", ARM_FEATURE_V8 },
+};
+
+static uint32_t *m_sysreg_ptr(CPUARMState *env, MProfileSysreg reg, bool sec)
+{
+uint32_t *ptr;
+
+switch (reg) {
+case M_SYSREG_MSP:
+ptr = arm_v7m_get_sp_ptr(env, sec, false, true);
+break;
+case M_SYSREG_PSP:
+ptr = arm_v7m_get_sp_ptr(env, sec, true, true);
+break;
+case M_SYSREG_MSPLIM:
+ptr = &env->v7m.msplim[sec];
+break;
+case M_SYSREG_PSPLIM:
+ptr = &env->v7m.psplim[sec];
+break;
+case M_SYSREG_PRIMASK:
+ptr = &env->v7m.primask[sec];
+break;
+case M_SYSREG_BASEPRI:
+ptr = &env->v7m.basepri[sec];
+break;
+case M_SYSREG_FAULTMASK:
+ptr = &env->v7m.faultmask[sec];
+break;
+case M_SYSREG_CONTROL:
+ptr = &env->v7m.control[sec];
+break;
+default:
+return NULL;
+}
+return arm_feature(env, m_sysreg_def[reg].feature) ? ptr : NULL;
+}
+
+static int m_sysreg_get(CPUARMState *env, GByteArray *buf,
+MProfileSysreg reg, bool secure)
+{
+uint32_t *ptr = m_sysreg_ptr(env, reg, secure);
+
+if (ptr == NULL) {
+return 0;
+}
+return gdb_get_reg32(buf, *ptr);
+}
+
+static int m_sysreg_set(CPUARMState *env, uint8_t *buf,
+MProfileSysreg reg, bool secure)
+{
+uint32_t *ptr = m_sysreg_ptr(env, reg, secure);
+
+if (ptr == NULL) {
+return 0;
+}
+*ptr = ldl_p(buf);
+return 4;
+}
+
+static int arm_gdb_get_m_systemreg(CPUARMState *env, GByteArray *buf, int reg)
+{
+/*
+ * Here, we emulate MRS instruction, where CONTROL has a mix of
+ * banked and non-banked bits.
+ */
+if (reg == M_SYSREG_CONTROL) {
+return gdb_get_reg32(buf, arm_v7m_mrs_control(env, env->v7m.secure));
+}
+return m_sysreg_get(env, buf, reg, env->v7m.secure);
+}
+
+static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg)
+{
+/* Control is a mix of banked and non-banked bits -- disallow write. */
+if (reg == M_SYSREG_CONTROL) {
+return 0;
+}
+return m_sysreg_set(env, buf, reg, env->v7m.secure);
+}
+
+static int arm_gen_dynamic_m_systemreg_xml(CPUState *cs, int orig_base_reg)
+{
+ARMCPU *cpu = ARM_CPU(cs);
+CPUARMState *env = &cpu->env;
+GString *s = g_string_new(NULL);
+int base_reg = orig_base_reg;
+int i;
+
+g_string_printf(s, "");
+g_string_append_printf(s, "");
+g_string_append_printf(s, "\n");
+
+for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
+if (arm_feature(env, m_sysreg_def[i].feature)) {
+g_string_append_printf(s,
+"\n",
+m_sysreg_def[i].name, base_reg++);
+}
+}
+
+g_string_append_printf(s, "");
+cpu->dyn_m_systemreg_xml.desc = g_string_free(s, false);
+cpu->dyn_m_systemreg_xml.num = base_reg - orig_base_reg;
+
+return cpu->dyn_m_systemreg_xml.num;
+}
+
+#ifndef CONFIG_USER_ONLY
+/*
+ * 

[PATCH v2 13/14] target/arm: Export arm_v7m_get_sp_ptr

2023-02-20 Thread Richard Henderson
From: David Reiss 

Allow the function to be used outside of m_helper.c.
Move to be outside of ifndef CONFIG_USER_ONLY block.
Rename from get_v7m_sp_ptr.

Reviewed-by: Peter Maydell 
Signed-off-by: David Reiss 
[rth: Split out of a larger patch]
Signed-off-by: Richard Henderson 
---
 target/arm/internals.h | 10 +
 target/arm/m_helper.c  | 84 +-
 2 files changed, 51 insertions(+), 43 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 89052b1c94..523822ac87 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1342,6 +1342,16 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
 /* Read the CONTROL register as the MRS instruction would. */
 uint32_t arm_v7m_mrs_control(CPUARMState *env, uint32_t secure);
 
+/*
+ * Return a pointer to the location where we currently store the
+ * stack pointer for the requested security state and thread mode.
+ * This pointer will become invalid if the CPU state is updated
+ * such that the stack pointers are switched around (eg changing
+ * the SPSEL control bit).
+ */
+uint32_t *arm_v7m_get_sp_ptr(CPUARMState *env, bool secure,
+ bool threadmode, bool spsel);
+
 #ifdef CONFIG_USER_ONLY
 static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
 #else
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 03be79e7bf..081fc3f5f7 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -650,42 +650,6 @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
 arm_rebuild_hflags(env);
 }
 
-static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
-bool spsel)
-{
-/*
- * Return a pointer to the location where we currently store the
- * stack pointer for the requested security state and thread mode.
- * This pointer will become invalid if the CPU state is updated
- * such that the stack pointers are switched around (eg changing
- * the SPSEL control bit).
- * Compare the v8M ARM ARM pseudocode LookUpSP_with_security_mode().
- * Unlike that pseudocode, we require the caller to pass us in the
- * SPSEL control bit value; this is because we also use this
- * function in handling of pushing of the callee-saves registers
- * part of the v8M stack frame (pseudocode PushCalleeStack()),
- * and in the tailchain codepath the SPSEL bit comes from the exception
- * return magic LR value from the previous exception. The pseudocode
- * opencodes the stack-selection in PushCalleeStack(), but we prefer
- * to make this utility function generic enough to do the job.
- */
-bool want_psp = threadmode && spsel;
-
-if (secure == env->v7m.secure) {
-if (want_psp == v7m_using_psp(env)) {
-return &env->regs[13];
-} else {
-return &env->v7m.other_sp;
-}
-} else {
-if (want_psp) {
-return &env->v7m.other_ss_psp;
-} else {
-return &env->v7m.other_ss_msp;
-}
-}
-}
-
 static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
 uint32_t *pvec)
 {
@@ -810,8 +774,8 @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, 
bool dotailchain,
 !mode;
 
 mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, M_REG_S, priv);
-frame_sp_p = get_v7m_sp_ptr(env, M_REG_S, mode,
-lr & R_V7M_EXCRET_SPSEL_MASK);
+frame_sp_p = arm_v7m_get_sp_ptr(env, M_REG_S, mode,
+lr & R_V7M_EXCRET_SPSEL_MASK);
 want_psp = mode && (lr & R_V7M_EXCRET_SPSEL_MASK);
 if (want_psp) {
 limit = env->v7m.psplim[M_REG_S];
@@ -1656,10 +1620,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
  * use 'frame_sp_p' after we do something that makes it invalid.
  */
 bool spsel = env->v7m.control[return_to_secure] & 
R_V7M_CONTROL_SPSEL_MASK;
-uint32_t *frame_sp_p = get_v7m_sp_ptr(env,
-  return_to_secure,
-  !return_to_handler,
-  spsel);
+uint32_t *frame_sp_p = arm_v7m_get_sp_ptr(env, return_to_secure,
+  !return_to_handler, spsel);
 uint32_t frameptr = *frame_sp_p;
 bool pop_ok = true;
 ARMMMUIdx mmu_idx;
@@ -1965,7 +1927,7 @@ static bool do_v7m_function_return(ARMCPU *cpu)
 threadmode = !arm_v7m_is_handler_mode(env);
 spsel = env->v7m.control[M_REG_S] & R_V7M_CONTROL_SPSEL_MASK;
 
-frame_sp_p = get_v7m_sp_ptr(env, true, threadmode, spsel);
+frame_sp_p = arm_v7m_get_sp_ptr(env, true, threadmode, spsel);
 frameptr = *frame_sp_p;
 
 /*
@@ -2900,3 +2862,39 @@ uint32_t HELPER(v7m_tt)(CPUARMState 

[PATCH v2 07/14] target/arm: Fix svep width in arm_gen_dynamic_svereg_xml

2023-02-20 Thread Richard Henderson
Define svep based on the size of the predicates,
not the primary vector registers.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/gdbstub64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 895e19f084..d0e1305f6f 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -297,7 +297,7 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int 
orig_base_reg)
 /* Create the predicate vector type. */
 g_string_append_printf(s,
"",
-   reg_width / 8);
+   pred_width / 8);
 
 /* Define the vector registers. */
 for (i = 0; i < 32; i++) {
-- 
2.34.1




[PATCH v2 00/14] target/arm: gdbstub cleanups and additions

2023-02-20 Thread Richard Henderson
This is my pauth enhancements from last year, the corresponding gdb
patches for which are nearing merge.  If lore and patchew are to be
believed, I never posted this to the list, only pushed a branch so
that issue #1105 could see it.

Since the cleanups there conflict with the recent m-profile gdbstub
patch set, I set about to resolve those.  In the process, I merged
the secure extension code with the sysregs, since they're simply
presenting different views of the same registers.

Changes for v2:
  * Incorporate feedback for pauth.
  * Rewrite m-profile systemreg and secext xml.
- Since these are Known to gdb, do not merge the two xml.
- Upstream gdb only knows about {M,P}SP, but David's extension
  to include the other registers makes sense and Luis confirms
  that it's ok to have extra registers in the two features.
- Continue to share code between the two xml, but separate
  out the mapping from gdbstub regno to internal enumeration.


r~


David Reiss (2):
  target/arm: Export arm_v7m_mrs_control
  target/arm: Export arm_v7m_get_sp_ptr

Richard Henderson (12):
  target/arm: Normalize aarch64 gdbstub get/set function names
  target/arm: Unexport arm_gen_dynamic_sysreg_xml
  target/arm: Move arm_gen_dynamic_svereg_xml to gdbstub64.c
  target/arm: Split out output_vector_union_type
  target/arm: Simplify register counting in arm_gen_dynamic_svereg_xml
  target/arm: Hoist pred_width in arm_gen_dynamic_svereg_xml
  target/arm: Fix svep width in arm_gen_dynamic_svereg_xml
  target/arm: Add name argument to output_vector_union_type
  target/arm: Simplify iteration over bit widths
  target/arm: Create pauth_ptr_mask
  target/arm: Implement gdbstub pauth extension
  target/arm: Implement gdbstub m-profile systemreg and secext

 configs/targets/aarch64-linux-user.mak|   2 +-
 configs/targets/aarch64-softmmu.mak   |   2 +-
 configs/targets/aarch64_be-linux-user.mak |   2 +-
 target/arm/cpu.h  |   9 +-
 target/arm/internals.h|  34 ++-
 target/arm/gdbstub.c  | 294 ++
 target/arm/gdbstub64.c| 175 -
 target/arm/m_helper.c |  90 ---
 target/arm/pauth_helper.c |  26 +-
 gdb-xml/aarch64-pauth.xml |  15 ++
 10 files changed, 474 insertions(+), 175 deletions(-)
 create mode 100644 gdb-xml/aarch64-pauth.xml

-- 
2.34.1




[PATCH v2 08/14] target/arm: Add name argument to output_vector_union_type

2023-02-20 Thread Richard Henderson
This will make the function usable between SVE and SME.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/gdbstub64.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index d0e1305f6f..36166bf81e 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -210,7 +210,8 @@ int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, 
int reg)
 return 0;
 }
 
-static void output_vector_union_type(GString *s, int reg_width)
+static void output_vector_union_type(GString *s, int reg_width,
+ const char *name)
 {
 struct TypeSize {
 const char *gdb_type;
@@ -240,39 +241,38 @@ static void output_vector_union_type(GString *s, int 
reg_width)
 };
 
 static const char suf[] = { 'q', 'd', 's', 'h', 'b' };
-
-g_autoptr(GString) ts = g_string_new("");
 int i, j, bits;
 
 /* First define types and totals in a whole VL */
 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
-int count = reg_width / vec_lanes[i].size;
-g_string_printf(ts, "svev%c%c", vec_lanes[i].sz, vec_lanes[i].suffix);
 g_string_append_printf(s,
-   "",
-   ts->str, vec_lanes[i].gdb_type, count);
+   "",
+   name, vec_lanes[i].sz, vec_lanes[i].suffix,
+   vec_lanes[i].gdb_type, reg_width / 
vec_lanes[i].size);
 }
+
 /*
  * Now define a union for each size group containing unsigned and
  * signed and potentially float versions of each size from 128 to
  * 8 bits.
  */
 for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
-g_string_append_printf(s, "", suf[i]);
+g_string_append_printf(s, "", name, suf[i]);
 for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) {
 if (vec_lanes[j].size == bits) {
-g_string_append_printf(s, "",
-   vec_lanes[j].suffix,
+g_string_append_printf(s, "",
+   vec_lanes[j].suffix, name,
vec_lanes[j].sz, vec_lanes[j].suffix);
 }
 }
 g_string_append(s, "");
 }
+
 /* And now the final union of unions */
-g_string_append(s, "");
+g_string_append_printf(s, "", name);
 for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
-g_string_append_printf(s, "",
-   suf[i], suf[i]);
+g_string_append_printf(s, "",
+   suf[i], name, suf[i]);
 }
 g_string_append(s, "");
 }
@@ -292,7 +292,7 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int 
orig_base_reg)
 g_string_append_printf(s, "");
 
 /* Create the vector union type. */
-output_vector_union_type(s, reg_width);
+output_vector_union_type(s, reg_width, "svev");
 
 /* Create the predicate vector type. */
 g_string_append_printf(s,
-- 
2.34.1




[PATCH v2 02/14] target/arm: Unexport arm_gen_dynamic_sysreg_xml

2023-02-20 Thread Richard Henderson
This function is not used outside gdbstub.c.

Reviewed-by: Fabiano Rosas 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h | 1 -
 target/arm/gdbstub.c | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 12b1082537..32ca6c9a0d 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1116,7 +1116,6 @@ int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t 
*buf, int reg);
  * Helpers to dynamically generates XML descriptions of the sysregs
  * and SVE registers. Returns the number of registers in each set.
  */
-int arm_gen_dynamic_sysreg_xml(CPUState *cpu, int base_reg);
 int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
 
 /* Returns the dynamically generated XML for the gdb stub.
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index cf1c01e3cf..52581e9784 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -305,7 +305,7 @@ static void arm_register_sysreg_for_xml(gpointer key, 
gpointer value,
 }
 }
 
-int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
+static int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
 {
 ARMCPU *cpu = ARM_CPU(cs);
 GString *s = g_string_new(NULL);
-- 
2.34.1




[PATCH v2 12/14] target/arm: Export arm_v7m_mrs_control

2023-02-20 Thread Richard Henderson
From: David Reiss 

Allow the function to be used outside of m_helper.c.
Rename with an "arm_" prefix.

Reviewed-by: Peter Maydell 
Signed-off-by: David Reiss 
[rth: Split out of a larger patch]
Signed-off-by: Richard Henderson 
---
 target/arm/internals.h | 3 +++
 target/arm/m_helper.c  | 6 +++---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index fb88b16579..89052b1c94 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1339,6 +1339,9 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
 #endif
 
+/* Read the CONTROL register as the MRS instruction would. */
+uint32_t arm_v7m_mrs_control(CPUARMState *env, uint32_t secure);
+
 #ifdef CONFIG_USER_ONLY
 static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
 #else
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index f94e87e728..03be79e7bf 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -56,7 +56,7 @@ static uint32_t v7m_mrs_xpsr(CPUARMState *env, uint32_t reg, 
unsigned el)
 return xpsr_read(env) & mask;
 }
 
-static uint32_t v7m_mrs_control(CPUARMState *env, uint32_t secure)
+uint32_t arm_v7m_mrs_control(CPUARMState *env, uint32_t secure)
 {
 uint32_t value = env->v7m.control[secure];
 
@@ -93,7 +93,7 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
 case 0 ... 7: /* xPSR sub-fields */
 return v7m_mrs_xpsr(env, reg, 0);
 case 20: /* CONTROL */
-return v7m_mrs_control(env, 0);
+return arm_v7m_mrs_control(env, 0);
 default:
 /* Unprivileged reads others as zero.  */
 return 0;
@@ -2465,7 +2465,7 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
 case 0 ... 7: /* xPSR sub-fields */
 return v7m_mrs_xpsr(env, reg, el);
 case 20: /* CONTROL */
-return v7m_mrs_control(env, env->v7m.secure);
+return arm_v7m_mrs_control(env, env->v7m.secure);
 case 0x94: /* CONTROL_NS */
 /*
  * We have to handle this here because unprivileged Secure code
-- 
2.34.1




[PATCH v2 03/14] target/arm: Move arm_gen_dynamic_svereg_xml to gdbstub64.c

2023-02-20 Thread Richard Henderson
The function is only used for aarch64, so move it to the
file that has the other aarch64 gdbstub stuff.  Move the
declaration to internals.h.

Reviewed-by: Fabiano Rosas 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h   |   6 ---
 target/arm/internals.h |   1 +
 target/arm/gdbstub.c   | 120 -
 target/arm/gdbstub64.c | 118 
 4 files changed, 119 insertions(+), 126 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 32ca6c9a0d..059fe62eaa 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1112,12 +1112,6 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, 
vaddr addr,
 int arm_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
 int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
-/*
- * Helpers to dynamically generates XML descriptions of the sysregs
- * and SVE registers. Returns the number of registers in each set.
- */
-int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
-
 /* Returns the dynamically generated XML for the gdb stub.
  * Returns a pointer to the XML contents for the specified XML file or NULL
  * if the XML name doesn't match the predefined one.
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 121ecd420b..32b8562cbf 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1326,6 +1326,7 @@ static inline uint64_t pmu_counter_mask(CPUARMState *env)
 }
 
 #ifdef TARGET_AARCH64
+int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
 int aarch64_gdb_get_sve_reg(CPUARMState *env, GByteArray *buf, int reg);
 int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, int reg);
 int aarch64_gdb_get_fpu_reg(CPUARMState *env, GByteArray *buf, int reg);
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 52581e9784..bf8aff7824 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -322,126 +322,6 @@ static int arm_gen_dynamic_sysreg_xml(CPUState *cs, int 
base_reg)
 return cpu->dyn_sysreg_xml.num;
 }
 
-struct TypeSize {
-const char *gdb_type;
-int  size;
-const char sz, suffix;
-};
-
-static const struct TypeSize vec_lanes[] = {
-/* quads */
-{ "uint128", 128, 'q', 'u' },
-{ "int128", 128, 'q', 's' },
-/* 64 bit */
-{ "ieee_double", 64, 'd', 'f' },
-{ "uint64", 64, 'd', 'u' },
-{ "int64", 64, 'd', 's' },
-/* 32 bit */
-{ "ieee_single", 32, 's', 'f' },
-{ "uint32", 32, 's', 'u' },
-{ "int32", 32, 's', 's' },
-/* 16 bit */
-{ "ieee_half", 16, 'h', 'f' },
-{ "uint16", 16, 'h', 'u' },
-{ "int16", 16, 'h', 's' },
-/* bytes */
-{ "uint8", 8, 'b', 'u' },
-{ "int8", 8, 'b', 's' },
-};
-
-
-int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
-{
-ARMCPU *cpu = ARM_CPU(cs);
-GString *s = g_string_new(NULL);
-DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
-g_autoptr(GString) ts = g_string_new("");
-int i, j, bits, reg_width = (cpu->sve_max_vq * 128);
-info->num = 0;
-g_string_printf(s, "");
-g_string_append_printf(s, "");
-g_string_append_printf(s, "");
-
-/* First define types and totals in a whole VL */
-for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
-int count = reg_width / vec_lanes[i].size;
-g_string_printf(ts, "svev%c%c", vec_lanes[i].sz, vec_lanes[i].suffix);
-g_string_append_printf(s,
-   "",
-   ts->str, vec_lanes[i].gdb_type, count);
-}
-/*
- * Now define a union for each size group containing unsigned and
- * signed and potentially float versions of each size from 128 to
- * 8 bits.
- */
-for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
-const char suf[] = { 'q', 'd', 's', 'h', 'b' };
-g_string_append_printf(s, "", suf[i]);
-for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) {
-if (vec_lanes[j].size == bits) {
-g_string_append_printf(s, "",
-   vec_lanes[j].suffix,
-   vec_lanes[j].sz, vec_lanes[j].suffix);
-}
-}
-g_string_append(s, "");
-}
-/* And now the final union of unions */
-g_string_append(s, "");
-for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
-const char suf[] = { 'q', 'd', 's', 'h', 'b' };
-g_string_append_printf(s, "",
-   suf[i], suf[i]);
-}
-g_string_append(s, "");
-
-/* Finally the sve prefix type */
-g_string_append_printf(s,
-   "",
-   reg_width / 8);
-
-/* Then define each register in parts for each vq */
-for (i = 0; i < 32; i++) {
-g_string_append_printf(s,
-   "",
-   i, reg_width, base_reg++);
-info->num++;
-}
-/* fpscr & status registers */
-g_string_app

[PATCH v2 04/14] target/arm: Split out output_vector_union_type

2023-02-20 Thread Richard Henderson
Create a subroutine for creating the union of unions
of the various type sizes that a vector may contain.

Reviewed-by: Fabiano Rosas 
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/gdbstub64.c | 83 +++---
 1 file changed, 45 insertions(+), 38 deletions(-)

diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 59fb5465d5..811833d8de 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -210,44 +210,39 @@ int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t 
*buf, int reg)
 return 0;
 }
 
-struct TypeSize {
-const char *gdb_type;
-short size;
-char sz, suffix;
-};
-
-static const struct TypeSize vec_lanes[] = {
-/* quads */
-{ "uint128", 128, 'q', 'u' },
-{ "int128", 128, 'q', 's' },
-/* 64 bit */
-{ "ieee_double", 64, 'd', 'f' },
-{ "uint64", 64, 'd', 'u' },
-{ "int64", 64, 'd', 's' },
-/* 32 bit */
-{ "ieee_single", 32, 's', 'f' },
-{ "uint32", 32, 's', 'u' },
-{ "int32", 32, 's', 's' },
-/* 16 bit */
-{ "ieee_half", 16, 'h', 'f' },
-{ "uint16", 16, 'h', 'u' },
-{ "int16", 16, 'h', 's' },
-/* bytes */
-{ "uint8", 8, 'b', 'u' },
-{ "int8", 8, 'b', 's' },
-};
-
-int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
+static void output_vector_union_type(GString *s, int reg_width)
 {
-ARMCPU *cpu = ARM_CPU(cs);
-GString *s = g_string_new(NULL);
-DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
+struct TypeSize {
+const char *gdb_type;
+short size;
+char sz, suffix;
+};
+
+static const struct TypeSize vec_lanes[] = {
+/* quads */
+{ "uint128", 128, 'q', 'u' },
+{ "int128", 128, 'q', 's' },
+/* 64 bit */
+{ "ieee_double", 64, 'd', 'f' },
+{ "uint64", 64, 'd', 'u' },
+{ "int64", 64, 'd', 's' },
+/* 32 bit */
+{ "ieee_single", 32, 's', 'f' },
+{ "uint32", 32, 's', 'u' },
+{ "int32", 32, 's', 's' },
+/* 16 bit */
+{ "ieee_half", 16, 'h', 'f' },
+{ "uint16", 16, 'h', 'u' },
+{ "int16", 16, 'h', 's' },
+/* bytes */
+{ "uint8", 8, 'b', 'u' },
+{ "int8", 8, 'b', 's' },
+};
+
+static const char suf[] = { 'q', 'd', 's', 'h', 'b' };
+
 g_autoptr(GString) ts = g_string_new("");
-int i, j, bits, reg_width = (cpu->sve_max_vq * 128);
-info->num = 0;
-g_string_printf(s, "");
-g_string_append_printf(s, "");
-g_string_append_printf(s, "");
+int i, j, bits;
 
 /* First define types and totals in a whole VL */
 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
@@ -263,7 +258,6 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
  * 8 bits.
  */
 for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
-const char suf[] = { 'q', 'd', 's', 'h', 'b' };
 g_string_append_printf(s, "", suf[i]);
 for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) {
 if (vec_lanes[j].size == bits) {
@@ -277,11 +271,24 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
 /* And now the final union of unions */
 g_string_append(s, "");
 for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
-const char suf[] = { 'q', 'd', 's', 'h', 'b' };
 g_string_append_printf(s, "",
suf[i], suf[i]);
 }
 g_string_append(s, "");
+}
+
+int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
+{
+ARMCPU *cpu = ARM_CPU(cs);
+GString *s = g_string_new(NULL);
+DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
+int i, reg_width = (cpu->sve_max_vq * 128);
+info->num = 0;
+g_string_printf(s, "");
+g_string_append_printf(s, "");
+g_string_append_printf(s, "");
+
+output_vector_union_type(s, reg_width);
 
 /* Finally the sve prefix type */
 g_string_append_printf(s,
-- 
2.34.1




[PATCH v2 05/14] target/arm: Simplify register counting in arm_gen_dynamic_svereg_xml

2023-02-20 Thread Richard Henderson
Rather than increment base_reg and num, compute num
from the change to base_reg at the end.  Clean up some
nearby comments.

Signed-off-by: Richard Henderson 
---
 target/arm/gdbstub64.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 811833d8de..070ba20d99 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -277,32 +277,35 @@ static void output_vector_union_type(GString *s, int 
reg_width)
 g_string_append(s, "");
 }
 
-int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
+int arm_gen_dynamic_svereg_xml(CPUState *cs, int orig_base_reg)
 {
 ARMCPU *cpu = ARM_CPU(cs);
 GString *s = g_string_new(NULL);
 DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
-int i, reg_width = (cpu->sve_max_vq * 128);
-info->num = 0;
+int reg_width = cpu->sve_max_vq * 128;
+int base_reg = orig_base_reg;
+int i;
+
 g_string_printf(s, "");
 g_string_append_printf(s, "");
 g_string_append_printf(s, "");
 
+/* Create the vector union type. */
 output_vector_union_type(s, reg_width);
 
-/* Finally the sve prefix type */
+/* Create the predicate vector type. */
 g_string_append_printf(s,
"",
reg_width / 8);
 
-/* Then define each register in parts for each vq */
+/* Define the vector registers. */
 for (i = 0; i < 32; i++) {
 g_string_append_printf(s,
"",
i, reg_width, base_reg++);
-info->num++;
 }
+
 /* fpscr & status registers */
 g_string_append_printf(s, "", base_reg++);
-info->num += 2;
 
+/* Define the predicate registers. */
 for (i = 0; i < 16; i++) {
 g_string_append_printf(s,
"",
i, cpu->sve_max_vq * 16, base_reg++);
-info->num++;
 }
 g_string_append_printf(s,
"",
cpu->sve_max_vq * 16, base_reg++);
+
+/* Define the vector length pseudo-register. */
 g_string_append_printf(s,
"",
base_reg++);
-info->num += 2;
-g_string_append_printf(s, "");
-info->desc = g_string_free(s, false);
 
+g_string_append_printf(s, "");
+
+info->desc = g_string_free(s, false);
+info->num = base_reg - orig_base_reg;
 return info->num;
 }
-- 
2.34.1




[PATCH v3 6/6] Python: Drop support for Python 3.6

2023-02-20 Thread John Snow
Python 3.6 was EOL 2021-12-31. Newer versions of upstream libraries have
been dropping support for this version and it is becoming more
cumbersome to support. Avocado-framework and qemu.qmp each have their
own reasons for wanting to drop Python 3.6, but won't until QEMU does.

Versions of Python available in our supported build platforms as of today,
with optional versions available in parentheses:

openSUSE Leap 15.4: 3.6.15 (3.9.10, 3.10.2)
CentOS Stream 8:3.6.8  (3.8.13, 3.9.16)
CentOS Stream 9:3.9.13
Fedora 36:  3.10
Fedora 37:  3.11
Debian 11:  3.9.2
Alpine 3.14, 3.15:  3.9.16
Alpine 3.16, 3.17:  3.10.10
Ubuntu 20.04 LTS:   3.8.10
Ubuntu 22.04 LTS:   3.10.4
NetBSD 9.3: 3.9.13*
FreeBSD 12.4:   3.9.16
FreeBSD 13.1:   3.9.16
OpenBSD 7.2:3.9.16

Note: Our VM tests install 3.7 specifically for freebsd and netbsd; the
default for "python" or "python3" in FreeBSD is 3.9.16. NetBSD does not
appear to have a default meta-package, but offers several options, the
lowest of which is 3.7.15. "python39" appears to be a pre-requisite to
one of the other packages we request in tests/vm/netbsd.

Since it is safe under our supported platform policy, bump our minimum
supported version of Python to 3.7.

Signed-off-by: John Snow 
---
 docs/conf.py |  4 ++--
 configure|  8 
 python/Makefile  | 10 +-
 python/setup.cfg |  7 +++
 python/tests/minreqs.txt |  2 +-
 scripts/qapi/mypy.ini|  2 +-
 6 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/docs/conf.py b/docs/conf.py
index 73a287a4f27..d40448f35d9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -37,9 +37,9 @@
 # In newer versions of Sphinx this will display nicely; in older versions
 # Sphinx will also produce a Python backtrace but at least the information
 # gets printed...
-if sys.version_info < (3,6):
+if sys.version_info < (3,7):
 raise ConfigError(
-"QEMU requires a Sphinx that uses Python 3.6 or better\n")
+"QEMU requires a Sphinx that uses Python 3.7 or better\n")
 
 # The per-manual conf.py will set qemu_docdir for a single-manual build;
 # otherwise set it here if this is an entire-manual-set build.
diff --git a/configure b/configure
index 0d0cca53f09..ea0d0e49b2d 100755
--- a/configure
+++ b/configure
@@ -594,9 +594,9 @@ esac
 
 
 check_py_version() {
-# We require python >= 3.6.
+# We require python >= 3.7.
 # NB: a True python conditional creates a non-zero return code (Failure)
-"$1" -c 'import sys; sys.exit(sys.version_info < (3,6))'
+"$1" -c 'import sys; sys.exit(sys.version_info < (3,7))'
 }
 
 python=
@@ -605,7 +605,7 @@ explicit_python=no
 # Check for $PYTHON, python3, python, then explicitly-versioned interpreters.
 for binary in "${PYTHON-python3}" ${PYTHON:+python3} python \
   python3.11 python3.10 python3.9 \
-  python3.8 python3.7 python3.6
+  python3.8 python3.7
 do
 if has "$binary"
 then
@@ -1058,7 +1058,7 @@ then
 fi
 
 if ! check_py_version "$python"; then
-  error_exit "Cannot use '$python', Python >= 3.6 is required." \
+  error_exit "Cannot use '$python', Python >= 3.7 is required." \
  "Use --python=/path/to/python to specify a supported Python." \
  "Maybe try:" \
  "  openSUSE Leap 15.3+: zypper install python39" \
diff --git a/python/Makefile b/python/Makefile
index c5bd6ff83ac..f660d999143 100644
--- a/python/Makefile
+++ b/python/Makefile
@@ -9,14 +9,14 @@ help:
@echo "make check-minreqs:"
@echo "Run tests in the minreqs virtual environment."
@echo "These tests use the oldest dependencies."
-   @echo "Requires: Python 3.6"
-   @echo "Hint (Fedora): 'sudo dnf install python3.6'"
+   @echo "Requires: Python 3.7"
+   @echo "Hint (Fedora): 'sudo dnf install python3.7'"
@echo ""
@echo "make check-tox:"
@echo "Run tests against multiple python versions."
@echo "These tests use the newest dependencies."
-   @echo "Requires: Python 3.6 - 3.10, and tox."
-   @echo "Hint (Fedora): 'sudo dnf install python3-tox python3.10'"
+   @echo "Requires: Python 3.7 - 3.11, and tox."
+   @echo "Hint (Fedora): 'sudo dnf install python3-tox python3.11'"
@echo "The variable QEMU_TOX_EXTRA_ARGS can be use to pass extra"
@echo "arguments to tox".
@echo ""
@@ -58,7 +58,7 @@ pipenv check-pipenv:
 min-venv: $(QEMU_MINVENV_DIR) $(QEMU_MINVENV_DIR)/bin/activate
 $(QEMU_MINVENV_DIR) $(QEMU_MINVENV_DIR)/bin/activate: setup.cfg 
tests/minreqs.txt
@echo "VENV $(QEMU_MINVENV_DIR)"
-   @python3.6 -m venv $(QEMU_MINVENV_DIR)
+   @python3.7 -m venv $(QEMU_MINVENV_DIR)
@(  \
echo "ACTIVATE $(QEMU_MI

[PATCH v3 1/6] configure: Look for auxiliary Python installations

2023-02-20 Thread John Snow
At the moment, we look for just "python3" and "python", which is good
enough almost all of the time. But ... if you are on a platform that
uses an older Python by default and only offers a newer Python as an
option, you'll have to specify --python=/usr/bin/foo every time.

As a courtesy, we can make a cursory attempt to locate a suitable Python
binary ourselves, looking for the remaining well-known binaries. This
also has the added benefit of making configure "just work" more often
on various BSD distributions that do not have the concept of a
"platform default python".

This configure loop will prefer, in order:

1. Whatever is specified in $PYTHON
2. python3
3. python (Which is usually 2.x, but might be 3.x on some platforms.)
4. python3.11 down through python3.6

Notes:

- Python virtual environments provide binaries for "python3", "python",
  and whichever version you used to create the venv,
  e.g. "python3.8". If configure is invoked from inside of a venv, this
  configure loop will not "break out" of that venv unless that venv is
  created using an explicitly non-suitable version of Python that we
  cannot use.

- In the event that no suitable python is found, the first python found
  is the version used to generate the human-readable error message.

- The error message isn't printed right away to allow later
  configuration code to pick up an explicitly configured python.

Signed-off-by: John Snow 
---
 configure | 34 ++
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/configure b/configure
index cf6db3d5518..6abf5a72078 100755
--- a/configure
+++ b/configure
@@ -592,20 +592,40 @@ esac
 
 : ${make=${MAKE-make}}
 
-# We prefer python 3.x. A bare 'python' is traditionally
-# python 2.x, but some distros have it as python 3.x, so
-# we check that too
+
+check_py_version() {
+# We require python >= 3.6.
+# NB: a True python conditional creates a non-zero return code (Failure)
+"$1" -c 'import sys; sys.exit(sys.version_info < (3,6))'
+}
+
 python=
+first_python=
 explicit_python=no
-for binary in "${PYTHON-python3}" python
+# Check for $PYTHON, python3, python, then explicitly-versioned interpreters.
+for binary in "${PYTHON-python3}" ${PYTHON:+python3} python \
+  python3.11 python3.10 python3.9 \
+  python3.8 python3.7 python3.6
 do
 if has "$binary"
 then
 python=$(command -v "$binary")
-break
+if test -z "$first_python"; then
+   first_python=$python
+fi
+if check_py_version "$python"; then
+# This one is good.
+first_python=
+break
+fi
 fi
 done
 
+# If first_python is set, we didn't find a suitable binary.
+# Use this one for possible future error messages.
+if test -n "$first_python"; then
+python="$first_python"
+fi
 
 # Check for ancillary tools used in testing
 genisoimage=
@@ -1037,9 +1057,7 @@ then
 error_exit "GNU make ($make) not found"
 fi
 
-# Note that if the Python conditional here evaluates True we will exit
-# with status 1 which is a shell 'false' value.
-if ! $python -c 'import sys; sys.exit(sys.version_info < (3,6))'; then
+if ! check_py_version "$python"; then
   error_exit "Cannot use '$python', Python >= 3.6 is required." \
   "Use --python=/path/to/python to specify a supported Python."
 fi
-- 
2.39.0




Re: [PATCH v4 0/6] qapi: static typing conversion, pt5c

2023-02-20 Thread John Snow
On Wed, Feb 15, 2023 at 8:39 AM Markus Armbruster  wrote:
>
> I had a few suggestions, but none of them requires a respin.  Let's
> discuss them, and then I merge.

Hiya, I lost track of things a little due to the other Python
discussion. Who is waiting for whom?

--js




[PATCH v3 0/6] Python: Drop support for Python 3.6

2023-02-20 Thread John Snow
CI: https://gitlab.com/jsnow/qemu/-/pipelines/783612696
[Updated for v3, still all green.]
GL: https://gitlab.com/jsnow/qemu/-/commits/python-require-37

Hi, discussion about this series is ongoing. This series (v3) is not
meant to address all of that discussion, but rather is an updated
baseline for what we are capable of right now, today, without much
additional engineering. It's meant to serve as a reference for further
discussion.

To my knowledge, the inconveniences caused by this patchset as currently
written are:

(1) Users of CentOS 8 and OpenSUSE 15.4 would need to install an
additional python package that will exist side-by-side with their
base platform's Python 3.6 package.

"zypper install python39" or "dnf install python38" is enough;
configure will do the rest of the work.

It's my understanding that this is largely a non-issue.

(2) Due to our Sphinx plugin that imports QAPI code from the tree,
distro-provided versions of Sphinx that are installed and tied to
Python 3.6 will no longer be suitable. Users may forego building
docs or install a suitable sphinx using "pip".

It's my understanding that this one is "kind of a bummer".

I feel that the inconvenience caused by (1) is minimized as is possible;
the inconvenience caused by (2) is slightly worse and I concede the
workaround has some complexities that I would otherwise seek to avoid.

As far as I am aware, the way forward is to work with Paolo to implement
a proper venv solution for the build tree that will help mitigate the
fallout from (2) by automating the use of a pip-provided Sphinx in the
cases where the distro-provided version is insufficient.

OK, seeya later!
--js

John Snow (6):
  configure: Look for auxiliary Python installations
  configure: Add courtesy hint to Python version failure message
  DO-NOT-MERGE: testing: Add Python >= 3.7 to Centos, OpenSuSE
  DO-NOT-MERGE: testing: add pip-installed sphinx-build to CentOS 8
  meson: prefer 'sphinx-build' to 'sphinx-build-3'
  Python: Drop support for Python 3.6

 docs/conf.py  |  4 +-
 docs/meson.build  |  2 +-
 configure | 41 ++-
 python/Makefile   | 10 ++---
 python/setup.cfg  |  7 ++--
 python/tests/minreqs.txt  |  2 +-
 scripts/qapi/mypy.ini |  2 +-
 tests/docker/dockerfiles/centos8.docker   |  5 +++
 tests/docker/dockerfiles/opensuse-leap.docker |  1 +
 9 files changed, 50 insertions(+), 24 deletions(-)

-- 
2.39.0





[PATCH v3 2/6] configure: Add courtesy hint to Python version failure message

2023-02-20 Thread John Snow
If we begin requiring Python 3.7+, a few platforms are going to need to
install an additional Python interpreter package.

As a courtesy to the user, suggest the optional package they might need
to install. This will hopefully minimize any downtime caused by the
change in Python dependency.

Signed-off-by: John Snow 
---
 configure | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 6abf5a72078..0d0cca53f09 100755
--- a/configure
+++ b/configure
@@ -1059,7 +1059,10 @@ fi
 
 if ! check_py_version "$python"; then
   error_exit "Cannot use '$python', Python >= 3.6 is required." \
-  "Use --python=/path/to/python to specify a supported Python."
+ "Use --python=/path/to/python to specify a supported Python." \
+ "Maybe try:" \
+ "  openSUSE Leap 15.3+: zypper install python39" \
+ "  CentOS 8: dnf install python38"
 fi
 
 # Suppress writing compiled files
-- 
2.39.0




[PATCH v3 5/6] meson: prefer 'sphinx-build' to 'sphinx-build-3'

2023-02-20 Thread John Snow
Once upon a time, "sphinx-build" on certain RPM platforms invoked
specifically a Python 2.x version, while "sphinx-build-3" was a distro
shim for the Python 3.x version.

These days, none of our supported platforms utilize a 2.x version, so it
should be safe to search for 'sphinx-build' prior to 'sphinx-build-3',
which will prefer pip/venv installed versions of sphinx if they're
available.

This adds an extremely convenient ability to test document building
ability in QEMU across multiple versions of Sphinx for the purposes of
compatibility testing.

Signed-off-by: John Snow 
---
 docs/meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/meson.build b/docs/meson.build
index 9136fed3b73..906034f9a87 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -1,5 +1,5 @@
 if get_option('sphinx_build') == ''
-  sphinx_build = find_program(['sphinx-build-3', 'sphinx-build'],
+  sphinx_build = find_program(['sphinx-build', 'sphinx-build-3'],
   required: get_option('docs'))
 else
   sphinx_build = find_program(get_option('sphinx_build'),
-- 
2.39.0




[PATCH v3 4/6] DO-NOT-MERGE: testing: add pip-installed sphinx-build to CentOS 8

2023-02-20 Thread John Snow
This is just for sake of demonstration again; by modifying the
dockerfile we can continue to support building docs on CentOS 8 with
minimal pain.

Note: This uses pip to install packages as root; this is hygienically
not a *great* idea for arbitrary systems. For CI, I am abusing the fact
that this is a custom-built environment that does not get altered after
being built. Individual developers should almost certainly just use a
virtual environment to avoid interfering with their system.

That process can look like this:

1. Install the new python interpreter:
   > sudo dnf install python38

2. Go to a folder where you'd be happy to store some python crud:
   > cd ~/.cache

3. Create a virtual environment using the new python:
   > python3.8 -m venv qemu_venv

4. Install a modern version of sphinx into this venv:
   > ./qemu_venv/bin/pip install sphinx

5. Try running sphinx-build:
   > ./qemu_venv/bin/sphinx-build --help

>From here, you can specify ~/.cache/qemu_venv/bin/sphinx-build as your
sphinx binary to configure in order to get doc building. This approach
doesn't interfere with anything; it requires you specifically to opt
into using it, which is likely the safest option if you don't have a lot
of Python knowhow.

Signed-off-by: John Snow 
---
 tests/docker/dockerfiles/centos8.docker | 4 
 1 file changed, 4 insertions(+)

diff --git a/tests/docker/dockerfiles/centos8.docker 
b/tests/docker/dockerfiles/centos8.docker
index a3bfddf382d..a53ccada55a 100644
--- a/tests/docker/dockerfiles/centos8.docker
+++ b/tests/docker/dockerfiles/centos8.docker
@@ -129,6 +129,10 @@ RUN dnf distro-sync -y && \
 ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
 ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
 
+RUN /usr/bin/python3.8 -m ensurepip && \
+/usr/bin/python3.8 -m pip --no-cache-dir install sphinx sphinx-rtd-theme
+
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
-- 
2.39.0




[PATCH v3 3/6] DO-NOT-MERGE: testing: Add Python >= 3.7 to Centos, OpenSuSE

2023-02-20 Thread John Snow
This is just a proof-of-concept patch, as these files are lcitool
generated. The real fix will involve updating the lcitool configuration
and updating these files that way.

Paolo has been working on this part:
https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg03547.html

This patch, meanwhile, is just to prove that bumping our dependency does
not introduce any regressions in our test suite or developer
processes. It also is meant to demonstrate the relatively small changes
needed to begin utilizing 3.7 as a minimum.

Signed-off-by: John Snow 
---
 tests/docker/dockerfiles/centos8.docker   | 1 +
 tests/docker/dockerfiles/opensuse-leap.docker | 1 +
 2 files changed, 2 insertions(+)

diff --git a/tests/docker/dockerfiles/centos8.docker 
b/tests/docker/dockerfiles/centos8.docker
index fbc953c6dcc..a3bfddf382d 100644
--- a/tests/docker/dockerfiles/centos8.docker
+++ b/tests/docker/dockerfiles/centos8.docker
@@ -95,6 +95,7 @@ RUN dnf distro-sync -y && \
 pkgconfig \
 pulseaudio-libs-devel \
 python3 \
+python38 \
 python3-PyYAML \
 python3-numpy \
 python3-pillow \
diff --git a/tests/docker/dockerfiles/opensuse-leap.docker 
b/tests/docker/dockerfiles/opensuse-leap.docker
index 4b2c02d6abf..9e688c1d441 100644
--- a/tests/docker/dockerfiles/opensuse-leap.docker
+++ b/tests/docker/dockerfiles/opensuse-leap.docker
@@ -89,6 +89,7 @@ RUN zypper update -y && \
pam-devel \
pcre-devel-static \
pkgconfig \
+   python39 \
python3-Pillow \
python3-PyYAML \
python3-Sphinx \
-- 
2.39.0




Re: [PATCH v2 07/18] hw/ide/piix: Ensure IDE output IRQs are wired at realization

2023-02-20 Thread BALATON Zoltan

On Mon, 20 Feb 2023, Bernhard Beschow wrote:
IIUC, QEMU guarantees a deprecation period for at least two major 
versions. So if we deprecated user-creatable piix-ide in 8.1, we are not 
allowed to remove it before 10.1. Let's stick to our rules to give our 
users a chance to adapt gracefully.


I think that's not 2 major releases just 2 releases so in your example 
could be removed in 9.0. qemu/docs/about/deprecated.rst says:


"The feature will remain functional for the release in which it was 
deprecated and one further release. After these two releases, the feature 
is liable to be removed."


Regards,
BALATON Zoltan



Re: [PATCH v2 07/18] hw/ide/piix: Ensure IDE output IRQs are wired at realization

2023-02-20 Thread Bernhard Beschow



Am 19. Februar 2023 21:54:34 UTC schrieb "Philippe Mathieu-Daudé" 
:
>+Daniel, Igor, Marcel & libvirt
>
>On 16/2/23 16:33, Philippe Mathieu-Daudé wrote:
>> On 16/2/23 15:43, Bernhard Beschow wrote:
>>> 
>>> 
>>> On Wed, Feb 15, 2023 at 5:20 PM Philippe Mathieu-Daudé >> > wrote:
>>> 
>>>     Ensure both IDE output IRQ lines are wired.
>>> 
>>>     We can remove the last use of isa_get_irq(NULL).
>>> 
>>>     Signed-off-by: Philippe Mathieu-Daudé >>     >
>>>     ---
>>>   hw/ide/piix.c | 13 -
>>>   1 file changed, 8 insertions(+), 5 deletions(-)
>>> 
>>>     diff --git a/hw/ide/piix.c b/hw/ide/piix.c
>>>     index 9d876dd4a7..b75a4ddcca 100644
>>>     --- a/hw/ide/piix.c
>>>     +++ b/hw/ide/piix.c
>>>     @@ -133,14 +133,17 @@ static bool pci_piix_init_bus(PCIIDEState *d,
>>>     unsigned i, Error **errp)
>>>       static const struct {
>>>           int iobase;
>>>           int iobase2;
>>>     -        int isairq;
>>>       } port_info[] = {
>>>     -        {0x1f0, 0x3f6, 14},
>>>     -        {0x170, 0x376, 15},
>>>     +        {0x1f0, 0x3f6},
>>>     +        {0x170, 0x376},
>>>       };
>>>       int ret;
>>> 
>>>     -    qemu_irq irq_out = d->irq[i] ? : isa_get_irq(NULL,
>>>     port_info[i].isairq);
>>>     +    if (!d->irq[i]) {
>>>     +        error_setg(errp, "output IDE IRQ %u not connected", i);
>>>     +        return false;
>>>     +    }
>>>     +
>>>       ide_bus_init(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
>>>       ret = ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
>>>                             port_info[i].iobase2);
>>>     @@ -149,7 +152,7 @@ static bool pci_piix_init_bus(PCIIDEState *d,
>>>     unsigned i, Error **errp)
>>>                            object_get_typename(OBJECT(d)), i);
>>>           return false;
>>>       }
>>>     -    ide_bus_init_output_irq(&d->bus[i], irq_out);
>>>     +    ide_bus_init_output_irq(&d->bus[i], d->irq[i]);
>>> 
>>>       bmdma_init(&d->bus[i], &d->bmdma[i], d);
>>>       d->bmdma[i].bus = &d->bus[i];
>>>     --     2.38.1
>>> 
>>> 
>>> This now breaks user-created  piix3-ide:
>>> 
>>>    qemu-system-x86_64 -M q35 -device piix3-ide
>>> 
>>> Results in:
>>> 
>>>    qemu-system-x86_64: -device piix3-ide: output IDE IRQ 0 not connected
>> 
>> Thank you for this real-life-impossible-but-exists-in-QEMU test-case!
>
>Do we really want to maintain this Frankenstein use case?
>
>1/ Q35 comes with a PCIe bus on which sits a ICH chipset, which already
>   contains a AHCI function exposing multiple IDE buses.
>   What is the point on using an older tech?

I just chose Q35 in the test case to demonstrate that we'd not meet our own 
deprecation rules.

IIUC, QEMU guarantees a deprecation period for at least two major versions. So 
if we deprecated user-creatable piix-ide in 8.1, we are not allowed to remove 
it before 10.1. Let's stick to our rules to give our users a chance to adapt 
gracefully.

>
>2/ Why can we plug a PCI function on a PCIe bridge without using a
>   pcie-pci-bridge?
>
>3/ Chipsets come as a whole. Software drivers might expect all PCI
>   functions working (Linux considering each function individually
>   is not the norm)
>
>
>I get your use case working with the following diff [*]:
>
>-- >8 --
>diff --git a/hw/ide/piix.c b/hw/ide/piix.c
>index 74e2f4288d..cb1628963a 100644
>--- a/hw/ide/piix.c
>+++ b/hw/ide/piix.c
>@@ -140,8 +140,19 @@ static bool pci_piix_init_bus(PCIIDEState *d, unsigned i, 
>Error **errp)
> };
>
> if (!d->irq[i]) {
>-error_setg(errp, "output IDE IRQ %u not connected", i);
>-return false;
>+if (DEVICE_GET_CLASS(d)->user_creatable) {
>+/* Returns NULL unless there is exactly one ISA bus */
>+Object *isabus = object_resolve_path_type("", TYPE_ISA_BUS, NULL);
>+
>+if (!isabus) {
>+error_setg(errp, "Unable to find a single ISA bus");
>+return false;
>+}
>+d->irq[i] = isa_bus_get_irq(ISA_BUS(isabus), 14 + i);
>+} else {
>+error_setg(errp, "output IDE IRQ %u not connected", i);
>+return false;
>+}
> }
>
> ide_bus_init(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
>@@ -201,6 +212,13 @@ static void piix3_ide_class_init(ObjectClass *klass, void 
>*data)
> k->class_id = PCI_CLASS_STORAGE_IDE;
> set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
> dc->hotpluggable = false;
>+/*
>+ * This function is part of a Super I/O chip and shouldn't be user
>+ * creatable. However QEMU accepts impossible hardware setups such
>+ * plugging a PIIX IDE function on a ICH ISA bridge.
>+ * Keep this Frankenstein (ab)use working.
>+ */
>+dc->user_creatable = true;
> }
>
> static const TypeInfo piix3_ide_info = {
>@@ -224,6 +242,8 @@ static void piix4_ide_class_init(ObjectClass *klass, vo

Re: [PATCH 21/22] target/arm: Enable RME for -cpu max

2023-02-20 Thread Richard Henderson

On 2/10/23 04:20, Peter Maydell wrote:

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
 wrote:


Add a cpu property to set GPCCR_EL3.L0GPTSZ, for testing
various possible configurations.

Signed-off-by: Richard Henderson 


Looks OK, but I think we probably shouldn't enable RME by default
until we're happy with what we're planning to do at the
system/board level (eg should it be like MTE where it's only
turned on if the board has support and turns it on?)


You're probably right about not enabling by default, and certainly right about figuring 
out what firmware actually expects and needs.



r~



[PATCH v2 02/21] target/arm: Add isar_feature_aa64_rme

2023-02-20 Thread Richard Henderson
Add the missing field for ID_AA64PFR0, and the predicate.
Disable it if EL3 is forced off by the board or command-line.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h | 6 ++
 target/arm/cpu.c | 4 
 2 files changed, 10 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 12b1082537..04f000cc54 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2190,6 +2190,7 @@ FIELD(ID_AA64PFR0, SEL2, 36, 4)
 FIELD(ID_AA64PFR0, MPAM, 40, 4)
 FIELD(ID_AA64PFR0, AMU, 44, 4)
 FIELD(ID_AA64PFR0, DIT, 48, 4)
+FIELD(ID_AA64PFR0, RME, 52, 4)
 FIELD(ID_AA64PFR0, CSV2, 56, 4)
 FIELD(ID_AA64PFR0, CSV3, 60, 4)
 
@@ -3802,6 +3803,11 @@ static inline bool isar_feature_aa64_sel2(const 
ARMISARegisters *id)
 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0;
 }
 
+static inline bool isar_feature_aa64_rme(const ARMISARegisters *id)
+{
+return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0;
+}
+
 static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
 {
 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 876ab8f3bf..83685ed247 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1947,6 +1947,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0);
 cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
ID_AA64PFR0, EL3, 0);
+
+/* Disable the realm management extension, which requires EL3. */
+cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
+   ID_AA64PFR0, RME, 0);
 }
 
 if (!cpu->has_el2) {
-- 
2.34.1




[PATCH v2 15/21] target/arm: Move s1_is_el0 into S1Translate

2023-02-20 Thread Richard Henderson
Instead of passing this to get_phys_addr_lpae, stash it
in the S1Translate structure.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 26 --
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 6e980654be..d4027ce763 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -22,6 +22,12 @@ typedef struct S1Translate {
 ARMSecuritySpace in_space;
 bool in_secure;
 bool in_debug;
+/*
+ * If this is stage 2 of a stage 1+2 page table walk, then this must
+ * be true if stage 1 is an EL0 access; otherwise this is ignored.
+ * Stage 2 is indicated by in_mmu_idx set to ARMMMUIdx_Stage2{,_S}.
+ */
+bool in_s1_is_el0;
 bool out_secure;
 bool out_rw;
 bool out_be;
@@ -33,7 +39,7 @@ typedef struct S1Translate {
 
 static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
uint64_t address,
-   MMUAccessType access_type, bool s1_is_el0,
+   MMUAccessType access_type,
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
 __attribute__((nonnull));
 
@@ -1257,17 +1263,12 @@ static int check_s2_mmu_setup(ARMCPU *cpu, bool 
is_aa64, uint64_t tcr,
  * @ptw: Current and next stage parameters for the walk.
  * @address: virtual address to get physical address for
  * @access_type: MMU_DATA_LOAD, MMU_DATA_STORE or MMU_INST_FETCH
- * @s1_is_el0: if @ptw->in_mmu_idx is ARMMMUIdx_Stage2
- * (so this is a stage 2 page table walk),
- * must be true if this is stage 2 of a stage 1+2
- * walk for an EL0 access. If @mmu_idx is anything else,
- * @s1_is_el0 is ignored.
  * @result: set on translation success,
  * @fi: set to fault info if the translation fails
  */
 static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
uint64_t address,
-   MMUAccessType access_type, bool s1_is_el0,
+   MMUAccessType access_type,
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
 {
 ARMCPU *cpu = env_archcpu(env);
@@ -1600,7 +1601,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 result->f.prot = get_S2prot_noexecute(ap);
 } else {
 xn = extract64(attrs, 53, 2);
-result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
+result->f.prot = get_S2prot(env, ap, xn, ptw->in_s1_is_el0);
 }
 } else {
 int nse, ns = extract32(attrs, 5, 1);
@@ -2822,7 +2823,6 @@ static bool get_phys_addr_twostage(CPUARMState *env, 
S1Translate *ptw,
 bool ret, ipa_secure, s2walk_secure;
 ARMCacheAttrs cacheattrs1;
 ARMSecuritySpace ipa_space, s2walk_space;
-bool is_el0;
 uint64_t hcr;
 
 ret = get_phys_addr_with_struct(env, ptw, address, access_type, result, 
fi);
@@ -2847,7 +2847,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, 
S1Translate *ptw,
 s2walk_space = ipa_space;
 }
 
-is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
+ptw->in_s1_is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
 ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
 ptw->in_ptw_idx = arm_space_to_phys(s2walk_space);
 ptw->in_secure = s2walk_secure;
@@ -2866,8 +2866,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, 
S1Translate *ptw,
 ret = get_phys_addr_pmsav8(env, ipa, access_type,
ptw->in_mmu_idx, is_secure, result, fi);
 } else {
-ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
- is_el0, result, fi);
+ret = get_phys_addr_lpae(env, ptw, ipa, access_type, result, fi);
 }
 fi->s2addr = ipa;
 
@@ -3043,8 +3042,7 @@ static bool get_phys_addr_with_struct(CPUARMState *env, 
S1Translate *ptw,
 }
 
 if (regime_using_lpae_format(env, mmu_idx)) {
-return get_phys_addr_lpae(env, ptw, address, access_type, false,
-  result, fi);
+return get_phys_addr_lpae(env, ptw, address, access_type, result, fi);
 } else if (arm_feature(env, ARM_FEATURE_V7) ||
regime_sctlr(env, mmu_idx) & SCTLR_XP) {
 return get_phys_addr_v6(env, ptw, address, access_type, result, fi);
-- 
2.34.1




[PATCH v2 01/21] target/arm: Rewrite check_s2_mmu_setup

2023-02-20 Thread Richard Henderson
Integrate neighboring code from get_phys_addr_lpae which computed
starting level, as it is easier to validate when doing both at the
same time.  Mirror the checks at the start of AArch{64,32}.S2Walk,
especially S2InvalidSL and S2InconsistentSL.

This reverts 49ba115bb74, which was incorrect -- there is nothing
in the ARM pseudocode that depends on TxSZ, i.e. outputsize; the
pseudocode is consistent in referencing PAMax.

Fixes: 49ba115bb74 ("target/arm: Pass outputsize down to check_s2_mmu_setup")
Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 173 ++-
 1 file changed, 97 insertions(+), 76 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 2b125fff44..6fb72fb086 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1077,70 +1077,119 @@ static ARMVAParameters aa32_va_parameters(CPUARMState 
*env, uint32_t va,
  * check_s2_mmu_setup
  * @cpu:ARMCPU
  * @is_aa64:True if the translation regime is in AArch64 state
- * @startlevel: Suggested starting level
- * @inputsize:  Bitsize of IPAs
+ * @tcr:VTCR_EL2 or VSTCR_EL2
+ * @ds: Effective value of TCR.DS.
+ * @iasize: Bitsize of IPAs
  * @stride: Page-table stride (See the ARM ARM)
  *
- * Returns true if the suggested S2 translation parameters are OK and
- * false otherwise.
+ * Decode the starting level of the S2 lookup, returning INT_MIN if
+ * the configuration is invalid.
  */
-static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
-   int inputsize, int stride, int outputsize)
+static int check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, uint64_t tcr,
+  bool ds, int iasize, int stride)
 {
-const int grainsize = stride + 3;
-int startsizecheck;
-
-/*
- * Negative levels are usually not allowed...
- * Except for FEAT_LPA2, 4k page table, 52-bit address space, which
- * begins with level -1.  Note that previous feature tests will have
- * eliminated this combination if it is not enabled.
- */
-if (level < (inputsize == 52 && stride == 9 ? -1 : 0)) {
-return false;
-}
-
-startsizecheck = inputsize - ((3 - level) * stride + grainsize);
-if (startsizecheck < 1 || startsizecheck > stride + 4) {
-return false;
-}
+int sl0, sl2, startlevel, granulebits, levels;
+int s1_min_iasize, s1_max_iasize;
 
+sl0 = extract32(tcr, 6, 2);
 if (is_aa64) {
+/*
+ * AArch64.S2InvalidTxSZ: While we checked tsz_oob near the top of
+ * get_phys_addr_lpae, that used aa64_va_parameters which apply
+ * to aarch64.  If Stage1 is aarch32, the min_txsz is larger.
+ * See AArch64.S2MinTxSZ, where min_tsz is 24, translated to
+ * inputsize is 64 - 24 = 40.
+ */
+if (iasize < 40 && !arm_el_is_aa64(&cpu->env, 1)) {
+goto fail;
+}
+
+/*
+ * AArch64.S2InvalidSL: Interpretation of SL depends on the page size,
+ * so interleave AArch64.S2StartLevel.
+ */
 switch (stride) {
-case 13: /* 64KB Pages.  */
-if (level == 0 || (level == 1 && outputsize <= 42)) {
-return false;
+case 9: /* 4KB */
+/* SL2 is RES0 unless DS=1 & 4KB granule. */
+sl2 = extract64(tcr, 33, 1);
+if (ds && sl2) {
+if (sl0 != 0) {
+goto fail;
+}
+startlevel = -1;
+} else {
+startlevel = 2 - sl0;
+switch (sl0) {
+case 2:
+if (arm_pamax(cpu) < 44) {
+goto fail;
+}
+break;
+case 3:
+if (!cpu_isar_feature(aa64_st, cpu)) {
+goto fail;
+}
+startlevel = 3;
+break;
+}
 }
 break;
-case 11: /* 16KB Pages.  */
-if (level == 0 || (level == 1 && outputsize <= 40)) {
-return false;
+case 11: /* 16KB */
+switch (sl0) {
+case 2:
+if (arm_pamax(cpu) < 42) {
+goto fail;
+}
+break;
+case 3:
+if (!ds) {
+goto fail;
+}
+break;
 }
+startlevel = 3 - sl0;
 break;
-case 9: /* 4KB Pages.  */
-if (level == 0 && outputsize <= 42) {
-return false;
+case 13: /* 64KB */
+switch (sl0) {
+case 2:
+if (arm_pamax(cpu) < 44) {
+goto fail;
+}
+break;
+case 3:
+goto fail;
 }
+startlevel = 3 - sl0;
 break;

[PATCH v2 12/21] target/arm: Handle Block and Page bits for security space

2023-02-20 Thread Richard Henderson
With Realm security state, bit 55 of a block or page descriptor during
the stage2 walk becomes the NS bit; during the stage1 walk the bit 5
NS bit is RES0.  With Root security state, bit 11 of the block or page
descriptor during the stage1 walk becomes the NSE bit.

Rather than collecting an NS bit and applying it later, compute the
output pa space from the input pa space and unconditionally assign.
This means that we no longer need to adjust the output space earlier
for the NSTable bit.

Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 91 ++--
 1 file changed, 73 insertions(+), 18 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index d612e5f38a..a9a9a8a403 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -956,12 +956,14 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn, 
bool s1_is_el0)
  * @mmu_idx: MMU index indicating required translation regime
  * @is_aa64: TRUE if AArch64
  * @ap:  The 2-bit simple AP (AP[2:1])
- * @ns:  NS (non-secure) bit
  * @xn:  XN (execute-never) bit
  * @pxn: PXN (privileged execute-never) bit
+ * @in_pa:   The original input pa space
+ * @out_pa:  The output pa space, modified by NSTable, NS, and NSE
  */
 static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
-  int ap, int ns, int xn, int pxn)
+  int ap, int xn, int pxn,
+  ARMSecuritySpace in_pa, ARMSecuritySpace out_pa)
 {
 bool is_user = regime_is_user(env, mmu_idx);
 int prot_rw, user_rw;
@@ -982,7 +984,8 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, 
bool is_aa64,
 }
 }
 
-if (ns && arm_is_secure(env) && (env->cp15.scr_el3 & SCR_SIF)) {
+if (out_pa == ARMSS_NonSecure && in_pa == ARMSS_Secure &&
+(env->cp15.scr_el3 & SCR_SIF)) {
 return prot_rw;
 }
 
@@ -1250,11 +1253,12 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 int32_t stride;
 int addrsize, inputsize, outputsize;
 uint64_t tcr = regime_tcr(env, mmu_idx);
-int ap, ns, xn, pxn;
+int ap, xn, pxn;
 uint32_t el = regime_el(env, mmu_idx);
 uint64_t descaddrmask;
 bool aarch64 = arm_el_is_aa64(env, el);
 uint64_t descriptor, new_descriptor;
+ARMSecuritySpace out_space;
 
 /* TODO: This code does not support shareability levels. */
 if (aarch64) {
@@ -1437,8 +1441,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 ptw->in_ptw_idx += 1;
 ptw->in_secure = false;
 ptw->in_space = ARMSS_NonSecure;
-result->f.attrs.secure = false;
-result->f.attrs.space = ARMSS_NonSecure;
 }
 
 if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
@@ -1556,15 +1558,75 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 }
 
 ap = extract32(attrs, 6, 2);
+out_space = ptw->in_space;
 if (regime_is_stage2(mmu_idx)) {
-ns = mmu_idx == ARMMMUIdx_Stage2;
+/*
+ * R_GYNXY: For stage2 in Realm security state, bit 55 is NS.
+ * The bit remains ignored for other security states.
+ */
+if (out_space == ARMSS_Realm && extract64(attrs, 55, 1)) {
+out_space = ARMSS_NonSecure;
+}
 xn = extract64(attrs, 53, 2);
 result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
 } else {
-ns = extract32(attrs, 5, 1);
+int nse, ns = extract32(attrs, 5, 1);
+switch (out_space) {
+case ARMSS_Root:
+/*
+ * R_GVZML: Bit 11 becomes the NSE field in the EL3 regime.
+ * R_XTYPW: NSE and NS together select the output pa space.
+ */
+nse = extract32(attrs, 11, 1);
+out_space = (nse << 1) | ns;
+if (out_space == ARMSS_Secure &&
+!cpu_isar_feature(aa64_sel2, cpu)) {
+out_space = ARMSS_NonSecure;
+}
+break;
+case ARMSS_Secure:
+if (ns) {
+out_space = ARMSS_NonSecure;
+}
+break;
+case ARMSS_Realm:
+switch (mmu_idx) {
+case ARMMMUIdx_Stage1_E0:
+case ARMMMUIdx_Stage1_E1:
+case ARMMMUIdx_Stage1_E1_PAN:
+/* I_CZPRF: For Realm EL1&0 stage1, NS bit is RES0. */
+break;
+case ARMMMUIdx_E2:
+case ARMMMUIdx_E20_0:
+case ARMMMUIdx_E20_2:
+case ARMMMUIdx_E20_2_PAN:
+/*
+ * R_LYKFZ, R_WGRZN: For Realm EL2 and EL2&1,
+ * NS changes the output to non-secure space.
+ */
+if (ns) {
+out_space = ARMSS_NonSecure;
+}
+break;
+default:
+g_assert_not_reached();
+}
+break;
+case ARMSS_NonSecure:
+/* R

[PATCH v2 19/21] target/arm: Implement the granule protection check

2023-02-20 Thread Richard Henderson
Place the check at the end of get_phys_addr_with_struct,
so that we check all physical results.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 246 +++
 1 file changed, 228 insertions(+), 18 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index a797750f9b..b2f55f7f66 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -37,12 +37,11 @@ typedef struct S1Translate {
 void *out_host;
 } S1Translate;
 
-static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
-  target_ulong address,
-  MMUAccessType access_type,
-  GetPhysAddrResult *result,
-  ARMMMUFaultInfo *fi)
-__attribute__((nonnull));
+static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
+target_ulong address,
+MMUAccessType access_type,
+GetPhysAddrResult *result,
+ARMMMUFaultInfo *fi);
 
 /* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */
 static const uint8_t pamax_map[] = {
@@ -198,6 +197,197 @@ static bool regime_translation_disabled(CPUARMState *env, 
ARMMMUIdx mmu_idx,
 return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
 }
 
+static bool granule_protection_check(CPUARMState *env, uint64_t paddress,
+ ARMSecuritySpace pspace,
+ ARMMMUFaultInfo *fi)
+{
+MemTxAttrs attrs = {
+.secure = true,
+.space = ARMSS_Root,
+};
+ARMCPU *cpu = env_archcpu(env);
+uint64_t gpccr = env->cp15.gpccr_el3;
+unsigned pps, pgs, l0gptsz, level = 0;
+uint64_t tableaddr, pps_mask, align, entry, index;
+AddressSpace *as;
+MemTxResult result;
+int gpi;
+
+if (!FIELD_EX64(gpccr, GPCCR, GPC)) {
+return true;
+}
+
+/*
+ * GPC Priority 1 (R_GMGRR):
+ * R_JWCSM: If the configuration of GPCCR_EL3 is invalid,
+ * the access fails as GPT walk fault at level 0.
+ */
+
+/*
+ * Configuration of PPS to a value exceeding the implemented
+ * physical address size is invalid.
+ */
+pps = FIELD_EX64(gpccr, GPCCR, PPS);
+if (pps > FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE)) {
+goto fault_walk;
+}
+pps = pamax_map[pps];
+pps_mask = MAKE_64BIT_MASK(0, pps);
+
+switch (FIELD_EX64(gpccr, GPCCR, SH)) {
+case 0b10: /* outer shareable */
+break;
+case 0b00: /* non-shareable */
+case 0b11: /* inner shareable */
+/* Inner and Outer non-cacheable requires Outer shareable. */
+if (FIELD_EX64(gpccr, GPCCR, ORGN) == 0 &&
+FIELD_EX64(gpccr, GPCCR, IRGN) == 0) {
+goto fault_walk;
+}
+break;
+default:   /* reserved */
+goto fault_walk;
+}
+
+switch (FIELD_EX64(gpccr, GPCCR, PGS)) {
+case 0b00: /* 4KB */
+pgs = 12;
+break;
+case 0b01: /* 64KB */
+pgs = 16;
+break;
+case 0b10: /* 16KB */
+pgs = 14;
+break;
+default: /* reserved */
+goto fault_walk;
+}
+
+/* Note this field is read-only and fixed at reset. */
+l0gptsz = 30 + FIELD_EX64(gpccr, GPCCR, L0GPTSZ);
+
+/*
+ * GPC Priority 2: Secure, Realm or Root address exceeds PPS.
+ * R_CPDSB: A NonSecure physical address input exceeding PPS
+ * does not experience any fault.
+ */
+if (paddress & ~pps_mask) {
+if (pspace == ARMSS_NonSecure) {
+return true;
+}
+goto fault_size;
+}
+
+/* GPC Priority 3: the base address of GPTBR_EL3 exceeds PPS. */
+tableaddr = env->cp15.gptbr_el3 << 12;
+if (tableaddr & ~pps_mask) {
+goto fault_size;
+}
+
+/*
+ * BADDR is aligned per a function of PPS and L0GPTSZ.
+ * These bits of GPTBR_EL3 are RES0, but are not a configuration error,
+ * unlike the RES0 bits of the GPT entries (R_XNKFZ).
+ */
+align = MAX(pps - l0gptsz + 3, 12);
+align = MAKE_64BIT_MASK(0, align);
+tableaddr &= ~align;
+
+as = arm_addressspace(env_cpu(env), attrs);
+
+/* Level 0 lookup. */
+index = extract64(paddress, l0gptsz, pps - l0gptsz);
+tableaddr += index * 8;
+entry = address_space_ldq_le(as, tableaddr, attrs, &result);
+if (result != MEMTX_OK) {
+goto fault_eabt;
+}
+
+switch (extract32(entry, 0, 4)) {
+case 1: /* block descriptor */
+if (entry >> 8) {
+goto fault_walk; /* RES0 bits not 0 */
+}
+gpi = extract32(entry, 4, 4);
+goto found;
+case 3: /* table descriptor */
+tableaddr = entry & ~0xf;
+align = MAX(l0gptsz - pgs - 1, 12);
+align = MAKE_64BIT_MASK(0, align);
+if (tableaddr &

[PATCH v2 14/21] target/arm: Use get_phys_addr_with_struct in S1_ptw_translate

2023-02-20 Thread Richard Henderson
Do not provide a fast-path for physical addresses,
as those will need to be validated for GPC.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 35 ++-
 1 file changed, 14 insertions(+), 21 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 54e72baff5..6e980654be 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -234,29 +234,22 @@ static bool S1_ptw_translate(CPUARMState *env, 
S1Translate *ptw,
  * From gdbstub, do not use softmmu so that we don't modify the
  * state of the cpu at all, including softmmu tlb contents.
  */
-if (regime_is_stage2(s2_mmu_idx)) {
-S1Translate s2ptw = {
-.in_mmu_idx = s2_mmu_idx,
-.in_ptw_idx = arm_space_to_phys(space),
-.in_space = space,
-.in_secure = is_secure,
-.in_debug = true,
-};
-GetPhysAddrResult s2 = { };
+S1Translate s2ptw = {
+.in_mmu_idx = s2_mmu_idx,
+.in_ptw_idx = arm_space_to_phys(space),
+.in_space = space,
+.in_secure = is_secure,
+.in_debug = true,
+};
+GetPhysAddrResult s2 = { };
 
-if (get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
-   false, &s2, fi)) {
-goto fail;
-}
-ptw->out_phys = s2.f.phys_addr;
-pte_attrs = s2.cacheattrs.attrs;
-pte_secure = s2.f.attrs.secure;
-} else {
-/* Regime is physical. */
-ptw->out_phys = addr;
-pte_attrs = 0;
-pte_secure = is_secure;
+if (get_phys_addr_with_struct(env, &s2ptw, addr,
+  MMU_DATA_LOAD, &s2, fi)) {
+goto fail;
 }
+ptw->out_phys = s2.f.phys_addr;
+pte_attrs = s2.cacheattrs.attrs;
+pte_secure = s2.f.attrs.secure;
 ptw->out_host = NULL;
 ptw->out_rw = false;
 } else {
-- 
2.34.1




[PATCH v2 17/21] target/arm: Add GPC syndrome

2023-02-20 Thread Richard Henderson
The function takes the fields as filled in by
the Arm ARM pseudocode for TakeGPCException.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/syndrome.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
index d27d1bc31f..62254d0e51 100644
--- a/target/arm/syndrome.h
+++ b/target/arm/syndrome.h
@@ -50,6 +50,7 @@ enum arm_exception_class {
 EC_SVEACCESSTRAP  = 0x19,
 EC_ERETTRAP   = 0x1a,
 EC_SMETRAP= 0x1d,
+EC_GPC= 0x1e,
 EC_INSNABORT  = 0x20,
 EC_INSNABORT_SAME_EL  = 0x21,
 EC_PCALIGNMENT= 0x22,
@@ -247,6 +248,15 @@ static inline uint32_t syn_bxjtrap(int cv, int cond, int 
rm)
 (cv << 24) | (cond << 20) | rm;
 }
 
+static inline uint32_t syn_gpc(int s2ptw, int ind, int gpcsc,
+   int cm, int s1ptw, int wnr, int fsc)
+{
+/* TODO: FEAT_NV2 adds VNCR */
+return (EC_GPC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (s2ptw << 21)
+| (ind << 20) | (gpcsc << 14) | (cm << 8) | (s1ptw << 7)
+| (wnr << 6) | fsc;
+}
+
 static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
 {
 return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
-- 
2.34.1




[NOTFORMERGE PATCH v2 20/21] target/arm: Enable RME for -cpu max

2023-02-20 Thread Richard Henderson
Add a cpu property to set GPCCR_EL3.L0GPTSZ, for testing
various possible configurations.

Signed-off-by: Richard Henderson 
---
 target/arm/cpu64.c | 37 +
 1 file changed, 37 insertions(+)

diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 4066950da1..70c173ee3d 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -672,6 +672,40 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp)
 cpu->isar.id_aa64mmfr0 = t;
 }
 
+static void cpu_max_set_l0gptsz(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+uint32_t value;
+
+if (!visit_type_uint32(v, name, &value, errp)) {
+return;
+}
+
+/* Encode the value for the GPCCR_EL3 field. */
+switch (value) {
+case 30:
+case 34:
+case 36:
+case 39:
+cpu->reset_l0gptsz = value - 30;
+break;
+default:
+error_setg(errp, "invalid value for l0gptsz");
+error_append_hint(errp, "valid values are 30, 34, 36, 39\n");
+break;
+}
+}
+
+static void cpu_max_get_l0gptsz(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+uint32_t value = cpu->reset_l0gptsz + 30;
+
+visit_type_uint32(v, name, &value, errp);
+}
+
 static void aarch64_a57_initfn(Object *obj)
 {
 ARMCPU *cpu = ARM_CPU(obj);
@@ -1200,6 +1234,7 @@ static void aarch64_max_initfn(Object *obj)
 t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
 t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1);  /* FEAT_SEL2 */
 t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1);   /* FEAT_DIT */
+t = FIELD_DP64(t, ID_AA64PFR0, RME, 1);   /* FEAT_RME */
 t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2);  /* FEAT_CSV2_2 */
 t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1);  /* FEAT_CSV3 */
 cpu->isar.id_aa64pfr0 = t;
@@ -1301,6 +1336,8 @@ static void aarch64_max_initfn(Object *obj)
 object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
 cpu_max_set_sve_max_vq, NULL, NULL);
 qdev_property_add_static(DEVICE(obj), &arm_cpu_lpa2_property);
+object_property_add(obj, "l0gptsz", "uint32", cpu_max_get_l0gptsz,
+cpu_max_set_l0gptsz, NULL, NULL);
 }
 
 static const ARMCPUInfo aarch64_cpus[] = {
-- 
2.34.1




[NOTFORMERGE PATCH v2 21/21] hw/arm/virt: Add some memory for Realm Management Monitor

2023-02-20 Thread Richard Henderson
This is arbitrary, but used by the Huawei TF-A test code.

Signed-off-by: Richard Henderson 
---
 include/hw/arm/virt.h |  2 ++
 hw/arm/virt.c | 43 +++
 2 files changed, 45 insertions(+)

diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index e1ddbea96b..5c0c8a67e4 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -86,6 +86,7 @@ enum {
 VIRT_ACPI_GED,
 VIRT_NVDIMM_ACPI,
 VIRT_PVTIME,
+VIRT_RMM_MEM,
 VIRT_LOWMEMMAP_LAST,
 };
 
@@ -159,6 +160,7 @@ struct VirtMachineState {
 bool virt;
 bool ras;
 bool mte;
+bool rmm;
 bool dtb_randomness;
 OnOffAuto acpi;
 VirtGICType gic_version;
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ac626b3bef..067f16cd77 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -159,6 +159,7 @@ static const MemMapEntry base_memmap[] = {
 /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
 [VIRT_PLATFORM_BUS] =   { 0x0c00, 0x0200 },
 [VIRT_SECURE_MEM] = { 0x0e00, 0x0100 },
+[VIRT_RMM_MEM] ={ 0x0f00, 0x0010 },
 [VIRT_PCIE_MMIO] =  { 0x1000, 0x2eff },
 [VIRT_PCIE_PIO] =   { 0x3eff, 0x0001 },
 [VIRT_PCIE_ECAM] =  { 0x3f00, 0x0100 },
@@ -1602,6 +1603,25 @@ static void create_secure_ram(VirtMachineState *vms,
 g_free(nodename);
 }
 
+static void create_rmm_ram(VirtMachineState *vms,
+   MemoryRegion *sysmem,
+   MemoryRegion *tag_sysmem)
+{
+MemoryRegion *rmm_ram = g_new(MemoryRegion, 1);
+hwaddr base = vms->memmap[VIRT_RMM_MEM].base;
+hwaddr size = vms->memmap[VIRT_RMM_MEM].size;
+
+memory_region_init_ram(rmm_ram, NULL, "virt.rmm-ram", size,
+   &error_fatal);
+memory_region_add_subregion(sysmem, base, rmm_ram);
+
+/* do not fill in fdt to hide rmm from normal world guest */
+
+if (tag_sysmem) {
+create_tag_ram(tag_sysmem, base, size, "mach-virt.rmm-tag");
+}
+}
+
 static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
 {
 const VirtMachineState *board = container_of(binfo, VirtMachineState,
@@ -2283,6 +2303,10 @@ static void machvirt_init(MachineState *machine)
machine->ram_size, "mach-virt.tag");
 }
 
+if (vms->rmm) {
+create_rmm_ram(vms, sysmem, tag_sysmem);
+}
+
 vms->highmem_ecam &= (!firmware_loaded || aarch64);
 
 create_rtc(vms);
@@ -2562,6 +2586,20 @@ static void virt_set_mte(Object *obj, bool value, Error 
**errp)
 vms->mte = value;
 }
 
+static bool virt_get_rmm(Object *obj, Error **errp)
+{
+VirtMachineState *vms = VIRT_MACHINE(obj);
+
+return vms->rmm;
+}
+
+static void virt_set_rmm(Object *obj, bool value, Error **errp)
+{
+VirtMachineState *vms = VIRT_MACHINE(obj);
+
+vms->rmm = value;
+}
+
 static char *virt_get_gic_version(Object *obj, Error **errp)
 {
 VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -3115,6 +3153,11 @@ static void virt_machine_class_init(ObjectClass *oc, 
void *data)
   "guest CPU which implements the ARM "
   "Memory Tagging Extension");
 
+object_class_property_add_bool(oc, "rmm", virt_get_rmm, virt_set_rmm);
+object_class_property_set_description(oc, "rmm",
+  "Set on/off to enable/disable ram "
+  "for the Realm Management Monitor");
+
 object_class_property_add_bool(oc, "its", virt_get_its,
virt_set_its);
 object_class_property_set_description(oc, "its",
-- 
2.34.1




[PATCH v2 05/21] target/arm: Add RME cpregs

2023-02-20 Thread Richard Henderson
This includes GPCCR, GPTBR, MFAR, the TLB flush insns PAALL, PAALLOS,
RPALOS, RPAOS, and the cache flush insns CIPAPA and CIGDPAPA.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h| 19 +++
 target/arm/helper.c | 83 +
 2 files changed, 102 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 486baf3924..6a97c727d1 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -541,6 +541,11 @@ typedef struct CPUArchState {
 uint64_t fgt_read[2]; /* HFGRTR, HDFGRTR */
 uint64_t fgt_write[2]; /* HFGWTR, HDFGWTR */
 uint64_t fgt_exec[1]; /* HFGITR */
+
+/* RME registers */
+uint64_t gpccr_el3;
+uint64_t gptbr_el3;
+uint64_t mfar_el3;
 } cp15;
 
 struct {
@@ -1043,6 +1048,7 @@ struct ArchCPU {
 uint64_t reset_cbar;
 uint32_t reset_auxcr;
 bool reset_hivecs;
+uint8_t reset_l0gptsz;
 
 /*
  * Intermediate values used during property parsing.
@@ -2336,6 +2342,19 @@ FIELD(MVFR1, SIMDFMAC, 28, 4)
 FIELD(MVFR2, SIMDMISC, 0, 4)
 FIELD(MVFR2, FPMISC, 4, 4)
 
+FIELD(GPCCR, PPS, 0, 3)
+FIELD(GPCCR, IRGN, 8, 2)
+FIELD(GPCCR, ORGN, 10, 2)
+FIELD(GPCCR, SH, 12, 2)
+FIELD(GPCCR, PGS, 14, 2)
+FIELD(GPCCR, GPC, 16, 1)
+FIELD(GPCCR, GPCP, 17, 1)
+FIELD(GPCCR, L0GPTSZ, 20, 4)
+
+FIELD(MFAR, FPA, 12, 40)
+FIELD(MFAR, NSE, 62, 1)
+FIELD(MFAR, NS, 63, 1)
+
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= 
R_V7M_CSSELR_INDEX_MASK);
 
 /* If adding a feature bit which corresponds to a Linux ELF
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2ebca3e2b6..c769218763 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6932,6 +6932,83 @@ static const ARMCPRegInfo sme_reginfo[] = {
   .access = PL2_RW, .accessfn = access_esm,
   .type = ARM_CP_CONST, .resetvalue = 0 },
 };
+
+static void tlbi_aa64_paall_write(CPUARMState *env, const ARMCPRegInfo *ri,
+  uint64_t value)
+{
+CPUState *cs = env_cpu(env);
+
+tlb_flush(cs);
+}
+
+static void gpccr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+uint64_t value)
+{
+/* L0GPTSZ is RO; other bits not mentioned are RES0. */
+uint64_t rw_mask = R_GPCCR_PPS_MASK | R_GPCCR_IRGN_MASK |
+R_GPCCR_ORGN_MASK | R_GPCCR_SH_MASK | R_GPCCR_PGS_MASK |
+R_GPCCR_GPC_MASK | R_GPCCR_GPCP_MASK;
+
+env->cp15.gpccr_el3 = (value & rw_mask) | (env->cp15.gpccr_el3 & ~rw_mask);
+}
+
+static void gpccr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+env->cp15.gpccr_el3 = FIELD_DP64(0, GPCCR, L0GPTSZ,
+ env_archcpu(env)->reset_l0gptsz);
+}
+
+static void tlbi_aa64_paallos_write(CPUARMState *env, const ARMCPRegInfo *ri,
+uint64_t value)
+{
+CPUState *cs = env_cpu(env);
+
+tlb_flush_all_cpus_synced(cs);
+}
+
+static const ARMCPRegInfo rme_reginfo[] = {
+{ .name = "GPCCR_EL3", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 1, .opc2 = 6,
+  .access = PL3_RW, .writefn = gpccr_write, .resetfn = gpccr_reset,
+  .fieldoffset = offsetof(CPUARMState, cp15.gpccr_el3) },
+{ .name = "GPTBR_EL3", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 1, .opc2 = 4,
+  .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.gptbr_el3) },
+{ .name = "MFAR_EL3", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 6, .crn = 6, .crm = 0, .opc2 = 5,
+  .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mfar_el3) },
+{ .name = "TLBI_PAALL", .state = ARM_CP_STATE_AA64,
+  .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 4,
+  .access = PL3_W, .type = ARM_CP_NO_RAW,
+  .writefn = tlbi_aa64_paall_write },
+{ .name = "TLBI_PAALLOS", .state = ARM_CP_STATE_AA64,
+  .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 4,
+  .access = PL3_W, .type = ARM_CP_NO_RAW,
+  .writefn = tlbi_aa64_paallos_write },
+/*
+ * QEMU does not have a way to invalidate by physical address, thus
+ * invalidating a range of physical addresses is accomplished by
+ * flushing all tlb entries in the outer sharable domain,
+ * just like PAALLOS.
+ */
+{ .name = "TLBI_RPALOS", .state = ARM_CP_STATE_AA64,
+  .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 4, .opc2 = 7,
+  .access = PL3_W, .type = ARM_CP_NO_RAW,
+  .writefn = tlbi_aa64_paallos_write },
+{ .name = "TLBI_RPAOS", .state = ARM_CP_STATE_AA64,
+  .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 4, .opc2 = 3,
+  .access = PL3_W, .type = ARM_CP_NO_RAW,
+  .writefn = tlbi_aa64_paallos_write },
+{ .name = "DC_CIPAPA", .state = ARM_CP_STATE_AA64,
+  .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 14, .opc2 = 1,
+  .access = PL3_W, .type = ARM_CP_NOP },
+};
+
+static const ARMCPRegInfo rme_mte_reginfo[] = {
+{ .name = "DC_CIGDPAPA", .state = ARM_CP_STATE_AA64,
+  

[PATCH v2 04/21] target/arm: SCR_EL3.NS may be RES1

2023-02-20 Thread Richard Henderson
With RME, SEL2 must also be present to support secure state.
The NS bit is RES1 if SEL2 is not present.

Signed-off-by: Richard Henderson 
---
 target/arm/helper.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 42d94e0904..2ebca3e2b6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1856,6 +1856,9 @@ static void scr_write(CPUARMState *env, const 
ARMCPRegInfo *ri, uint64_t value)
 }
 if (cpu_isar_feature(aa64_sel2, cpu)) {
 valid_mask |= SCR_EEL2;
+} else if (cpu_isar_feature(aa64_rme, cpu)) {
+/* With RME and without SEL2, NS is RES1 (R_GSWWH, I_DJJQJ). */
+value |= SCR_NS;
 }
 if (cpu_isar_feature(aa64_mte, cpu)) {
 valid_mask |= SCR_ATA;
-- 
2.34.1




[PATCH v2 13/21] target/arm: Handle no-execute for Realm and Root regimes

2023-02-20 Thread Richard Henderson
While Root and Realm may read and write data from other spaces,
neither may execute from other pa spaces.

This happens for Stage1 EL3, EL2, EL2&0, but stage2 EL1&0.

Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 52 ++--
 1 file changed, 46 insertions(+), 6 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index a9a9a8a403..54e72baff5 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -909,7 +909,7 @@ do_fault:
  * @xn:  XN (execute-never) bits
  * @s1_is_el0: true if this is S2 of an S1+2 walk for EL0
  */
-static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
+static int get_S2prot_noexecute(int s2ap)
 {
 int prot = 0;
 
@@ -919,6 +919,12 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn, 
bool s1_is_el0)
 if (s2ap & 2) {
 prot |= PAGE_WRITE;
 }
+return prot;
+}
+
+static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
+{
+int prot = get_S2prot_noexecute(s2ap);
 
 if (cpu_isar_feature(any_tts2uxn, env_archcpu(env))) {
 switch (xn) {
@@ -984,9 +990,39 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, 
bool is_aa64,
 }
 }
 
-if (out_pa == ARMSS_NonSecure && in_pa == ARMSS_Secure &&
-(env->cp15.scr_el3 & SCR_SIF)) {
-return prot_rw;
+if (in_pa != out_pa) {
+switch (in_pa) {
+case ARMSS_Root:
+/*
+ * R_ZWRVD: permission fault for insn fetched from non-Root,
+ * I_WWBFB: SIF has no effect in EL3.
+ */
+return prot_rw;
+case ARMSS_Realm:
+/*
+ * R_PKTDS: permission fault for insn fetched from non-Realm,
+ * for Realm EL2 or EL2&0.  The corresponding fault for EL1&0
+ * happens during any stage2 translation.
+ */
+switch (mmu_idx) {
+case ARMMMUIdx_E2:
+case ARMMMUIdx_E20_0:
+case ARMMMUIdx_E20_2:
+case ARMMMUIdx_E20_2_PAN:
+return prot_rw;
+default:
+break;
+}
+break;
+case ARMSS_Secure:
+if (env->cp15.scr_el3 & SCR_SIF) {
+return prot_rw;
+}
+break;
+default:
+/* Input NonSecure must have output NonSecure. */
+g_assert_not_reached();
+}
 }
 
 /* TODO have_wxn should be replaced with
@@ -1563,12 +1599,16 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 /*
  * R_GYNXY: For stage2 in Realm security state, bit 55 is NS.
  * The bit remains ignored for other security states.
+ * R_YMCSL: Executing an insn fetched from non-Realm causes
+ * a stage2 permission fault.
  */
 if (out_space == ARMSS_Realm && extract64(attrs, 55, 1)) {
 out_space = ARMSS_NonSecure;
+result->f.prot = get_S2prot_noexecute(ap);
+} else {
+xn = extract64(attrs, 53, 2);
+result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
 }
-xn = extract64(attrs, 53, 2);
-result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
 } else {
 int nse, ns = extract32(attrs, 5, 1);
 switch (out_space) {
-- 
2.34.1




[PATCH v2 10/21] target/arm: Pipe ARMSecuritySpace through ptw.c

2023-02-20 Thread Richard Henderson
Add input and output space members to S1Translate.
Set and adjust them in S1_ptw_translate, and the
various points at which we drop secure state.
Initialize the space in get_phys_addr; for now
leave get_phys_addr_with_secure considering only
secure vs non-secure spaces.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 95 ++--
 1 file changed, 76 insertions(+), 19 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 5a0c5edc88..7745287a46 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -19,11 +19,13 @@
 typedef struct S1Translate {
 ARMMMUIdx in_mmu_idx;
 ARMMMUIdx in_ptw_idx;
+ARMSecuritySpace in_space;
 bool in_secure;
 bool in_debug;
 bool out_secure;
 bool out_rw;
 bool out_be;
+ARMSecuritySpace out_space;
 hwaddr out_virt;
 hwaddr out_phys;
 void *out_host;
@@ -218,6 +220,7 @@ static bool S2_attrs_are_device(uint64_t hcr, uint8_t attrs)
 static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
  hwaddr addr, ARMMMUFaultInfo *fi)
 {
+ARMSecuritySpace space = ptw->in_space;
 bool is_secure = ptw->in_secure;
 ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
 ARMMMUIdx s2_mmu_idx = ptw->in_ptw_idx;
@@ -234,7 +237,8 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate 
*ptw,
 if (regime_is_stage2(s2_mmu_idx)) {
 S1Translate s2ptw = {
 .in_mmu_idx = s2_mmu_idx,
-.in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS,
+.in_ptw_idx = arm_space_to_phys(space),
+.in_space = space,
 .in_secure = is_secure,
 .in_debug = true,
 };
@@ -292,10 +296,17 @@ static bool S1_ptw_translate(CPUARMState *env, 
S1Translate *ptw,
 }
 
 /* Check if page table walk is to secure or non-secure PA space. */
-ptw->out_secure = (is_secure
-   && !(pte_secure
+if (is_secure) {
+bool out_secure = !(pte_secure
 ? env->cp15.vstcr_el2 & VSTCR_SW
-: env->cp15.vtcr_el2 & VTCR_NSW));
+: env->cp15.vtcr_el2 & VTCR_NSW);
+if (!out_secure) {
+is_secure = false;
+space = ARMSS_NonSecure;
+}
+}
+ptw->out_secure = is_secure;
+ptw->out_space = space;
 ptw->out_be = regime_translation_big_endian(env, mmu_idx);
 return true;
 
@@ -326,7 +337,10 @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate 
*ptw,
 }
 } else {
 /* Page tables are in MMIO. */
-MemTxAttrs attrs = { .secure = ptw->out_secure };
+MemTxAttrs attrs = {
+.secure = ptw->out_secure,
+.space = ptw->out_space,
+};
 AddressSpace *as = arm_addressspace(cs, attrs);
 MemTxResult result = MEMTX_OK;
 
@@ -369,7 +383,10 @@ static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate 
*ptw,
 #endif
 } else {
 /* Page tables are in MMIO. */
-MemTxAttrs attrs = { .secure = ptw->out_secure };
+MemTxAttrs attrs = {
+.secure = ptw->out_secure,
+.space = ptw->out_space,
+};
 AddressSpace *as = arm_addressspace(cs, attrs);
 MemTxResult result = MEMTX_OK;
 
@@ -875,6 +892,7 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate 
*ptw,
  * regime, because the attribute will already be non-secure.
  */
 result->f.attrs.secure = false;
+result->f.attrs.space = ARMSS_NonSecure;
 }
 result->f.phys_addr = phys_addr;
 return false;
@@ -1579,6 +1597,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
  * regime, because the attribute will already be non-secure.
  */
 result->f.attrs.secure = false;
+result->f.attrs.space = ARMSS_NonSecure;
 }
 
 /* When in aarch64 mode, and BTI is enabled, remember GP in the TLB.  */
@@ -2363,6 +2382,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, 
uint32_t address,
  */
 if (sattrs.ns) {
 result->f.attrs.secure = false;
+result->f.attrs.space = ARMSS_NonSecure;
 } else if (!secure) {
 /*
  * NS access to S memory must fault.
@@ -2712,6 +2732,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, 
S1Translate *ptw,
 bool is_secure = ptw->in_secure;
 bool ret, ipa_secure, s2walk_secure;
 ARMCacheAttrs cacheattrs1;
+ARMSecuritySpace ipa_space, s2walk_space;
 bool is_el0;
 uint64_t hcr;
 
@@ -2724,20 +2745,24 @@ static bool get_phys_addr_twostage(CPUARMState *env, 
S1Translate *ptw,
 
 ipa = result->f.phys_addr;
 ipa_secure = result->f.attrs.secure;
+ipa_space = result->f.attrs.space;
 if (is_secure) {
 /* Select TCR based on the NS bit fr

[PATCH v2 09/21] target/arm: Introduce ARMMMUIdx_Phys_{Realm,Root}

2023-02-20 Thread Richard Henderson
With FEAT_RME, there are four physical address spaces.
For now, just define the symbols, and mention them in
the same spots as the other Phys indexes in ptw.c.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu-param.h |  2 +-
 target/arm/cpu.h   | 23 +--
 target/arm/ptw.c   | 10 --
 3 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
index 53cac9c89b..8dfd7a0bb6 100644
--- a/target/arm/cpu-param.h
+++ b/target/arm/cpu-param.h
@@ -47,6 +47,6 @@
 bool guarded;
 #endif
 
-#define NB_MMU_MODES 12
+#define NB_MMU_MODES 14
 
 #endif
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c9585390d4..4bafe8340e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2864,8 +2864,10 @@ typedef enum ARMMMUIdx {
 ARMMMUIdx_Stage2= 9 | ARM_MMU_IDX_A,
 
 /* TLBs with 1-1 mapping to the physical address spaces. */
-ARMMMUIdx_Phys_S= 10 | ARM_MMU_IDX_A,
-ARMMMUIdx_Phys_NS   = 11 | ARM_MMU_IDX_A,
+ARMMMUIdx_Phys_S = 10 | ARM_MMU_IDX_A,
+ARMMMUIdx_Phys_NS= 11 | ARM_MMU_IDX_A,
+ARMMMUIdx_Phys_Root  = 12 | ARM_MMU_IDX_A,
+ARMMMUIdx_Phys_Realm = 13 | ARM_MMU_IDX_A,
 
 /*
  * These are not allocated TLBs and are used only for AT system
@@ -2929,6 +2931,23 @@ typedef enum ARMASIdx {
 ARMASIdx_TagS = 3,
 } ARMASIdx;
 
+static inline ARMMMUIdx arm_space_to_phys(ARMSecuritySpace space)
+{
+/* Assert the relative order of the physical mmu indexes. */
+QEMU_BUILD_BUG_ON(ARMSS_Secure != 0);
+QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_NS != ARMMMUIdx_Phys_S + ARMSS_NonSecure);
+QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_Root != ARMMMUIdx_Phys_S + ARMSS_Root);
+QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_Realm != ARMMMUIdx_Phys_S + ARMSS_Realm);
+
+return ARMMMUIdx_Phys_S + space;
+}
+
+static inline ARMSecuritySpace arm_phys_to_space(ARMMMUIdx idx)
+{
+assert(idx >= ARMMMUIdx_Phys_S && idx <= ARMMMUIdx_Phys_Realm);
+return idx - ARMMMUIdx_Phys_S;
+}
+
 static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
 {
 /* If all the CLIDR.Ctypem bits are 0 there are no caches, and
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 5ed5bb5039..5a0c5edc88 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -182,8 +182,10 @@ static bool regime_translation_disabled(CPUARMState *env, 
ARMMMUIdx mmu_idx,
 case ARMMMUIdx_E3:
 break;
 
-case ARMMMUIdx_Phys_NS:
 case ARMMMUIdx_Phys_S:
+case ARMMMUIdx_Phys_NS:
+case ARMMMUIdx_Phys_Root:
+case ARMMMUIdx_Phys_Realm:
 /* No translation for physical address spaces. */
 return true;
 
@@ -2632,8 +2634,10 @@ static bool get_phys_addr_disabled(CPUARMState *env, 
target_ulong address,
 switch (mmu_idx) {
 case ARMMMUIdx_Stage2:
 case ARMMMUIdx_Stage2_S:
-case ARMMMUIdx_Phys_NS:
 case ARMMMUIdx_Phys_S:
+case ARMMMUIdx_Phys_NS:
+case ARMMMUIdx_Phys_Root:
+case ARMMMUIdx_Phys_Realm:
 break;
 
 default:
@@ -2830,6 +2834,8 @@ static bool get_phys_addr_with_struct(CPUARMState *env, 
S1Translate *ptw,
 switch (mmu_idx) {
 case ARMMMUIdx_Phys_S:
 case ARMMMUIdx_Phys_NS:
+case ARMMMUIdx_Phys_Root:
+case ARMMMUIdx_Phys_Realm:
 /* Checking Phys early avoids special casing later vs regime_el. */
 return get_phys_addr_disabled(env, address, access_type, mmu_idx,
   is_secure, result, fi);
-- 
2.34.1




[PATCH v2 16/21] target/arm: Use get_phys_addr_with_struct for stage2

2023-02-20 Thread Richard Henderson
This fixes a bug in which we failed to initialize
the result attributes properly after the memset.

Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 13 +
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index d4027ce763..a797750f9b 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -37,12 +37,6 @@ typedef struct S1Translate {
 void *out_host;
 } S1Translate;
 
-static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
-   uint64_t address,
-   MMUAccessType access_type,
-   GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
-__attribute__((nonnull));
-
 static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
   target_ulong address,
   MMUAccessType access_type,
@@ -2862,12 +2856,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, 
S1Translate *ptw,
 cacheattrs1 = result->cacheattrs;
 memset(result, 0, sizeof(*result));
 
-if (arm_feature(env, ARM_FEATURE_PMSA)) {
-ret = get_phys_addr_pmsav8(env, ipa, access_type,
-   ptw->in_mmu_idx, is_secure, result, fi);
-} else {
-ret = get_phys_addr_lpae(env, ptw, ipa, access_type, result, fi);
-}
+ret = get_phys_addr_with_struct(env, ptw, ipa, access_type, result, fi);
 fi->s2addr = ipa;
 
 /* Combine the S1 and S2 perms.  */
-- 
2.34.1




[PATCH v2 07/21] include/exec/memattrs: Add two bits of space to MemTxAttrs

2023-02-20 Thread Richard Henderson
We will need 2 bits to represent ARMSecurityState.

Do not attempt to replace or widen secure, even though it
logically overlaps the new field -- there are uses within
e.g. hw/block/pflash_cfi01.c, which don't know anything
specific about ARM.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 include/exec/memattrs.h | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
index 9fb98bc1ef..d04170aa27 100644
--- a/include/exec/memattrs.h
+++ b/include/exec/memattrs.h
@@ -29,10 +29,17 @@ typedef struct MemTxAttrs {
  * "didn't specify" if necessary.
  */
 unsigned int unspecified:1;
-/* ARM/AMBA: TrustZone Secure access
+/*
+ * ARM/AMBA: TrustZone Secure access
  * x86: System Management Mode access
  */
 unsigned int secure:1;
+/*
+ * ARM: ArmSecuritySpace.  This partially overlaps secure, but it is
+ * easier to have both fields to assist code that does not understand
+ * ARMv9 RME, or no specific knowledge of ARM at all (e.g. pflash).
+ */
+unsigned int space:2;
 /* Memory access is usermode (unprivileged) */
 unsigned int user:1;
 /*
-- 
2.34.1




[PATCH v2 18/21] target/arm: Implement GPC exceptions

2023-02-20 Thread Richard Henderson
Handle GPC Fault types in arm_deliver_fault, reporting as
either a GPC exception at EL3, or falling through to insn
or data aborts at various exception levels.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h|  1 +
 target/arm/internals.h  | 27 
 target/arm/helper.c |  5 +++
 target/arm/tlb_helper.c | 96 +++--
 4 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 4bafe8340e..faafb63520 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -57,6 +57,7 @@
 #define EXCP_UNALIGNED  22   /* v7M UNALIGNED UsageFault */
 #define EXCP_DIVBYZERO  23   /* v7M DIVBYZERO UsageFault */
 #define EXCP_VSERR  24
+#define EXCP_GPC25   /* v9 Granule Protection Check Fault */
 /* NB: add new EXCP_ defines to the array in arm_log_exception() too */
 
 #define ARMV7M_EXCP_RESET   1
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 759b70c646..5e88649fea 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -352,14 +352,27 @@ typedef enum ARMFaultType {
 ARMFault_ICacheMaint,
 ARMFault_QEMU_NSCExec, /* v8M: NS executing in S&NSC memory */
 ARMFault_QEMU_SFault, /* v8M: SecureFault INVTRAN, INVEP or AUVIOL */
+ARMFault_GPCFOnWalk,
+ARMFault_GPCFOnOutput,
 } ARMFaultType;
 
+typedef enum ARMGPCF {
+GPCF_None,
+GPCF_AddressSize,
+GPCF_Walk,
+GPCF_EABT,
+GPCF_Fail,
+} ARMGPCF;
+
 /**
  * ARMMMUFaultInfo: Information describing an ARM MMU Fault
  * @type: Type of fault
+ * @gpcf: Subtype of ARMFault_GPCFOn{Walk,Output}.
  * @level: Table walk level (for translation, access flag and permission 
faults)
  * @domain: Domain of the fault address (for non-LPAE CPUs only)
  * @s2addr: Address that caused a fault at stage 2
+ * @paddr: physical address that caused a fault for gpc
+ * @paddr_space: physical address space that caused a fault for gpc
  * @stage2: True if we faulted at stage 2
  * @s1ptw: True if we faulted at stage 2 while doing a stage 1 page-table walk
  * @s1ns: True if we faulted on a non-secure IPA while in secure state
@@ -368,7 +381,10 @@ typedef enum ARMFaultType {
 typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
 struct ARMMMUFaultInfo {
 ARMFaultType type;
+ARMGPCF gpcf;
 target_ulong s2addr;
+target_ulong paddr;
+ARMSecuritySpace paddr_space;
 int level;
 int domain;
 bool stage2;
@@ -542,6 +558,17 @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo *fi)
 case ARMFault_Exclusive:
 fsc = 0x35;
 break;
+case ARMFault_GPCFOnWalk:
+assert(fi->level >= -1 && fi->level <= 3);
+if (fi->level < 0) {
+fsc = 0b100011;
+} else {
+fsc = 0b100100 | fi->level;
+}
+break;
+case ARMFault_GPCFOnOutput:
+fsc = 0b101000;
+break;
 default:
 /* Other faults can't occur in a context that requires a
  * long-format status code.
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 13af812215..5dc3329f0c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -10235,6 +10235,7 @@ void arm_log_exception(CPUState *cs)
 [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
 [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
 [EXCP_VSERR] = "Virtual SERR",
+[EXCP_GPC] = "Granule Protection Check",
 };
 
 if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
@@ -10963,6 +10964,10 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
 }
 
 switch (cs->exception_index) {
+case EXCP_GPC:
+qemu_log_mask(CPU_LOG_INT, "...with MFAR 0x%" PRIx64 "\n",
+  env->cp15.mfar_el3);
+/* fall through */
 case EXCP_PREFETCH_ABORT:
 case EXCP_DATA_ABORT:
 /*
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
index 60abcbebe6..aa03d3f8dc 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tlb_helper.c
@@ -109,17 +109,106 @@ static uint32_t compute_fsr_fsc(CPUARMState *env, 
ARMMMUFaultInfo *fi,
 return fsr;
 }
 
+static bool report_as_gpc_exception(ARMCPU *cpu, int current_el,
+ARMMMUFaultInfo *fi)
+{
+bool ret;
+
+switch (fi->gpcf) {
+case GPCF_None:
+return false;
+case GPCF_AddressSize:
+case GPCF_Walk:
+case GPCF_EABT:
+/* R_PYTGX: GPT faults are reported as GPC. */
+ret = true;
+break;
+case GPCF_Fail:
+/*
+ * R_BLYPM: A GPF at EL3 is reported as insn or data abort.
+ * R_VBZMW, R_LXHQR: A GPF at EL[0-2] is reported as a GPC
+ * if SCR_EL3.GPF is set, otherwise an insn or data abort.
+ */
+ret = (cpu->env.cp15.scr_el3 & SCR_GPF) && current_el != 3;
+break;
+default:
+g_assert_not_reached();
+}
+
+assert(cpu_isar_feature(aa64_rme, cpu));
+  

[PATCH v2 03/21] target/arm: Update SCR and HCR for RME

2023-02-20 Thread Richard Henderson
Define the missing SCR and HCR bits, allow SCR_NSE and {SCR,HCR}_GPF
to be set, and invalidate TLBs when NSE changes.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h|  5 +++--
 target/arm/helper.c | 10 --
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 04f000cc54..486baf3924 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1650,7 +1650,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t 
val, uint32_t mask)
 #define HCR_TERR  (1ULL << 36)
 #define HCR_TEA   (1ULL << 37)
 #define HCR_MIOCNCE   (1ULL << 38)
-/* RES0 bit 39 */
+#define HCR_TME   (1ULL << 39)
 #define HCR_APK   (1ULL << 40)
 #define HCR_API   (1ULL << 41)
 #define HCR_NV(1ULL << 42)
@@ -1659,7 +1659,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t 
val, uint32_t mask)
 #define HCR_NV2   (1ULL << 45)
 #define HCR_FWB   (1ULL << 46)
 #define HCR_FIEN  (1ULL << 47)
-/* RES0 bit 48 */
+#define HCR_GPF   (1ULL << 48)
 #define HCR_TID4  (1ULL << 49)
 #define HCR_TICAB (1ULL << 50)
 #define HCR_AMVOFFEN  (1ULL << 51)
@@ -1724,6 +1724,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t 
val, uint32_t mask)
 #define SCR_TRNDR (1ULL << 40)
 #define SCR_ENTP2 (1ULL << 41)
 #define SCR_GPF   (1ULL << 48)
+#define SCR_NSE   (1ULL << 62)
 
 #define HSTR_TTEE (1 << 16)
 #define HSTR_TJDBX (1 << 17)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 07d4100365..42d94e0904 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1875,6 +1875,9 @@ static void scr_write(CPUARMState *env, const 
ARMCPRegInfo *ri, uint64_t value)
 if (cpu_isar_feature(aa64_fgt, cpu)) {
 valid_mask |= SCR_FGTEN;
 }
+if (cpu_isar_feature(aa64_rme, cpu)) {
+valid_mask |= SCR_NSE | SCR_GPF;
+}
 } else {
 valid_mask &= ~(SCR_RW | SCR_ST);
 if (cpu_isar_feature(aa32_ras, cpu)) {
@@ -1904,10 +1907,10 @@ static void scr_write(CPUARMState *env, const 
ARMCPRegInfo *ri, uint64_t value)
 env->cp15.scr_el3 = value;
 
 /*
- * If SCR_EL3.NS changes, i.e. arm_is_secure_below_el3, then
+ * If SCR_EL3.{NS,NSE} changes, i.e. change of security state,
  * we must invalidate all TLBs below EL3.
  */
-if (changed & SCR_NS) {
+if (changed & (SCR_NS | SCR_NSE)) {
 tlb_flush_by_mmuidx(env_cpu(env), (ARMMMUIdxBit_E10_0 |
ARMMMUIdxBit_E20_0 |
ARMMMUIdxBit_E10_1 |
@@ -5655,6 +5658,9 @@ static void do_hcr_write(CPUARMState *env, uint64_t 
value, uint64_t valid_mask)
 if (cpu_isar_feature(aa64_fwb, cpu)) {
 valid_mask |= HCR_FWB;
 }
+if (cpu_isar_feature(aa64_rme, cpu)) {
+valid_mask |= HCR_GPF;
+}
 }
 
 if (cpu_isar_feature(any_evt, cpu)) {
-- 
2.34.1




[PATCH v2 00/21] target/arm: Implement FEAT_RME

2023-02-20 Thread Richard Henderson
This is based on mainline, without any extra ARMv9-A dependencies
which are still under development.  This is good enough to pass
all of the tests within

https://github.com/Huawei/Huawei_CCA_QEMU

Changes for v2:
  * Drop "Fix pmsav8 stage2 secure parameter".
  * Incorporate review feedback.
  * Mark last two patches as "NOTFORMERGE".


r~


Richard Henderson (21):
  target/arm: Rewrite check_s2_mmu_setup
  target/arm: Add isar_feature_aa64_rme
  target/arm: Update SCR and HCR for RME
  target/arm: SCR_EL3.NS may be RES1
  target/arm: Add RME cpregs
  target/arm: Introduce ARMSecuritySpace
  include/exec/memattrs: Add two bits of space to MemTxAttrs
  target/arm: Adjust the order of Phys and Stage2 ARMMMUIdx
  target/arm: Introduce ARMMMUIdx_Phys_{Realm,Root}
  target/arm: Pipe ARMSecuritySpace through ptw.c
  target/arm: NSTable is RES0 for the RME EL3 regime
  target/arm: Handle Block and Page bits for security space
  target/arm: Handle no-execute for Realm and Root regimes
  target/arm: Use get_phys_addr_with_struct in S1_ptw_translate
  target/arm: Move s1_is_el0 into S1Translate
  target/arm: Use get_phys_addr_with_struct for stage2
  target/arm: Add GPC syndrome
  target/arm: Implement GPC exceptions
  target/arm: Implement the granule protection check
  target/arm: Enable RME for -cpu max
  hw/arm/virt: Add some memory for Realm Management Monitor

 include/exec/memattrs.h |   9 +-
 include/hw/arm/virt.h   |   2 +
 target/arm/cpu-param.h  |   2 +-
 target/arm/cpu.h| 148 ++--
 target/arm/internals.h  |  27 ++
 target/arm/syndrome.h   |  10 +
 hw/arm/virt.c   |  43 +++
 target/arm/cpu.c|   4 +
 target/arm/cpu64.c  |  37 ++
 target/arm/helper.c | 155 -
 target/arm/ptw.c| 748 ++--
 target/arm/tlb_helper.c |  96 +-
 12 files changed, 1058 insertions(+), 223 deletions(-)

-- 
2.34.1




[PATCH v2 06/21] target/arm: Introduce ARMSecuritySpace

2023-02-20 Thread Richard Henderson
Introduce both the enumeration and functions to retrieve
the current state, and state outside of EL3.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h| 86 +++--
 target/arm/helper.c | 54 
 2 files changed, 122 insertions(+), 18 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 6a97c727d1..1b982dc94c 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2409,23 +2409,53 @@ static inline int arm_feature(CPUARMState *env, int 
feature)
 
 void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp);
 
+/*
+ * ARM v9 security states.
+ * The ordering of the enumeration corresponds to the low 2 bits
+ * of the GPI value, and (except for Root) the concat of NSE:NS.
+ */
+
+typedef enum ARMSecuritySpace {
+ARMSS_Secure = 0,
+ARMSS_NonSecure  = 1,
+ARMSS_Root   = 2,
+ARMSS_Realm  = 3,
+} ARMSecuritySpace;
+
+/* Return true if @space is secure, in the pre-v9 sense. */
+static inline bool arm_space_is_secure(ARMSecuritySpace space)
+{
+return space == ARMSS_Secure || space == ARMSS_Root;
+}
+
+/* Return the ARMSecuritySpace for @secure, assuming !RME or EL[0-2]. */
+static inline ARMSecuritySpace arm_secure_to_space(bool secure)
+{
+return secure ? ARMSS_Secure : ARMSS_NonSecure;
+}
+
 #if !defined(CONFIG_USER_ONLY)
-/* Return true if exception levels below EL3 are in secure state,
- * or would be following an exception return to that level.
- * Unlike arm_is_secure() (which is always a question about the
- * _current_ state of the CPU) this doesn't care about the current
- * EL or mode.
+/**
+ * arm_security_space_below_el3:
+ * @env: cpu context
+ *
+ * Return the security space of exception levels below EL3, following
+ * an exception return to those levels.  Unlike arm_security_space,
+ * this doesn't care about the current EL.
+ */
+ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env);
+
+/**
+ * arm_is_secure_below_el3:
+ * @env: cpu context
+ *
+ * Return true if exception levels below EL3 are in secure state,
+ * or would be following an exception return to those levels.
  */
 static inline bool arm_is_secure_below_el3(CPUARMState *env)
 {
-if (arm_feature(env, ARM_FEATURE_EL3)) {
-return !(env->cp15.scr_el3 & SCR_NS);
-} else {
-/* If EL3 is not supported then the secure state is implementation
- * defined, in which case QEMU defaults to non-secure.
- */
-return false;
-}
+ARMSecuritySpace ss = arm_security_space_below_el3(env);
+return ss == ARMSS_Secure;
 }
 
 /* Return true if the CPU is AArch64 EL3 or AArch32 Mon */
@@ -2444,13 +2474,23 @@ static inline bool arm_is_el3_or_mon(CPUARMState *env)
 return false;
 }
 
-/* Return true if the processor is in secure state */
+/**
+ * arm_security_space:
+ * @env: cpu context
+ *
+ * Return the current security space of the cpu.
+ */
+ARMSecuritySpace arm_security_space(CPUARMState *env);
+
+/**
+ * arm_is_secure:
+ * @env: cpu context
+ *
+ * Return true if the processor is in secure state.
+ */
 static inline bool arm_is_secure(CPUARMState *env)
 {
-if (arm_is_el3_or_mon(env)) {
-return true;
-}
-return arm_is_secure_below_el3(env);
+return arm_space_is_secure(arm_security_space(env));
 }
 
 /*
@@ -2469,11 +2509,21 @@ static inline bool arm_is_el2_enabled(CPUARMState *env)
 }
 
 #else
+static inline ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env)
+{
+return ARMSS_NonSecure;
+}
+
 static inline bool arm_is_secure_below_el3(CPUARMState *env)
 {
 return false;
 }
 
+static inline ARMSecuritySpace arm_security_space(CPUARMState *env)
+{
+return ARMSS_NonSecure;
+}
+
 static inline bool arm_is_secure(CPUARMState *env)
 {
 return false;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index c769218763..13af812215 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -12535,3 +12535,57 @@ void aarch64_sve_change_el(CPUARMState *env, int 
old_el,
 }
 }
 #endif
+
+#ifndef CONFIG_USER_ONLY
+ARMSecuritySpace arm_security_space(CPUARMState *env)
+{
+/*
+ * If EL3 is not supported then the secure state is implementation
+ * defined, in which case QEMU defaults to non-secure.
+ */
+if (!arm_feature(env, ARM_FEATURE_EL3)) {
+return ARMSS_NonSecure;
+}
+
+/* Check for AArch64 EL3 or AArch32 Mon. */
+if (is_a64(env)) {
+if (extract32(env->pstate, 2, 2) == 3) {
+if (cpu_isar_feature(aa64_rme, env_archcpu(env))) {
+return ARMSS_Root;
+} else {
+return ARMSS_Secure;
+}
+}
+} else {
+if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) {
+return ARMSS_Secure;
+}
+}
+
+return arm_security_space_below_el3(env);
+}
+
+ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env)
+{
+/*
+ * If EL3 is not s

[PATCH v2 11/21] target/arm: NSTable is RES0 for the RME EL3 regime

2023-02-20 Thread Richard Henderson
Test in_space instead of in_secure so that we don't switch
out of Root space.  Handle the output space change immediately,
rather than try and combine the NSTable and NS bits later.

Signed-off-by: Richard Henderson 
---
 target/arm/ptw.c | 27 ++-
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 7745287a46..d612e5f38a 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1240,7 +1240,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 {
 ARMCPU *cpu = env_archcpu(env);
 ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
-bool is_secure = ptw->in_secure;
 int32_t level;
 ARMVAParameters param;
 uint64_t ttbr;
@@ -1256,7 +1255,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 uint64_t descaddrmask;
 bool aarch64 = arm_el_is_aa64(env, el);
 uint64_t descriptor, new_descriptor;
-bool nstable;
 
 /* TODO: This code does not support shareability levels. */
 if (aarch64) {
@@ -1417,20 +1415,19 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 descaddrmask = MAKE_64BIT_MASK(0, 40);
 }
 descaddrmask &= ~indexmask_grainsize;
-
-/*
- * Secure accesses start with the page table in secure memory and
- * can be downgraded to non-secure at any step. Non-secure accesses
- * remain non-secure. We implement this by just ORing in the NSTable/NS
- * bits at each step.
- */
-tableattrs = is_secure ? 0 : (1 << 4);
+tableattrs = 0;
 
  next_level:
 descaddr |= (address >> (stride * (4 - level))) & indexmask;
 descaddr &= ~7ULL;
-nstable = extract32(tableattrs, 4, 1);
-if (nstable && ptw->in_secure) {
+
+/*
+ * Process the NSTable bit from the previous level.  This changes
+ * the table address space and the output space from Secure to
+ * NonSecure.  With RME, the EL3 translation regime does not change
+ * from Root to NonSecure.
+ */
+if (extract32(tableattrs, 4, 1) && ptw->in_space == ARMSS_Secure) {
 /*
  * Stage2_S -> Stage2 or Phys_S -> Phys_NS
  * Assert the relative order of the secure/non-secure indexes.
@@ -1439,7 +1436,11 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2_S + 1 != ARMMMUIdx_Stage2);
 ptw->in_ptw_idx += 1;
 ptw->in_secure = false;
+ptw->in_space = ARMSS_NonSecure;
+result->f.attrs.secure = false;
+result->f.attrs.space = ARMSS_NonSecure;
 }
+
 if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
 goto do_fault;
 }
@@ -1542,7 +1543,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
  */
 attrs = new_descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 
14));
 if (!regime_is_stage2(mmu_idx)) {
-attrs |= nstable << 5; /* NS */
+attrs |= !ptw->in_secure << 5; /* NS */
 if (!param.hpd) {
 attrs |= extract64(tableattrs, 0, 2) << 53; /* XN, PXN */
 /*
-- 
2.34.1




[PATCH v2 08/21] target/arm: Adjust the order of Phys and Stage2 ARMMMUIdx

2023-02-20 Thread Richard Henderson
It will be helpful to have ARMMMUIdx_Phys_* to be in the same
relative order as ARMSecuritySpace enumerators. This requires
the adjustment to the nstable check. While there, check for being
in secure state rather than rely on clearing the low bit making
no change to non-secure state.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h | 12 ++--
 target/arm/ptw.c | 12 +---
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 1b982dc94c..c9585390d4 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2854,18 +2854,18 @@ typedef enum ARMMMUIdx {
 ARMMMUIdx_E2= 6 | ARM_MMU_IDX_A,
 ARMMMUIdx_E3= 7 | ARM_MMU_IDX_A,
 
-/* TLBs with 1-1 mapping to the physical address spaces. */
-ARMMMUIdx_Phys_NS   = 8 | ARM_MMU_IDX_A,
-ARMMMUIdx_Phys_S= 9 | ARM_MMU_IDX_A,
-
 /*
  * Used for second stage of an S12 page table walk, or for descriptor
  * loads during first stage of an S1 page table walk.  Note that both
  * are in use simultaneously for SecureEL2: the security state for
  * the S2 ptw is selected by the NS bit from the S1 ptw.
  */
-ARMMMUIdx_Stage2= 10 | ARM_MMU_IDX_A,
-ARMMMUIdx_Stage2_S  = 11 | ARM_MMU_IDX_A,
+ARMMMUIdx_Stage2_S  = 8 | ARM_MMU_IDX_A,
+ARMMMUIdx_Stage2= 9 | ARM_MMU_IDX_A,
+
+/* TLBs with 1-1 mapping to the physical address spaces. */
+ARMMMUIdx_Phys_S= 10 | ARM_MMU_IDX_A,
+ARMMMUIdx_Phys_NS   = 11 | ARM_MMU_IDX_A,
 
 /*
  * These are not allocated TLBs and are used only for AT system
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 6fb72fb086..5ed5bb5039 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1410,16 +1410,14 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
S1Translate *ptw,
 descaddr |= (address >> (stride * (4 - level))) & indexmask;
 descaddr &= ~7ULL;
 nstable = extract32(tableattrs, 4, 1);
-if (nstable) {
+if (nstable && ptw->in_secure) {
 /*
  * Stage2_S -> Stage2 or Phys_S -> Phys_NS
- * Assert that the non-secure idx are even, and relative order.
+ * Assert the relative order of the secure/non-secure indexes.
  */
-QEMU_BUILD_BUG_ON((ARMMMUIdx_Phys_NS & 1) != 0);
-QEMU_BUILD_BUG_ON((ARMMMUIdx_Stage2 & 1) != 0);
-QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_NS + 1 != ARMMMUIdx_Phys_S);
-QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2 + 1 != ARMMMUIdx_Stage2_S);
-ptw->in_ptw_idx &= ~1;
+QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_S + 1 != ARMMMUIdx_Phys_NS);
+QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2_S + 1 != ARMMMUIdx_Stage2);
+ptw->in_ptw_idx += 1;
 ptw->in_secure = false;
 }
 if (!S1_ptw_translate(env, ptw, descaddr, fi)) {
-- 
2.34.1




Re: [PATCH] hw/acpi: Set memory regions to native endian as a work around

2023-02-20 Thread BALATON Zoltan

On Mon, 20 Feb 2023, Michael S. Tsirkin wrote:

On Mon, Feb 20, 2023 at 07:24:59PM +0100, BALATON Zoltan wrote:

On Tue, 22 Feb 2022, Michael S. Tsirkin wrote:

On Wed, Jan 19, 2022 at 04:19:14AM -0500, Michael S. Tsirkin wrote:

On Sat, Nov 13, 2021 at 07:47:20PM +0100, BALATON Zoltan wrote:

On Mon, 8 Nov 2021, BALATON Zoltan wrote:

On Mon, 8 Nov 2021, Paolo Bonzini wrote:

On 11/8/21 15:30, Paolo Bonzini wrote:

On 11/8/21 14:05, BALATON Zoltan wrote:

When using ACPI on big endian machine (such as ppc/pegasos2 which has
a VT8231 south bridge with ACPI) writes to ACPI registers come out
byte swapped. This may be caused by a bug in memory subsystem but
until that is fixed setting the ACPI memory regions to native endian
makes it usable for big endian machines. This fixes ACPI shutdown with
pegasos2 when using the board firmware for now.
This could be reverted when the memory layer is fixed.


What is the path to the swapped writes?  Even just a backtrace
might be enough to understand what's going on, and especially
where the bug is.


Ok, Michael pointed me at 
https://lore.kernel.org/all/20211011080528-mutt-send-email-...@kernel.org/.


Ping? I haven't seen an alternative fix yet. If you don't have time now this
could be postponed to next version with the native endian work around for
now.

Regards,
BALATON Zoltan


Paolo, ping?


ping


Can this be fixed please or my proposed workaround taken until it will be?
Original patch I've sent is here:
http://patchew.org/QEMU/20211108130934.59b48748...@zero.eik.bme.hu/

I hope to make pegasos2 more usable in next release so maybe more people
will want to use it soon.

Regards,
BALATON Zoltan


Any chance of fixing it in memory core? No one else seems to care.


I think fundamentally you need to check for the condition
Size < mr->ops->impl.min_access_size in memory_region_dispatch_write
and then make a read, combine the result with
the value and make a write.


I neither know that part nor feel confident enough breaking such low level 
stuff so I think setting the affected regions NATIVE_ENDIAN for now until 
somebody takes care of this is safer and not likely to break anyting (or 
if it does, much less widely and I'm more likely to be able to fix that 
than your proposed changes). So I'd rather let you do that but I'd like 
this fixed one way or another at last.


Regards,
BALATON Zoltan

Re: [PATCH 5/6] hw/mips/gt64xxx_pci: Endian-swap using PCI_HOST_BRIDGE MemoryRegionOps

2023-02-20 Thread Alex Bennée


Nathan Chancellor  writes:

> Hi Philippe,
>
> On Wed, Jan 04, 2023 at 02:39:34PM +0100, Philippe Mathieu-Daudé wrote:
>> GT64120's PCI endianness swapping works on little-endian hosts,
>> but doesn't on big-endian ones. Instead of complicating how
>> CFGADDR/CFGDATA registers deal with endianness, use the existing
>> MemoryRegionOps from hw/pci/pci_host.c. Doing so also reduce the
>> access to internal PCI_HOST_BRIDGE fields.
>> 
>> Map the PCI_HOST_BRIDGE MemoryRegionOps into the corresponding
>> CFGADDR/CFGDATA regions in the ISD MMIO and remove the unused
>> code in the current ISD read/write handlers.
>> 
>> Update the mapping when PCI0_CMD register is accessed (in case
>> the endianness is changed).
>> 
>> This allows using the GT64120 on a big-endian host (and boot
>> the MIPS Malta machine in little-endian).
>> 
>> Signed-off-by: Philippe Mathieu-Daudé 
>
> This change as commit 145e2198d7 ("hw/mips/gt64xxx_pci: Endian-swap
> using PCI_HOST_BRIDGE MemoryRegionOps") in QEMU master causes a hang
> when trying to poweroff a malta_defconfig + CONFIG_CPU_BIG_ENDIAN=y
> kernel on an x86_64 host. The kernel has been built from latest mainline
> using the kernel.org toolchains [1], just in case it matters.
>
> $ timeout --foreground 30s qemu-system-mips \
> -cpu 24Kf \
> -machine malta \
> -kernel vmlinux \
> -display none \
> -initrd rootfs.cpio \
> -m 512m \
> -nodefaults \
> -no-reboot \
> -serial mon:stdio
> ...


Ahh also this commit got fingered by the tuxrun test for the same
combination:

  ./run --runtime docker --qemu-binary 
/home/alex.bennee/lsrc/qemu.git/builds/bisect/qemu-system-mips64 --device 
qemu-mips64

with my in flight patches for tuxrun's host support.

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro



Re: [Pixman] pixman_blt on aarch64

2023-02-20 Thread Heiko Lewin

  
  
On 2/19/23 00:38, BALATON Zoltan wrote:
On Sun,
  5 Feb 2023, BALATON Zoltan wrote:
  
  On Sun, 5 Feb 2023, Richard Henderson
wrote:

On 2/4/23 06:57, BALATON Zoltan wrote:
  
  This has just bounced, I hoped to
still be able to post after moderation but now I'm resending
it after subscribing to the pixman list. Meanwhile I've
found this ticket as well:
https://gitlab.freedesktop.org/pixman/pixman/-/merge_requests/71

See the rest of the message below. Looks like this is being
worked on but I'm not sure how far is it from getting
resolved. Any info on that?

  
  
  Please try this:
  
  
  https://gitlab.freedesktop.org/rth7680/pixman/-/tree/general
  
  
  It provides a pure C version for ultimate fallback.
  
  Unfortunately, there are no test cases for this, nor
  documentation.
  


Thanks, I don't have hardware to test this but maybe Akihiko or
somebody else here cam try. Do you think pixman_fill won't have
the same problem? It seems to have at least a fast_path
implementation but I'm not sure how pixman selects these.

  
  
  We have tried the branch above and while it does make it better
  and usable in 16bit mode, 8bit is still missing (no wonder as it
  does not have that implemented but the AmigaOS driver only allows
  16bit and 8bit with the sm501 device this is used in but probably
  that's not important when 16 bit works). Even in 16bit more there
  were some graphics problems seen but that may need some more
  checking to make sure it's not some other change as the report was
  not clear if that worked before. I've asked to check the changes
  in
  https://gitlab.freedesktop.org/pixman/pixman/-/merge_requests/71
  next to see if that would work better.
  
  
  Regards,
  
  BALATON Zoltan
  


Hello!
I just wanted to say that I have just made the last few changes to
https://gitlab.freedesktop.org/pixman/pixman/-/merge_requests/71
that were obviously missing in that patch.
However, I have no easy way to test the lib on Apple hardware -
neither if building the lib works with Xcode et al
nor if the resulting binaries are good. I used clang to
cross-compile for Apple arm64 from a linux system which
seemed to work. Feel free to test the PR and report problems.

Regards,
Heiko
  




Re: [PATCH] hw/acpi: Set memory regions to native endian as a work around

2023-02-20 Thread Michael S. Tsirkin
On Mon, Feb 20, 2023 at 07:24:59PM +0100, BALATON Zoltan wrote:
> On Tue, 22 Feb 2022, Michael S. Tsirkin wrote:
> > On Wed, Jan 19, 2022 at 04:19:14AM -0500, Michael S. Tsirkin wrote:
> > > On Sat, Nov 13, 2021 at 07:47:20PM +0100, BALATON Zoltan wrote:
> > > > On Mon, 8 Nov 2021, BALATON Zoltan wrote:
> > > > > On Mon, 8 Nov 2021, Paolo Bonzini wrote:
> > > > > > On 11/8/21 15:30, Paolo Bonzini wrote:
> > > > > > > On 11/8/21 14:05, BALATON Zoltan wrote:
> > > > > > > > When using ACPI on big endian machine (such as ppc/pegasos2 
> > > > > > > > which has
> > > > > > > > a VT8231 south bridge with ACPI) writes to ACPI registers come 
> > > > > > > > out
> > > > > > > > byte swapped. This may be caused by a bug in memory subsystem 
> > > > > > > > but
> > > > > > > > until that is fixed setting the ACPI memory regions to native 
> > > > > > > > endian
> > > > > > > > makes it usable for big endian machines. This fixes ACPI 
> > > > > > > > shutdown with
> > > > > > > > pegasos2 when using the board firmware for now.
> > > > > > > > This could be reverted when the memory layer is fixed.
> > > > > > > 
> > > > > > > What is the path to the swapped writes?  Even just a backtrace
> > > > > > > might be enough to understand what's going on, and especially
> > > > > > > where the bug is.
> > > > > > 
> > > > > > Ok, Michael pointed me at 
> > > > > > https://lore.kernel.org/all/20211011080528-mutt-send-email-...@kernel.org/.
> > > > 
> > > > Ping? I haven't seen an alternative fix yet. If you don't have time now 
> > > > this
> > > > could be postponed to next version with the native endian work around 
> > > > for
> > > > now.
> > > > 
> > > > Regards,
> > > > BALATON Zoltan
> > > 
> > > Paolo, ping?
> > 
> > ping
> 
> Can this be fixed please or my proposed workaround taken until it will be?
> Original patch I've sent is here:
> http://patchew.org/QEMU/20211108130934.59b48748...@zero.eik.bme.hu/
> 
> I hope to make pegasos2 more usable in next release so maybe more people
> will want to use it soon.
> 
> Regards,
> BALATON Zoltan

Any chance of fixing it in memory core? No one else seems to care.


I think fundamentally you need to check for the condition
Size < mr->ops->impl.min_access_size in memory_region_dispatch_write
and then make a read, combine the result with
the value and make a write.






> > > > > I was about to say that here's the original thread:
> > > > > 
> > > > > https://lists.nongnu.org/archive/html/qemu-devel/2021-10/msg01972.html
> > > > > 
> > > > > and here's the backtrace:
> > > > > 
> > > > > #0  acpi_pm1_cnt_write (val=40, ar=0x5695f340) at 
> > > > > ../hw/acpi/core.c:556
> > > > > #1  acpi_pm_cnt_write (opaque=0x5695f340, addr=1, val=40, width=2)
> > > > > at ../hw/acpi/core.c:602
> > > > > #2  0x55b3a82f in memory_region_write_accessor
> > > > >(mr=mr@entry=0x5695f590, addr=1,
> > > > > value=value@entry=0x7fffefffdd08, size=size@entry=2, shift= > > > > out>, mask=mask@entry=65535, attrs=...)
> > > > >at ../softmmu/memory.c:492
> > > > > #3  0x55b3813e in access_with_adjusted_size
> > > > >(addr=addr@entry=1, value=value@entry=0x7fffefffdd08,
> > > > > size=size@entry=1, access_size_min=,
> > > > > access_size_max=, access_fn=
> > > > >0x55b3a7b0 , mr=0x5695f590,
> > > > > attrs=...) at ../softmmu/memory.c:554
> > > > > #4  0x55b3c449 in memory_region_dispatch_write
> > > > > (mr=mr@entry=0x5695f590, addr=1, data=, 
> > > > > op= > > > > out>, attrs=attrs@entry=...)
> > > > >at ../softmmu/memory.c:1511
> > > > > #5  0x55b2c121 in flatview_write_continue
> > > > >(fv=fv@entry=0x7fff84d23b30, addr=addr@entry=4261416709,
> > > > > attrs=attrs@entry=..., ptr=ptr@entry=0x7fffefffdec0, len=len@entry=1,
> > > > > addr1=,
> > > > > l=, mr=0x5695f590) at host-utils.h:165
> > > > > #6  0x55b2c399 in flatview_write (len=1, buf=0x7fffefffdec0,
> > > > > attrs=..., addr=4261416709, fv=0x7fff84d23b30) at
> > > > > ../softmmu/physmem.c:2822
> > > > > #7  subpage_write (opaque=, addr=,
> > > > > value=, len=1, attrs=...) at ../softmmu/physmem.c:2488
> > > > > #8  0x55b380de in access_with_adjusted_size
> > > > >(addr=addr@entry=3845, value=value@entry=0x7fffefffdf88,
> > > > > size=size@entry=1, access_size_min=,
> > > > > access_size_max=, access_fn=
> > > > >0x55b3aa80 ,
> > > > > mr=0x7fff84710bb0, attrs=...) at ../softmmu/memory.c:549
> > > > > #9  0x55b3c449 in memory_region_dispatch_write
> > > > > (mr=mr@entry=0x7fff84710bb0, addr=addr@entry=3845, data= > > > > out>,
> > > > > data@entry=40, op=op@entry=MO_8, attrs=...)
> > > > >at ../softmmu/memory.c:1511
> > > > > #10 0x55c07b4c in io_writex
> > > > >(env=env@entry=0x5666a820,
> > > > > iotlbentry=iotlbentry@entry=0x7fff843367f0, mmu_idx=1, 
> > > > > val=val@entry=40,
> > > > > addr=addr@entry=4261416709,
> > > > > retaddr=retaddr@entry=140736116523268, op=MO_8) at
> > > > > ../accel/tcg/c

Re: Detecting qemu from guest on arm/hvf (apple arm)

2023-02-20 Thread John-Mark Gurney
Hello Peter,

btw, please keep me CC'd, as I'm not subscribed to the mailing list.

> I guess the question is, why do you want to know? Typically

The main reason is that FreeBSD (and other operating systems)
adjust some of the clock periods to be longer for better
effeciency.  When FreeBSD detects that it's a VM, is slows
down hz to 100 instead of 1000:
https://cgit.freebsd.org/src/tree/sys/kern/subr_param.c#n177

And in my case, if I didn't set hz to 100 manually, even an
idle machine would consume tons of host CPU, and on top of it
(I'm not sure why), it would run at a constant >1000 int/s,
compared to running hz at 100 where the int/s would drop to
around 50/s...

I'm not sure how good/bad the time counter is on ARM hardware
as I'm more familar w/ x86 time counter hardware, and I do know
that there's a large variety of quality of time counter hardware
and the expense to accessing it.

FreeBSD is using the ARM MPCore Timecounter, and it reports:
kern.timecounter.tc.ARM MPCore Timecounter.quality: 1000
kern.timecounter.tc.ARM MPCore Timecounter.frequency: 2400
kern.timecounter.tc.ARM MPCore Timecounter.counter: 2182594876
kern.timecounter.tc.ARM MPCore Timecounter.mask: 4294967295

There isn't any other time counter hardware reported (except dummy,
but that isn't usable)...

FreeBSD has code to detect hyperv and xen, and detect VMWare through
SMBios.

> the guest OS shouldn't care about whether it's running
> on bare metal, under a hypervisor, or under emulated QEMU,
> except to the extent that it wants to use specific features,
> in which case the question is more "how do I query for the
> existence of feature X?".

Thanks for your help.
-- 
  John-Mark Gurney  Voice: +1 415 225 5579

 "All that I will do, has been done, All that I have, has not."



Re: [PATCH 17/22] target/arm: Use get_phys_addr_with_struct for stage2

2023-02-20 Thread Richard Henderson

On 2/10/23 03:28, Peter Maydell wrote:

On Tue, 24 Jan 2023 at 00:01, Richard Henderson
 wrote:


This fixes a bug in which we failed to initialize
the result attributes properly after the memset.

Signed-off-by: Richard Henderson 
---
  target/arm/ptw.c | 13 +
  1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index eaa47f6b62..3205339957 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -32,12 +32,6 @@ typedef struct S1Translate {
  void *out_host;
  } S1Translate;

-static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
-   uint64_t address,
-   MMUAccessType access_type,
-   GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
-__attribute__((nonnull));


The definition of the function doesn't have the __attribute__,
so if we drop this forward declaration we need to move the attribute.


Eh.  It was useful as an intermediary during one of the ptw reorgs, but now that we've 
eliminated the use case in which NULL had been passed, it can go away.  I assume you'd 
prefer that as a separate patch?



@@ -2854,12 +2848,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, 
S1Translate *ptw,
  cacheattrs1 = result->cacheattrs;
  memset(result, 0, sizeof(*result));

-if (arm_feature(env, ARM_FEATURE_PMSA)) {
-ret = get_phys_addr_pmsav8(env, ipa, access_type,
-   ptw->in_mmu_idx, s2walk_secure, result, fi);
-} else {
-ret = get_phys_addr_lpae(env, ptw, ipa, access_type, result, fi);
-}
+ret = get_phys_addr_with_struct(env, ptw, ipa, access_type, result, fi);
  fi->s2addr = ipa;

  /* Combine the S1 and S2 perms.  */


Does this do the right thing for PMSAv8 ? The code in get_phys_addr_twostage
sets up various things in ptw based on s2walk_secure, which (per previous
patch) is not really well defined for PMSA.


As far as I can tell, yes, since as you say current PMSAv8 is all NonSecure.


r~




[PATCH v2 15/15] win32: replace closesocket() with close() wrapper

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

Use a close() wrapper instead, so that we don't need to worry about
closesocket() vs close() anymore, let's hope.

Signed-off-by: Marc-André Lureau 
---
 include/sysemu/os-posix.h   |  2 --
 include/sysemu/os-win32.h   |  8 
 backends/tpm/tpm_emulator.c |  6 +++---
 crypto/afalg.c  |  6 +++---
 hw/hyperv/syndbg.c  |  4 ++--
 io/channel-socket.c | 10 +-
 net/dgram.c | 14 +++---
 net/socket.c| 22 +++---
 tests/qtest/libqtest.c  |  8 
 tests/qtest/microbit-test.c |  2 +-
 tests/qtest/netdev-socket.c | 10 +-
 tests/unit/socket-helpers.c |  8 
 util/oslib-win32.c  | 21 +++--
 util/qemu-sockets.c | 22 +++---
 14 files changed, 71 insertions(+), 72 deletions(-)

diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index 378213fc86..1030d39904 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -51,8 +51,6 @@ void os_daemonize(void);
 void os_setup_post(void);
 int os_mlock(void);
 
-#define closesocket(s) close(s)
-
 int os_set_daemonize(bool d);
 bool is_daemonized(void);
 
diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index d440f4e03e..f9a6f71b5a 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -155,6 +155,10 @@ bool qemu_socket_unselect(int sockfd, Error **errp);
  * set errno based on WSAGetLastError()
  */
 
+#undef close
+#define close qemu_close_wrap
+int qemu_close_wrap(int fd);
+
 #undef connect
 #define connect qemu_connect_wrap
 int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,
@@ -186,10 +190,6 @@ int qemu_shutdown_wrap(int sockfd, int how);
 #define ioctlsocket qemu_ioctlsocket_wrap
 int qemu_ioctlsocket_wrap(int fd, int req, void *val);
 
-#undef closesocket
-#define closesocket qemu_closesocket_wrap
-int qemu_closesocket_wrap(int fd);
-
 #undef getsockopt
 #define getsockopt qemu_getsockopt_wrap
 int qemu_getsockopt_wrap(int sockfd, int level, int optname,
diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index d18144b92e..402a2d6312 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -573,13 +573,13 @@ static int tpm_emulator_prepare_data_fd(TPMEmulator 
*tpm_emu)
 goto err_exit;
 }
 
-closesocket(fds[1]);
+close(fds[1]);
 
 return 0;
 
 err_exit:
-closesocket(fds[0]);
-closesocket(fds[1]);
+close(fds[0]);
+close(fds[1]);
 return -1;
 }
 
diff --git a/crypto/afalg.c b/crypto/afalg.c
index 10046bb0ae..348301e703 100644
--- a/crypto/afalg.c
+++ b/crypto/afalg.c
@@ -59,7 +59,7 @@ qcrypto_afalg_socket_bind(const char *type, const char *name,
 
 if (bind(sbind, (const struct sockaddr *)&salg, sizeof(salg)) != 0) {
 error_setg_errno(errp, errno, "Failed to bind socket");
-closesocket(sbind);
+close(sbind);
 return -1;
 }
 
@@ -105,11 +105,11 @@ void qcrypto_afalg_comm_free(QCryptoAFAlg *afalg)
 }
 
 if (afalg->tfmfd != -1) {
-closesocket(afalg->tfmfd);
+close(afalg->tfmfd);
 }
 
 if (afalg->opfd != -1) {
-closesocket(afalg->opfd);
+close(afalg->opfd);
 }
 
 g_free(afalg);
diff --git a/hw/hyperv/syndbg.c b/hw/hyperv/syndbg.c
index 94fe1b534b..065e12fb1e 100644
--- a/hw/hyperv/syndbg.c
+++ b/hw/hyperv/syndbg.c
@@ -340,7 +340,7 @@ static void hv_syndbg_realize(DeviceState *dev, Error 
**errp)
 syndbg->servaddr.sin_family = AF_INET;
 if (connect(syndbg->socket, (struct sockaddr *)&syndbg->servaddr,
 sizeof(syndbg->servaddr)) < 0) {
-closesocket(syndbg->socket);
+close(syndbg->socket);
 error_setg(errp, "%s failed to connect to socket", TYPE_HV_SYNDBG);
 return;
 }
@@ -357,7 +357,7 @@ static void hv_syndbg_unrealize(DeviceState *dev)
 
 if (syndbg->socket > 0) {
 qemu_set_fd_handler(syndbg->socket, NULL, NULL, NULL);
-closesocket(syndbg->socket);
+close(syndbg->socket);
 }
 }
 
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 03757c7a7e..b0ea7d48b3 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -159,7 +159,7 @@ int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
 
 trace_qio_channel_socket_connect_complete(ioc, fd);
 if (qio_channel_socket_set_fd(ioc, fd, errp) < 0) {
-closesocket(fd);
+close(fd);
 return -1;
 }
 
@@ -233,7 +233,7 @@ int qio_channel_socket_listen_sync(QIOChannelSocket *ioc,
 
 trace_qio_channel_socket_listen_complete(ioc, fd);
 if (qio_channel_socket_set_fd(ioc, fd, errp) < 0) {
-closesocket(fd);
+close(fd);
 return -1;
 }
 qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_LISTEN);
@@ -310,7 +310,7 @@ int qio_channel_socket_dgram_sync(QIOChannelSocket *ioc,
 
 trace_qio_channel_socket_dgram_complete(ioc

[PATCH v2 14/15] os-posix: remove useless ioctlsocket() define

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

The API is specific to win32.

Signed-off-by: Marc-André Lureau 
---
 include/sysemu/os-posix.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index 58de7c994d..378213fc86 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -52,7 +52,6 @@ void os_setup_post(void);
 int os_mlock(void);
 
 #define closesocket(s) close(s)
-#define ioctlsocket(s, r, v) ioctl(s, r, v)
 
 int os_set_daemonize(bool d);
 bool is_daemonized(void);
-- 
2.39.1




[PATCH v2 04/15] error: add global &error_warn destination

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

This can help debugging issues or develop, when error handling is
introduced.

Signed-off-by: Marc-André Lureau 
---
 include/qapi/error.h |  6 ++
 util/error.c | 10 +++---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/include/qapi/error.h b/include/qapi/error.h
index d798faeec3..f21a231bb1 100644
--- a/include/qapi/error.h
+++ b/include/qapi/error.h
@@ -519,6 +519,12 @@ static inline void 
error_propagator_cleanup(ErrorPropagator *prop)
 
 G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup);
 
+/*
+ * Special error destination to warn on error.
+ * See error_setg() and error_propagate() for details.
+ */
+extern Error *error_warn;
+
 /*
  * Special error destination to abort on error.
  * See error_setg() and error_propagate() for details.
diff --git a/util/error.c b/util/error.c
index 1e7af665b8..5537245da6 100644
--- a/util/error.c
+++ b/util/error.c
@@ -27,8 +27,9 @@ struct Error
 
 Error *error_abort;
 Error *error_fatal;
+Error *error_warn;
 
-static void error_handle_fatal(Error **errp, Error *err)
+static void error_handle(Error **errp, Error *err)
 {
 if (errp == &error_abort) {
 fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
@@ -43,6 +44,9 @@ static void error_handle_fatal(Error **errp, Error *err)
 error_report_err(err);
 exit(1);
 }
+if (errp == &error_warn) {
+warn_report_err(err);
+}
 }
 
 G_GNUC_PRINTF(6, 0)
@@ -71,7 +75,7 @@ static void error_setv(Error **errp,
 err->line = line;
 err->func = func;
 
-error_handle_fatal(errp, err);
+error_handle(errp, err);
 *errp = err;
 
 errno = saved_errno;
@@ -284,7 +288,7 @@ void error_propagate(Error **dst_errp, Error *local_err)
 if (!local_err) {
 return;
 }
-error_handle_fatal(dst_errp, local_err);
+error_handle(dst_errp, local_err);
 if (dst_errp && !*dst_errp) {
 *dst_errp = local_err;
 } else {
-- 
2.39.1




[PATCH v2 13/15] win32: avoid mixing SOCKET and file descriptor space

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

Until now, a win32 SOCKET handle is often cast to an int file
descriptor, as this is what other OS use for sockets. When necessary,
QEMU eventually queries whether it's a socket with the help of
fd_is_socket(). However, there is no guarantee of conflict between the
fd and SOCKET space. Such conflict would have surprising consequences,
we shouldn't mix them.

Also, it is often forgotten that SOCKET must be closed with
closesocket(), and not close().

Instead, let's make the win32 socket wrapper functions return and take a
file descriptor, and let util/ wrappers do the fd/SOCKET conversion as
necessary. A bit of adaptation is necessary in io/ as well.

Unfortunately, we can't drop closesocket() usage, despite
_open_osfhandle() documentation claiming transfer of ownership, testing
shows bad behaviour if you forget to call closesocket().

Signed-off-by: Marc-André Lureau 
---
 include/sysemu/os-win32.h |   4 +-
 io/channel-watch.c|   6 +-
 util/aio-win32.c  |   9 +-
 util/oslib-win32.c| 178 --
 4 files changed, 164 insertions(+), 33 deletions(-)

diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index ae0c9a3659..d440f4e03e 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -146,10 +146,10 @@ static inline void qemu_funlockfile(FILE *f)
 }
 
 /* Helper for WSAEventSelect, to report errors */
-bool qemu_socket_select(SOCKET s, WSAEVENT hEventObject,
+bool qemu_socket_select(int sockfd, WSAEVENT hEventObject,
 long lNetworkEvents, Error **errp);
 
-bool qemu_socket_unselect(SOCKET s, Error **errp);
+bool qemu_socket_unselect(int sockfd, Error **errp);
 
 /* We wrap all the sockets functions so that we can
  * set errno based on WSAGetLastError()
diff --git a/io/channel-watch.c b/io/channel-watch.c
index 6ac41009fa..64b486e378 100644
--- a/io/channel-watch.c
+++ b/io/channel-watch.c
@@ -275,13 +275,13 @@ GSource *qio_channel_create_fd_watch(QIOChannel *ioc,
 
 #ifdef CONFIG_WIN32
 GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
- int socket,
+ int sockfd,
  GIOCondition condition)
 {
 GSource *source;
 QIOChannelSocketSource *ssource;
 
-qemu_socket_select(socket, ioc->event,
+qemu_socket_select(sockfd, ioc->event,
FD_READ | FD_ACCEPT | FD_CLOSE |
FD_CONNECT | FD_WRITE | FD_OOB, NULL);
 
@@ -293,7 +293,7 @@ GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
 object_ref(OBJECT(ioc));
 
 ssource->condition = condition;
-ssource->socket = socket;
+ssource->socket = _get_osfhandle(sockfd);
 ssource->revents = 0;
 
 ssource->fd.fd = (gintptr)ioc->event;
diff --git a/util/aio-win32.c b/util/aio-win32.c
index 08e8f5615d..6bded009a4 100644
--- a/util/aio-win32.c
+++ b/util/aio-win32.c
@@ -73,15 +73,18 @@ void aio_set_fd_handler(AioContext *ctx,
 {
 AioHandler *old_node;
 AioHandler *node = NULL;
+SOCKET s;
 
 if (!fd_is_socket(fd)) {
 error_report("fd=%d is not a socket, AIO implementation is missing", 
fd);
 return;
 }
 
+s = _get_osfhandle(fd);
+
 qemu_lockcnt_lock(&ctx->list_lock);
 QLIST_FOREACH(old_node, &ctx->aio_handlers, node) {
-if (old_node->pfd.fd == fd && !old_node->deleted) {
+if (old_node->pfd.fd == s && !old_node->deleted) {
 break;
 }
 }
@@ -92,7 +95,7 @@ void aio_set_fd_handler(AioContext *ctx,
 
 /* Alloc and insert if it's not already there */
 node = g_new0(AioHandler, 1);
-node->pfd.fd = fd;
+node->pfd.fd = s;
 
 node->pfd.events = 0;
 if (node->io_read) {
@@ -120,7 +123,7 @@ void aio_set_fd_handler(AioContext *ctx,
 
 QLIST_INSERT_HEAD_RCU(&ctx->aio_handlers, node, node);
 event = event_notifier_get_handle(&ctx->notifier);
-qemu_socket_select(node->pfd.fd, event, bitmask, NULL);
+qemu_socket_select(fd, event, bitmask, NULL);
 }
 if (old_node) {
 aio_remove_fd_handler(ctx, old_node);
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index dbd32acc98..1efeb2d262 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -283,13 +283,20 @@ char *qemu_get_pid_name(pid_t pid)
 }
 
 
-bool qemu_socket_select(SOCKET s, WSAEVENT hEventObject,
+bool qemu_socket_select(int sockfd, WSAEVENT hEventObject,
 long lNetworkEvents, Error **errp)
 {
+SOCKET s = _get_osfhandle(sockfd);
+
 if (errp == NULL) {
 errp = &error_warn;
 }
 
+if (s == INVALID_SOCKET) {
+error_setg(errp, "invalid socket fd=%d", sockfd);
+return false;
+}
+
 if (WSAEventSelect(s, hEventObject, lNetworkEvents) != 0) {
 error_setg_win32(errp, WSAGetLastError(), "failed to 
WSAEventSelect()");
 return false;

[PATCH v2 00/15] win32: do not mix SOCKET and fd space

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

Hi,

A win32 SOCKET handle is often cast to an int file descriptor, as this is what
other OS use for sockets. When necessary, QEMU eventually queries whether it's a
socket with the help of fd_is_socket(). However, there is no guarantee of
conflict between the fd and SOCKET space. Such conflict would have surprising
consequences. We can fix this by using FDs only.

After fixing a few missed closesocket(), this patch series makes the win32
socket API wrappers take FDs. It finally get rid of closesocket() usage by using
a close() wrapper instead. (note that fdopen/fclose would not be enough either
to close the underlying socket appropriately)

v2:
- add clean up patch "util: drop qemu_fork()"
- add a "&error_warn", to help with basic error reporting
- fix errno handling after _get_osfhandle()
- introduce qemu_socket_(un)select() helpers
- add patch "aio_set_fd_handler() only supports SOCKET"
- add meson slirp.wrap RFC
- various misc cleanups
- add r-b tags

Marc-André Lureau (15):
  util: drop qemu_fork()
  tests: use closesocket()
  io: use closesocket()
  error: add global &error_warn destination
  win32/socket: introduce qemu_socket_select() helper
  win32/socket: introduce qemu_socket_unselect() helper
  aio: make aio_set_fd_poll() static to aio-posix.c
  aio/win32: aio_set_fd_handler() only supports SOCKET
  RFC: build-sys: add slirp.wrap
  main-loop: remove qemu_fd_register(), win32/slirp/socket specific
  slirp: unregister the win32 SOCKET
  slirp: open-code qemu_socket_(un)select()
  win32: avoid mixing SOCKET and file descriptor space
  os-posix: remove useless ioctlsocket() define
  win32: replace closesocket() with close() wrapper

 include/block/aio.h |   8 --
 include/qapi/error.h|   6 ++
 include/qemu/main-loop.h|   2 -
 include/qemu/osdep.h|  14 ---
 include/sysemu/os-posix.h   |   3 -
 include/sysemu/os-win32.h   |  15 ++-
 backends/tpm/tpm_emulator.c |   6 +-
 crypto/afalg.c  |   6 +-
 hw/hyperv/syndbg.c  |   4 +-
 io/channel-socket.c |   8 +-
 io/channel-watch.c  |  10 +-
 net/dgram.c |  14 +--
 net/slirp.c |  16 ++-
 net/socket.c|  22 ++--
 tests/qtest/libqtest.c  |   8 +-
 tests/qtest/microbit-test.c |   2 +-
 tests/qtest/netdev-socket.c |  10 +-
 tests/unit/socket-helpers.c |   2 +-
 util/aio-posix.c|   6 +-
 util/aio-win32.c|  23 ++--
 util/error.c|  10 +-
 util/main-loop.c|  11 --
 util/oslib-posix.c  |  70 -
 util/oslib-win32.c  | 202 ++--
 util/qemu-sockets.c |  22 ++--
 .gitignore  |   2 +
 subprojects/slirp.wrap  |   6 ++
 27 files changed, 289 insertions(+), 219 deletions(-)
 create mode 100644 subprojects/slirp.wrap

-- 
2.39.1




[PATCH v2 12/15] slirp: open-code qemu_socket_(un)select()

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

We are about to make the QEMU socket API use file-descriptor space only,
but libslirp gives us SOCKET as fd, still.

Signed-off-by: Marc-André Lureau 
---
 net/slirp.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/net/slirp.c b/net/slirp.c
index a7c35778a6..c33b3e02e7 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -251,16 +251,20 @@ static void net_slirp_register_poll_fd(int fd, void 
*opaque)
 #ifdef WIN32
 AioContext *ctxt = qemu_get_aio_context();
 
-qemu_socket_select(fd, event_notifier_get_handle(&ctxt->notifier),
+if (WSAEventSelect(fd, event_notifier_get_handle(&ctxt->notifier),
FD_READ | FD_ACCEPT | FD_CLOSE |
-   FD_CONNECT | FD_WRITE | FD_OOB, NULL);
+   FD_CONNECT | FD_WRITE | FD_OOB) != 0) {
+error_setg_win32(&error_warn, WSAGetLastError(), "failed to 
WSAEventSelect()");
+}
 #endif
 }
 
 static void net_slirp_unregister_poll_fd(int fd, void *opaque)
 {
 #ifdef WIN32
-qemu_socket_unselect(fd, NULL);
+if (WSAEventSelect(fd, NULL, 0) != 0) {
+error_setg_win32(&error_warn, WSAGetLastError(), "failed to 
WSAEventSelect()");
+}
 #endif
 }
 
-- 
2.39.1




[PATCH v2 02/15] tests: use closesocket()

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

Because they are actually sockets...

Signed-off-by: Marc-André Lureau 
Reviewed-by: Thomas Huth 
---
 tests/unit/socket-helpers.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/unit/socket-helpers.c b/tests/unit/socket-helpers.c
index eecadf3a3c..914b3aa0cf 100644
--- a/tests/unit/socket-helpers.c
+++ b/tests/unit/socket-helpers.c
@@ -117,13 +117,13 @@ static int socket_can_bind_connect(const char *hostname, 
int family)
 
  cleanup:
 if (afd != -1) {
-close(afd);
+closesocket(afd);
 }
 if (cfd != -1) {
-close(cfd);
+closesocket(cfd);
 }
 if (lfd != -1) {
-close(lfd);
+closesocket(lfd);
 }
 if (res) {
 freeaddrinfo(res);
-- 
2.39.1




[PATCH v2 05/15] win32/socket: introduce qemu_socket_select() helper

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

This is a wrapper for WSAEventSelect, with Error handling. By default,
it will produce a warning, so callers don't have to be modified
now, and yet we can spot potential mis-use.

Signed-off-by: Marc-André Lureau 
---
 include/sysemu/os-win32.h |  5 +
 io/channel-socket.c   |  4 ++--
 io/channel-watch.c|  6 +++---
 util/aio-win32.c  |  2 +-
 util/main-loop.c  |  6 +++---
 util/oslib-win32.c| 17 -
 6 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index 5b38c7bd04..0afb79cc2e 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include "qemu/typedefs.h"
 
 #ifdef HAVE_AFUNIX_H
 #include 
@@ -144,6 +145,10 @@ static inline void qemu_funlockfile(FILE *f)
 #endif
 }
 
+/* Helper for WSAEventSelect, to report errors */
+bool qemu_socket_select(SOCKET s, WSAEVENT hEventObject,
+long lNetworkEvents, Error **errp);
+
 /* We wrap all the sockets functions so that we can
  * set errno based on WSAGetLastError()
  */
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 2040297d2b..0bc29c4808 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -442,7 +442,7 @@ static void qio_channel_socket_finalize(Object *obj)
 }
 }
 #ifdef WIN32
-WSAEventSelect(ioc->fd, NULL, 0);
+qemu_socket_select(ioc->fd, NULL, 0, NULL);
 #endif
 closesocket(ioc->fd);
 ioc->fd = -1;
@@ -846,7 +846,7 @@ qio_channel_socket_close(QIOChannel *ioc,
 
 if (sioc->fd != -1) {
 #ifdef WIN32
-WSAEventSelect(sioc->fd, NULL, 0);
+qemu_socket_select(sioc->fd, NULL, 0, NULL);
 #endif
 if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_LISTEN)) {
 socket_listen_cleanup(sioc->fd, errp);
diff --git a/io/channel-watch.c b/io/channel-watch.c
index ad7c568a84..6ac41009fa 100644
--- a/io/channel-watch.c
+++ b/io/channel-watch.c
@@ -281,9 +281,9 @@ GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
 GSource *source;
 QIOChannelSocketSource *ssource;
 
-WSAEventSelect(socket, ioc->event,
-   FD_READ | FD_ACCEPT | FD_CLOSE |
-   FD_CONNECT | FD_WRITE | FD_OOB);
+qemu_socket_select(socket, ioc->event,
+   FD_READ | FD_ACCEPT | FD_CLOSE |
+   FD_CONNECT | FD_WRITE | FD_OOB, NULL);
 
 source = g_source_new(&qio_channel_socket_source_funcs,
   sizeof(QIOChannelSocketSource));
diff --git a/util/aio-win32.c b/util/aio-win32.c
index 80cfe012ad..be5136e486 100644
--- a/util/aio-win32.c
+++ b/util/aio-win32.c
@@ -115,7 +115,7 @@ void aio_set_fd_handler(AioContext *ctx,
 
 QLIST_INSERT_HEAD_RCU(&ctx->aio_handlers, node, node);
 event = event_notifier_get_handle(&ctx->notifier);
-WSAEventSelect(node->pfd.fd, event, bitmask);
+qemu_socket_select(node->pfd.fd, event, bitmask, NULL);
 }
 if (old_node) {
 aio_remove_fd_handler(ctx, old_node);
diff --git a/util/main-loop.c b/util/main-loop.c
index 3c0f525192..16e837fb12 100644
--- a/util/main-loop.c
+++ b/util/main-loop.c
@@ -416,9 +416,9 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc 
*func, void *opaque)
 
 void qemu_fd_register(int fd)
 {
-WSAEventSelect(fd, event_notifier_get_handle(&qemu_aio_context->notifier),
-   FD_READ | FD_ACCEPT | FD_CLOSE |
-   FD_CONNECT | FD_WRITE | FD_OOB);
+qemu_socket_select(fd, 
event_notifier_get_handle(&qemu_aio_context->notifier),
+   FD_READ | FD_ACCEPT | FD_CLOSE |
+   FD_CONNECT | FD_WRITE | FD_OOB, NULL);
 }
 
 static int pollfds_fill(GArray *pollfds, fd_set *rfds, fd_set *wfds,
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 528c9ee156..df752fc762 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -180,7 +180,7 @@ static int socket_error(void)
 void qemu_socket_set_block(int fd)
 {
 unsigned long opt = 0;
-WSAEventSelect(fd, NULL, 0);
+qemu_socket_select(fd, NULL, 0, NULL);
 ioctlsocket(fd, FIONBIO, &opt);
 }
 
@@ -283,6 +283,21 @@ char *qemu_get_pid_name(pid_t pid)
 }
 
 
+bool qemu_socket_select(SOCKET s, WSAEVENT hEventObject,
+long lNetworkEvents, Error **errp)
+{
+if (errp == NULL) {
+errp = &error_warn;
+}
+
+if (WSAEventSelect(s, hEventObject, lNetworkEvents) != 0) {
+error_setg_win32(errp, WSAGetLastError(), "failed to 
WSAEventSelect()");
+return false;
+}
+
+return true;
+}
+
 #undef connect
 int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,
   socklen_t addrlen)
-- 
2.39.1




[PATCH v2 11/15] slirp: unregister the win32 SOCKET

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

Presumably, this is what should happen when the SOCKET is to be removed.
(it probably worked until now because closesocket() does it implicitly,
but we never now how the slirp library could use the SOCKET later)

Signed-off-by: Marc-André Lureau 
---
 net/slirp.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/slirp.c b/net/slirp.c
index 0730a935ba..a7c35778a6 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -259,7 +259,9 @@ static void net_slirp_register_poll_fd(int fd, void *opaque)
 
 static void net_slirp_unregister_poll_fd(int fd, void *opaque)
 {
-/* no qemu_fd_unregister */
+#ifdef WIN32
+qemu_socket_unselect(fd, NULL);
+#endif
 }
 
 static void net_slirp_notify(void *opaque)
-- 
2.39.1




[PATCH v2 07/15] aio: make aio_set_fd_poll() static to aio-posix.c

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
---
 include/block/aio.h | 8 
 util/aio-posix.c| 6 +++---
 util/aio-win32.c| 7 ---
 3 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/include/block/aio.h b/include/block/aio.h
index 8fba6a3584..543717f294 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -482,14 +482,6 @@ void aio_set_fd_handler(AioContext *ctx,
 IOHandler *io_poll_ready,
 void *opaque);
 
-/* Set polling begin/end callbacks for a file descriptor that has already been
- * registered with aio_set_fd_handler.  Do nothing if the file descriptor is
- * not registered.
- */
-void aio_set_fd_poll(AioContext *ctx, int fd,
- IOHandler *io_poll_begin,
- IOHandler *io_poll_end);
-
 /* Register an event notifier and associated callbacks.  Behaves very similarly
  * to event_notifier_set_handler.  Unlike event_notifier_set_handler, these 
callbacks
  * will be invoked when using aio_poll().
diff --git a/util/aio-posix.c b/util/aio-posix.c
index 6cc6256d53..a8be940f76 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -180,9 +180,9 @@ void aio_set_fd_handler(AioContext *ctx,
 }
 }
 
-void aio_set_fd_poll(AioContext *ctx, int fd,
- IOHandler *io_poll_begin,
- IOHandler *io_poll_end)
+static void aio_set_fd_poll(AioContext *ctx, int fd,
+IOHandler *io_poll_begin,
+IOHandler *io_poll_end)
 {
 AioHandler *node = find_aio_handler(ctx, fd);
 
diff --git a/util/aio-win32.c b/util/aio-win32.c
index be5136e486..74d63fa21e 100644
--- a/util/aio-win32.c
+++ b/util/aio-win32.c
@@ -125,13 +125,6 @@ void aio_set_fd_handler(AioContext *ctx,
 aio_notify(ctx);
 }
 
-void aio_set_fd_poll(AioContext *ctx, int fd,
- IOHandler *io_poll_begin,
- IOHandler *io_poll_end)
-{
-/* Not implemented */
-}
-
 void aio_set_event_notifier(AioContext *ctx,
 EventNotifier *e,
 bool is_external,
-- 
2.39.1




[PATCH v2 06/15] win32/socket: introduce qemu_socket_unselect() helper

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

A more explicit version of qemu_socket_select() with no events.

Signed-off-by: Marc-André Lureau 
---
 include/sysemu/os-win32.h | 2 ++
 io/channel-socket.c   | 4 ++--
 util/oslib-win32.c| 7 ++-
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index 0afb79cc2e..ae0c9a3659 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -149,6 +149,8 @@ static inline void qemu_funlockfile(FILE *f)
 bool qemu_socket_select(SOCKET s, WSAEVENT hEventObject,
 long lNetworkEvents, Error **errp);
 
+bool qemu_socket_unselect(SOCKET s, Error **errp);
+
 /* We wrap all the sockets functions so that we can
  * set errno based on WSAGetLastError()
  */
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 0bc29c4808..03757c7a7e 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -442,7 +442,7 @@ static void qio_channel_socket_finalize(Object *obj)
 }
 }
 #ifdef WIN32
-qemu_socket_select(ioc->fd, NULL, 0, NULL);
+qemu_socket_unselect(ioc->fd, NULL);
 #endif
 closesocket(ioc->fd);
 ioc->fd = -1;
@@ -846,7 +846,7 @@ qio_channel_socket_close(QIOChannel *ioc,
 
 if (sioc->fd != -1) {
 #ifdef WIN32
-qemu_socket_select(sioc->fd, NULL, 0, NULL);
+qemu_socket_unselect(sioc->fd, NULL);
 #endif
 if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_LISTEN)) {
 socket_listen_cleanup(sioc->fd, errp);
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index df752fc762..dbd32acc98 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -180,7 +180,7 @@ static int socket_error(void)
 void qemu_socket_set_block(int fd)
 {
 unsigned long opt = 0;
-qemu_socket_select(fd, NULL, 0, NULL);
+qemu_socket_unselect(fd, NULL);
 ioctlsocket(fd, FIONBIO, &opt);
 }
 
@@ -298,6 +298,11 @@ bool qemu_socket_select(SOCKET s, WSAEVENT hEventObject,
 return true;
 }
 
+bool qemu_socket_unselect(SOCKET s, Error **errp)
+{
+return qemu_socket_select(s, NULL, 0, errp);
+}
+
 #undef connect
 int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,
   socklen_t addrlen)
-- 
2.39.1




[PATCH v2 10/15] main-loop: remove qemu_fd_register(), win32/slirp/socket specific

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

Open-code the socket registration where it's needed, to avoid
artificially used or unclear generic interface.

Furthermore, the following patches are going to make socket handling use
FD-only inside QEMU, but we need to handle win32 SOCKET from libslirp.

Signed-off-by: Marc-André Lureau 
---
 include/qemu/main-loop.h |  2 --
 net/slirp.c  |  8 +++-
 util/main-loop.c | 11 ---
 3 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
index c25f390696..b3e54e00bc 100644
--- a/include/qemu/main-loop.h
+++ b/include/qemu/main-loop.h
@@ -387,8 +387,6 @@ void qemu_cond_timedwait_iothread(QemuCond *cond, int ms);
 
 /* internal interfaces */
 
-void qemu_fd_register(int fd);
-
 #define qemu_bh_new(cb, opaque) \
 qemu_bh_new_full((cb), (opaque), (stringify(cb)))
 QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name);
diff --git a/net/slirp.c b/net/slirp.c
index 2ee3f1a0d7..0730a935ba 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -248,7 +248,13 @@ static void net_slirp_timer_mod(void *timer, int64_t 
expire_timer,
 
 static void net_slirp_register_poll_fd(int fd, void *opaque)
 {
-qemu_fd_register(fd);
+#ifdef WIN32
+AioContext *ctxt = qemu_get_aio_context();
+
+qemu_socket_select(fd, event_notifier_get_handle(&ctxt->notifier),
+   FD_READ | FD_ACCEPT | FD_CLOSE |
+   FD_CONNECT | FD_WRITE | FD_OOB, NULL);
+#endif
 }
 
 static void net_slirp_unregister_poll_fd(int fd, void *opaque)
diff --git a/util/main-loop.c b/util/main-loop.c
index 16e837fb12..e180c85145 100644
--- a/util/main-loop.c
+++ b/util/main-loop.c
@@ -252,10 +252,6 @@ static int max_priority;
 static int glib_pollfds_idx;
 static int glib_n_poll_fds;
 
-void qemu_fd_register(int fd)
-{
-}
-
 static void glib_pollfds_fill(int64_t *cur_timeout)
 {
 GMainContext *context = g_main_context_default();
@@ -414,13 +410,6 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc 
*func, void *opaque)
 }
 }
 
-void qemu_fd_register(int fd)
-{
-qemu_socket_select(fd, 
event_notifier_get_handle(&qemu_aio_context->notifier),
-   FD_READ | FD_ACCEPT | FD_CLOSE |
-   FD_CONNECT | FD_WRITE | FD_OOB, NULL);
-}
-
 static int pollfds_fill(GArray *pollfds, fd_set *rfds, fd_set *wfds,
 fd_set *xfds)
 {
-- 
2.39.1




[PATCH v2 09/15] RFC: build-sys: add slirp.wrap

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

This allows to build with --enable-slirp / -D slirp=enabled, even when
libslirp is not installed on the system. Meson will pull it from git in
that case.

RFC because this is very convenient, for a developper targetting
different environments, but might not be considered appropriate, as it
is "a kind of" git submodule (without git submodule integration issues
though, afaik, experience should tell).

Signed-off-by: Marc-André Lureau 
---
 .gitignore | 2 ++
 subprojects/slirp.wrap | 6 ++
 2 files changed, 8 insertions(+)
 create mode 100644 subprojects/slirp.wrap

diff --git a/.gitignore b/.gitignore
index 61fa39967b..1ea59f4819 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,5 @@ GTAGS
 *.swp
 *.patch
 *.gcov
+
+/subprojects/slirp
diff --git a/subprojects/slirp.wrap b/subprojects/slirp.wrap
new file mode 100644
index 00..87cdd8dcd8
--- /dev/null
+++ b/subprojects/slirp.wrap
@@ -0,0 +1,6 @@
+[wrap-git]
+url = https://gitlab.freedesktop.org/slirp/libslirp
+revision = 15c52d69
+
+[provide]
+slirp = libslirp_dep
-- 
2.39.1




[PATCH v2 01/15] util: drop qemu_fork()

2023-02-20 Thread marcandre . lureau
From: Marc-André Lureau 

Fortunately, qemu_fork() is no longer used since commit
a95570e3e4d6 ("io/command: use glib GSpawn, instead of open-coding
fork/exec"). (GSpawn uses posix_spawn() whenever possible instead)

Signed-off-by: Marc-André Lureau 
---
 include/qemu/osdep.h | 14 -
 util/oslib-posix.c   | 70 
 util/oslib-win32.c   |  9 --
 3 files changed, 93 deletions(-)

diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 88c9facbf2..f68b5d8708 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -665,20 +665,6 @@ void qemu_prealloc_mem(int fd, char *area, size_t sz, int 
max_threads,
  */
 char *qemu_get_pid_name(pid_t pid);
 
-/**
- * qemu_fork:
- *
- * A version of fork that avoids signal handler race
- * conditions that can lead to child process getting
- * signals that are otherwise only expected by the
- * parent. It also resets all signal handlers to the
- * default settings.
- *
- * Returns 0 to child process, pid number to parent
- * or -1 on failure.
- */
-pid_t qemu_fork(Error **errp);
-
 /* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
  * when intptr_t is 32-bit and we are aligning a long long.
  */
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 77d882e681..760390b31e 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -583,76 +583,6 @@ char *qemu_get_pid_name(pid_t pid)
 }
 
 
-pid_t qemu_fork(Error **errp)
-{
-sigset_t oldmask, newmask;
-struct sigaction sig_action;
-int saved_errno;
-pid_t pid;
-
-/*
- * Need to block signals now, so that child process can safely
- * kill off caller's signal handlers without a race.
- */
-sigfillset(&newmask);
-if (pthread_sigmask(SIG_SETMASK, &newmask, &oldmask) != 0) {
-error_setg_errno(errp, errno,
- "cannot block signals");
-return -1;
-}
-
-pid = fork();
-saved_errno = errno;
-
-if (pid < 0) {
-/* attempt to restore signal mask, but ignore failure, to
- * avoid obscuring the fork failure */
-(void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
-error_setg_errno(errp, saved_errno,
- "cannot fork child process");
-errno = saved_errno;
-return -1;
-} else if (pid) {
-/* parent process */
-
-/* Restore our original signal mask now that the child is
- * safely running. Only documented failures are EFAULT (not
- * possible, since we are using just-grabbed mask) or EINVAL
- * (not possible, since we are using correct arguments).  */
-(void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
-} else {
-/* child process */
-size_t i;
-
-/* Clear out all signal handlers from parent so nothing
- * unexpected can happen in our child once we unblock
- * signals */
-sig_action.sa_handler = SIG_DFL;
-sig_action.sa_flags = 0;
-sigemptyset(&sig_action.sa_mask);
-
-for (i = 1; i < NSIG; i++) {
-/* Only possible errors are EFAULT or EINVAL The former
- * won't happen, the latter we expect, so no need to check
- * return value */
-(void)sigaction(i, &sig_action, NULL);
-}
-
-/* Unmask all signals in child, since we've no idea what the
- * caller's done with their signal mask and don't want to
- * propagate that to children */
-sigemptyset(&newmask);
-if (pthread_sigmask(SIG_SETMASK, &newmask, NULL) != 0) {
-Error *local_err = NULL;
-error_setg_errno(&local_err, errno,
- "cannot unblock signals");
-error_report_err(local_err);
-_exit(1);
-}
-}
-return pid;
-}
-
 void *qemu_alloc_stack(size_t *sz)
 {
 void *ptr, *guardpage;
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 07ade41800..528c9ee156 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -283,15 +283,6 @@ char *qemu_get_pid_name(pid_t pid)
 }
 
 
-pid_t qemu_fork(Error **errp)
-{
-errno = ENOSYS;
-error_setg_errno(errp, errno,
- "cannot fork child process");
-return -1;
-}
-
-
 #undef connect
 int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,
   socklen_t addrlen)
-- 
2.39.1




  1   2   3   4   5   >