RE: [PATCH] target/i386/hax: Add XCR0 support

2023-01-10 Thread Wang, Wenchao
Hi, Paolo,

Sorry for bothering you. Do you think my answer is reasonable? Or do you have 
any other questions on that? If you agree, could you help to merge this patch 
in your coming pull request? Thanks a lot.


Best Regards,
Wenchao

From: Wang, Wenchao
Sent: Wednesday, December 28, 2022 16:55
To: Paolo Bonzini 
Cc: Philippe Mathieu-Daudé ; qemu-devel 
; haxm-team 
Subject: RE: [PATCH] target/i386/hax: Add XCR0 support

Hi, Paolo,

Thanks for your question.
This buffer is only used by the interfaces of ioctl(HAX_VCPU_SET_REGS) or 
ioctl(HAX_VCPU_GET_REGS). It is currently sizeof(struct vcpu_state_t), which is 
changed by the patch. Currently, the parameters passed by different ioctl() are 
not same, so it may not be possible to allocate only a 4KB size of memory for 
shared use.


Best Regards,
Wenchao

From: Paolo Bonzini mailto:pbonz...@redhat.com>>
Sent: Wednesday, December 28, 2022 16:24
To: Wang, Wenchao mailto:wenchao.w...@intel.com>>
Cc: Philippe Mathieu-Daudé mailto:phi...@linaro.org>>; 
qemu-devel mailto:qemu-devel@nongnu.org>>; haxm-team 
mailto:haxm-t...@intel.com>>
Subject: Re: [PATCH] target/i386/hax: Add XCR0 support

Does it make sense to just allocate 4k of memory or so?

Paolo

Il mer 28 dic 2022, 03:55 Wang, Wenchao 
mailto:wenchao.w...@intel.com>> ha scritto:
Hi, Paolo,

Thanks for your reply.

The reason why the variable xcr0 must be added to the header file of QEMU is 
because HAXM needs QEMU to allocate memory from user space and pass it to the 
kernel. This patch is only used to expand the buffer size of the structure, and 
HAXM will use and maintain this variable.
Without this patch, HAXM v7.8.0 will break support for QEMU and the HAXM 
versions older than 7.8.0 cannot support QEMU with this patch, either. It will 
work on any version since HAXM v7.8.0. I know QEMU treats the structure as a 
black box, but HAXM never supported xcr0 before and the structure size is not 
enough if it has been supported. We have verified the patched QEMU and it can 
launch all guest OSes. Thanks.


Best Regards,
Wenchao

From: Paolo Bonzini mailto:pbonz...@redhat.com>>
Sent: Tuesday, December 27, 2022 23:13
To: Wang, Wenchao mailto:wenchao.w...@intel.com>>
Cc: Philippe Mathieu-Daudé mailto:phi...@linaro.org>>; 
qemu-devel mailto:qemu-devel@nongnu.org>>; haxm-team 
mailto:haxm-t...@intel.com>>
Subject: Re: [PATCH] target/i386/hax: Add XCR0 support


Il lun 28 nov 2022, 09:12 Wang, Wenchao 
mailto:wenchao.w...@intel.com>> ha scritto:
Hi, Philippe,

It is just the full patch. Currently, the implementation of HAXM is simple, we 
did not synchronize the vCPU register for xcr0 from QEMU. HAXM will handle the 
xcr0 state within the kernel space, including initialization, update, etc. This 
patch adds the xcr0 variable for allocating extra 8-byte buffer occupation, 
which will be passed between QEMU and HAXM when hax_sync_vcpu_state() is 
invoked. We have verified the patched QEMU and it can launch all guest OSes. 
Thanks for your comments.

I don't understand the patch very well, and I am on the phone so it's hard to 
check QEMU's HAXM support sources right now. Did HAXM 7.8.0 break support for 
QEMU without this patch, and likewise will QEMU with this patch will HAXM 
versions older than 7.8.0?

Or does this work on any version because QEMU treats the struct as a black box?

Paolo




Best Regards,
Wenchao

-Original Message-
From: Philippe Mathieu-Daudé mailto:phi...@linaro.org>>
Sent: Friday, November 25, 2022 21:37
To: Wang, Wenchao mailto:wenchao.w...@intel.com>>; 
qemu-devel@nongnu.org
Cc: haxm-team mailto:haxm-t...@intel.com>>; Paolo Bonzini 
mailto:pbonz...@redhat.com>>
Subject: Re: [PATCH] target/i386/hax: Add XCR0 support

Hi,

On 25/11/22 13:18, Wang, Wenchao wrote:
> Hi, maintainers,
>
> As HAXM v7.8.0 is released and it added XCR0 support, could you help
> to merge this patch to add corresponding support into HAX user space
> of QEMU? The patch has been included in the attachment. Thanks.

See
https://www.qemu.org/docs/master/devel/submitting-a-patch.html#submitting-your-patches
on how to send patches to a mailing list.

>
> Best Regards,
>
> Wenchao
>
>  From b1789f2523d06798b8883664bfa9a9df797bfccf Mon Sep 17 00:00:00
> 2001
>
> From: Wenchao Wang mailto:wenchao.w...@intel.com>>
>
> Date: Fri, 25 Nov 2022 18:37:34 +0800
>
> Subject: [PATCH] target/i386/hax: Add XCR0 support
>
> Introduce extended control register XCR0 to support XSAVE feature set.
>
> Note: This change requires at least HAXM v7.8.0 to support.
>
> Reviewed-by: Hang Yuan mailto:hang.y...@intel.com>>
>
> Signed-off-by: Wenchao Wang 
> mailto:wenchao.w...@intel.com>>
>
> ---
>
> target/i386/hax/hax-interface.h | 2 ++
>
> 1 file changed, 2 insertions(+)
>
> diff --git a/target/i386/hax/hax-interface.h
> b/target/i386/hax/hax-interface.h
>
> index 537ae084e9..1d13bb2380 100644
>
> --- a/target/i386/hax/hax-interface.h
>
> +++ b/target/i386/hax/hax-interface.h
>
> @@ -201,6 +201,8 @@ struct v

[PATCH v5 0/1] python/machine: Fix AF_UNIX path too long

2023-01-10 Thread Peter Delevoryas
v1: https://lore.kernel.org/qemu-devel/20220705214659.73369-1-pe...@pjd.dev/
v2: https://lore.kernel.org/qemu-devel/20220716173434.17183-1-pe...@pjd.dev/
v3:
- Changed QEMUMachine._name to f"{id(self):x}". Suggestion was to do
  f"{id(self):02x}", but the id's look like they are probably just the
  object address (8-byte pointer), so the "02" had no effect.
- Changed QMP socket name suffix from "-monitor.sock" to ".qmp".
- Changed console socket name suffix from "-console.sock" to ".con".
v4:
- Just resending v3 after rebasing from a long time ago
v5:
- I forgot to disable the VPN on my laptop before sending the v4 series,
  and I always have very mysterious errors and/or delays when I send email
  through the VPN because our security team doesn't allow split tunneling.
- I also forgot to include the reviewed-by tags. Daniel reviewed v3,
  Phil reviewed v4.

I tried to run `make check-avocado` before sending again, but it looks like
there is some other issue. Probably related to the python version I have (I
have like 5 different Python versions installed on my work laptop).

Thanks,
Peter

$ make check-avocado
changing dir to build for /Library/Developer/CommandLineTools/usr/bin/make 
"check-avocado"...
  GIT ui/keycodemapdb tests/fp/berkeley-testfloat-3 
tests/fp/berkeley-softfloat-3 dtc
  VENV/Users/pdel/qemu/build/tests/venv
  VENVPIP install -e /Users/pdel/qemu/python/
  VENVPIP install -r /Users/pdel/qemu/tests/requirements.txt
  MKDIR   /Users/pdel/qemu/build/tests/results
  AVOCADO Downloading avocado tests VM image for aarch64
The image was downloaded:
Provider Version Architecture File
fedora   31  aarch64  
/Users/pdel/avocado/data/cache/by_location/4f156e531446a679cbfe13caef8b7c9f9f79aafa/Fedora-C
loud-Base-31-1.9.aarch64.qcow2
  AVOCADO tests/avocado
Fetching asset from 
tests/avocado/boot_linux_console.py:BootLinuxConsole.test_aarch64_raspi3_atf
Fetching asset from 
tests/avocado/boot_xen.py:BootXen.test_arm64_xen_411_and_dom0
Fetching asset from 
tests/avocado/boot_xen.py:BootXen.test_arm64_xen_414_and_dom0
Fetching asset from 
tests/avocado/boot_xen.py:BootXen.test_arm64_xen_415_and_dom0
Fetching asset from 
tests/avocado/machine_aarch64_virt.py:Aarch64VirtMachine.test_alpine_virt_tcg_gic_max
Fetching asset from 
tests/avocado/machine_aarch64_virt.py:Aarch64VirtMachine.test_aarch64_virt
Fetching asset from 
tests/avocado/replay_kernel.py:ReplayKernelNormal.test_aarch64_virt
Fetching asset from 
tests/avocado/reverse_debugging.py:ReverseDebugging_AArch64.test_aarch64_virt
JOB ID : 18a949ed9150e22d6ecea69b99ede1ded17233f4
JOB LOG: 
/Users/pdel/qemu/build/tests/results/job-2023-01-10T00.03-18a949e/job.log

Avocado crashed: TypeError: cannot pickle '_thread.RLock' object

Peter Delevoryas (1):
  python/machine: Fix AF_UNIX path too long on macOS

 python/qemu/machine/machine.py | 6 +++---
 tests/avocado/avocado_qemu/__init__.py | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

-- 
2.39.0




Re: [PATCH] remove unnecessary extern "C" blocks

2023-01-10 Thread Daniel P . Berrangé
On Tue, Jan 10, 2023 at 09:49:46AM +0100, Paolo Bonzini wrote:
> A handful of header files in QEMU are wrapped with extern "C" blocks.
> These are not necessary: there are C++ source files anymore in QEMU,

s/are/are no/

> and even where there were some, they did not include most of these
> files anyway.
> 
> Remove them for consistency.
> 
> Signed-off-by: Paolo Bonzini 

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [RFC PATCH 4/4] qom: Warn when deprecated class property can be removed

2023-01-10 Thread Bernhard Beschow



Am 9. Januar 2023 22:54:19 UTC schrieb "Philippe Mathieu-Daudé" 
:
>Per docs/system/deprecated.rst, a deprecated feature can be
>removed after 2 releases. Since we commit when a class property
>is deprecated, we can warn when the deprecation period is over.
>
>See also commit ef1f5b0a96 ("docs: clarify deprecation schedule").
>
>Signed-off-by: Philippe Mathieu-Daudé 
>---
> qom/object.c | 7 +++
> 1 file changed, 7 insertions(+)
>
>diff --git a/qom/object.c b/qom/object.c
>index 05b97cd424..cb829f1e44 100644
>--- a/qom/object.c
>+++ b/qom/object.c
>@@ -17,6 +17,7 @@
> #include "qom/object_interfaces.h"
> #include "qemu/cutils.h"
> #include "qemu/memalign.h"
>+#include "qemu/qemu-version.h"
> #include "qapi/visitor.h"
> #include "qapi/string-input-visitor.h"
> #include "qapi/string-output-visitor.h"
>@@ -1300,6 +1301,12 @@ void object_class_property_deprecate(ObjectClass *klass,
> ObjectProperty *prop = object_class_property_find(klass, name);
> 
> assert(prop);
>+if (qemu_version_delta_current(version_major, version_minor) <= 2) {
>+warn_report_once("Property '%s.%s' has been deprecated in release"
>+ " v%u.%u and can be removed.",
>+ object_class_get_name(klass), name,
>+ version_major, version_minor);
>+}
> prop->deprecation_reason = reason;
> }
> 

Great series!

Perhaps turn object_class_property_deprecate() into a macro and warn at compile 
time already? That way we won't miss removing any properties and users won't 
see a warning they can't do anything about.

Best regards,
Bernhard



[PATCH v4 00/11] iotests: use vm.cmd()

2023-01-10 Thread Vladimir Sementsov-Ogievskiy
Hi all!

Let's get rid of pattern

result = self.vm.qmp(...)
self.assert_qmp(result, 'return', {})

And switch to just

self.vm.cmd(...)

v4: resend to fix CC
v3: rebase on master, fix some over-80 lines

Vladimir Sementsov-Ogievskiy (11):
  python: rename QEMUMonitorProtocol.cmd() to cmd_raw()
  python/qemu: rename command() to cmd()
  python/machine.py: upgrade vm.cmd() method
  iotests: QemuStorageDaemon: add cmd() method like in QEMUMachine.
  iotests: add some missed checks of qmp result
  iotests: refactor some common qmp result checks into generic pattern
  iotests: drop some occasional semicolons
  iotests: drop some extra ** in qmp() call
  iotests.py: pause_job(): drop return value
  tests/vm/basevm.py: use cmd() instead of qmp()
  python: use vm.cmd() instead of vm.qmp() where appropriate

 docs/devel/testing.rst|  10 +-
 python/qemu/machine/machine.py|  20 +-
 python/qemu/qmp/legacy.py |  10 +-
 python/qemu/qmp/qmp_shell.py  |  13 +-
 python/qemu/utils/qemu_ga_client.py   |   2 +-
 python/qemu/utils/qom.py  |   8 +-
 python/qemu/utils/qom_common.py   |   2 +-
 python/qemu/utils/qom_fuse.py |   6 +-
 scripts/cpu-x86-uarch-abi.py  |   8 +-
 scripts/device-crash-test |   8 +-
 scripts/render_block_graph.py |   8 +-
 tests/avocado/avocado_qemu/__init__.py|   4 +-
 tests/avocado/cpu_queries.py  |   5 +-
 tests/avocado/hotplug_cpu.py  |  10 +-
 tests/avocado/info_usernet.py |   4 +-
 tests/avocado/machine_arm_integratorcp.py |   6 +-
 tests/avocado/machine_m68k_nextcube.py|   4 +-
 tests/avocado/machine_mips_malta.py   |   6 +-
 tests/avocado/machine_s390_ccw_virtio.py  |  28 +-
 tests/avocado/migration.py|  10 +-
 tests/avocado/pc_cpu_hotplug_props.py |   2 +-
 tests/avocado/version.py  |   4 +-
 tests/avocado/virtio_check_params.py  |   6 +-
 tests/avocado/virtio_version.py   |   5 +-
 tests/avocado/vnc.py  |  16 +-
 tests/avocado/x86_cpu_model_versions.py   |  13 +-
 tests/migration/guestperf/engine.py   | 150 +++---
 tests/qemu-iotests/030| 168 +++---
 tests/qemu-iotests/040| 171 +++
 tests/qemu-iotests/041| 482 --
 tests/qemu-iotests/045|  15 +-
 tests/qemu-iotests/055|  62 +--
 tests/qemu-iotests/056|  77 ++-
 tests/qemu-iotests/093|  42 +-
 tests/qemu-iotests/118| 225 
 tests/qemu-iotests/124| 102 ++--
 tests/qemu-iotests/129|  14 +-
 tests/qemu-iotests/132|   5 +-
 tests/qemu-iotests/139|  45 +-
 tests/qemu-iotests/147|  30 +-
 tests/qemu-iotests/151|  56 +-
 tests/qemu-iotests/152|   8 +-
 tests/qemu-iotests/155|  55 +-
 tests/qemu-iotests/165|   8 +-
 tests/qemu-iotests/196|   3 +-
 tests/qemu-iotests/205|   6 +-
 tests/qemu-iotests/218| 105 ++--
 tests/qemu-iotests/245| 245 -
 tests/qemu-iotests/256|  34 +-
 tests/qemu-iotests/257|  36 +-
 tests/qemu-iotests/264|  31 +-
 tests/qemu-iotests/281|  21 +-
 tests/qemu-iotests/295|  16 +-
 tests/qemu-iotests/296|  21 +-
 tests/qemu-iotests/298|  13 +-
 tests/qemu-iotests/300|  54 +-
 tests/qemu-iotests/iotests.py |  18 +-
 .../tests/export-incoming-iothread|   6 +-
 .../qemu-iotests/tests/graph-changes-while-io |   6 +-
 tests/qemu-iotests/tests/image-fleecing   |   3 +-
 .../tests/migrate-bitmaps-postcopy-test   |  31 +-
 tests/qemu-iotests/tests/migrate-bitmaps-test |  45 +-
 .../qemu-iotests/tests/migrate-during-backup  |  41 +-
 .../qemu-iotests/tests/migration-permissions  |   9 +-
 .../tests/mirror-ready-cancel-error   |  74 ++-
 tests/qemu-iotests/tests/mirror-top-perms |  16 +-
 tests/qemu-iotests/tests/nbd-multiconn|  12 +-
 tests/qemu-iotests/tests/reopen-file  |   3 +-
 .../qemu-iotests/tests/stream-error-on-reset  |   6 +-
 tests/vm/basevm.py|   4 +-
 70 files changed, 1179 insertions(+), 1613 deletions(-)

-- 
2.34.1




Re: [PATCH v4 1/1] python/machine: Fix AF_UNIX path too long on macOS

2023-01-10 Thread Daniel P . Berrangé
On Tue, Jan 10, 2023 at 12:07:56AM -0800, Peter Delevoryas wrote:
> On macOS, private $TMPDIR's are the default. These $TMPDIR's are
> generated from a user's unix UID and UUID [1], which can create a
> relatively long path:
> 
> /var/folders/d7/rz20f6hd709c1ty8f6_6y_z4gn/T/
> 
> QEMU's avocado tests create a temporary directory prefixed by
> "avo_qemu_sock_", and create QMP sockets within _that_ as well.
> The QMP socket is unnecessarily long, because a temporary directory
> is created for every QEMUMachine object.
> 
> /avo_qemu_sock_uh3w_dgc/qemu-37331-10bacf110-monitor.sock
> 
> The path limit for unix sockets on macOS is 104: [2]
> 
> /*
>  * [XSI] Definitions for UNIX IPC domain.
>  */
> struct  sockaddr_un {
> unsigned char   sun_len;/* sockaddr len including null */
> sa_family_t sun_family; /* [XSI] AF_UNIX */
> charsun_path[104];  /* [XSI] path name (gag) */
> };
> 
> This results in avocado tests failing on macOS because the QMP unix
> socket can't be created, because the path is too long:
> 
> ERROR| Failed to establish connection: OSError: AF_UNIX path too long
> 
> This change resolves by reducing the size of the socket directory prefix
> and the suffix on the QMP and console socket names.
> 
> The result is paths like this:
> 
> pdel@pdel-mbp:/var/folders/d7/rz20f6hd709c1ty8f6_6y_z4gn/T
> $ tree qemu*
> qemu_df4evjeq
> qemu_jbxel3gy
> qemu_ml9s_gg7
> qemu_oc7h7f3u
> qemu_oqb1yf97
> ├── 10a004050.con
> └── 10a004050.qmp
> 
> [1] 
> https://apple.stackexchange.com/questions/353832/why-is-mac-osx-temp-directory-in-weird-path
> [2] 
> /Library/Developer/CommandLineTools/SDKs/MacOSX12.3.sdk/usr/include/sys/un.h
> 
> Signed-off-by: Peter Delevoryas 
> ---
>  python/qemu/machine/machine.py | 6 +++---
>  tests/avocado/avocado_qemu/__init__.py | 2 +-
>  2 files changed, 4 insertions(+), 4 deletions(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH v2 2/5] util/qht: add missing atomic_set(hashes[i])

2023-01-10 Thread Alex Bennée


Emilio Cota  writes:

> We forgot to add this one in "a890643958 util/qht: atomically set b->hashes".
>
> Detected with tsan.
>
> Reviewed-by: Richard Henderson 
> Reviewed-by: Philippe Mathieu-Daudé 
> Signed-off-by: Emilio Cota 

Reviewed-by: Alex Bennée 

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro



Re: [PATCH v3 3/8] configure: replace Perl usage with sed

2023-01-10 Thread Thomas Huth

On 10/01/2023 09.02, marcandre.lur...@redhat.com wrote:

From: Marc-André Lureau 

Let's try to reduce our Perl usage during config/build-time.

Note: this patch might be dropped if "configure: remove
backwards-compatibility code" is merged earlier.

Signed-off-by: Marc-André Lureau 
---
  configure | 8 +++-
  1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/configure b/configure
index 2281892657..9a944698b4 100755
--- a/configure
+++ b/configure
@@ -2571,11 +2571,9 @@ else
if test -f meson-private/cmd_line.txt; then
  # Adjust old command line options whose type was changed
  # Avoids having to use "setup --wipe" when Meson is upgraded
-perl -i -ne '
-  s/^gettext = true$/gettext = auto/;
-  s/^gettext = false$/gettext = disabled/;
-  /^b_staticpic/ && next;
-  print;' meson-private/cmd_line.txt
+sed -i.bak -e 's/^gettext = true$/gettext = auto/g' \
+  -e 's/^gettext = false$/gettext = disabled/g' \
+  -e '/^b_staticpic/d' meson-private/cmd_line.txt
fi
  fi


I've ran "make vm-build-freebsd" and "make vm-build-openbsd" with this patch 
and it worked fine, I didn't spot anything in the console output, thus:


Tested-by: Thomas Huth 




Re: [PATCH v4 16/17] ui: Split hmp_mouse_set() and move the HMP part to ui/

2023-01-10 Thread Daniel P . Berrangé
On Mon, Jan 09, 2023 at 08:03:20PM +0100, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster 
> ---
>  include/monitor/hmp.h |  1 +
>  include/ui/console.h  |  2 +-
>  monitor/misc.c|  1 -
>  ui/input.c| 15 +++
>  ui/ui-hmp-cmds.c  |  8 
>  5 files changed, 17 insertions(+), 10 deletions(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH v4 10/11] tests/vm/basevm.py: use cmd() instead of qmp()

2023-01-10 Thread Vladimir Sementsov-Ogievskiy
We don't expect failure here and need 'result' object. cmd() is better
in this case.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
 tests/vm/basevm.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 2276364c42..ff7e4fea15 100644
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -311,8 +311,8 @@ def boot(self, img, extra_args=[]):
 self._guest = guest
 # Init console so we can start consuming the chars.
 self.console_init()
-usernet_info = guest.qmp("human-monitor-command",
- command_line="info usernet").get("return")
+usernet_info = guest.cmd("human-monitor-command",
+ command_line="info usernet")
 self.ssh_port = get_info_usernet_hostfwd_port(usernet_info)
 if not self.ssh_port:
 raise Exception("Cannot find ssh port from 'info usernet':\n%s" % \
-- 
2.34.1




Re: [PATCH 1/5] migration: Updated QAPI format for 'migrate' qemu monitor command

2023-01-10 Thread Daniel P . Berrangé
On Tue, Jan 10, 2023 at 01:09:35PM +0530, Het Gala wrote:
> 
> On 09/01/23 7:37 pm, Daniel P. Berrangé wrote:
> > On Mon, Dec 26, 2022 at 05:33:25AM +, Het Gala wrote:
> > > From: Author Het Gala 
> > > 
> > > Existing 'migrate' QAPI design enforces transport mechanism, ip address
> > > of destination interface and corresponding port number in the form
> > > of a unified string 'uri' parameter. This scheme does seem to have an 
> > > issue
> > > in it, i.e. double-level encoding of URIs.
> > > 
> > > The current patch maps existing QAPI design into a well-defined data
> > > structure - 'MigrateChannel' only from the design perspective. Please 
> > > note that
> > > the existing 'uri' parameter is kept untouched for backward compatibility.
> > > 
> > > +##
> > > +# @MigrateExecAddr:
> > > + #
> > > + # Since 8.0
> > > + ##
> > > +{ 'struct': 'MigrateExecAddr',
> > > +   'data' : {'exec-str': 'str' } }
> > Currently for 'exec:cmdstr' the 'cmdstr' part is a shell command
> > that is passed
> > 
> >const char *argv[] = { "/bin/sh", "-c", command, NULL };
> > 
> > I have a strong preference for making it possible to avoid use
> > of shell when spawning commands, since much of thue time it is
> > not required and has the potential to open up vulnerabilities.
> > It would be nice to be able to just take the full argv directly
> > IOW
> > 
> >   { 'struct': 'MigrateExecAddr',
> >  'data' : {'argv': ['str'] } }
> > 
> > If the caller wants to keep life safe and simple now they can
> > use
> > ["/bin/nc", "-U", "/some/sock"]
> > 
> > but if they still want to send it via shell, they can also do
> > so
> > 
> > ["/bin/sh", "-c", "...arbitrary shell script code"]
> Okay Daniel. I get your point and it makes sense too. This will also have
> some code changes in exec.c file I assume.
> > > +
> > > +##
> > > +# @MigrateRdmaAddr:
> > > +#
> > > +# Since 8.0
> > > +##
> > > +{ 'struct': 'MigrateRdmaAddr',
> > > +   'data' : {'rdma-str': 'str' } }
> > Loooking at the RDMA code it takes the str, and treats it
> > as an IPv4 address:
> > 
> > 
> >  addr = g_new(InetSocketAddress, 1);
> >  if (!inet_parse(addr, host_port, NULL)) {
> >  rdma->port = atoi(addr->port);
> >  rdma->host = g_strdup(addr->host);
> >  rdma->host_port = g_strdup(host_port);
> >  }
> > 
> > so we really ought to accept an InetSocketAddress struct
> > directly
> > 
> >   { 'struct': 'MigrateRdmaAddr',
> >  'data' : {'rdma-str': 'InetSocketAddress' } }
> > 
> Yes, It resembles to InetSocketAddress. Will make the relevant changes in
> rdma.c file.
> 
> With this, I had a small question in mind, do qemu need to develop /
> leverage some functionality to check the correctness for host or port.
> So that if the user enters an invalid host address, they get an error
> message to enter correct address, if trying to migrate via qmp command line
> interface.

When the RDMA code uses the host address to resolve the RDMA
endpoint, it will fail and report an error back.


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH v3 1/8] build-sys: fix crlf-ending C code

2023-01-10 Thread Thomas Huth

On 10/01/2023 09.02, marcandre.lur...@redhat.com wrote:

From: Marc-André Lureau 

On msys2, the shader-to-C script produces bad C:
./ui/shader/texture-blit-vert.h:2:5: error: missing terminating " character 
[-Werror]

Fix it by changing the line ending from crlf to lf, and convert the
script to Python (qemu build seems perl-free after that).

Signed-off-by: Marc-André Lureau 
Acked-by: Thomas Huth 
---
  meson.build  |  2 +-
  scripts/shaderinclude.pl | 16 
  scripts/shaderinclude.py | 26 ++
  3 files changed, 27 insertions(+), 17 deletions(-)
  delete mode 100644 scripts/shaderinclude.pl
  create mode 100755 scripts/shaderinclude.py


This seems to break our "make vm-build-freebsd" test... I'm now getting:

[281/1485] Generating ui/shader/texture-blit-frag.h with a custom command 
(wrapped by meson to capture output)

FAILED: ui/shader/texture-blit-frag.h
/usr/local/bin/python3.7 /usr/home/qemu/qemu-test.SnknY0/src/meson/meson.py 
--internal exe --capture ui/shader/texture-blit-frag.h -- 
/usr/home/qemu/qemu-test.SnknY0/src/scripts/shaderinclude.py 
../src/ui/shader/texture-blit.frag

--- stderr ---
env: python3: No such file or directory

Looks like you've got to do "chmod a-x scripts/shaderinclude.py" to get this 
fixed, after removing the executable bits, I'm getting:


[281/1485] Generating ui/shader/texture-blit-frag.h with a custom command 
(wrapped by meson to capture output)


and the compilation process continues happily.

 Thomas




Re: [PATCH] python: QEMUMachine: enable qmp accept timeout by default

2023-01-10 Thread Vladimir Sementsov-Ogievskiy

On 7/12/22 00:21, John Snow wrote:

On Mon, Jul 11, 2022 at 5:16 PM John Snow  wrote:


On Fri, Jun 24, 2022 at 3:53 PM Vladimir Sementsov-Ogievskiy
 wrote:


I've spent much time trying to debug hanging pipeline in gitlab. I
started from and idea that I have problem in code in my series (which
has some timeouts). Finally I found that the problem is that I've used
QEMUMachine class directly to avoid qtest, and didn't add necessary
arguments. Qemu fails and we wait for qmp accept endlessly. In gitlab
it's just stopped by timeout (one hour) with no sign of what's going
wrong.

With timeout enabled, gitlab don't wait for an hour and prints all
needed information.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---

Hi all!

Just compare this
   https://gitlab.com/vsementsov/qemu/-/pipelines/572232557
and this
   https://gitlab.com/vsementsov/qemu/-/pipelines/572526252

and you'll see that the latter is much better.

  python/qemu/machine/machine.py | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 37191f433b..01a12f6f73 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -131,7 +131,7 @@ def __init__(self,
   drain_console: bool = False,
   console_log: Optional[str] = None,
   log_dir: Optional[str] = None,
- qmp_timer: Optional[float] = None):
+ qmp_timer: float = 30):
  '''
  Initialize a QEMUMachine

--
2.25.1



Oh, this is because machine.py uses the qmp_timer for *all* timeouts,
and not just the QMP commands themselves, and this relates to the work
Marc Andre is doing with regards to changing the launch mechanism to
handle the race condition when the QEMU launch fails, but the QMP
connection just sits waiting.

I'm quite of the mind that it's really time to rewrite machine.py to
use the native asyncio interfaces I've been writing to help manage
this, but in the meantime I think this is probably a reasonable
concession and a more useful default.

...I think. Willing to take it for now and re-investigate when the
other fixes make it to the tree.

Reviewed-by: John Snow 


Oh, keep the type as Optional[float], though, so the timeout can be
disabled again, and keeps the type consistent with the qtest
derivative class. I've staged your patch with that change made, let me
know if that's not OK. Modified patch is on my python branch:

Thanks, merged.



Hmm, seems that's lost.. I don't see it neither in master nor in your python 
branch..

--
Best regards,
Vladimir




[PATCH v5 1/1] python/machine: Fix AF_UNIX path too long on macOS

2023-01-10 Thread Peter Delevoryas
On macOS, private $TMPDIR's are the default. These $TMPDIR's are
generated from a user's unix UID and UUID [1], which can create a
relatively long path:

/var/folders/d7/rz20f6hd709c1ty8f6_6y_z4gn/T/

QEMU's avocado tests create a temporary directory prefixed by
"avo_qemu_sock_", and create QMP sockets within _that_ as well.
The QMP socket is unnecessarily long, because a temporary directory
is created for every QEMUMachine object.

/avo_qemu_sock_uh3w_dgc/qemu-37331-10bacf110-monitor.sock

The path limit for unix sockets on macOS is 104: [2]

/*
 * [XSI] Definitions for UNIX IPC domain.
 */
struct  sockaddr_un {
unsigned char   sun_len;/* sockaddr len including null */
sa_family_t sun_family; /* [XSI] AF_UNIX */
charsun_path[104];  /* [XSI] path name (gag) */
};

This results in avocado tests failing on macOS because the QMP unix
socket can't be created, because the path is too long:

ERROR| Failed to establish connection: OSError: AF_UNIX path too long

This change resolves by reducing the size of the socket directory prefix
and the suffix on the QMP and console socket names.

The result is paths like this:

pdel@pdel-mbp:/var/folders/d7/rz20f6hd709c1ty8f6_6y_z4gn/T
$ tree qemu*
qemu_df4evjeq
qemu_jbxel3gy
qemu_ml9s_gg7
qemu_oc7h7f3u
qemu_oqb1yf97
├── 10a004050.con
└── 10a004050.qmp

[1] 
https://apple.stackexchange.com/questions/353832/why-is-mac-osx-temp-directory-in-weird-path
[2] /Library/Developer/CommandLineTools/SDKs/MacOSX12.3.sdk/usr/include/sys/un.h

Signed-off-by: Peter Delevoryas 
Reviewed-by: Daniel P. Berrangé 
Reviewed-by: Philippe Mathieu-Daudé 
---
 python/qemu/machine/machine.py | 6 +++---
 tests/avocado/avocado_qemu/__init__.py | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 748a0d807c9d..d70977378305 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -157,7 +157,7 @@ def __init__(self,
 self._wrapper = wrapper
 self._qmp_timer = qmp_timer
 
-self._name = name or f"qemu-{os.getpid()}-{id(self):02x}"
+self._name = name or f"{id(self):x}"
 self._temp_dir: Optional[str] = None
 self._base_temp_dir = base_temp_dir
 self._sock_dir = sock_dir
@@ -167,7 +167,7 @@ def __init__(self,
 self._monitor_address = monitor_address
 else:
 self._monitor_address = os.path.join(
-self.sock_dir, f"{self._name}-monitor.sock"
+self.sock_dir, f"{self._name}.qmp"
 )
 
 self._console_log_path = console_log
@@ -192,7 +192,7 @@ def __init__(self,
 self._console_set = False
 self._console_device_type: Optional[str] = None
 self._console_address = os.path.join(
-self.sock_dir, f"{self._name}-console.sock"
+self.sock_dir, f"{self._name}.con"
 )
 self._console_socket: Optional[socket.socket] = None
 self._remove_files: List[str] = []
diff --git a/tests/avocado/avocado_qemu/__init__.py 
b/tests/avocado/avocado_qemu/__init__.py
index 910f3ba1eab8..25a546842fab 100644
--- a/tests/avocado/avocado_qemu/__init__.py
+++ b/tests/avocado/avocado_qemu/__init__.py
@@ -306,7 +306,7 @@ def require_netdev(self, netdevname):
 self.cancel('no support for user networking')
 
 def _new_vm(self, name, *args):
-self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_")
+self._sd = tempfile.TemporaryDirectory(prefix="qemu_")
 vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir,
  sock_dir=self._sd.name, log_dir=self.logdir)
 self.log.debug('QEMUMachine "%s" created', name)
-- 
2.39.0




Re: [PATCH v4 17/17] ui: Simplify control flow in qemu_mouse_set()

2023-01-10 Thread Daniel P . Berrangé
On Mon, Jan 09, 2023 at 08:03:21PM +0100, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster 
> ---
>  ui/input.c | 24 +++-
>  1 file changed, 11 insertions(+), 13 deletions(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH v6 4/4] softmmu/rtc: Emit warning when using driftfix=slew on systems without mc146818

2023-01-10 Thread Thomas Huth
The 'slew' lost tick policy is only available on systems with a mc146818
RTC. On other systems, "-rtc driftfix=slew" is currently silently ignored.
Let's emit at least a warning in this case to make the users aware that
there is something wrong in their command line settings.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Thomas Huth 
---
 softmmu/rtc.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/softmmu/rtc.c b/softmmu/rtc.c
index 7e2956f81e..f7114bed7d 100644
--- a/softmmu/rtc.c
+++ b/softmmu/rtc.c
@@ -33,6 +33,7 @@
 #include "sysemu/replay.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/rtc.h"
+#include "hw/rtc/mc146818rtc.h"
 
 static enum {
 RTC_BASE_UTC,
@@ -177,10 +178,13 @@ void configure_rtc(QemuOpts *opts)
 value = qemu_opt_get(opts, "driftfix");
 if (value) {
 if (!strcmp(value, "slew")) {
-object_register_sugar_prop("mc146818rtc",
+object_register_sugar_prop(TYPE_MC146818_RTC,
"lost_tick_policy",
"slew",
false);
+if (!object_class_by_name(TYPE_MC146818_RTC)) {
+warn_report("driftfix 'slew' is not available with this 
machine");
+}
 } else if (!strcmp(value, "none")) {
 /* discard is default */
 } else {
-- 
2.31.1




[PATCH v2 5/5] hw/i2c/versatile_i2c: Rename versatile_i2c -> arm_sbcon_i2c

2023-01-10 Thread Philippe Mathieu-Daudé
This device model started with the Versatile board, named
TYPE_VERSATILE_I2C, then ended up renamed TYPE_ARM_SBCON_I2C
as per the official "ARM SBCon two-wire serial bus interface"
description from:
https://developer.arm.com/documentation/dui0440/b/programmer-s-reference/two-wire-serial-bus-interface--sbcon

Use the latter name as a better description.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
---
 MAINTAINERS |  1 +
 hw/arm/Kconfig  |  4 ++--
 hw/i2c/Kconfig  |  2 +-
 hw/i2c/{versatile_i2c.c => arm_sbcon_i2c.c} | 24 ++---
 hw/i2c/meson.build  |  2 +-
 5 files changed, 17 insertions(+), 16 deletions(-)
 rename hw/i2c/{versatile_i2c.c => arm_sbcon_i2c.c} (81%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 5606e5dbd2..e6bfce8fe2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -942,6 +942,7 @@ M: Peter Maydell 
 L: qemu-...@nongnu.org
 S: Maintained
 F: hw/*/versatile*
+F: hw/i2c/arm_sbcon_i2c.c
 F: include/hw/i2c/arm_sbcon_i2c.h
 F: hw/misc/arm_sysctl.c
 F: docs/system/arm/versatile.rst
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 17fcde8e1c..7db0ad7e8f 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -207,7 +207,7 @@ config REALVIEW
 select PL110
 select PL181  # display
 select PL310  # cache controller
-select VERSATILE_I2C
+select ARM_SBCON_I2C
 select DS1338 # I2C RTC+NVRAM
 select USB_OHCI
 
@@ -472,7 +472,7 @@ config MPS2
 select SPLIT_IRQ
 select UNIMP
 select CMSDK_APB_WATCHDOG
-select VERSATILE_I2C
+select ARM_SBCON_I2C
 
 config FSL_IMX7
 bool
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
index 9bb8870517..7ac9cadffa 100644
--- a/hw/i2c/Kconfig
+++ b/hw/i2c/Kconfig
@@ -14,7 +14,7 @@ config SMBUS_EEPROM
 bool
 select SMBUS
 
-config VERSATILE_I2C
+config ARM_SBCON_I2C
 bool
 select BITBANG_I2C
 
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/arm_sbcon_i2c.c
similarity index 81%
rename from hw/i2c/versatile_i2c.c
rename to hw/i2c/arm_sbcon_i2c.c
index d19df62265..979ccbe0ed 100644
--- a/hw/i2c/versatile_i2c.c
+++ b/hw/i2c/arm_sbcon_i2c.c
@@ -37,7 +37,7 @@ REG32(CONTROL_CLR, 4)
 #define SCL BIT(0)
 #define SDA BIT(1)
 
-static uint64_t versatile_i2c_read(void *opaque, hwaddr offset,
+static uint64_t arm_sbcon_i2c_read(void *opaque, hwaddr offset,
unsigned size)
 {
 ArmSbconI2CState *s = opaque;
@@ -52,7 +52,7 @@ static uint64_t versatile_i2c_read(void *opaque, hwaddr 
offset,
 }
 }
 
-static void versatile_i2c_write(void *opaque, hwaddr offset,
+static void arm_sbcon_i2c_write(void *opaque, hwaddr offset,
 uint64_t value, unsigned size)
 {
 ArmSbconI2CState *s = opaque;
@@ -72,13 +72,13 @@ static void versatile_i2c_write(void *opaque, hwaddr offset,
 s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & SDA) != 0);
 }
 
-static const MemoryRegionOps versatile_i2c_ops = {
-.read = versatile_i2c_read,
-.write = versatile_i2c_write,
+static const MemoryRegionOps arm_sbcon_i2c_ops = {
+.read = arm_sbcon_i2c_read,
+.write = arm_sbcon_i2c_write,
 .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void versatile_i2c_init(Object *obj)
+static void arm_sbcon_i2c_init(Object *obj)
 {
 DeviceState *dev = DEVICE(obj);
 ArmSbconI2CState *s = ARM_SBCON_I2C(obj);
@@ -87,21 +87,21 @@ static void versatile_i2c_init(Object *obj)
 
 bus = i2c_init_bus(dev, "i2c");
 bitbang_i2c_init(&s->bitbang, bus);
-memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s,
+memory_region_init_io(&s->iomem, obj, &arm_sbcon_i2c_ops, s,
   "arm_sbcon_i2c", 0x1000);
 sysbus_init_mmio(sbd, &s->iomem);
 }
 
-static const TypeInfo versatile_i2c_info = {
+static const TypeInfo arm_sbcon_i2c_info = {
 .name  = TYPE_ARM_SBCON_I2C,
 .parent= TYPE_SYS_BUS_DEVICE,
 .instance_size = sizeof(ArmSbconI2CState),
-.instance_init = versatile_i2c_init,
+.instance_init = arm_sbcon_i2c_init,
 };
 
-static void versatile_i2c_register_types(void)
+static void arm_sbcon_i2c_register_types(void)
 {
-type_register_static(&versatile_i2c_info);
+type_register_static(&arm_sbcon_i2c_info);
 }
 
-type_init(versatile_i2c_register_types)
+type_init(arm_sbcon_i2c_register_types)
diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build
index 6e7340aaac..32ac30abae 100644
--- a/hw/i2c/meson.build
+++ b/hw/i2c/meson.build
@@ -11,7 +11,7 @@ i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: 
files('mpc_i2c.c'))
 i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c'))
 i2c_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_smbus.c'))
 i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c'))
-i2c_ss.add(when: 'CONFIG_VERSATILE_I2C', if_true: files('versatile_i2c.c'))
+i2c_ss.add(when: 'CONFIG_ARM_SBCON_I2C', if_true:

[PATCH] mips: always include nanomips disassembler

2023-01-10 Thread Paolo Bonzini
Since the nanomips disassembler is not C++ code anymore, it need not
depend on link_language == cpp.  Always include it and remove the
CONFIG_NANOMIPS_DIS symbol.

Cc: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 disas/meson.build | 3 +--
 include/exec/poison.h | 1 -
 meson.build   | 7 +--
 target/mips/cpu.c | 2 --
 4 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/disas/meson.build b/disas/meson.build
index 1977f5cd92ef..c865bdd8827f 100644
--- a/disas/meson.build
+++ b/disas/meson.build
@@ -4,8 +4,7 @@ common_ss.add(when: 'CONFIG_HEXAGON_DIS', if_true: 
files('hexagon.c'))
 common_ss.add(when: 'CONFIG_HPPA_DIS', if_true: files('hppa.c'))
 common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c'))
 common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c'))
-common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c'))
-common_ss.add(when: 'CONFIG_NANOMIPS_DIS', if_true: files('nanomips.c'))
+common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c', 'nanomips.c'))
 common_ss.add(when: 'CONFIG_NIOS2_DIS', if_true: files('nios2.c'))
 common_ss.add(when: 'CONFIG_RISCV_DIS', if_true: files('riscv.c'))
 common_ss.add(when: 'CONFIG_SH4_DIS', if_true: files('sh4.c'))
diff --git a/include/exec/poison.h b/include/exec/poison.h
index f0959bc84ef5..140daa4a85a4 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -74,7 +74,6 @@
 #pragma GCC poison CONFIG_M68K_DIS
 #pragma GCC poison CONFIG_MICROBLAZE_DIS
 #pragma GCC poison CONFIG_MIPS_DIS
-#pragma GCC poison CONFIG_NANOMIPS_DIS
 #pragma GCC poison CONFIG_NIOS2_DIS
 #pragma GCC poison CONFIG_PPC_DIS
 #pragma GCC poison CONFIG_RISCV_DIS
diff --git a/meson.build b/meson.build
index 175517eafde8..bfb461d1efac 100644
--- a/meson.build
+++ b/meson.build
@@ -2478,7 +2478,7 @@ disassemblers = {
   'x86_64' : ['CONFIG_I386_DIS'],
   'm68k' : ['CONFIG_M68K_DIS'],
   'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
-  'mips' : ['CONFIG_MIPS_DIS'],
+  'mips' : [ 'CONFIG_MIPS_DIS'],
   'nios2' : ['CONFIG_NIOS2_DIS'],
   'or1k' : ['CONFIG_OPENRISC_DIS'],
   'ppc' : ['CONFIG_PPC_DIS'],
@@ -2490,11 +2490,6 @@ disassemblers = {
   'xtensa' : ['CONFIG_XTENSA_DIS'],
   'loongarch' : ['CONFIG_LOONGARCH_DIS'],
 }
-if link_language == 'cpp'
-  disassemblers += {
-'mips' : [ 'CONFIG_MIPS_DIS', 'CONFIG_NANOMIPS_DIS'],
-  }
-endif
 
 have_ivshmem = config_host_data.get('CONFIG_EVENTFD')
 host_kconfig = \
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index c614b04607a2..a216cb0df072 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -439,9 +439,7 @@ static void mips_cpu_disas_set_info(CPUState *s, 
disassemble_info *info)
 info->print_insn = print_insn_little_mips;
 #endif
 } else {
-#if defined(CONFIG_NANOMIPS_DIS)
 info->print_insn = print_insn_nanomips;
-#endif
 }
 }
 
-- 
2.38.1




[PATCH v4 02/11] python/qemu: rename command() to cmd()

2023-01-10 Thread Vladimir Sementsov-Ogievskiy
Use a shorter name. We are going to move in iotests from qmp() to
command() where possible. But command() is longer than qmp() and don't
look better. Let's rename.

You can simply grep for '\.command(' and for 'def command(' to check
that everything is updated (command() in tests/docker/docker.py is
unrelated).

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
 docs/devel/testing.rst|  10 +-
 python/qemu/machine/machine.py|   8 +-
 python/qemu/qmp/legacy.py |   2 +-
 python/qemu/qmp/qmp_shell.py  |   2 +-
 python/qemu/utils/qemu_ga_client.py   |   2 +-
 python/qemu/utils/qom.py  |   8 +-
 python/qemu/utils/qom_common.py   |   2 +-
 python/qemu/utils/qom_fuse.py |   6 +-
 scripts/cpu-x86-uarch-abi.py  |   8 +-
 scripts/device-crash-test |   8 +-
 scripts/render_block_graph.py |   8 +-
 tests/avocado/avocado_qemu/__init__.py|   4 +-
 tests/avocado/cpu_queries.py  |   5 +-
 tests/avocado/hotplug_cpu.py  |  10 +-
 tests/avocado/info_usernet.py |   4 +-
 tests/avocado/machine_arm_integratorcp.py |   6 +-
 tests/avocado/machine_m68k_nextcube.py|   4 +-
 tests/avocado/machine_mips_malta.py   |   6 +-
 tests/avocado/machine_s390_ccw_virtio.py  |  28 ++--
 tests/avocado/migration.py|  10 +-
 tests/avocado/pc_cpu_hotplug_props.py |   2 +-
 tests/avocado/version.py  |   4 +-
 tests/avocado/virtio_check_params.py  |   6 +-
 tests/avocado/virtio_version.py   |   5 +-
 tests/avocado/x86_cpu_model_versions.py   |  13 +-
 tests/migration/guestperf/engine.py   | 150 +++---
 tests/qemu-iotests/256|  34 ++---
 tests/qemu-iotests/257|  36 +++---
 28 files changed, 198 insertions(+), 193 deletions(-)

diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
index e10c47b5a7..e3d7bb218c 100644
--- a/docs/devel/testing.rst
+++ b/docs/devel/testing.rst
@@ -988,8 +988,8 @@ class.  Here's a simple usage example:
   """
   def test_qmp_human_info_version(self):
   self.vm.launch()
-  res = self.vm.command('human-monitor-command',
-command_line='info version')
+  res = self.vm.cmd('human-monitor-command',
+command_line='info version')
   self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
 
 To execute your test, run:
@@ -1039,15 +1039,15 @@ and hypothetical example follows:
   first_machine.launch()
   second_machine.launch()
 
-  first_res = first_machine.command(
+  first_res = first_machine.cmd(
   'human-monitor-command',
   command_line='info version')
 
-  second_res = second_machine.command(
+  second_res = second_machine.cmd(
   'human-monitor-command',
   command_line='info version')
 
-  third_res = self.get_vm(name='third_machine').command(
+  third_res = self.get_vm(name='third_machine').cmd(
   'human-monitor-command',
   command_line='info version')
 
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 9059dc3948..75f1f1c246 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -679,16 +679,16 @@ def qmp(self, cmd: str,
 self._quit_issued = True
 return ret
 
-def command(self, cmd: str,
-conv_keys: bool = True,
-**args: Any) -> QMPReturnValue:
+def cmd(self, cmd: str,
+conv_keys: bool = True,
+**args: Any) -> QMPReturnValue:
 """
 Invoke a QMP command.
 On success return the response dict.
 On failure raise an exception.
 """
 qmp_args = self._qmp_args(conv_keys, args)
-ret = self._qmp.command(cmd, **qmp_args)
+ret = self._qmp.cmd(cmd, **qmp_args)
 if cmd == 'quit':
 self._quit_issued = True
 return ret
diff --git a/python/qemu/qmp/legacy.py b/python/qemu/qmp/legacy.py
index 8e1a504052..f5b4b1a717 100644
--- a/python/qemu/qmp/legacy.py
+++ b/python/qemu/qmp/legacy.py
@@ -199,7 +199,7 @@ def cmd_raw(self, name: str,
 qmp_cmd['arguments'] = args
 return self.cmd_obj(qmp_cmd)
 
-def command(self, cmd: str, **kwds: object) -> QMPReturnValue:
+def cmd(self, cmd: str, **kwds: object) -> QMPReturnValue:
 """
 Build and send a QMP command to the monitor, report errors if any
 """
diff --git a/python/qemu/qmp/qmp_shell.py b/python/qemu/qmp/qmp_shell.py
index 5c0d87a0ec..5c578b50e2 100644
--- a/python/qemu/qmp/qmp_shell.py
+++ b/python/qemu/qmp/qmp_shell.py
@@ -195,7 +195,7 @@ def close(self) -> None:
 
 def _fill_completion(self) -> None:
 try:
-cmds = self.command('query-commands')
+

[PATCH v6 2/4] hw/core/qdev-properties-system: Allow the 'slew' policy only on x86

2023-01-10 Thread Thomas Huth
The 'slew' tick policy is currently enforced to be only available on
x86 via some "#ifdef TARGET_I386" statements in mc146818rtc.c. We
want to get rid of those #ifdefs, so we need a different way of
checking whether the policy is allowed or not. Using the setter
function in hw/core/qdev-properties-system.c seems to be a good
place, so let's add a check here.

Suggested-by: Mark Cave-Ayland 
Signed-off-by: Thomas Huth 
---
 hw/core/qdev-properties-system.c | 28 +++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 54a09fa9ac..d42493f630 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -33,6 +33,7 @@
 #include "net/net.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pcie.h"
+#include "hw/i386/x86.h"
 #include "util/block-helpers.h"
 
 static bool check_prop_still_unset(Object *obj, const char *name,
@@ -558,13 +559,38 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo 
*nd)
 
 /* --- lost tick policy --- */
 
+static void qdev_propinfo_set_losttickpolicy(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+Property *prop = opaque;
+int *ptr = object_field_prop_ptr(obj, prop);
+int value;
+
+if (!visit_type_enum(v, name, &value, prop->info->enum_table, errp)) {
+return;
+}
+
+if (value == LOST_TICK_POLICY_SLEW) {
+MachineState *ms = MACHINE(qdev_get_machine());
+
+if (!object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) {
+error_setg(errp,
+   "the 'slew' policy is only available for x86 machines");
+return;
+}
+}
+
+*ptr = value;
+}
+
 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
 
 const PropertyInfo qdev_prop_losttickpolicy = {
 .name  = "LostTickPolicy",
 .enum_table  = &LostTickPolicy_lookup,
 .get   = qdev_propinfo_get_enum,
-.set   = qdev_propinfo_set_enum,
+.set   = qdev_propinfo_set_losttickpolicy,
 .set_default_value = qdev_propinfo_set_default_value_enum,
 };
 
-- 
2.31.1




[PATCH v2 4/5] hw/i2c/versatile_i2c: Use ARM_SBCON_I2C() macro

2023-01-10 Thread Philippe Mathieu-Daudé
ARM_SBCON_I2C() macro and ArmSbconI2CState typedef are
already declared via the QOM DECLARE_INSTANCE_CHECKER()
macro in "hw/i2c/arm_sbcon_i2c.h". Drop the VERSATILE_I2C
declarations from versatile_i2c.c.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
---
 hw/i2c/versatile_i2c.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
index b95c70608b..d19df62265 100644
--- a/hw/i2c/versatile_i2c.c
+++ b/hw/i2c/versatile_i2c.c
@@ -29,11 +29,6 @@
 #include "qemu/module.h"
 #include "qom/object.h"
 
-typedef ArmSbconI2CState VersatileI2CState;
-DECLARE_INSTANCE_CHECKER(ArmSbconI2CState, VERSATILE_I2C,
- TYPE_ARM_SBCON_I2C)
-
-
 
 REG32(CONTROL_GET, 0)
 REG32(CONTROL_SET, 0)
@@ -86,7 +81,7 @@ static const MemoryRegionOps versatile_i2c_ops = {
 static void versatile_i2c_init(Object *obj)
 {
 DeviceState *dev = DEVICE(obj);
-ArmSbconI2CState *s = VERSATILE_I2C(obj);
+ArmSbconI2CState *s = ARM_SBCON_I2C(obj);
 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 I2CBus *bus;
 
-- 
2.38.1




[PATCH v4 03/11] python/machine.py: upgrade vm.cmd() method

2023-01-10 Thread Vladimir Sementsov-Ogievskiy
The method is not popular in iotests, we prefer use vm.qmp() and then
check success by hand.. But that's not optimal. To simplify movement to
vm.cmd() let's support same interface improvements like in vm.qmp().

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
 python/qemu/machine/machine.py | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 75f1f1c246..c45be440de 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -680,13 +680,23 @@ def qmp(self, cmd: str,
 return ret
 
 def cmd(self, cmd: str,
-conv_keys: bool = True,
+args_dict: Optional[Dict[str, object]] = None,
+conv_keys: Optional[bool] = None,
 **args: Any) -> QMPReturnValue:
 """
 Invoke a QMP command.
 On success return the response dict.
 On failure raise an exception.
 """
+if args_dict is not None:
+assert not args
+assert conv_keys is None
+args = args_dict
+conv_keys = False
+
+if conv_keys is None:
+conv_keys = True
+
 qmp_args = self._qmp_args(conv_keys, args)
 ret = self._qmp.cmd(cmd, **qmp_args)
 if cmd == 'quit':
-- 
2.34.1




Re: [RFC PATCH 4/4] qom: Warn when deprecated class property can be removed

2023-01-10 Thread Daniel P . Berrangé
On Mon, Jan 09, 2023 at 11:54:19PM +0100, Philippe Mathieu-Daudé wrote:
> Per docs/system/deprecated.rst, a deprecated feature can be
> removed after 2 releases. Since we commit when a class property
> is deprecated, we can warn when the deprecation period is over.
> 
> See also commit ef1f5b0a96 ("docs: clarify deprecation schedule").
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  qom/object.c | 7 +++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/qom/object.c b/qom/object.c
> index 05b97cd424..cb829f1e44 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -17,6 +17,7 @@
>  #include "qom/object_interfaces.h"
>  #include "qemu/cutils.h"
>  #include "qemu/memalign.h"
> +#include "qemu/qemu-version.h"
>  #include "qapi/visitor.h"
>  #include "qapi/string-input-visitor.h"
>  #include "qapi/string-output-visitor.h"
> @@ -1300,6 +1301,12 @@ void object_class_property_deprecate(ObjectClass 
> *klass,
>  ObjectProperty *prop = object_class_property_find(klass, name);
>  
>  assert(prop);
> +if (qemu_version_delta_current(version_major, version_minor) <= 2) {
> +warn_report_once("Property '%s.%s' has been deprecated in release"
> + " v%u.%u and can be removed.",
> + object_class_get_name(klass), name,
> + version_major, version_minor);
> +}

IMHO this is not really appropriate. Removal of deprecated features
is a job for maintainers, but this is printing a message at users.

Maintainers have a record of deprecations in the docs that they can
periodically review to identify stuff that can now be deleted.


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH v6 0/4] Make the mc146818 RTC device target independent

2023-01-10 Thread Thomas Huth
The basic idea of this patch set is to change hw/rtc/mc146818rtc.c into
target independent code so that the file only has to be compiled once
instead of multiple times (and that it can be used in a qemu-system-all
binary once we get there).

The first patch extracts some functions from the APIC code that will be
required for linking when the mc146818rtc becomes target-independent.

The second patch adds a new way for checking whether the "driftfix=slew"
policy is available or not (since the corresponding #ifdefs in the
mc146818rtc code will be removed).

The third patch then removes the "#ifdef TARGET" switches and turns
the mc146818rtc code into a target-independent file.

The fourth patch just fixes a small cosmetic nit that I discovered along
the way: On systems without mc146818, the "-rtc driftfix=slew" simply
got ignored silently. We should at least emit a warning in this case.

Changes since last iteration:
- Dropped the approach of using a new "slew-tick-policy-available"
  property that needs to be set by the machine code (and thus dropped
  the clean-up patches from Bernhard from this series since they are
  no longer required here now)
- Use a new check in hw/core/qdev-properties-system.c instead
  (see the second patch)

Thomas Huth (4):
  hw/intc: Extract the IRQ counting functions into a separate file
  hw/core/qdev-properties-system: Allow the 'slew' policy only on x86
  hw/rtc/mc146818rtc: Make the mc146818 RTC device target independent
  softmmu/rtc: Emit warning when using driftfix=slew on systems without
mc146818

 include/hw/i386/apic.h   |  2 --
 include/hw/i386/apic_internal.h  |  1 -
 include/hw/intc/kvm_irqcount.h   | 10 +++
 include/hw/rtc/mc146818rtc.h |  1 +
 hw/core/qdev-properties-system.c | 28 +-
 hw/i386/kvm/i8259.c  |  4 +--
 hw/i386/kvm/ioapic.c |  4 +--
 hw/intc/apic.c   |  3 +-
 hw/intc/apic_common.c| 30 ++-
 hw/intc/kvm_irqcount.c   | 49 
 hw/rtc/mc146818rtc.c | 20 ++---
 softmmu/rtc.c|  6 +++-
 hw/intc/meson.build  |  6 
 hw/intc/trace-events |  9 +++---
 hw/rtc/meson.build   |  3 +-
 15 files changed, 115 insertions(+), 61 deletions(-)
 create mode 100644 include/hw/intc/kvm_irqcount.h
 create mode 100644 hw/intc/kvm_irqcount.c

-- 
2.31.1




Re: [RFC PATCH 1/4] qom: Introduce object_class_property_deprecate()

2023-01-10 Thread Daniel P . Berrangé
On Mon, Jan 09, 2023 at 11:54:16PM +0100, Philippe Mathieu-Daudé wrote:
> Introduce object_class_property_deprecate() to register
> a QOM property as deprecated. When this property's getter /
> setter is called, a deprecation warning is displayed on the
> monitor.
> 
> Inspired-by: Daniel P. Berrange 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  include/qom/object.h | 17 +
>  qom/object.c | 23 +++
>  2 files changed, 40 insertions(+)
> 
> diff --git a/include/qom/object.h b/include/qom/object.h
> index ef7258a5e1..b76724292c 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -97,6 +97,7 @@ struct ObjectProperty
>  ObjectPropertyInit *init;
>  void *opaque;
>  QObject *defval;
> +const char *deprecation_reason;
>  };
>  
>  /**
> @@ -1075,6 +1076,22 @@ ObjectProperty *object_class_property_add(ObjectClass 
> *klass, const char *name,
>ObjectPropertyRelease *release,
>void *opaque);
>  
> +/**
> + * object_class_property_deprecate:
> + * @klass: the class to add a property to
> + * @name: the name of the property.  This can contain any character except 
> for
> + *  a forward slash.  In general, you should use hyphens '-' instead of
> + *  underscores '_' when naming properties.
> + * @reason: the deprecation reason.
> + * @version_major: the major version since this property is deprecated.
> + * @version_minor: the minor version since this property is deprecated.
> + *
> + * Deprecate a class property.
> + */
> +void object_class_property_deprecate(ObjectClass *klass,
> + const char *name, const char *reason,
> + int version_major, int version_minor);
> +
>  /**
>   * object_property_set_default_bool:
>   * @prop: the property to set
> diff --git a/qom/object.c b/qom/object.c
> index e25f1e96db..05b97cd424 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -1293,6 +1293,16 @@ object_class_property_add(ObjectClass *klass,
>  return prop;
>  }
>  
> +void object_class_property_deprecate(ObjectClass *klass,
> + const char *name, const char *reason,
> + int version_major, int version_minor)
> +{
> +ObjectProperty *prop = object_class_property_find(klass, name);
> +
> +assert(prop);
> +prop->deprecation_reason = reason;
> +}

Nothing is using the 'version_major' / 'version_minor' parameters so
they look redundant.

> @@ -1392,6 +1413,7 @@ bool object_property_get(Object *obj, const char *name, 
> Visitor *v,
>  return false;
>  }
>  
> +object_property_check_deprecation(obj, name, prop);
>  if (!prop->get) {
>  error_setg(errp, "Property '%s.%s' is not readable",
> object_get_typename(obj), name);
> @@ -1412,6 +1434,7 @@ bool object_property_set(Object *obj, const char *name, 
> Visitor *v,
>  return false;
>  }
>  
> +object_property_check_deprecation(obj, name, prop);
>  if (!prop->set) {
>  error_setg(errp, "Property '%s.%s' is not writable",
> object_get_typename(obj), name);
> -- 
> 2.38.1
> 

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH v6 0/4] Make the mc146818 RTC device target independent

2023-01-10 Thread Philippe Mathieu-Daudé

On 10/1/23 10:53, Thomas Huth wrote:

The basic idea of this patch set is to change hw/rtc/mc146818rtc.c into
target independent code so that the file only has to be compiled once
instead of multiple times (and that it can be used in a qemu-system-all
binary once we get there).



Thomas Huth (4):
   hw/intc: Extract the IRQ counting functions into a separate file
   hw/core/qdev-properties-system: Allow the 'slew' policy only on x86
   hw/rtc/mc146818rtc: Make the mc146818 RTC device target independent
   softmmu/rtc: Emit warning when using driftfix=slew on systems without
 mc146818


I was happy enough with each iterations, but the changes requested over
each iter was worth having a v6, it is now very clean.

Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH v5 0/1] python/machine: Fix AF_UNIX path too long

2023-01-10 Thread Peter Delevoryas
On Tue, Jan 10, 2023 at 09:38:38AM +0100, Philippe Mathieu-Daudé wrote:
> On 10/1/23 09:29, Peter Delevoryas wrote:
> 
> > $ make check-avocado
> 
> > Avocado crashed: TypeError: cannot pickle '_thread.RLock' object
> 
> Yeah... you have to pick Cleber's patches from
> https://gitlab.com/cleber.gnu/qemu/-/commits/WIP/tests_fixes
> and run as:
> 
> $ TMPDIR=/tmp avocado run --test-runner=nrunner ...

I guess I still get this error from `make check-avocado` on Aarch64 tests:

 (17/35) tests/avocado/replay_linux.py:ReplayLinuxAarch64.test_virt_gicv2: 
ERROR: Failed to fetch Fedora-Cloud-Base-31-1.9
.aarch64.qcow2 (Can't pickle local object 'url_download..download'). 
(0.89 s)

But `./build/tests/venv/bin/avocado run tests/avocado` worked ok.

> 
> This is tracked on the avocado project:
> https://github.com/avocado-framework/avocado/issues/5138#issuecomment-1314551148

Thanks!
- Peter

> 



[PATCH v6 1/4] hw/intc: Extract the IRQ counting functions into a separate file

2023-01-10 Thread Thomas Huth
These IRQ counting functions will soon be required in binaries that
do not include the APIC code, too, so let's extract them into a
separate file that can be linked independently of the APIC code.

While we're at it, change the apic_* prefix into kvm_* since the
functions are used from the i8259 PIC (i.e. not the APIC), too.

Reviewed-by: Bernhard Beschow 
Signed-off-by: Thomas Huth 
---
 include/hw/i386/apic.h  |  2 --
 include/hw/i386/apic_internal.h |  1 -
 include/hw/intc/kvm_irqcount.h  | 10 +++
 hw/i386/kvm/i8259.c |  4 +--
 hw/i386/kvm/ioapic.c|  4 +--
 hw/intc/apic.c  |  3 +-
 hw/intc/apic_common.c   | 30 ++--
 hw/intc/kvm_irqcount.c  | 49 +
 hw/rtc/mc146818rtc.c|  6 ++--
 hw/intc/meson.build |  6 
 hw/intc/trace-events|  9 +++---
 11 files changed, 81 insertions(+), 43 deletions(-)
 create mode 100644 include/hw/intc/kvm_irqcount.h
 create mode 100644 hw/intc/kvm_irqcount.c

diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h
index da1d2fe155..bdc15a7a73 100644
--- a/include/hw/i386/apic.h
+++ b/include/hw/i386/apic.h
@@ -9,8 +9,6 @@ int apic_accept_pic_intr(DeviceState *s);
 void apic_deliver_pic_intr(DeviceState *s, int level);
 void apic_deliver_nmi(DeviceState *d);
 int apic_get_interrupt(DeviceState *s);
-void apic_reset_irq_delivered(void);
-int apic_get_irq_delivered(void);
 void cpu_set_apic_base(DeviceState *s, uint64_t val);
 uint64_t cpu_get_apic_base(DeviceState *s);
 void cpu_set_apic_tpr(DeviceState *s, uint8_t val);
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
index 968b6648b3..5f2ba24bfc 100644
--- a/include/hw/i386/apic_internal.h
+++ b/include/hw/i386/apic_internal.h
@@ -199,7 +199,6 @@ typedef struct VAPICState {
 
 extern bool apic_report_tpr_access;
 
-void apic_report_irq_delivered(int delivered);
 bool apic_next_timer(APICCommonState *s, int64_t current_time);
 void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
 void apic_enable_vapic(DeviceState *d, hwaddr paddr);
diff --git a/include/hw/intc/kvm_irqcount.h b/include/hw/intc/kvm_irqcount.h
new file mode 100644
index 00..0ed5999e49
--- /dev/null
+++ b/include/hw/intc/kvm_irqcount.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#ifndef KVM_IRQCOUNT_H
+#define KVM_IRQCOUNT_H
+
+void kvm_report_irq_delivered(int delivered);
+void kvm_reset_irq_delivered(void);
+int kvm_get_irq_delivered(void);
+
+#endif
diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c
index d61bae4dc3..3ca0e1ff03 100644
--- a/hw/i386/kvm/i8259.c
+++ b/hw/i386/kvm/i8259.c
@@ -14,7 +14,7 @@
 #include "hw/isa/i8259_internal.h"
 #include "hw/intc/i8259.h"
 #include "qemu/module.h"
-#include "hw/i386/apic_internal.h"
+#include "hw/intc/kvm_irqcount.h"
 #include "hw/irq.h"
 #include "sysemu/kvm.h"
 #include "qom/object.h"
@@ -117,7 +117,7 @@ static void kvm_pic_set_irq(void *opaque, int irq, int 
level)
 
 pic_stat_update_irq(irq, level);
 delivered = kvm_set_irq(kvm_state, irq, level);
-apic_report_irq_delivered(delivered);
+kvm_report_irq_delivered(delivered);
 }
 
 static void kvm_pic_realize(DeviceState *dev, Error **errp)
diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c
index ee7c8ef68b..272e26b4a2 100644
--- a/hw/i386/kvm/ioapic.c
+++ b/hw/i386/kvm/ioapic.c
@@ -15,7 +15,7 @@
 #include "hw/i386/x86.h"
 #include "hw/qdev-properties.h"
 #include "hw/i386/ioapic_internal.h"
-#include "hw/i386/apic_internal.h"
+#include "hw/intc/kvm_irqcount.h"
 #include "sysemu/kvm.h"
 
 /* PC Utility function */
@@ -116,7 +116,7 @@ static void kvm_ioapic_set_irq(void *opaque, int irq, int 
level)
 
 ioapic_stat_update_irq(common, irq, level);
 delivered = kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level);
-apic_report_irq_delivered(delivered);
+kvm_report_irq_delivered(delivered);
 }
 
 static void kvm_ioapic_realize(DeviceState *dev, Error **errp)
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 3df11c34d6..2d3e55f4e2 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -22,6 +22,7 @@
 #include "hw/i386/apic.h"
 #include "hw/i386/ioapic.h"
 #include "hw/intc/i8259.h"
+#include "hw/intc/kvm_irqcount.h"
 #include "hw/pci/msi.h"
 #include "qemu/host-utils.h"
 #include "sysemu/kvm.h"
@@ -399,7 +400,7 @@ void apic_poll_irq(DeviceState *dev)
 
 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode)
 {
-apic_report_irq_delivered(!apic_get_bit(s->irr, vector_num));
+kvm_report_irq_delivered(!apic_get_bit(s->irr, vector_num));
 
 apic_set_bit(s->irr, vector_num);
 if (trigger_mode)
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index 2a20982066..4a34f03047 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -25,6 +25,7 @@
 #include "qapi/visitor.h"
 #include "hw/i386/apic.h"
 #include "hw/i386/apic_internal.h"
+#include "hw/intc/kv

Re: [RFC PATCH 2/4] hw/block: Rename TYPE_PFLASH_CFI02 'width' property as 'device-width'

2023-01-10 Thread Daniel P . Berrangé
On Mon, Jan 09, 2023 at 11:54:17PM +0100, Philippe Mathieu-Daudé wrote:
> Use the same property name than the TYPE_PFLASH_CFI01 model.
> 
> Deprecate the current 'width' property and add the 'device-width'
> property pointing to the same field in PFlashCFI02.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/block/pflash_cfi02.c | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)

docs/about/deprecated.rst must be updated for any deprecations
to be valid.

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH v6 3/4] hw/rtc/mc146818rtc: Make the mc146818 RTC device target independent

2023-01-10 Thread Thomas Huth
The only reason for this code being target dependent was the IRQ-counting
related code in rtc_policy_slew_deliver_irq(). Since these functions have
been moved into a new, separate file (kvm_irqcount.c) which is now always
compiled and linked if necessary, we can get rid of the #ifdef TARGET_I386
switches in mc146818rtc.c and declare it in the softmmu_ss instead of
specific_ss, so that the code only gets compiled once for all targets.

Signed-off-by: Thomas Huth 
---
 include/hw/rtc/mc146818rtc.h |  1 +
 hw/rtc/mc146818rtc.c | 14 --
 hw/rtc/meson.build   |  3 +--
 3 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h
index 1db0fcee92..45bcd6f040 100644
--- a/include/hw/rtc/mc146818rtc.h
+++ b/include/hw/rtc/mc146818rtc.h
@@ -55,5 +55,6 @@ ISADevice *mc146818_rtc_init(ISABus *bus, int base_year,
  qemu_irq intercept_irq);
 void rtc_set_memory(ISADevice *dev, int addr, int val);
 int rtc_get_memory(ISADevice *dev, int addr);
+void qmp_rtc_reset_reinjection(Error **errp);
 
 #endif /* HW_RTC_MC146818RTC_H */
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index 947d68c257..bc1192b7ae 100644
--- a/hw/rtc/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -45,10 +45,6 @@
 #include "qapi/visitor.h"
 #include "hw/rtc/mc146818rtc_regs.h"
 
-#ifdef TARGET_I386
-#include "qapi/qapi-commands-misc-target.h"
-#endif
-
 //#define DEBUG_CMOS
 //#define DEBUG_COALESCED
 
@@ -112,7 +108,6 @@ static void rtc_coalesced_timer_update(RTCState *s)
 static QLIST_HEAD(, RTCState) rtc_devices =
 QLIST_HEAD_INITIALIZER(rtc_devices);
 
-#ifdef TARGET_I386
 void qmp_rtc_reset_reinjection(Error **errp)
 {
 RTCState *s;
@@ -145,13 +140,6 @@ static void rtc_coalesced_timer(void *opaque)
 
 rtc_coalesced_timer_update(s);
 }
-#else
-static bool rtc_policy_slew_deliver_irq(RTCState *s)
-{
-assert(0);
-return false;
-}
-#endif
 
 static uint32_t rtc_periodic_clock_ticks(RTCState *s)
 {
@@ -922,12 +910,10 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
 rtc_set_date_from_host(isadev);
 
 switch (s->lost_tick_policy) {
-#ifdef TARGET_I386
 case LOST_TICK_POLICY_SLEW:
 s->coalesced_timer =
 timer_new_ns(rtc_clock, rtc_coalesced_timer, s);
 break;
-#endif
 case LOST_TICK_POLICY_DISCARD:
 break;
 default:
diff --git a/hw/rtc/meson.build b/hw/rtc/meson.build
index dc33973384..34a4d316fa 100644
--- a/hw/rtc/meson.build
+++ b/hw/rtc/meson.build
@@ -13,5 +13,4 @@ softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: 
files('aspeed_rtc.c'))
 softmmu_ss.add(when: 'CONFIG_GOLDFISH_RTC', if_true: files('goldfish_rtc.c'))
 softmmu_ss.add(when: 'CONFIG_LS7A_RTC', if_true: files('ls7a_rtc.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-rtc.c'))
-
-specific_ss.add(when: 'CONFIG_MC146818RTC', if_true: files('mc146818rtc.c'))
+softmmu_ss.add(when: 'CONFIG_MC146818RTC', if_true: files('mc146818rtc.c'))
-- 
2.31.1




Re: [PATCH v3 1/6] migration: Allow immutable device state to be migrated early (i.e., before RAM)

2023-01-10 Thread David Hildenbrand

On 09.01.23 20:54, Peter Xu wrote:

On Mon, Jan 09, 2023 at 03:34:48PM +0100, David Hildenbrand wrote:

On 05.01.23 18:15, Peter Xu wrote:

On Thu, Jan 05, 2023 at 09:35:54AM +0100, David Hildenbrand wrote:

On 04.01.23 18:23, Peter Xu wrote:

On Thu, Dec 22, 2022 at 12:02:10PM +0100, David Hildenbrand wrote:

Migrating device state before we start iterating is currently impossible.
Introduce and use qemu_savevm_state_start_precopy(), and use
a new special migration priority -- MIG_PRI_POST_SETUP -- to decide whether
state will be saved in qemu_savevm_state_start_precopy() or in
qemu_savevm_state_complete_precopy_*().


Can something like this be done in qemu_savevm_state_setup()?


Hi Peter,


Hi, David,



Do you mean

(a) Moving qemu_savevm_state_start_precopy() effectively into
  qemu_savevm_state_setup()

(b) Using se->ops->save_setup()


I meant (b).



I first tried going via (b), but decided to go the current way of using a
proper vmstate with properties (instead of e.g., filling the stream
manually), which also made vmdesc handling possible (and significantly
cleaner).

Regarding (a), I decided to not move logic of
qemu_savevm_state_start_precopy() into qemu_savevm_state_setup(), because it
looked cleaner to save device state with the BQL held and for background
snapshots, the VM has been stopped. To decouple device state saving from the
setup path, just like we do it right now for all vmstates.


Is BQL required or optional?  IIUC it's at least still not taken in the
migration thread path, only in savevm path.



Having that said, for virtio-mem, it would still work because that state is
immutable once migration starts, but it felt cleaner to separate the setup()
phase from actual device state saving.


I get the point.  My major concerns are:

(1) The new migration priority is changing the semantic of original,
making it over-complicated

(2) The new precopy-start routine added one more step to the migration
framework, while it's somehow overlapping (if not to say, mostly the
same as..) save_setup().

For (1): the old priority was only deciding the order of save entries in
the global list, nothing more than that.  Even if we want to have a
precopy-start phase, I'd suggest we use something else and keep the
migration priority simple.  Otherwise we really need serious documentation
for MigrationPriority and if so I'd rather don't bother and not reuse the
priority field.

For (2), if you see there're a bunch of save_setup() that already does
things like transferring static data besides the device states.  Besides
the notorious ram_save_setup() there's also dirty_bitmap_save_setup() which
also sends a bitmap during save_setup() and some others.  It looks clean to
me to do it in the same way as we used to.

Reusing vmstate_save() and vmsd structures are useful too which I totally
agree.  So.. can we just call vmstate_save_state() in the save_setup() of
the other new vmsd of virtio-mem?



I went halfway that way, by moving stuff into qemu_savevm_state_setup()
and avoiding using a new migration priority. Seems to work:


The whole point of my suggestion is not moving things into
qemu_savevm_state_setup(), but avoid introducing more complexity to the
migration framework if unnecessary, so keep the generic framework as simple
as possible.


IMHO, the current approach is actually quite simple and clean. But ...




I think we could go one step further and perform it from a save_setup() 
callback,
however, I'm not convinced that this gets particularly cleaner (vmdesc handling
eventually).


What I wanted to suggest is exactly trying to avoid vmsd handling.  To be
more explicit, I mean: besides vmstate_virtio_mem_device_early, virtio-mem
can register with another new SaveVMHandlers with both save_setup and
load_setup registered, then e.g. in its save_setup(), one simply calls:


... I can see if it can be made working that way and how the result looks. I 
know
that we use vmstate_save_state() from virtio code, but I don't remember using
it in save_setup() from QEMU_VM_SECTION_START and not QEMU_VM_SECTION_FULL.


There is this interesting bit in register_savevm_live(), which sets "se->is_ram = 
1".
qemu_save_device_state() will not include the state. As it's used by XEN, I 
don't
particularly care.




   vmstate_save_state(f, &vmstate_virtio_mem_device_early, virtio_mem_dev,
  NULL);

I'm not sure whether the JSONWriter* is required in this case, maybe not
yet to at least make it work.


It was required when handling vmstates the current way to make
analyze-migration.py not bail out (which is a good thing because one can
actually inspect the migration content):

$ ./scripts/analyze-migration.py -f STATEFILE
{
"ram (2)": {
"section sizes": {
":00:03.0/mem0": "0x000f",
"pc.ram": "0x0001",
"/rom@etc/acpi/tables": "0x0002",
"pc.bios": "0x0004"

Re: [PATCH v3 0/8] Fix win32/msys2 shader compilation & update lcitool deps

2023-01-10 Thread Thomas Huth

On 10/01/2023 11.41, Alex Bennée wrote:


marcandre.lur...@redhat.com writes:


From: Marc-André Lureau 

Hi,

Fix the shader compilation error on win32/msys2 and convert the related script
from perl to python. Drop unneeded dependencies from lcitool project.


Queued to testing/next, thanks.


Please make sure to fix the permissions (a-x) of the new script in the first 
patch.


 Thanks,
  Thomas




Re: [PATCH v3 1/8] build-sys: fix crlf-ending C code

2023-01-10 Thread Marc-André Lureau
Hi

On Tue, Jan 10, 2023 at 12:33 PM Thomas Huth  wrote:

> On 10/01/2023 09.02, marcandre.lur...@redhat.com wrote:
> > From: Marc-André Lureau 
> >
> > On msys2, the shader-to-C script produces bad C:
> > ./ui/shader/texture-blit-vert.h:2:5: error: missing terminating "
> character [-Werror]
> >
> > Fix it by changing the line ending from crlf to lf, and convert the
> > script to Python (qemu build seems perl-free after that).
> >
> > Signed-off-by: Marc-André Lureau 
> > Acked-by: Thomas Huth 
> > ---
> >   meson.build  |  2 +-
> >   scripts/shaderinclude.pl | 16 
> >   scripts/shaderinclude.py | 26 ++
> >   3 files changed, 27 insertions(+), 17 deletions(-)
> >   delete mode 100644 scripts/shaderinclude.pl
> >   create mode 100755 scripts/shaderinclude.py
>
> This seems to break our "make vm-build-freebsd" test... I'm now getting:
>
> [281/1485] Generating ui/shader/texture-blit-frag.h with a custom command
> (wrapped by meson to capture output)
> FAILED: ui/shader/texture-blit-frag.h
> /usr/local/bin/python3.7
> /usr/home/qemu/qemu-test.SnknY0/src/meson/meson.py
> --internal exe --capture ui/shader/texture-blit-frag.h --
> /usr/home/qemu/qemu-test.SnknY0/src/scripts/shaderinclude.py
> ../src/ui/shader/texture-blit.frag
> --- stderr ---
> env: python3: No such file or directory
>
> Looks like you've got to do "chmod a-x scripts/shaderinclude.py" to get
> this
> fixed, after removing the executable bits, I'm getting:
>
> [281/1485] Generating ui/shader/texture-blit-frag.h with a custom command
> (wrapped by meson to capture output)
>
> and the compilation process continues happily.
>

thanks for the tip, indeed since 0.51 "find_program: use Meson's Python3
for non-executable Python scripts":
https://github.com/mesonbuild/meson/commit/0078d808a2a2b01c634483ca4a986f52ffe1ce3c

It's a bit annoying to have a mix of executable and non-executable
scripts/*.py, but python.., oh well.. I suppose the ones used during build
are -x, the one used manually are +x.


Re: [PATCH v4 00/12] Compiler warning fixes for libvhost-user, libvduse

2023-01-10 Thread Paolo Bonzini
Il gio 5 gen 2023, 02:58 Michael S. Tsirkin  ha scritto:

> Paolo I understand you are merging this?
>

It would be fine either way; when I find issues in a series I tend to queue
it just in case the other maintainer prefers to leave further handling to
me. In this case it caught my eye due to the meson.build implications.

Anyhow I have already passed it through CI (a bit slow due to the holidays)
and will send the PR today or tomorrow.

Paolo


> Reviewed-by: Michael S. Tsirkin 
>
> >  subprojects/libvduse/libvduse.c   |  9 --
> >  subprojects/libvduse/meson.build  |  8 -
> >  subprojects/libvhost-user/libvhost-user.c | 36 +--
> >  subprojects/libvhost-user/meson.build |  8 -
> >  4 files changed, 42 insertions(+), 19 deletions(-)
> >
> > --
> > 2.38.1
> >
> >
> >
>
>


Re: [PATCH v4] qapi/qmp: Add timestamps to qmp command responses

2023-01-10 Thread Denis Plotnikov

[ping]

On 01.11.2022 18:37, Denis Plotnikov wrote:

Add "start" & "end" time values to QMP command responses.

These time values are added to let the qemu management layer get the exact
command execution time without any other time variance which might be brought
by other parts of management layer or qemu internals.
This helps to look for problems poactively from the management layer side.
The management layer would be able to detect problem cases by calculating
QMP command execution time:
1. execution_time_from_mgmt_perspective -
execution_time_of_qmp_command > some_threshold
This detects problems with management layer or internal qemu QMP command
dispatching
2. current_qmp_command_execution_time > avg_qmp_command_execution_time
This detects that a certain QMP command starts to execute longer than
usual
In both these cases more thorough investigation of the root cases should be
done by using some qemu tracepoints depending on particular QMP command under
investigation or by other means. The timestamps help to avoid excessive log
output when qemu tracepoints are used to address similar cases.

Example of result:

 ./qemu/scripts/qmp/qmp-shell /tmp/qmp.socket

 (QEMU) query-status
 {"end": {"seconds": 1650367305, "microseconds": 831032},
  "start": {"seconds": 1650367305, "microseconds": 831012},
  "return": {"status": "running", "singlestep": false, "running": true}}

The response of the QMP command contains the start & end time of
the QMP command processing.

Also, "start" & "end" timestaps are added to qemu guest agent responses as
qemu-ga shares the same code for request dispatching.

Suggested-by: Andrey Ryabinin
Signed-off-by: Denis Plotnikov
Reviewed-by: Daniel P. Berrangé
---
v3->v4
  - rewrite commit message [Markus]
  - use new fileds description in doc [Markus]
  - change type to int64_t [Markus]
  - simplify tests [Markus]

v2->v3:
  - fix typo "timestaps -> timestamps" [Marc-André]

v1->v2:
  - rephrase doc descriptions [Daniel]
  - add tests for qmp timestamps to qmp test and qga test [Daniel]
  - adjust asserts in test-qmp-cmds according to the new number of returning 
keys

v0->v1:
  - remove interface to control "start" and "end" time values: return 
timestamps unconditionally
  - add description to qmp specification
  - leave the same timestamp format in "seconds", "microseconds" to be 
consistent with events
timestamp
  - fix patch description

  docs/interop/qmp-spec.txt  | 28 ++--
  qapi/qmp-dispatch.c| 18 ++
  tests/qtest/qmp-test.c | 32 
  tests/unit/test-qga.c  | 29 +
  tests/unit/test-qmp-cmds.c |  4 ++--
  5 files changed, 107 insertions(+), 4 deletions(-)

diff --git a/docs/interop/qmp-spec.txt b/docs/interop/qmp-spec.txt
index b0e8351d5b261..0dd8e716c02f0 100644
--- a/docs/interop/qmp-spec.txt
+++ b/docs/interop/qmp-spec.txt
@@ -158,7 +158,9 @@ responses that have an unknown "id" field.
  
  The format of a success response is:
  
-{ "return": json-value, "id": json-value }

+{ "return": json-value, "id": json-value,
+  "start": {"seconds": json-value, "microseconds": json-value},
+  "end": {"seconds": json-value, "microseconds": json-value} }
  
   Where,
  
@@ -169,13 +171,25 @@ The format of a success response is:

command does not return data
  - The "id" member contains the transaction identification associated
with the command execution if issued by the Client
+- The "start" member contains the exact time of when the server
+  started executing the command. This excludes any time the
+  command request spent queued, after reading it off the wire.
+  It is a json-object with the number of seconds and microseconds
+  since the Unix epoch
+- The "end" member contains the exact time of when the server
+  finished executing the command. This excludes any time the
+  command response spent queued, waiting to be sent on the wire.
+  It is a json-object with the number of seconds and microseconds
+  since the Unix epoch
  
  2.4.2 error

  ---
  
  The format of an error response is:
  
-{ "error": { "class": json-string, "desc": json-string }, "id": json-value }

+{ "error": { "class": json-string, "desc": json-string }, "id": json-value
+  "start": {"seconds": json-value, "microseconds": json-value},
+  "end": {"seconds": json-value, "microseconds": json-value} }
  
   Where,
  
@@ -184,6 +198,16 @@ The format of an error response is:

not attempt to parse this message.
  - The "id" member contains the transaction identification associated with
the command execution if issued by the Client
+- The "start" member contains the exact time of when the server
+  started executing the command. This excludes any time the
+  command request spent queued, after reading it off the wire.
+  It is a json-object with the number of seconds and microseconds
+  since the Unix epoch
+- The "end" member contains

Re: [RFC PATCH 1/4] qom: Introduce object_class_property_deprecate()

2023-01-10 Thread Daniel P . Berrangé
On Mon, Jan 09, 2023 at 11:54:16PM +0100, Philippe Mathieu-Daudé wrote:
> Introduce object_class_property_deprecate() to register
> a QOM property as deprecated. When this property's getter /
> setter is called, a deprecation warning is displayed on the
> monitor.
> 
> Inspired-by: Daniel P. Berrange 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  include/qom/object.h | 17 +
>  qom/object.c | 23 +++
>  2 files changed, 40 insertions(+)
> 
> diff --git a/include/qom/object.h b/include/qom/object.h
> index ef7258a5e1..b76724292c 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -97,6 +97,7 @@ struct ObjectProperty
>  ObjectPropertyInit *init;
>  void *opaque;
>  QObject *defval;
> +const char *deprecation_reason;
>  };

qapi/qom.list should change ObjectPropertyInfo type to
include a 'deprecated': 'bool'  field, as we've done
for machine types and CPU models. Then qmp_qom_list
should set this flag  "deprecated = !!deprecation_reason"


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH] remove unnecessary extern "C" blocks

2023-01-10 Thread Peter Maydell
On Tue, 10 Jan 2023 at 09:33, Paolo Bonzini  wrote:
>
> A handful of header files in QEMU are wrapped with extern "C" blocks.
> These are not necessary: there are C++ source files anymore in QEMU,
> and even where there were some, they did not include most of these
> files anyway.

Any reason not to also take out the extern "C" block in osdep.h
and the uses of QEMU_EXTERN_C ?

thanks
-- PMM



Re: [PATCH] mips: always include nanomips disassembler

2023-01-10 Thread Daniel P . Berrangé
On Tue, Jan 10, 2023 at 09:49:42AM +0100, Paolo Bonzini wrote:
> Since the nanomips disassembler is not C++ code anymore, it need not
> depend on link_language == cpp.  Always include it and remove the
> CONFIG_NANOMIPS_DIS symbol.
> 
> Cc: Philippe Mathieu-Daud?? 

The accent in Philippe's name got mangled by something

> Signed-off-by: Paolo Bonzini 
> ---
>  disas/meson.build | 3 +--
>  include/exec/poison.h | 1 -
>  meson.build   | 7 +--
>  target/mips/cpu.c | 2 --
>  4 files changed, 2 insertions(+), 11 deletions(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH v3 0/8] Fix win32/msys2 shader compilation & update lcitool deps

2023-01-10 Thread Marc-André Lureau
Hi

On Tue, Jan 10, 2023 at 2:41 PM Alex Bennée  wrote:

>
> marcandre.lur...@redhat.com writes:
>
> > From: Marc-André Lureau 
> >
> > Hi,
> >
> > Fix the shader compilation error on win32/msys2 and convert the related
> script
> > from perl to python. Drop unneeded dependencies from lcitool project.
>
> Queued to testing/next, thanks.
>

Thanks but wait for v4, Thomas pointed out some issues with the python
scripts +x.


Re: [PATCH v4 01/11] python: rename QEMUMonitorProtocol.cmd() to cmd_raw()

2023-01-10 Thread Daniel P . Berrangé
On Tue, Jan 10, 2023 at 11:37:48AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> Having cmd() and command() methods in one class doesn't look good.
> Rename cmd() to cmd_raw(), to show its meaning better.
> 
> We also want to rename command() to cmd() in future, so this commit is a
> necessary first step.
> 
> Keep new cmd_raw() only in a few places where it's really needed and
> move to command() where possible.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  python/qemu/machine/machine.py |  2 +-
>  python/qemu/qmp/legacy.py  |  8 ++--
>  python/qemu/qmp/qmp_shell.py   | 13 +++--
>  scripts/cpu-x86-uarch-abi.py   | 12 ++--
>  tests/qemu-iotests/iotests.py  |  2 +-
>  5 files changed, 17 insertions(+), 20 deletions(-)
> 
> diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
> index 748a0d807c..9059dc3948 100644
> --- a/python/qemu/machine/machine.py
> +++ b/python/qemu/machine/machine.py
> @@ -674,7 +674,7 @@ def qmp(self, cmd: str,
>  conv_keys = True
>  
>  qmp_args = self._qmp_args(conv_keys, args)
> -ret = self._qmp.cmd(cmd, args=qmp_args)
> +ret = self._qmp.cmd_raw(cmd, args=qmp_args)
>  if cmd == 'quit' and 'error' not in ret and 'return' in ret:
>  self._quit_issued = True
>  return ret
> diff --git a/python/qemu/qmp/legacy.py b/python/qemu/qmp/legacy.py
> index 1951754455..8e1a504052 100644
> --- a/python/qemu/qmp/legacy.py
> +++ b/python/qemu/qmp/legacy.py
> @@ -186,21 +186,17 @@ def cmd_obj(self, qmp_cmd: QMPMessage) -> QMPMessage:
>  )
>  )
>  
> -def cmd(self, name: str,
> -args: Optional[Dict[str, object]] = None,
> -cmd_id: Optional[object] = None) -> QMPMessage:
> +def cmd_raw(self, name: str,
> +args: Optional[Dict[str, object]] = None) -> QMPMessage:
>  """
>  Build a QMP command and send it to the QMP Monitor.
>  
>  :param name: command name (string)
>  :param args: command arguments (dict)
> -:param cmd_id: command id (dict, list, string or int)
>  """
>  qmp_cmd: QMPMessage = {'execute': name}
>  if args:
>  qmp_cmd['arguments'] = args
> -if cmd_id:
> -qmp_cmd['id'] = cmd_id

The commit message didn't say anything about dropping the
cmd_id parameter. Presumably you've found that it is not
used in any caller that exists, but still it feels like
a valid parameter to want to support in this method ?


>  return self.cmd_obj(qmp_cmd)
>  
>  def command(self, cmd: str, **kwds: object) -> QMPReturnValue:
> diff --git a/python/qemu/qmp/qmp_shell.py b/python/qemu/qmp/qmp_shell.py
> index 619ab42ced..5c0d87a0ec 100644
> --- a/python/qemu/qmp/qmp_shell.py
> +++ b/python/qemu/qmp/qmp_shell.py
> @@ -98,7 +98,7 @@
>  Sequence,
>  )
>  
> -from qemu.qmp import ConnectError, QMPError, SocketAddrT
> +from qemu.qmp import ConnectError, QMPError, SocketAddrT, ExecuteError
>  from qemu.qmp.legacy import (
>  QEMUMonitorProtocol,
>  QMPBadPortError,
> @@ -194,11 +194,12 @@ def close(self) -> None:
>  super().close()
>  
>  def _fill_completion(self) -> None:
> -cmds = self.cmd('query-commands')
> -if 'error' in cmds:
> -return
> -for cmd in cmds['return']:
> -self._completer.append(cmd['name'])
> +try:
> +cmds = self.command('query-commands')
> +for cmd in cmds:
> +self._completer.append(cmd['name'])
> +except ExecuteError:
> +pass
>  
>  def _completer_setup(self) -> None:
>  self._completer = QMPCompleter()

I'd suggest that re-writing callers to use 'command' is better
done in a prior patch, so that this patch is purely a rename of
cmd -> cmd_raw with no functional changes intermixed.

> diff --git a/scripts/cpu-x86-uarch-abi.py b/scripts/cpu-x86-uarch-abi.py
> index 82ff07582f..893afd1b35 100644
> --- a/scripts/cpu-x86-uarch-abi.py
> +++ b/scripts/cpu-x86-uarch-abi.py
> @@ -69,7 +69,7 @@
>  shell = QEMUMonitorProtocol(sock)
>  shell.connect()
>  
> -models = shell.cmd("query-cpu-definitions")
> +models = shell.command("query-cpu-definitions")
>  
>  # These QMP props don't correspond to CPUID fatures
>  # so ignore them
> @@ -85,7 +85,7 @@
>  
>  names = []
>  
> -for model in models["return"]:
> +for model in models:
>  if "alias-of" in model:
>  continue
>  names.append(model["name"])
> @@ -93,12 +93,12 @@
>  models = {}
>  
>  for name in sorted(names):
> -cpu = shell.cmd("query-cpu-model-expansion",
> - { "type": "static",
> -   "model": { "name": name }})
> +cpu = shell.command("query-cpu-model-expansion",
> +{ "type": "static",
> +  "model": { "name": name }})
>  
>  got = {}
> -for (feature, present) in cpu["return"]["model"]["props"].it

Re: [PATCH v4 02/11] python/qemu: rename command() to cmd()

2023-01-10 Thread Daniel P . Berrangé
On Tue, Jan 10, 2023 at 11:37:49AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> Use a shorter name. We are going to move in iotests from qmp() to
> command() where possible. But command() is longer than qmp() and don't
> look better. Let's rename.
> 
> You can simply grep for '\.command(' and for 'def command(' to check
> that everything is updated (command() in tests/docker/docker.py is
> unrelated).
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  docs/devel/testing.rst|  10 +-
>  python/qemu/machine/machine.py|   8 +-
>  python/qemu/qmp/legacy.py |   2 +-
>  python/qemu/qmp/qmp_shell.py  |   2 +-
>  python/qemu/utils/qemu_ga_client.py   |   2 +-
>  python/qemu/utils/qom.py  |   8 +-
>  python/qemu/utils/qom_common.py   |   2 +-
>  python/qemu/utils/qom_fuse.py |   6 +-
>  scripts/cpu-x86-uarch-abi.py  |   8 +-
>  scripts/device-crash-test |   8 +-
>  scripts/render_block_graph.py |   8 +-
>  tests/avocado/avocado_qemu/__init__.py|   4 +-
>  tests/avocado/cpu_queries.py  |   5 +-
>  tests/avocado/hotplug_cpu.py  |  10 +-
>  tests/avocado/info_usernet.py |   4 +-
>  tests/avocado/machine_arm_integratorcp.py |   6 +-
>  tests/avocado/machine_m68k_nextcube.py|   4 +-
>  tests/avocado/machine_mips_malta.py   |   6 +-
>  tests/avocado/machine_s390_ccw_virtio.py  |  28 ++--
>  tests/avocado/migration.py|  10 +-
>  tests/avocado/pc_cpu_hotplug_props.py |   2 +-
>  tests/avocado/version.py  |   4 +-
>  tests/avocado/virtio_check_params.py  |   6 +-
>  tests/avocado/virtio_version.py   |   5 +-
>  tests/avocado/x86_cpu_model_versions.py   |  13 +-
>  tests/migration/guestperf/engine.py   | 150 +++---
>  tests/qemu-iotests/256|  34 ++---
>  tests/qemu-iotests/257|  36 +++---
>  28 files changed, 198 insertions(+), 193 deletions(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH v3 0/8] Fix win32/msys2 shader compilation & update lcitool deps

2023-01-10 Thread Alex Bennée


marcandre.lur...@redhat.com writes:

> From: Marc-André Lureau 
>
> Hi,
>
> Fix the shader compilation error on win32/msys2 and convert the related script
> from perl to python. Drop unneeded dependencies from lcitool project.

Queued to testing/next, thanks.

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro



Re: [PATCH] mips: always include nanomips disassembler

2023-01-10 Thread Philippe Mathieu-Daudé

On 10/1/23 09:49, Paolo Bonzini wrote:

Since the nanomips disassembler is not C++ code anymore, it need not
depend on link_language == cpp.  Always include it and remove the
CONFIG_NANOMIPS_DIS symbol.

Cc: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
  disas/meson.build | 3 +--
  include/exec/poison.h | 1 -
  meson.build   | 7 +--
  target/mips/cpu.c | 2 --
  4 files changed, 2 insertions(+), 11 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 


diff --git a/meson.build b/meson.build
index 175517eafde8..bfb461d1efac 100644
--- a/meson.build
+++ b/meson.build
@@ -2478,7 +2478,7 @@ disassemblers = {
'x86_64' : ['CONFIG_I386_DIS'],
'm68k' : ['CONFIG_M68K_DIS'],
'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
-  'mips' : ['CONFIG_MIPS_DIS'],
+  'mips' : [ 'CONFIG_MIPS_DIS'],


Queue to mips-next (dropping this one-space change).


'nios2' : ['CONFIG_NIOS2_DIS'],
'or1k' : ['CONFIG_OPENRISC_DIS'],
'ppc' : ['CONFIG_PPC_DIS'],
@@ -2490,11 +2490,6 @@ disassemblers = {
'xtensa' : ['CONFIG_XTENSA_DIS'],
'loongarch' : ['CONFIG_LOONGARCH_DIS'],
  }





Re: [PATCH v14 01/11] s390x/cpu topology: adding s390 specificities to CPU topology

2023-01-10 Thread Thomas Huth

On 05/01/2023 15.53, Pierre Morel wrote:

S390 adds two new SMP levels, drawers and books to the CPU
topology.
The S390 CPU have specific toplogy features like dedication
and polarity to give to the guest indications on the host
vCPUs scheduling and help the guest take the best decisions
on the scheduling of threads on the vCPUs.

Let us provide the SMP properties with books and drawers levels
and S390 CPU with dedication and polarity,

Signed-off-by: Pierre Morel 
---

...

diff --git a/qapi/machine.json b/qapi/machine.json
index b9228a5e46..ff8f2b0e84 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -900,13 +900,15 @@
  # a CPU is being hotplugged.
  #
  # @node-id: NUMA node ID the CPU belongs to
-# @socket-id: socket number within node/board the CPU belongs to
+# @drawer-id: drawer number within node/board the CPU belongs to
+# @book-id: book number within drawer/node/board the CPU belongs to
+# @socket-id: socket number within book/node/board the CPU belongs to


I think the new entries need a "(since 8.0)" comment (similar to die-id and 
cluster-id below).


Other question: Do we have "node-id"s on s390x? If not, is that similar to 
books or drawers, i.e. just another word? If so, we should maybe rather 
re-use "nodes" instead of introducing a new name for the same thing?



  # @die-id: die number within socket the CPU belongs to (since 4.1)
  # @cluster-id: cluster number within die the CPU belongs to (since 7.1)
  # @core-id: core number within cluster the CPU belongs to
  # @thread-id: thread number within core the CPU belongs to
  #
-# Note: currently there are 6 properties that could be present
+# Note: currently there are 8 properties that could be present
  #   but management should be prepared to pass through other
  #   properties with device_add command to allow for future
  #   interface extension. This also requires the filed names to be kept in
@@ -916,6 +918,8 @@
  ##
  { 'struct': 'CpuInstanceProperties',
'data': { '*node-id': 'int',
+'*drawer-id': 'int',
+'*book-id': 'int',
  '*socket-id': 'int',
  '*die-id': 'int',
  '*cluster-id': 'int',
@@ -1465,6 +1469,10 @@
  #
  # @cpus: number of virtual CPUs in the virtual machine
  #
+# @drawers: number of drawers in the CPU topology
+#
+# @books: number of books in the CPU topology
+#


These also need a "(since 8.0)" comment at the end.


  # @sockets: number of sockets in the CPU topology
  #
  # @dies: number of dies per socket in the CPU topology
@@ -1481,6 +1489,8 @@
  ##
  { 'struct': 'SMPConfiguration', 'data': {
   '*cpus': 'int',
+ '*drawers': 'int',
+ '*books': 'int',
   '*sockets': 'int',
   '*dies': 'int',
   '*clusters': 'int',

...

diff --git a/qemu-options.hx b/qemu-options.hx
index 7f99d15b23..8dc9a4c052 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -250,11 +250,13 @@ SRST
  ERST
  
  DEF("smp", HAS_ARG, QEMU_OPTION_smp,

-"-smp 
[[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]\n"
+"-smp 
[[cpus=]n][,maxcpus=maxcpus][,drawers=drawers][,books=books][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]\n"


This line now got too long. Please add a newline inbetween.


  "set the number of initial CPUs to 'n' [default=1]\n"
  "maxcpus= maximum number of total CPUs, including\n"
  "offline CPUs for hotplug, etc\n"
-"sockets= number of sockets on the machine board\n"
+"drawers= number of drawers on the machine board\n"
+"books= number of books in one drawer\n"
+"sockets= number of sockets in one book\n"
  "dies= number of dies in one socket\n"
  "clusters= number of clusters in one die\n"
  "cores= number of cores in one cluster\n"


 Thomas




Re: [PATCH v5 10/11] hw/riscv/boot.c: consolidate all kernel init in riscv_load_kernel()

2023-01-10 Thread Daniel Henrique Barboza




On 1/8/23 00:33, Bin Meng wrote:

On Mon, Jan 2, 2023 at 7:55 PM Daniel Henrique Barboza
 wrote:

The microchip_icicle_kit, sifive_u, spike and virt boards are now doing
the same steps when '-kernel' is used:

- execute load_kernel()
- load init_rd()
- write kernel_cmdline

Let's fold everything inside riscv_load_kernel() to avoid code
repetition. To not change the behavior of boards that aren't calling
riscv_load_init(), add an 'load_initrd' flag to riscv_load_kernel() and

typo: should be riscv_load_initrd()


allow these boards to opt out from initrd loading.

Cc: Palmer Dabbelt 
Signed-off-by: Daniel Henrique Barboza 
---
  hw/riscv/boot.c| 22 +++---
  hw/riscv/microchip_pfsoc.c | 12 ++--
  hw/riscv/opentitan.c   |  2 +-
  hw/riscv/sifive_e.c|  3 ++-
  hw/riscv/sifive_u.c| 12 ++--
  hw/riscv/spike.c   | 11 +--
  hw/riscv/virt.c| 12 ++--
  include/hw/riscv/boot.h|  1 +
  8 files changed, 30 insertions(+), 45 deletions(-)


Otherwise,
Reviewed-by: Bin Meng 


Thanks!

Alistair, let me know if you want me to send another version with the commit
message typo fixed. I might as well take the change to rebase it with
riscv-to-apply.next.


Daniel




Re: [PATCH v3 1/6] migration: Allow immutable device state to be migrated early (i.e., before RAM)

2023-01-10 Thread David Hildenbrand

On 10.01.23 11:18, David Hildenbrand wrote:

On 09.01.23 20:54, Peter Xu wrote:

On Mon, Jan 09, 2023 at 03:34:48PM +0100, David Hildenbrand wrote:

On 05.01.23 18:15, Peter Xu wrote:

On Thu, Jan 05, 2023 at 09:35:54AM +0100, David Hildenbrand wrote:

On 04.01.23 18:23, Peter Xu wrote:

On Thu, Dec 22, 2022 at 12:02:10PM +0100, David Hildenbrand wrote:

Migrating device state before we start iterating is currently impossible.
Introduce and use qemu_savevm_state_start_precopy(), and use
a new special migration priority -- MIG_PRI_POST_SETUP -- to decide whether
state will be saved in qemu_savevm_state_start_precopy() or in
qemu_savevm_state_complete_precopy_*().


Can something like this be done in qemu_savevm_state_setup()?


Hi Peter,


Hi, David,



Do you mean

(a) Moving qemu_savevm_state_start_precopy() effectively into
   qemu_savevm_state_setup()

(b) Using se->ops->save_setup()


I meant (b).



I first tried going via (b), but decided to go the current way of using a
proper vmstate with properties (instead of e.g., filling the stream
manually), which also made vmdesc handling possible (and significantly
cleaner).

Regarding (a), I decided to not move logic of
qemu_savevm_state_start_precopy() into qemu_savevm_state_setup(), because it
looked cleaner to save device state with the BQL held and for background
snapshots, the VM has been stopped. To decouple device state saving from the
setup path, just like we do it right now for all vmstates.


Is BQL required or optional?  IIUC it's at least still not taken in the
migration thread path, only in savevm path.



Having that said, for virtio-mem, it would still work because that state is
immutable once migration starts, but it felt cleaner to separate the setup()
phase from actual device state saving.


I get the point.  My major concerns are:

 (1) The new migration priority is changing the semantic of original,
 making it over-complicated

 (2) The new precopy-start routine added one more step to the migration
 framework, while it's somehow overlapping (if not to say, mostly the
 same as..) save_setup().

For (1): the old priority was only deciding the order of save entries in
the global list, nothing more than that.  Even if we want to have a
precopy-start phase, I'd suggest we use something else and keep the
migration priority simple.  Otherwise we really need serious documentation
for MigrationPriority and if so I'd rather don't bother and not reuse the
priority field.

For (2), if you see there're a bunch of save_setup() that already does
things like transferring static data besides the device states.  Besides
the notorious ram_save_setup() there's also dirty_bitmap_save_setup() which
also sends a bitmap during save_setup() and some others.  It looks clean to
me to do it in the same way as we used to.

Reusing vmstate_save() and vmsd structures are useful too which I totally
agree.  So.. can we just call vmstate_save_state() in the save_setup() of
the other new vmsd of virtio-mem?



I went halfway that way, by moving stuff into qemu_savevm_state_setup()
and avoiding using a new migration priority. Seems to work:


The whole point of my suggestion is not moving things into
qemu_savevm_state_setup(), but avoid introducing more complexity to the
migration framework if unnecessary, so keep the generic framework as simple
as possible.


IMHO, the current approach is actually quite simple and clean. But ...




I think we could go one step further and perform it from a save_setup() 
callback,
however, I'm not convinced that this gets particularly cleaner (vmdesc handling
eventually).


What I wanted to suggest is exactly trying to avoid vmsd handling.  To be
more explicit, I mean: besides vmstate_virtio_mem_device_early, virtio-mem
can register with another new SaveVMHandlers with both save_setup and
load_setup registered, then e.g. in its save_setup(), one simply calls:


... I can see if it can be made working that way and how the result looks. I 
know
that we use vmstate_save_state() from virtio code, but I don't remember using
it in save_setup() from QEMU_VM_SECTION_START and not QEMU_VM_SECTION_FULL.


There is this interesting bit in register_savevm_live(), which sets "se->is_ram = 
1".
qemu_save_device_state() will not include the state. As it's used by XEN, I 
don't
particularly care.




vmstate_save_state(f, &vmstate_virtio_mem_device_early, virtio_mem_dev,
   NULL);

I'm not sure whether the JSONWriter* is required in this case, maybe not
yet to at least make it work.


It was required when handling vmstates the current way to make
analyze-migration.py not bail out (which is a good thing because one can
actually inspect the migration content):

$ ./scripts/analyze-migration.py -f STATEFILE
{
  "ram (2)": {
  "section sizes": {
  ":00:03.0/mem0": "0x000f",
  "pc.ram": "0x0001",
  "/rom@etc/acpi/tables": "0

Re: [PATCH 13/14] hw/intc/xilinx_intc: Use 'XpsIntc' typedef instead of 'struct xlx_pic'

2023-01-10 Thread Edgar E. Iglesias
On Mon, Jan 09, 2023 at 03:03:05PM +0100, Philippe Mathieu-Daudé wrote:
> This remove a use of 'struct' in the DECLARE_INSTANCE_CHECKER()
> macro call, to avoid after a QOM refactor:
> 
>   hw/intc/xilinx_intc.c:45:1: error: declaration of anonymous struct must be 
> a definition
>   DECLARE_INSTANCE_CHECKER(struct xlx_pic, XILINX_INTC,


Reviewed-by: Edgar E. Iglesias 


>^
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/intc/xilinx_intc.c | 28 +---
>  1 file changed, 13 insertions(+), 15 deletions(-)
> 
> diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
> index 4c4397b3d2..6e5012e66e 100644
> --- a/hw/intc/xilinx_intc.c
> +++ b/hw/intc/xilinx_intc.c
> @@ -42,10 +42,10 @@
>  #define R_MAX   8
>  
>  #define TYPE_XILINX_INTC "xlnx.xps-intc"
> -DECLARE_INSTANCE_CHECKER(struct xlx_pic, XILINX_INTC,
> - TYPE_XILINX_INTC)
> +typedef struct XpsIntc XpsIntc;
> +DECLARE_INSTANCE_CHECKER(XpsIntc, XILINX_INTC, TYPE_XILINX_INTC)
>  
> -struct xlx_pic
> +struct XpsIntc
>  {
>  SysBusDevice parent_obj;
>  
> @@ -62,7 +62,7 @@ struct xlx_pic
>  uint32_t irq_pin_state;
>  };
>  
> -static void update_irq(struct xlx_pic *p)
> +static void update_irq(XpsIntc *p)
>  {
>  uint32_t i;
>  
> @@ -87,10 +87,9 @@ static void update_irq(struct xlx_pic *p)
>  qemu_set_irq(p->parent_irq, (p->regs[R_MER] & 1) && p->regs[R_IPR]);
>  }
>  
> -static uint64_t
> -pic_read(void *opaque, hwaddr addr, unsigned int size)
> +static uint64_t pic_read(void *opaque, hwaddr addr, unsigned int size)
>  {
> -struct xlx_pic *p = opaque;
> +XpsIntc *p = opaque;
>  uint32_t r = 0;
>  
>  addr >>= 2;
> @@ -106,11 +105,10 @@ pic_read(void *opaque, hwaddr addr, unsigned int size)
>  return r;
>  }
>  
> -static void
> -pic_write(void *opaque, hwaddr addr,
> -  uint64_t val64, unsigned int size)
> +static void pic_write(void *opaque, hwaddr addr,
> +  uint64_t val64, unsigned int size)
>  {
> -struct xlx_pic *p = opaque;
> +XpsIntc *p = opaque;
>  uint32_t value = val64;
>  
>  addr >>= 2;
> @@ -154,7 +152,7 @@ static const MemoryRegionOps pic_ops = {
>  
>  static void irq_handler(void *opaque, int irq, int level)
>  {
> -struct xlx_pic *p = opaque;
> +XpsIntc *p = opaque;
>  
>  /* edge triggered interrupt */
>  if (p->c_kind_of_intr & (1 << irq) && p->regs[R_MER] & 2) {
> @@ -168,7 +166,7 @@ static void irq_handler(void *opaque, int irq, int level)
>  
>  static void xilinx_intc_init(Object *obj)
>  {
> -struct xlx_pic *p = XILINX_INTC(obj);
> +XpsIntc *p = XILINX_INTC(obj);
>  
>  qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
>  sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq);
> @@ -179,7 +177,7 @@ static void xilinx_intc_init(Object *obj)
>  }
>  
>  static Property xilinx_intc_properties[] = {
> -DEFINE_PROP_UINT32("kind-of-intr", struct xlx_pic, c_kind_of_intr, 0),
> +DEFINE_PROP_UINT32("kind-of-intr", XpsIntc, c_kind_of_intr, 0),
>  DEFINE_PROP_END_OF_LIST(),
>  };
>  
> @@ -193,7 +191,7 @@ static void xilinx_intc_class_init(ObjectClass *klass, 
> void *data)
>  static const TypeInfo xilinx_intc_info = {
>  .name  = TYPE_XILINX_INTC,
>  .parent= TYPE_SYS_BUS_DEVICE,
> -.instance_size = sizeof(struct xlx_pic),
> +.instance_size = sizeof(XpsIntc),
>  .instance_init = xilinx_intc_init,
>  .class_init= xilinx_intc_class_init,
>  };
> -- 
> 2.38.1
> 



Re: [PATCH 14/14] hw/timer/xilinx_timer: Use XpsTimerState instead of 'struct timerblock'

2023-01-10 Thread Edgar E. Iglesias
On Mon, Jan 09, 2023 at 03:03:06PM +0100, Philippe Mathieu-Daudé wrote:
> This remove a use of 'struct' in the DECLARE_INSTANCE_CHECKER()
> macro call, to avoid after a QOM refactor:
> 
>   hw/timer/xilinx_timer.c:65:1: error: declaration of anonymous struct must 
> be a definition
>   DECLARE_INSTANCE_CHECKER(struct timerblock, XILINX_TIMER,
>^


Reviewed-by: Edgar E. Iglesias 


> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/timer/xilinx_timer.c | 27 +--
>  1 file changed, 13 insertions(+), 14 deletions(-)
> 
> diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
> index c7f17cd646..32a9df69e0 100644
> --- a/hw/timer/xilinx_timer.c
> +++ b/hw/timer/xilinx_timer.c
> @@ -62,10 +62,10 @@ struct xlx_timer
>  };
>  
>  #define TYPE_XILINX_TIMER "xlnx.xps-timer"
> -DECLARE_INSTANCE_CHECKER(struct timerblock, XILINX_TIMER,
> - TYPE_XILINX_TIMER)
> +typedef struct XpsTimerState XpsTimerState;
> +DECLARE_INSTANCE_CHECKER(XpsTimerState, XILINX_TIMER, TYPE_XILINX_TIMER)
>  
> -struct timerblock
> +struct XpsTimerState
>  {
>  SysBusDevice parent_obj;
>  
> @@ -76,7 +76,7 @@ struct timerblock
>  struct xlx_timer *timers;
>  };
>  
> -static inline unsigned int num_timers(struct timerblock *t)
> +static inline unsigned int num_timers(XpsTimerState *t)
>  {
>  return 2 - t->one_timer_only;
>  }
> @@ -87,7 +87,7 @@ static inline unsigned int timer_from_addr(hwaddr addr)
>  return addr >> 2;
>  }
>  
> -static void timer_update_irq(struct timerblock *t)
> +static void timer_update_irq(XpsTimerState *t)
>  {
>  unsigned int i, irq = 0;
>  uint32_t csr;
> @@ -104,7 +104,7 @@ static void timer_update_irq(struct timerblock *t)
>  static uint64_t
>  timer_read(void *opaque, hwaddr addr, unsigned int size)
>  {
> -struct timerblock *t = opaque;
> +XpsTimerState *t = opaque;
>  struct xlx_timer *xt;
>  uint32_t r = 0;
>  unsigned int timer;
> @@ -155,7 +155,7 @@ static void
>  timer_write(void *opaque, hwaddr addr,
>  uint64_t val64, unsigned int size)
>  {
> -struct timerblock *t = opaque;
> +XpsTimerState *t = opaque;
>  struct xlx_timer *xt;
>  unsigned int timer;
>  uint32_t value = val64;
> @@ -202,7 +202,7 @@ static const MemoryRegionOps timer_ops = {
>  static void timer_hit(void *opaque)
>  {
>  struct xlx_timer *xt = opaque;
> -struct timerblock *t = xt->parent;
> +XpsTimerState *t = xt->parent;
>  D(fprintf(stderr, "%s %d\n", __func__, xt->nr));
>  xt->regs[R_TCSR] |= TCSR_TINT;
>  
> @@ -213,7 +213,7 @@ static void timer_hit(void *opaque)
>  
>  static void xilinx_timer_realize(DeviceState *dev, Error **errp)
>  {
> -struct timerblock *t = XILINX_TIMER(dev);
> +XpsTimerState *t = XILINX_TIMER(dev);
>  unsigned int i;
>  
>  /* Init all the ptimers.  */
> @@ -236,16 +236,15 @@ static void xilinx_timer_realize(DeviceState *dev, 
> Error **errp)
>  
>  static void xilinx_timer_init(Object *obj)
>  {
> -struct timerblock *t = XILINX_TIMER(obj);
> +XpsTimerState *t = XILINX_TIMER(obj);
>  
>  /* All timers share a single irq line.  */
>  sysbus_init_irq(SYS_BUS_DEVICE(obj), &t->irq);
>  }
>  
>  static Property xilinx_timer_properties[] = {
> -DEFINE_PROP_UINT32("clock-frequency", struct timerblock, freq_hz,
> -62 * 
> 100),
> -DEFINE_PROP_UINT8("one-timer-only", struct timerblock, one_timer_only, 
> 0),
> +DEFINE_PROP_UINT32("clock-frequency", XpsTimerState, freq_hz, 62 * 
> 100),
> +DEFINE_PROP_UINT8("one-timer-only", XpsTimerState, one_timer_only, 0),
>  DEFINE_PROP_END_OF_LIST(),
>  };
>  
> @@ -260,7 +259,7 @@ static void xilinx_timer_class_init(ObjectClass *klass, 
> void *data)
>  static const TypeInfo xilinx_timer_info = {
>  .name  = TYPE_XILINX_TIMER,
>  .parent= TYPE_SYS_BUS_DEVICE,
> -.instance_size = sizeof(struct timerblock),
> +.instance_size = sizeof(XpsTimerState),
>  .instance_init = xilinx_timer_init,
>  .class_init= xilinx_timer_class_init,
>  };
> -- 
> 2.38.1
> 



Re: [PATCH] hw/display/xlnx_dp: fix overflow in xlnx_dp_aux_push_tx_fifo()

2023-01-10 Thread Edgar E. Iglesias
On Mon, Jan 09, 2023 at 01:59:33PM +0800, Qiang Liu wrote:
> This patch checks if the s->tx_fifo is full.

+ CC: Fred

Reviewed-by: Edgar E. Iglesias 


> 
> Fixes: 58ac482a66de ("introduce xlnx-dp")
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1424
> Reported-by: Qiang Liu 
> Signed-off-by: Qiang Liu 
> ---
>  hw/display/xlnx_dp.c | 6 +-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
> index 972473d94f..617b394af2 100644
> --- a/hw/display/xlnx_dp.c
> +++ b/hw/display/xlnx_dp.c
> @@ -854,7 +854,11 @@ static void xlnx_dp_write(void *opaque, hwaddr offset, 
> uint64_t value,
>  break;
>  case DP_AUX_WRITE_FIFO: {
>  uint8_t c = value;
> -xlnx_dp_aux_push_tx_fifo(s, &c, 1);
> +if (fifo8_is_full(&s->tx_fifo)) {
> +qemu_log_mask(LOG_GUEST_ERROR, "xlnx_dp: TX fifo is full");
> +} else {
> +xlnx_dp_aux_push_tx_fifo(s, &c, 1);
> +}
>  break;
>  }
>  case DP_AUX_CLOCK_DIVIDER:
> -- 
> 2.25.1
> 
> 



[PATCH v6 32/51] hw/xen: Implement EVTCHNOP_bind_ipi

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c  | 69 +++
 hw/i386/kvm/xen_evtchn.h  |  2 ++
 target/i386/kvm/xen-emu.c | 15 +
 3 files changed, 86 insertions(+)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 4942663ddf..bbf234edaf 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -13,6 +13,7 @@
 #include "qemu/host-utils.h"
 #include "qemu/module.h"
 #include "qemu/main-loop.h"
+#include "qemu/log.h"
 #include "qapi/error.h"
 #include "qom/object.h"
 #include "exec/target_page.h"
@@ -224,6 +225,43 @@ static void inject_callback(XenEvtchnState *s, uint32_t 
vcpu)
 kvm_xen_inject_vcpu_callback_vector(vcpu, type);
 }
 
+static void deassign_kernel_port(evtchn_port_t port)
+{
+struct kvm_xen_hvm_attr ha;
+int ret;
+
+ha.type = KVM_XEN_ATTR_TYPE_EVTCHN;
+ha.u.evtchn.send_port = port;
+ha.u.evtchn.flags = KVM_XEN_EVTCHN_DEASSIGN;
+
+ret = kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &ha);
+if (ret) {
+qemu_log_mask(LOG_GUEST_ERROR, "Failed to unbind kernel port %d: %s\n",
+  port, strerror(ret));
+}
+}
+
+static int assign_kernel_port(uint16_t type, evtchn_port_t port,
+  uint32_t vcpu_id)
+{
+CPUState *cpu = qemu_get_cpu(vcpu_id);
+struct kvm_xen_hvm_attr ha;
+
+if (!cpu) {
+return -ENOENT;
+}
+
+ha.type = KVM_XEN_ATTR_TYPE_EVTCHN;
+ha.u.evtchn.send_port = port;
+ha.u.evtchn.type = type;
+ha.u.evtchn.flags = 0;
+ha.u.evtchn.deliver.port.port = port;
+ha.u.evtchn.deliver.port.vcpu = kvm_arch_vcpu_id(cpu);
+ha.u.evtchn.deliver.port.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
+
+return kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &ha);
+}
+
 static bool valid_port(evtchn_port_t port)
 {
 if (!port) {
@@ -542,6 +580,12 @@ static int close_port(XenEvtchnState *s, evtchn_port_t 
port)
   p->type_val, 0);
 break;
 
+case EVTCHNSTAT_ipi:
+if (s->evtchn_in_kernel) {
+deassign_kernel_port(port);
+}
+break;
+
 default:
 break;
 }
@@ -631,3 +675,28 @@ int xen_evtchn_bind_virq_op(struct evtchn_bind_virq *virq)
 
 return ret;
 }
+
+int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi)
+{
+XenEvtchnState *s = xen_evtchn_singleton;
+int ret;
+
+if (!s) {
+return -ENOTSUP;
+}
+
+if (!valid_vcpu(ipi->vcpu)) {
+return -ENOENT;
+}
+
+qemu_mutex_lock(&s->port_lock);
+
+ret = allocate_port(s, ipi->vcpu, EVTCHNSTAT_ipi, 0, &ipi->port);
+if (!ret && s->evtchn_in_kernel) {
+assign_kernel_port(EVTCHNSTAT_ipi, ipi->port, ipi->vcpu);
+}
+
+qemu_mutex_unlock(&s->port_lock);
+
+return ret;
+}
diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h
index 0ea13dda3a..107f420848 100644
--- a/hw/i386/kvm/xen_evtchn.h
+++ b/hw/i386/kvm/xen_evtchn.h
@@ -19,9 +19,11 @@ struct evtchn_status;
 struct evtchn_close;
 struct evtchn_unmask;
 struct evtchn_bind_virq;
+struct evtchn_bind_ipi;
 int xen_evtchn_status_op(struct evtchn_status *status);
 int xen_evtchn_close_op(struct evtchn_close *close);
 int xen_evtchn_unmask_op(struct evtchn_unmask *unmask);
 int xen_evtchn_bind_virq_op(struct evtchn_bind_virq *virq);
+int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi);
 
 #endif /* QEMU_XEN_EVTCHN_H */
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 6c56991aec..807c7caf8c 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -880,6 +880,21 @@ static bool kvm_xen_hcall_evtchn_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 }
 break;
 }
+case EVTCHNOP_bind_ipi: {
+struct evtchn_bind_ipi ipi;
+
+qemu_build_assert(sizeof(ipi) == 8);
+if (kvm_copy_from_gva(cs, arg, &ipi, sizeof(ipi))) {
+err = -EFAULT;
+break;
+}
+
+err = xen_evtchn_bind_ipi_op(&ipi);
+if (!err && kvm_copy_to_gva(cs, arg, &ipi, sizeof(ipi))) {
+err = -EFAULT;
+}
+break;
+}
 default:
 return false;
 }
-- 
2.35.3




[PATCH v6 50/51] hw/xen: Add xen_xenstore device for xenstore emulation

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Just the basic shell, with the event channel hookup. It only dumps the
buffer for now; a real ring implmentation will come in a subsequent patch.

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/meson.build|   1 +
 hw/i386/kvm/xen_evtchn.c   |   1 +
 hw/i386/kvm/xen_xenstore.c | 248 +
 hw/i386/kvm/xen_xenstore.h |  20 +++
 hw/i386/pc.c   |   2 +
 target/i386/kvm/xen-emu.c  |  12 ++
 6 files changed, 284 insertions(+)
 create mode 100644 hw/i386/kvm/xen_xenstore.c
 create mode 100644 hw/i386/kvm/xen_xenstore.h

diff --git a/hw/i386/kvm/meson.build b/hw/i386/kvm/meson.build
index 7b4675a3b0..662054dc9f 100644
--- a/hw/i386/kvm/meson.build
+++ b/hw/i386/kvm/meson.build
@@ -8,6 +8,7 @@ i386_kvm_ss.add(when: 'CONFIG_XEN_EMU', if_true: files(
   'xen_overlay.c',
   'xen_evtchn.c',
   'xen_gnttab.c',
+  'xen_xenstore.c',
   ))
 
 i386_ss.add_all(when: 'CONFIG_KVM', if_true: i386_kvm_ss)
diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 39ad3eec77..98a47066bc 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -33,6 +33,7 @@
 
 #include "xen_evtchn.h"
 #include "xen_overlay.h"
+#include "xen_xenstore.h"
 
 #include "sysemu/kvm.h"
 #include "sysemu/kvm_xen.h"
diff --git a/hw/i386/kvm/xen_xenstore.c b/hw/i386/kvm/xen_xenstore.c
new file mode 100644
index 00..bb3346f4e3
--- /dev/null
+++ b/hw/i386/kvm/xen_xenstore.c
@@ -0,0 +1,248 @@
+/*
+ * QEMU Xen emulation: Shared/overlay pages support
+ *
+ * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Authors: David Woodhouse 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "qemu/host-utils.h"
+#include "qemu/module.h"
+#include "qemu/main-loop.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "qom/object.h"
+#include "migration/vmstate.h"
+
+#include "hw/sysbus.h"
+#include "hw/xen/xen.h"
+#include "xen_overlay.h"
+#include "xen_evtchn.h"
+#include "xen_xenstore.h"
+
+#include "sysemu/kvm.h"
+#include "sysemu/kvm_xen.h"
+
+#include "standard-headers/xen/io/xs_wire.h"
+#include "standard-headers/xen/event_channel.h"
+
+#define TYPE_XEN_XENSTORE "xen-xenstore"
+OBJECT_DECLARE_SIMPLE_TYPE(XenXenstoreState, XEN_XENSTORE)
+
+#define XEN_PAGE_SHIFT 12
+#define XEN_PAGE_SIZE (1ULL << XEN_PAGE_SHIFT)
+
+#define ENTRIES_PER_FRAME_V1 (XEN_PAGE_SIZE / sizeof(grant_entry_v1_t))
+#define ENTRIES_PER_FRAME_V2 (XEN_PAGE_SIZE / sizeof(grant_entry_v2_t))
+
+#define XENSTORE_HEADER_SIZE ((unsigned int)sizeof(struct xsd_sockmsg))
+
+struct XenXenstoreState {
+/*< private >*/
+SysBusDevice busdev;
+/*< public >*/
+
+MemoryRegion xenstore_page;
+struct xenstore_domain_interface *xs;
+uint8_t req_data[XENSTORE_HEADER_SIZE + XENSTORE_PAYLOAD_MAX];
+uint8_t rsp_data[XENSTORE_HEADER_SIZE + XENSTORE_PAYLOAD_MAX];
+uint32_t req_offset;
+uint32_t rsp_offset;
+bool rsp_pending;
+bool fatal_error;
+
+evtchn_port_t guest_port;
+evtchn_port_t be_port;
+struct xenevtchn_handle *eh;
+};
+
+struct XenXenstoreState *xen_xenstore_singleton;
+
+static void xen_xenstore_event(void *opaque);
+
+static void xen_xenstore_realize(DeviceState *dev, Error **errp)
+{
+XenXenstoreState *s = XEN_XENSTORE(dev);
+
+if (xen_mode != XEN_EMULATE) {
+error_setg(errp, "Xen xenstore support is for Xen emulation");
+return;
+}
+memory_region_init_ram(&s->xenstore_page, OBJECT(dev), "xen:xenstore_page",
+   XEN_PAGE_SIZE, &error_abort);
+memory_region_set_enabled(&s->xenstore_page, true);
+s->xs = memory_region_get_ram_ptr(&s->xenstore_page);
+memset(s->xs, 0, XEN_PAGE_SIZE);
+
+/* We can't map it this early as KVM isn't ready */
+xen_xenstore_singleton = s;
+
+s->eh = xen_be_evtchn_open();
+if (!s->eh) {
+error_setg(errp, "Xenstore evtchn port init failed");
+return;
+}
+aio_set_fd_handler(qemu_get_aio_context(), xen_be_evtchn_fd(s->eh), true,
+   xen_xenstore_event, NULL, NULL, NULL, s);
+}
+
+static bool xen_xenstore_is_needed(void *opaque)
+{
+return xen_mode == XEN_EMULATE;
+}
+
+static int xen_xenstore_pre_save(void *opaque)
+{
+XenXenstoreState *s = opaque;
+
+if (s->eh) {
+s->guest_port = xen_be_evtchn_get_guest_port(s->eh);
+}
+return 0;
+}
+
+static int xen_xenstore_post_load(void *opaque, int ver)
+{
+XenXenstoreState *s = opaque;
+
+/*
+ * As qemu/dom0, rebind to the guest's port. The Windows drivers may
+ * unbind the XenStore evtchn and rebind to it, having obtained the
+ * "remote" port through EVTCHNOP_status. In the case that migration
+ * occurs while it's unbound, the "remote" port needs to be the same
+ * as before so that the guest can find it, but should remain unbound.
+  

[PATCH v6 42/51] hw/xen: Add xen_gnttab device for grant table emulation

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/meson.build   |   1 +
 hw/i386/kvm/xen_gnttab.c  | 110 ++
 hw/i386/kvm/xen_gnttab.h  |  18 +++
 hw/i386/pc.c  |   2 +
 target/i386/kvm/xen-emu.c |   3 ++
 5 files changed, 134 insertions(+)
 create mode 100644 hw/i386/kvm/xen_gnttab.c
 create mode 100644 hw/i386/kvm/xen_gnttab.h

diff --git a/hw/i386/kvm/meson.build b/hw/i386/kvm/meson.build
index 577eb50a18..7b4675a3b0 100644
--- a/hw/i386/kvm/meson.build
+++ b/hw/i386/kvm/meson.build
@@ -7,6 +7,7 @@ i386_kvm_ss.add(when: 'CONFIG_IOAPIC', if_true: 
files('ioapic.c'))
 i386_kvm_ss.add(when: 'CONFIG_XEN_EMU', if_true: files(
   'xen_overlay.c',
   'xen_evtchn.c',
+  'xen_gnttab.c',
   ))
 
 i386_ss.add_all(when: 'CONFIG_KVM', if_true: i386_kvm_ss)
diff --git a/hw/i386/kvm/xen_gnttab.c b/hw/i386/kvm/xen_gnttab.c
new file mode 100644
index 00..7a441445cd
--- /dev/null
+++ b/hw/i386/kvm/xen_gnttab.c
@@ -0,0 +1,110 @@
+/*
+ * QEMU Xen emulation: Grant table support
+ *
+ * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Authors: David Woodhouse 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+#include "qemu/module.h"
+#include "qemu/main-loop.h"
+#include "qapi/error.h"
+#include "qom/object.h"
+#include "exec/target_page.h"
+#include "exec/address-spaces.h"
+#include "migration/vmstate.h"
+
+#include "hw/sysbus.h"
+#include "hw/xen/xen.h"
+#include "xen_overlay.h"
+#include "xen_gnttab.h"
+
+#include "sysemu/kvm.h"
+#include "sysemu/kvm_xen.h"
+
+#include "standard-headers/xen/memory.h"
+#include "standard-headers/xen/grant_table.h"
+
+#define TYPE_XEN_GNTTAB "xen-gnttab"
+OBJECT_DECLARE_SIMPLE_TYPE(XenGnttabState, XEN_GNTTAB)
+
+#define XEN_PAGE_SHIFT 12
+#define XEN_PAGE_SIZE (1ULL << XEN_PAGE_SHIFT)
+
+struct XenGnttabState {
+/*< private >*/
+SysBusDevice busdev;
+/*< public >*/
+
+uint32_t nr_frames;
+uint32_t max_frames;
+};
+
+struct XenGnttabState *xen_gnttab_singleton;
+
+static void xen_gnttab_realize(DeviceState *dev, Error **errp)
+{
+XenGnttabState *s = XEN_GNTTAB(dev);
+
+if (xen_mode != XEN_EMULATE) {
+error_setg(errp, "Xen grant table support is for Xen emulation");
+return;
+}
+s->nr_frames = 0;
+s->max_frames = kvm_xen_get_gnttab_max_frames();
+}
+
+static bool xen_gnttab_is_needed(void *opaque)
+{
+return xen_mode == XEN_EMULATE;
+}
+
+static const VMStateDescription xen_gnttab_vmstate = {
+.name = "xen_gnttab",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = xen_gnttab_is_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(nr_frames, XenGnttabState),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void xen_gnttab_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = xen_gnttab_realize;
+dc->vmsd = &xen_gnttab_vmstate;
+}
+
+static const TypeInfo xen_gnttab_info = {
+.name  = TYPE_XEN_GNTTAB,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XenGnttabState),
+.class_init= xen_gnttab_class_init,
+};
+
+void xen_gnttab_create(void)
+{
+xen_gnttab_singleton = XEN_GNTTAB(sysbus_create_simple(TYPE_XEN_GNTTAB,
+   -1, NULL));
+}
+
+static void xen_gnttab_register_types(void)
+{
+type_register_static(&xen_gnttab_info);
+}
+
+type_init(xen_gnttab_register_types)
+
+int xen_gnttab_map_page(uint64_t idx, uint64_t gfn)
+{
+return -ENOSYS;
+}
+
diff --git a/hw/i386/kvm/xen_gnttab.h b/hw/i386/kvm/xen_gnttab.h
new file mode 100644
index 00..a7caa94c83
--- /dev/null
+++ b/hw/i386/kvm/xen_gnttab.h
@@ -0,0 +1,18 @@
+/*
+ * QEMU Xen emulation: Grant table support
+ *
+ * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Authors: David Woodhouse 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_XEN_GNTTAB_H
+#define QEMU_XEN_GNTTAB_H
+
+void xen_gnttab_create(void);
+int xen_gnttab_map_page(uint64_t idx, uint64_t gfn);
+
+#endif /* QEMU_XEN_GNTTAB_H */
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 61a90c9e5b..b9f92010f9 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -91,6 +91,7 @@
 #include "hw/virtio/virtio-mem-pci.h"
 #include "hw/i386/kvm/xen_overlay.h"
 #include "hw/i386/kvm/xen_evtchn.h"
+#include "hw/i386/kvm/xen_gnttab.h"
 #include "hw/mem/memory-device.h"
 #include "sysemu/replay.h"
 #include "target/i386/cpu.h"
@@ -1858,6 +1859,7 @@ int pc_machine_kvm_type(MachineState *machine, const char 
*kvm_type)
 if (xen_mode == XEN_EMULATE) {
 xen_overlay_create();
 xen_evtchn_create();
+xen_gnttab_create();
 

[PATCH v6 45/51] hw/xen: Implement GNTTABOP_query_size

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_gnttab.c  | 19 +++
 hw/i386/kvm/xen_gnttab.h  |  2 ++
 target/i386/kvm/xen-emu.c | 16 +++-
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/hw/i386/kvm/xen_gnttab.c b/hw/i386/kvm/xen_gnttab.c
index cdcfea5be3..5e8fc0184e 100644
--- a/hw/i386/kvm/xen_gnttab.c
+++ b/hw/i386/kvm/xen_gnttab.c
@@ -217,3 +217,22 @@ int xen_gnttab_get_version_op(struct gnttab_get_version 
*get)
 get->version = 1;
 return 0;
 }
+
+int xen_gnttab_query_size_op(struct gnttab_query_size *size)
+{
+XenGnttabState *s = xen_gnttab_singleton;
+
+if (!s) {
+return -ENOTSUP;
+}
+
+if (size->dom != DOMID_SELF && size->dom != xen_domid) {
+size->status = GNTST_bad_domain;
+return 0;
+}
+
+size->status = GNTST_okay;
+size->nr_frames = s->nr_frames;
+size->max_nr_frames = s->max_frames;
+return 0;
+}
diff --git a/hw/i386/kvm/xen_gnttab.h b/hw/i386/kvm/xen_gnttab.h
index 79579677ba..3bdbe96191 100644
--- a/hw/i386/kvm/xen_gnttab.h
+++ b/hw/i386/kvm/xen_gnttab.h
@@ -17,7 +17,9 @@ int xen_gnttab_map_page(uint64_t idx, uint64_t gfn);
 
 struct gnttab_set_version;
 struct gnttab_get_version;
+struct gnttab_query_size;
 int xen_gnttab_set_version_op(struct gnttab_set_version *set);
 int xen_gnttab_get_version_op(struct gnttab_get_version *get);
+int xen_gnttab_query_size_op(struct gnttab_query_size *size);
 
 #endif /* QEMU_XEN_GNTTAB_H */
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 8895f91d8b..a279d7ff89 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -1162,7 +1162,21 @@ static bool kvm_xen_hcall_gnttab_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 }
 break;
 }
-case GNTTABOP_query_size:
+case GNTTABOP_query_size: {
+struct gnttab_query_size size;
+
+qemu_build_assert(sizeof(size) == 16);
+if (kvm_copy_from_gva(cs, arg, &size, sizeof(size))) {
+err = -EFAULT;
+break;
+}
+
+err = xen_gnttab_query_size_op(&size);
+if (!err && kvm_copy_to_gva(cs, arg, &size, sizeof(size))) {
+err = -EFAULT;
+}
+break;
+}
 case GNTTABOP_setup_table:
 case GNTTABOP_copy:
 case GNTTABOP_map_grant_ref:
-- 
2.35.3




[PATCH v6 21/51] i386/xen: handle VCPUOP_register_vcpu_time_info

2023-01-10 Thread David Woodhouse
From: Joao Martins 

In order to support Linux vdso in Xen.

Signed-off-by: Joao Martins 
Signed-off-by: David Woodhouse 
---
 target/i386/cpu.h |   1 +
 target/i386/kvm/xen-emu.c | 100 +-
 target/i386/machine.c |   1 +
 3 files changed, 90 insertions(+), 12 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 109b2e5669..96c2d0d5cb 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1790,6 +1790,7 @@ typedef struct CPUArchState {
 struct kvm_nested_state *nested_state;
 uint64_t xen_vcpu_info_gpa;
 uint64_t xen_vcpu_info_default_gpa;
+uint64_t xen_vcpu_time_info_gpa;
 #endif
 #if defined(CONFIG_HVF)
 HVFX86LazyFlags hvf_lflags;
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index dc0dbffa40..e47eb03cc8 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -36,28 +36,41 @@
 #define hypercall_compat32(longmode) (false)
 #endif
 
-static int kvm_gva_rw(CPUState *cs, uint64_t gva, void *_buf, size_t sz,
-  bool is_write)
+static bool kvm_gva_to_gpa(CPUState *cs, uint64_t gva, uint64_t *gpa,
+   size_t *len, bool is_write)
 {
-uint8_t *buf = (uint8_t *)_buf;
-int ret;
-
-while (sz) {
 struct kvm_translation tr = {
 .linear_address = gva,
 };
 
-size_t len = TARGET_PAGE_SIZE - (tr.linear_address & 
~TARGET_PAGE_MASK);
-if (len > sz) {
-len = sz;
+if (len) {
+*len = TARGET_PAGE_SIZE - (gva & ~TARGET_PAGE_MASK);
+}
+
+if (kvm_vcpu_ioctl(cs, KVM_TRANSLATE, &tr) || !tr.valid ||
+(is_write && !tr.writeable)) {
+return false;
 }
+*gpa = tr.physical_address;
+return true;
+}
+
+static int kvm_gva_rw(CPUState *cs, uint64_t gva, void *_buf, size_t sz,
+  bool is_write)
+{
+uint8_t *buf = (uint8_t *)_buf;
+uint64_t gpa;
+size_t len;
 
-ret = kvm_vcpu_ioctl(cs, KVM_TRANSLATE, &tr);
-if (ret || !tr.valid || (is_write && !tr.writeable)) {
+while (sz) {
+if (!kvm_gva_to_gpa(cs, gva, &gpa, &len, is_write)) {
 return -EFAULT;
 }
+if (len > sz) {
+len = sz;
+}
 
-cpu_physical_memory_rw(tr.physical_address, buf, len, is_write);
+cpu_physical_memory_rw(gpa, buf, len, is_write);
 
 buf += len;
 sz -= len;
@@ -145,6 +158,7 @@ int kvm_xen_init_vcpu(CPUState *cs)
 
 env->xen_vcpu_info_gpa = INVALID_GPA;
 env->xen_vcpu_info_default_gpa = INVALID_GPA;
+env->xen_vcpu_time_info_gpa = INVALID_GPA;
 
 return 0;
 }
@@ -228,6 +242,17 @@ static void do_set_vcpu_info_gpa(CPUState *cs, 
run_on_cpu_data data)
   env->xen_vcpu_info_gpa);
 }
 
+static void do_set_vcpu_time_info_gpa(CPUState *cs, run_on_cpu_data data)
+{
+X86CPU *cpu = X86_CPU(cs);
+CPUX86State *env = &cpu->env;
+
+env->xen_vcpu_time_info_gpa = data.host_ulong;
+
+kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO,
+  env->xen_vcpu_time_info_gpa);
+}
+
 static void do_vcpu_soft_reset(CPUState *cs, run_on_cpu_data data)
 {
 X86CPU *cpu = X86_CPU(cs);
@@ -235,8 +260,11 @@ static void do_vcpu_soft_reset(CPUState *cs, 
run_on_cpu_data data)
 
 env->xen_vcpu_info_gpa = INVALID_GPA;
 env->xen_vcpu_info_default_gpa = INVALID_GPA;
+env->xen_vcpu_time_info_gpa = INVALID_GPA;
 
 kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO, INVALID_GPA);
+kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO,
+  INVALID_GPA);
 }
 
 static int xen_set_shared_info(uint64_t gfn)
@@ -450,6 +478,42 @@ static int vcpuop_register_vcpu_info(CPUState *cs, 
CPUState *target,
 return 0;
 }
 
+static int vcpuop_register_vcpu_time_info(CPUState *cs, CPUState *target,
+  uint64_t arg)
+{
+struct vcpu_register_time_memory_area tma;
+uint64_t gpa;
+size_t len;
+
+/* No need for 32/64 compat handling */
+qemu_build_assert(sizeof(tma) == 8);
+qemu_build_assert(sizeof(struct vcpu_time_info) == 32);
+
+if (!target) {
+return -ENOENT;
+}
+
+if (kvm_copy_from_gva(cs, arg, &tma, sizeof(tma))) {
+return -EFAULT;
+}
+
+/*
+ * Xen actually uses the GVA and does the translation through the guest
+ * page tables each time. But Linux/KVM uses the GPA, on the assumption
+ * that guests only ever use *global* addresses (kernel virtual addresses)
+ * for it. If Linux is changed to redo the GVA→GPA translation each time,
+ * it will offer a new vCPU attribute for that, and we'll use it instead.
+ */
+if (!kvm_gva_to_gpa(cs, tma.addr.p, &gpa, &len, false) ||
+len < sizeof(struct vcpu_time_info)) {
+return -EFAULT;
+}
+
+async_run_on_cpu(target, do_set_vcpu_time_info_

[PATCH v6 06/51] i386/hvm: Set Xen vCPU ID in KVM

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

There are (at least) three different vCPU ID number spaces. One is the
internal KVM vCPU index, based purely on which vCPU was chronologically
created in the kernel first. If userspace threads are all spawned and
create their KVM vCPUs in essentially random order, then the KVM indices
are basically random too.

The second number space is the APIC ID space, which is consistent and
useful for referencing vCPUs. MSIs will specify the target vCPU using
the APIC ID, for example, and the KVM Xen APIs also take an APIC ID
from userspace whenever a vCPU needs to be specified (as opposed to
just using the appropriate vCPU fd).

The third number space is not normally relevant to the kernel, and is
the ACPI/MADT/Xen CPU number which corresponds to cs->cpu_index. But
Xen timer hypercalls use it, and Xen timer hypercalls *really* want
to be accelerated in the kernel rather than handled in userspace, so
the kernel needs to be told.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 target/i386/kvm/kvm.c |  5 +
 target/i386/kvm/xen-emu.c | 28 
 target/i386/kvm/xen-emu.h |  1 +
 3 files changed, 34 insertions(+)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index e786a16c0b..4ab2c08af6 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1868,6 +1868,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
 }
 }
 
+r = kvm_xen_init_vcpu(cs);
+if (r) {
+return r;
+}
+
 kvm_base += 0x100;
 #else /* CONFIG_XEN_EMU */
 /* This should never happen as kvm_arch_init() would have died first. 
*/
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 34d5bc1bc9..4883b95d9d 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -52,6 +52,34 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
 return 0;
 }
 
+int kvm_xen_init_vcpu(CPUState *cs)
+{
+int err;
+
+/*
+ * The kernel needs to know the Xen/ACPI vCPU ID because that's
+ * what the guest uses in hypercalls such as timers. It doesn't
+ * match the APIC ID which is generally used for talking to the
+ * kernel about vCPUs. And if vCPU threads race with creating
+ * their KVM vCPUs out of order, it doesn't necessarily match
+ * with the kernel's internal vCPU indices either.
+ */
+if (kvm_xen_has_cap(EVTCHN_SEND)) {
+struct kvm_xen_vcpu_attr va = {
+.type = KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID,
+.u.vcpu_id = cs->cpu_index,
+};
+err = kvm_vcpu_ioctl(cs, KVM_XEN_VCPU_SET_ATTR, &va);
+if (err) {
+error_report("kvm: Failed to set Xen vCPU ID attribute: %s",
+ strerror(-err));
+return err;
+}
+}
+
+return 0;
+}
+
 uint32_t kvm_xen_get_caps(void)
 {
 return kvm_state->xen_caps;
diff --git a/target/i386/kvm/xen-emu.h b/target/i386/kvm/xen-emu.h
index 2101df0182..d62f1d8ed8 100644
--- a/target/i386/kvm/xen-emu.h
+++ b/target/i386/kvm/xen-emu.h
@@ -24,5 +24,6 @@
 #define XEN_VERSION(maj, min) ((maj) << 16 | (min))
 
 int kvm_xen_init(KVMState *s, uint32_t hypercall_msr);
+int kvm_xen_init_vcpu(CPUState *cs);
 
 #endif /* QEMU_I386_KVM_XEN_EMU_H */
-- 
2.35.3




[PATCH v6 46/51] i386/xen: handle PV timer hypercalls

2023-01-10 Thread David Woodhouse
From: Joao Martins 

Introduce support for one shot and periodic mode of Xen PV timers,
whereby timer interrupts come through a special virq event channel
with deadlines being set through:

1) set_timer_op hypercall (only oneshot)
2) vcpu_op hypercall for {set,stop}_{singleshot,periodic}_timer
hypercalls

Signed-off-by: Joao Martins 
Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c  |  31 +
 hw/i386/kvm/xen_evtchn.h  |   2 +
 target/i386/cpu.h |   5 +
 target/i386/kvm/xen-emu.c | 245 +-
 target/i386/machine.c |   1 +
 5 files changed, 282 insertions(+), 2 deletions(-)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index c82fac69a2..9b9a10fa43 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -1159,6 +1159,37 @@ int xen_evtchn_send_op(struct evtchn_send *send)
 return ret;
 }
 
+int xen_evtchn_set_port(uint16_t port)
+{
+XenEvtchnState *s = xen_evtchn_singleton;
+XenEvtchnPort *p;
+int ret = -EINVAL;
+
+if (!s) {
+return -ENOTSUP;
+}
+
+if (!valid_port(port)) {
+return -EINVAL;
+}
+
+qemu_mutex_lock(&s->port_lock);
+
+p = &s->port_table[port];
+
+/* QEMU has no business sending to anything but these */
+if (p->type == EVTCHNSTAT_virq ||
+(p->type == EVTCHNSTAT_interdomain &&
+ (p->type_val & PORT_INFO_TYPEVAL_REMOTE_QEMU))) {
+set_port_pending(s, port);
+ret = 0;
+}
+
+qemu_mutex_unlock(&s->port_lock);
+
+return ret;
+}
+
 static const char *type_names[] = {
 "closed",
 "unbound",
diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h
index 1f9ffc3f94..d85b45067b 100644
--- a/hw/i386/kvm/xen_evtchn.h
+++ b/hw/i386/kvm/xen_evtchn.h
@@ -20,6 +20,8 @@ int xen_evtchn_set_callback_param(uint64_t param);
 void xen_evtchn_connect_gsis(qemu_irq *system_gsis);
 void xen_evtchn_set_callback_level(int level);
 
+int xen_evtchn_set_port(uint16_t port);
+
 void hmp_xen_event_inject(Monitor *mon, const QDict *qdict);
 void hmp_xen_event_list(Monitor *mon, const QDict *qdict);
 
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index e8718c31e5..b579f0f0f8 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -26,6 +26,7 @@
 #include "exec/cpu-defs.h"
 #include "qapi/qapi-types-common.h"
 #include "qemu/cpu-float.h"
+#include "qemu/timer.h"
 
 #define XEN_NR_VIRQS 24
 
@@ -1800,6 +1801,10 @@ typedef struct CPUArchState {
 bool xen_callback_asserted;
 uint16_t xen_virq[XEN_NR_VIRQS];
 uint64_t xen_singleshot_timer_ns;
+QEMUTimer *xen_singleshot_timer;
+uint64_t xen_periodic_timer_period;
+QEMUTimer *xen_periodic_timer;
+QemuMutex xen_timers_lock;
 #endif
 #if defined(CONFIG_HVF)
 HVFX86LazyFlags hvf_lflags;
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index a279d7ff89..2a7750bacb 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -37,6 +37,9 @@
 
 #include "xen-compat.h"
 
+static void xen_vcpu_singleshot_timer_event(void *opaque);
+static void xen_vcpu_periodic_timer_event(void *opaque);
+
 #ifdef TARGET_X86_64
 #define hypercall_compat32(longmode) (!(longmode))
 #else
@@ -200,6 +203,23 @@ int kvm_xen_init_vcpu(CPUState *cs)
 env->xen_vcpu_time_info_gpa = INVALID_GPA;
 env->xen_vcpu_runstate_gpa = INVALID_GPA;
 
+qemu_mutex_init(&env->xen_timers_lock);
+env->xen_singleshot_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ xen_vcpu_singleshot_timer_event,
+ cpu);
+if (!env->xen_singleshot_timer) {
+return -ENOMEM;
+}
+env->xen_singleshot_timer->opaque = cs;
+
+env->xen_periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+   xen_vcpu_periodic_timer_event,
+   cpu);
+if (!env->xen_periodic_timer) {
+return -ENOMEM;
+}
+env->xen_periodic_timer->opaque = cs;
+
 return 0;
 }
 
@@ -231,7 +251,8 @@ static bool kvm_xen_hcall_xen_version(struct kvm_xen_exit 
*exit, X86CPU *cpu,
  1 << XENFEAT_writable_descriptor_tables |
  1 << XENFEAT_auto_translated_physmap |
  1 << XENFEAT_supervisor_mode_kernel |
- 1 << XENFEAT_hvm_callback_vector;
+ 1 << XENFEAT_hvm_callback_vector |
+ 1 << XENFEAT_hvm_safe_pvclock;
 }
 
 err = kvm_copy_to_gva(CPU(cpu), arg, &fi, sizeof(fi));
@@ -848,13 +869,192 @@ static int vcpuop_register_runstate_info(CPUState *cs, 
CPUState *target,
 return 0;
 }
 
+static uint64_t kvm_get_current_ns(void)
+{
+struct kvm_clock_data data;
+int ret;
+
+ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
+if (ret < 0) {
+fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
+abort(

[PATCH v6 33/51] hw/xen: Implement EVTCHNOP_send

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c  | 180 ++
 hw/i386/kvm/xen_evtchn.h  |   2 +
 target/i386/kvm/xen-emu.c |  12 +++
 3 files changed, 194 insertions(+)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index bbf234edaf..107249c48c 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -483,6 +483,133 @@ static int unmask_port(XenEvtchnState *s, evtchn_port_t 
port, bool do_unmask)
 }
 }
 
+static int do_set_port_lm(XenEvtchnState *s, evtchn_port_t port,
+  struct shared_info *shinfo,
+  struct vcpu_info *vcpu_info)
+{
+const int bits_per_word = BITS_PER_BYTE * 
sizeof(shinfo->evtchn_pending[0]);
+typeof(shinfo->evtchn_pending[0]) mask;
+int idx = port / bits_per_word;
+int offset = port % bits_per_word;
+
+mask = 1UL << offset;
+
+if (idx >= bits_per_word) {
+return -EINVAL;
+}
+
+/* Update the pending bit itself. If it was already set, we're done. */
+if (qatomic_fetch_or(&shinfo->evtchn_pending[idx], mask) & mask) {
+return 0;
+}
+
+/* Check if it's masked. */
+if (qatomic_fetch_or(&shinfo->evtchn_mask[idx], 0) & mask) {
+return 0;
+}
+
+/* Now on to the vcpu_info evtchn_pending_sel index... */
+mask = 1UL << idx;
+
+/* If a port in this word was already pending for this vCPU, all done. */
+if (qatomic_fetch_or(&vcpu_info->evtchn_pending_sel, mask) & mask) {
+return 0;
+}
+
+/* Set evtchn_upcall_pending for this vCPU */
+if (qatomic_fetch_or(&vcpu_info->evtchn_upcall_pending, 1)) {
+return 0;
+}
+
+inject_callback(s, s->port_table[port].vcpu);
+
+return 0;
+}
+
+static int do_set_port_compat(XenEvtchnState *s, evtchn_port_t port,
+  struct compat_shared_info *shinfo,
+  struct compat_vcpu_info *vcpu_info)
+{
+const int bits_per_word = BITS_PER_BYTE * 
sizeof(shinfo->evtchn_pending[0]);
+typeof(shinfo->evtchn_pending[0]) mask;
+int idx = port / bits_per_word;
+int offset = port % bits_per_word;
+
+mask = 1UL << offset;
+
+if (idx >= bits_per_word) {
+return -EINVAL;
+}
+
+/* Update the pending bit itself. If it was already set, we're done. */
+if (qatomic_fetch_or(&shinfo->evtchn_pending[idx], mask) & mask) {
+return 0;
+}
+
+/* Check if it's masked. */
+if (qatomic_fetch_or(&shinfo->evtchn_mask[idx], 0) & mask) {
+return 0;
+}
+
+/* Now on to the vcpu_info evtchn_pending_sel index... */
+mask = 1UL << idx;
+
+/* If a port in this word was already pending for this vCPU, all done. */
+if (qatomic_fetch_or(&vcpu_info->evtchn_pending_sel, mask) & mask) {
+return 0;
+}
+
+/* Set evtchn_upcall_pending for this vCPU */
+if (qatomic_fetch_or(&vcpu_info->evtchn_upcall_pending, 1)) {
+return 0;
+}
+
+inject_callback(s, s->port_table[port].vcpu);
+
+return 0;
+}
+
+static int set_port_pending(XenEvtchnState *s, evtchn_port_t port)
+{
+void *vcpu_info, *shinfo;
+
+if (s->port_table[port].type == EVTCHNSTAT_closed) {
+return -EINVAL;
+}
+
+if (s->evtchn_in_kernel) {
+XenEvtchnPort *p = &s->port_table[port];
+CPUState *cpu = qemu_get_cpu(p->vcpu);
+struct kvm_irq_routing_xen_evtchn evt;
+
+if (!cpu) {
+return 0;
+}
+
+evt.port = port;
+evt.vcpu = kvm_arch_vcpu_id(cpu);
+evt.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
+
+return kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_EVTCHN_SEND, &evt);
+}
+
+shinfo = xen_overlay_get_shinfo_ptr();
+if (!shinfo) {
+return -ENOTSUP;
+}
+
+vcpu_info = kvm_xen_get_vcpu_info_hva(s->port_table[port].vcpu);
+if (!vcpu_info) {
+return -EINVAL;
+}
+
+if (xen_is_long_mode()) {
+return do_set_port_lm(s, port, shinfo, vcpu_info);
+} else {
+return do_set_port_compat(s, port, shinfo, vcpu_info);
+}
+}
+
 static int clear_port_pending(XenEvtchnState *s, evtchn_port_t port)
 {
 void *p = xen_overlay_get_shinfo_ptr();
@@ -700,3 +827,56 @@ int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi)
 
 return ret;
 }
+
+int xen_evtchn_send_op(struct evtchn_send *send)
+{
+XenEvtchnState *s = xen_evtchn_singleton;
+XenEvtchnPort *p;
+int ret = 0;
+
+if (!s) {
+return -ENOTSUP;
+}
+
+if (!valid_port(send->port)) {
+return -EINVAL;
+}
+
+qemu_mutex_lock(&s->port_lock);
+
+p = &s->port_table[send->port];
+
+switch (p->type) {
+case EVTCHNSTAT_interdomain:
+if (p->type_val & PORT_INFO_TYPEVAL_REMOTE_QEMU) {
+/*
+ * This is an event from the guest to qemu itself, which is
+ * serving as the driver domain. Not yet implemented; it will
+ 

[PATCH v6 13/51] hw/xen: Add xen_overlay device for emulating shared xenheap pages

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

For the shared info page and for grant tables, Xen shares its own pages
from the "Xen heap" to the guest. The guest requests that a given page
from a certain address space (XENMAPSPACE_shared_info, etc.) be mapped
to a given GPA using the XENMEM_add_to_physmap hypercall.

To support that in qemu when *emulating* Xen, create a memory region
(migratable) and allow it to be mapped as an overlay when requested.

Xen theoretically allows the same page to be mapped multiple times
into the guest, but that's hard to track and reinstate over migration,
so we automatically *unmap* any previous mapping when creating a new
one. This approach has been used in production with a non-trivial
number of guests expecting true Xen, without any problems yet being
noticed.

This adds just the shared info page for now. The grant tables will be
a larger region, and will need to be overlaid one page at a time. I
think that means I need to create separate aliases for each page of
the overall grant_frames region, so that they can be mapped individually.

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/meson.build   |   1 +
 hw/i386/kvm/xen_overlay.c | 200 ++
 hw/i386/kvm/xen_overlay.h |  20 
 include/sysemu/kvm_xen.h  |   4 +
 4 files changed, 225 insertions(+)
 create mode 100644 hw/i386/kvm/xen_overlay.c
 create mode 100644 hw/i386/kvm/xen_overlay.h

diff --git a/hw/i386/kvm/meson.build b/hw/i386/kvm/meson.build
index 95467f1ded..6165cbf019 100644
--- a/hw/i386/kvm/meson.build
+++ b/hw/i386/kvm/meson.build
@@ -4,5 +4,6 @@ i386_kvm_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c'))
 i386_kvm_ss.add(when: 'CONFIG_I8254', if_true: files('i8254.c'))
 i386_kvm_ss.add(when: 'CONFIG_I8259', if_true: files('i8259.c'))
 i386_kvm_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic.c'))
+i386_kvm_ss.add(when: 'CONFIG_XEN_EMU', if_true: files('xen_overlay.c'))
 
 i386_ss.add_all(when: 'CONFIG_KVM', if_true: i386_kvm_ss)
diff --git a/hw/i386/kvm/xen_overlay.c b/hw/i386/kvm/xen_overlay.c
new file mode 100644
index 00..3e85bf912f
--- /dev/null
+++ b/hw/i386/kvm/xen_overlay.c
@@ -0,0 +1,200 @@
+/*
+ * QEMU Xen emulation: Shared/overlay pages support
+ *
+ * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Authors: David Woodhouse 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+#include "qemu/module.h"
+#include "qemu/main-loop.h"
+#include "qapi/error.h"
+#include "qom/object.h"
+#include "exec/target_page.h"
+#include "exec/address-spaces.h"
+#include "migration/vmstate.h"
+
+#include "hw/sysbus.h"
+#include "hw/xen/xen.h"
+#include "xen_overlay.h"
+
+#include "sysemu/kvm.h"
+#include "sysemu/kvm_xen.h"
+#include 
+
+#include "standard-headers/xen/memory.h"
+
+
+#define TYPE_XEN_OVERLAY "xen-overlay"
+OBJECT_DECLARE_SIMPLE_TYPE(XenOverlayState, XEN_OVERLAY)
+
+#define XEN_PAGE_SHIFT 12
+#define XEN_PAGE_SIZE (1ULL << XEN_PAGE_SHIFT)
+
+struct XenOverlayState {
+/*< private >*/
+SysBusDevice busdev;
+/*< public >*/
+
+MemoryRegion shinfo_mem;
+void *shinfo_ptr;
+uint64_t shinfo_gpa;
+};
+
+struct XenOverlayState *xen_overlay_singleton;
+
+static void xen_overlay_map_page_locked(MemoryRegion *page, uint64_t gpa)
+{
+/*
+ * Xen allows guests to map the same page as many times as it likes
+ * into guest physical frames. We don't, because it would be hard
+ * to track and restore them all. One mapping of each page is
+ * perfectly sufficient for all known guests... and we've tested
+ * that theory on a few now in other implementations. dwmw2.
+ */
+if (memory_region_is_mapped(page)) {
+if (gpa == INVALID_GPA) {
+memory_region_del_subregion(get_system_memory(), page);
+} else {
+/* Just move it */
+memory_region_set_address(page, gpa);
+}
+} else if (gpa != INVALID_GPA) {
+memory_region_add_subregion_overlap(get_system_memory(), gpa, page, 0);
+}
+}
+
+/* KVM is the only existing back end for now. Let's not overengineer it yet. */
+static int xen_overlay_set_be_shinfo(uint64_t gfn)
+{
+struct kvm_xen_hvm_attr xa = {
+.type = KVM_XEN_ATTR_TYPE_SHARED_INFO,
+.u.shared_info.gfn = gfn,
+};
+
+return kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &xa);
+}
+
+
+static void xen_overlay_realize(DeviceState *dev, Error **errp)
+{
+XenOverlayState *s = XEN_OVERLAY(dev);
+
+if (xen_mode != XEN_EMULATE) {
+error_setg(errp, "Xen overlay page support is for Xen emulation");
+return;
+}
+
+memory_region_init_ram(&s->shinfo_mem, OBJECT(dev), "xen:shared_info",
+   XEN_PAGE_SIZE, &error_abort);
+memory_region_set_enabled(&s->shinfo_mem, true);
+
+s->shinfo_ptr = memory_region_get_ram_ptr(&

[PATCH v6 25/51] i386/xen: implement HVMOP_set_param

2023-01-10 Thread David Woodhouse
From: Ankur Arora 

This is the hook for adding the HVM_PARAM_CALLBACK_IRQ parameter in a
subsequent commit.

Signed-off-by: Ankur Arora 
Signed-off-by: Joao Martins 
[dwmw2: Split out from another commit]
Signed-off-by: David Woodhouse 
---
 target/i386/kvm/xen-emu.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index d56d63b02e..a27facb90f 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -486,6 +486,36 @@ static bool kvm_xen_hcall_memory_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 return true;
 }
 
+static bool handle_set_param(struct kvm_xen_exit *exit, X86CPU *cpu,
+ uint64_t arg)
+{
+CPUState *cs = CPU(cpu);
+struct xen_hvm_param hp;
+int err = 0;
+
+/* No need for 32/64 compat handling */
+qemu_build_assert(sizeof(hp) == 16);
+
+if (kvm_copy_from_gva(cs, arg, &hp, sizeof(hp))) {
+err = -EFAULT;
+goto out;
+}
+
+if (hp.domid != DOMID_SELF && hp.domid != xen_domid) {
+err = -ESRCH;
+goto out;
+}
+
+switch (hp.index) {
+default:
+return false;
+}
+
+out:
+exit->u.hcall.result = err;
+return true;
+}
+
 static int kvm_xen_hcall_evtchn_upcall_vector(struct kvm_xen_exit *exit,
   X86CPU *cpu, uint64_t arg)
 {
@@ -527,6 +557,9 @@ static bool kvm_xen_hcall_hvm_op(struct kvm_xen_exit *exit, 
X86CPU *cpu,
 ret = -ENOSYS;
 break;
 
+case HVMOP_set_param:
+return handle_set_param(exit, cpu, arg);
+
 default:
 return false;
 }
-- 
2.35.3




[PATCH v6 35/51] hw/xen: Implement EVTCHNOP_bind_interdomain

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c  | 78 +++
 hw/i386/kvm/xen_evtchn.h  |  2 +
 target/i386/kvm/xen-emu.c | 16 
 3 files changed, 96 insertions(+)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 15c467ad7f..511d52a31d 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -713,6 +713,23 @@ static int close_port(XenEvtchnState *s, evtchn_port_t 
port)
 }
 break;
 
+case EVTCHNSTAT_interdomain:
+if (p->type_val & PORT_INFO_TYPEVAL_REMOTE_QEMU) {
+/* Not yet implemented. This can't happen! */
+} else {
+/* Loopback interdomain */
+XenEvtchnPort *rp = &s->port_table[p->type_val];
+if (!valid_port(p->type_val) || rp->type_val != port ||
+rp->type != EVTCHNSTAT_interdomain) {
+error_report("Inconsistent state for interdomain unbind");
+} else {
+/* Set the other end back to unbound */
+rp->type = EVTCHNSTAT_unbound;
+rp->type_val = 0;
+}
+}
+break;
+
 default:
 break;
 }
@@ -828,6 +845,67 @@ int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi)
 return ret;
 }
 
+int xen_evtchn_bind_interdomain_op(struct evtchn_bind_interdomain *interdomain)
+{
+XenEvtchnState *s = xen_evtchn_singleton;
+uint16_t type_val;
+int ret;
+
+if (!s) {
+return -ENOTSUP;
+}
+
+if (interdomain->remote_dom == DOMID_QEMU) {
+type_val = PORT_INFO_TYPEVAL_REMOTE_QEMU;
+} else if (interdomain->remote_dom == DOMID_SELF ||
+   interdomain->remote_dom == xen_domid) {
+type_val = 0;
+} else {
+return -ESRCH;
+}
+
+if (!valid_port(interdomain->remote_port)) {
+return -EINVAL;
+}
+
+qemu_mutex_lock(&s->port_lock);
+
+/* The newly allocated port starts out as unbound */
+ret = allocate_port(s, 0, EVTCHNSTAT_unbound, type_val,
+&interdomain->local_port);
+if (ret) {
+goto out;
+}
+
+if (interdomain->remote_dom == DOMID_QEMU) {
+/* We haven't hooked up QEMU's PV drivers to this yet */
+ret = -ENOSYS;
+} else {
+/* Loopback */
+XenEvtchnPort *rp = &s->port_table[interdomain->remote_port];
+XenEvtchnPort *lp = &s->port_table[interdomain->local_port];
+
+if (rp->type == EVTCHNSTAT_unbound && rp->type_val == 0) {
+/* It's a match! */
+rp->type = EVTCHNSTAT_interdomain;
+rp->type_val = interdomain->local_port;
+
+lp->type = EVTCHNSTAT_interdomain;
+lp->type_val = interdomain->remote_port;
+} else {
+ret = -EINVAL;
+}
+}
+
+if (ret) {
+free_port(s, interdomain->local_port);
+}
+ out:
+qemu_mutex_unlock(&s->port_lock);
+
+return ret;
+
+}
 int xen_evtchn_alloc_unbound_op(struct evtchn_alloc_unbound *alloc)
 {
 XenEvtchnState *s = xen_evtchn_singleton;
diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h
index fc080138e3..1ebc7580eb 100644
--- a/hw/i386/kvm/xen_evtchn.h
+++ b/hw/i386/kvm/xen_evtchn.h
@@ -22,6 +22,7 @@ struct evtchn_bind_virq;
 struct evtchn_bind_ipi;
 struct evtchn_send;
 struct evtchn_alloc_unbound;
+struct evtchn_bind_interdomain;
 int xen_evtchn_status_op(struct evtchn_status *status);
 int xen_evtchn_close_op(struct evtchn_close *close);
 int xen_evtchn_unmask_op(struct evtchn_unmask *unmask);
@@ -29,5 +30,6 @@ int xen_evtchn_bind_virq_op(struct evtchn_bind_virq *virq);
 int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi);
 int xen_evtchn_send_op(struct evtchn_send *send);
 int xen_evtchn_alloc_unbound_op(struct evtchn_alloc_unbound *alloc);
+int xen_evtchn_bind_interdomain_op(struct evtchn_bind_interdomain 
*interdomain);
 
 #endif /* QEMU_XEN_EVTCHN_H */
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 0787fed494..2471a4f703 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -922,6 +922,22 @@ static bool kvm_xen_hcall_evtchn_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 }
 break;
 }
+case EVTCHNOP_bind_interdomain: {
+struct evtchn_bind_interdomain interdomain;
+
+qemu_build_assert(sizeof(interdomain) == 12);
+if (kvm_copy_from_gva(cs, arg, &interdomain, sizeof(interdomain))) {
+err = -EFAULT;
+break;
+}
+
+err = xen_evtchn_bind_interdomain_op(&interdomain);
+if (!err &&
+kvm_copy_to_gva(cs, arg, &interdomain, sizeof(interdomain))) {
+err = -EFAULT;
+}
+break;
+}
 default:
 return false;
 }
-- 
2.35.3




[PATCH v6 10/51] i386/xen: implement HYPERVISOR_xen_version

2023-01-10 Thread David Woodhouse
From: Joao Martins 

This is just meant to serve as an example on how we can implement
hypercalls. xen_version specifically since Qemu does all kind of
feature controllability. So handling that here seems appropriate.

Signed-off-by: Joao Martins 
[dwmw2: Implement kvm_gva_rw() safely]
Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 target/i386/kvm/xen-emu.c | 86 +++
 1 file changed, 86 insertions(+)

diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 476f464ee2..1dea6feb90 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -14,9 +14,55 @@
 #include "sysemu/kvm_int.h"
 #include "sysemu/kvm_xen.h"
 #include "kvm/kvm_i386.h"
+#include "exec/address-spaces.h"
 #include "xen-emu.h"
 #include "trace.h"
 
+#include "standard-headers/xen/version.h"
+
+static int kvm_gva_rw(CPUState *cs, uint64_t gva, void *_buf, size_t sz,
+  bool is_write)
+{
+uint8_t *buf = (uint8_t *)_buf;
+int ret;
+
+while (sz) {
+struct kvm_translation tr = {
+.linear_address = gva,
+};
+
+size_t len = TARGET_PAGE_SIZE - (tr.linear_address & 
~TARGET_PAGE_MASK);
+if (len > sz) {
+len = sz;
+}
+
+ret = kvm_vcpu_ioctl(cs, KVM_TRANSLATE, &tr);
+if (ret || !tr.valid || (is_write && !tr.writeable)) {
+return -EFAULT;
+}
+
+cpu_physical_memory_rw(tr.physical_address, buf, len, is_write);
+
+buf += len;
+sz -= len;
+gva += len;
+}
+
+return 0;
+}
+
+static inline int kvm_copy_from_gva(CPUState *cs, uint64_t gva, void *buf,
+size_t sz)
+{
+return kvm_gva_rw(cs, gva, buf, sz, false);
+}
+
+static inline int kvm_copy_to_gva(CPUState *cs, uint64_t gva, void *buf,
+  size_t sz)
+{
+return kvm_gva_rw(cs, gva, buf, sz, true);
+}
+
 int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
 {
 const int required_caps = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR |
@@ -87,6 +133,43 @@ uint32_t kvm_xen_get_caps(void)
 return kvm_state->xen_caps;
 }
 
+static bool kvm_xen_hcall_xen_version(struct kvm_xen_exit *exit, X86CPU *cpu,
+ int cmd, uint64_t arg)
+{
+int err = 0;
+
+switch (cmd) {
+case XENVER_get_features: {
+struct xen_feature_info fi;
+
+/* No need for 32/64 compat handling */
+qemu_build_assert(sizeof(fi) == 8);
+
+err = kvm_copy_from_gva(CPU(cpu), arg, &fi, sizeof(fi));
+if (err) {
+break;
+}
+
+fi.submap = 0;
+if (fi.submap_idx == 0) {
+fi.submap |= 1 << XENFEAT_writable_page_tables |
+ 1 << XENFEAT_writable_descriptor_tables |
+ 1 << XENFEAT_auto_translated_physmap |
+ 1 << XENFEAT_supervisor_mode_kernel;
+}
+
+err = kvm_copy_to_gva(CPU(cpu), arg, &fi, sizeof(fi));
+break;
+}
+
+default:
+return false;
+}
+
+exit->u.hcall.result = err;
+return true;
+}
+
 static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
 {
 uint16_t code = exit->u.hcall.input;
@@ -97,6 +180,9 @@ static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct 
kvm_xen_exit *exit)
 }
 
 switch (code) {
+case __HYPERVISOR_xen_version:
+return kvm_xen_hcall_xen_version(exit, cpu, exit->u.hcall.params[0],
+ exit->u.hcall.params[1]);
 default:
 return false;
 }
-- 
2.35.3




[PATCH v6 34/51] hw/xen: Implement EVTCHNOP_alloc_unbound

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c  | 32 
 hw/i386/kvm/xen_evtchn.h  |  2 ++
 target/i386/kvm/xen-emu.c | 15 +++
 3 files changed, 49 insertions(+)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 107249c48c..15c467ad7f 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -828,6 +828,38 @@ int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi)
 return ret;
 }
 
+int xen_evtchn_alloc_unbound_op(struct evtchn_alloc_unbound *alloc)
+{
+XenEvtchnState *s = xen_evtchn_singleton;
+uint16_t type_val;
+int ret;
+
+if (!s) {
+return -ENOTSUP;
+}
+
+if (alloc->dom != DOMID_SELF && alloc->dom != xen_domid) {
+return -ESRCH;
+}
+
+if (alloc->remote_dom == DOMID_QEMU) {
+type_val = PORT_INFO_TYPEVAL_REMOTE_QEMU;
+} else if (alloc->remote_dom == DOMID_SELF ||
+   alloc->remote_dom == xen_domid) {
+type_val = 0;
+} else {
+return -EPERM;
+}
+
+qemu_mutex_lock(&s->port_lock);
+
+ret = allocate_port(s, 0, EVTCHNSTAT_unbound, type_val, &alloc->port);
+
+qemu_mutex_unlock(&s->port_lock);
+
+return ret;
+}
+
 int xen_evtchn_send_op(struct evtchn_send *send)
 {
 XenEvtchnState *s = xen_evtchn_singleton;
diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h
index 500fdbe8b8..fc080138e3 100644
--- a/hw/i386/kvm/xen_evtchn.h
+++ b/hw/i386/kvm/xen_evtchn.h
@@ -21,11 +21,13 @@ struct evtchn_unmask;
 struct evtchn_bind_virq;
 struct evtchn_bind_ipi;
 struct evtchn_send;
+struct evtchn_alloc_unbound;
 int xen_evtchn_status_op(struct evtchn_status *status);
 int xen_evtchn_close_op(struct evtchn_close *close);
 int xen_evtchn_unmask_op(struct evtchn_unmask *unmask);
 int xen_evtchn_bind_virq_op(struct evtchn_bind_virq *virq);
 int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi);
 int xen_evtchn_send_op(struct evtchn_send *send);
+int xen_evtchn_alloc_unbound_op(struct evtchn_alloc_unbound *alloc);
 
 #endif /* QEMU_XEN_EVTCHN_H */
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 3bb7026ffb..0787fed494 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -907,6 +907,21 @@ static bool kvm_xen_hcall_evtchn_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 err = xen_evtchn_send_op(&send);
 break;
 }
+case EVTCHNOP_alloc_unbound: {
+struct evtchn_alloc_unbound alloc;
+
+qemu_build_assert(sizeof(alloc) == 8);
+if (kvm_copy_from_gva(cs, arg, &alloc, sizeof(alloc))) {
+err = -EFAULT;
+break;
+}
+
+err = xen_evtchn_alloc_unbound_op(&alloc);
+if (!err && kvm_copy_to_gva(cs, arg, &alloc, sizeof(alloc))) {
+err = -EFAULT;
+}
+break;
+}
 default:
 return false;
 }
-- 
2.35.3




[PATCH v6 16/51] i386/xen: implement HYPERVISOR_memory_op

2023-01-10 Thread David Woodhouse
From: Joao Martins 

Specifically XENMEM_add_to_physmap with space XENMAPSPACE_shared_info to
allow the guest to set its shared_info page.

Signed-off-by: Joao Martins 
[dwmw2: Use the xen_overlay device, add compat support]
Signed-off-by: David Woodhouse 
---
 target/i386/kvm/trace-events |   1 +
 target/i386/kvm/xen-compat.h |  27 +
 target/i386/kvm/xen-emu.c| 114 ++-
 3 files changed, 141 insertions(+), 1 deletion(-)
 create mode 100644 target/i386/kvm/xen-compat.h

diff --git a/target/i386/kvm/trace-events b/target/i386/kvm/trace-events
index cd6f842b1f..0a47c26e80 100644
--- a/target/i386/kvm/trace-events
+++ b/target/i386/kvm/trace-events
@@ -8,3 +8,4 @@ kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
 
 # xen-emu.c
 kvm_xen_hypercall(int cpu, uint8_t cpl, uint64_t input, uint64_t a0, uint64_t 
a1, uint64_t a2, uint64_t ret) "xen_hypercall: cpu %d cpl %d input %" PRIu64 " 
a0 0x%" PRIx64 " a1 0x%" PRIx64 " a2 0x%" PRIx64" ret 0x%" PRIx64
+kvm_xen_set_shared_info(uint64_t gfn) "shared info at gfn 0x%" PRIx64
diff --git a/target/i386/kvm/xen-compat.h b/target/i386/kvm/xen-compat.h
new file mode 100644
index 00..0b7088662a
--- /dev/null
+++ b/target/i386/kvm/xen-compat.h
@@ -0,0 +1,27 @@
+/*
+ * Xen HVM emulation support in KVM
+ *
+ * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_I386_KVM_XEN_COMPAT_H
+#define QEMU_I386_KVM_XEN_COMPAT_H
+
+#include "standard-headers/xen/memory.h"
+
+typedef uint32_t compat_pfn_t;
+typedef uint32_t compat_ulong_t;
+
+struct compat_xen_add_to_physmap {
+domid_t domid;
+uint16_t size;
+unsigned int space;
+compat_ulong_t idx;
+compat_pfn_t gpfn;
+};
+
+#endif /* QEMU_I386_XEN_COMPAT_H */
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 80f09f33df..1f2e8275bc 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -11,6 +11,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/log.h"
+#include "hw/xen/xen.h"
 #include "sysemu/kvm_int.h"
 #include "sysemu/kvm_xen.h"
 #include "kvm/kvm_i386.h"
@@ -23,6 +24,15 @@
 
 #include "standard-headers/xen/version.h"
 #include "standard-headers/xen/sched.h"
+#include "standard-headers/xen/memory.h"
+
+#include "xen-compat.h"
+
+#ifdef TARGET_X86_64
+#define hypercall_compat32(longmode) (!(longmode))
+#else
+#define hypercall_compat32(longmode) (false)
+#endif
 
 static int kvm_gva_rw(CPUState *cs, uint64_t gva, void *_buf, size_t sz,
   bool is_write)
@@ -174,9 +184,108 @@ static bool kvm_xen_hcall_xen_version(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 return true;
 }
 
+static int xen_set_shared_info(uint64_t gfn)
+{
+uint64_t gpa = gfn << TARGET_PAGE_BITS;
+int err;
+
+/*
+ * The xen_overlay device tells KVM about it too, since it had to
+ * do that on migration load anyway (unless we're going to jump
+ * through lots of hoops to maintain the fiction that this isn't
+ * KVM-specific.
+ */
+err = xen_overlay_map_shinfo_page(gpa);
+if (err) {
+return err;
+}
+
+trace_kvm_xen_set_shared_info(gfn);
+
+return err;
+}
+
+static int add_to_physmap_one(uint32_t space, uint64_t idx, uint64_t gfn)
+{
+switch (space) {
+case XENMAPSPACE_shared_info:
+if (idx > 0) {
+return -EINVAL;
+}
+return xen_set_shared_info(gfn);
+
+case XENMAPSPACE_grant_table:
+case XENMAPSPACE_gmfn:
+case XENMAPSPACE_gmfn_range:
+return -ENOTSUP;
+
+case XENMAPSPACE_gmfn_foreign:
+case XENMAPSPACE_dev_mmio:
+return -EPERM;
+
+default:
+return -EINVAL;
+}
+}
+
+static int do_add_to_physmap(struct kvm_xen_exit *exit, X86CPU *cpu,
+ uint64_t arg)
+{
+struct xen_add_to_physmap xatp;
+CPUState *cs = CPU(cpu);
+
+if (hypercall_compat32(exit->u.hcall.longmode)) {
+struct compat_xen_add_to_physmap xatp32;
+
+qemu_build_assert(sizeof(struct compat_xen_add_to_physmap) == 16);
+if (kvm_copy_from_gva(cs, arg, &xatp32, sizeof(xatp32))) {
+return -EFAULT;
+}
+xatp.domid = xatp32.domid;
+xatp.size = xatp32.size;
+xatp.space = xatp32.space;
+xatp.idx = xatp32.idx;
+xatp.gpfn = xatp32.gpfn;
+} else {
+if (kvm_copy_from_gva(cs, arg, &xatp, sizeof(xatp))) {
+return -EFAULT;
+}
+}
+
+if (xatp.domid != DOMID_SELF && xatp.domid != xen_domid) {
+return -ESRCH;
+}
+
+return add_to_physmap_one(xatp.space, xatp.idx, xatp.gpfn);
+}
+
+static bool kvm_xen_hcall_memory_op(struct kvm_xen_exit *exit, X86CPU *cpu,
+   int cmd, uint64_t arg)
+{
+int err;
+
+switch (cmd) {
+case XENMEM_add_to_physmap:
+

[PATCH v6 04/51] i386/kvm: Add xen-version KVM accelerator property and init KVM Xen support

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

This just initializes the basic Xen support in KVM for now. Only permitted
on TYPE_PC_MACHINE because that's where the sysbus devices for Xen heap
overlay, event channel, grant tables and other stuff will exist. There's
no point having the basic hypercall support if nothing else works.

Provide sysemu/kvm_xen.h and a kvm_xen_get_caps() which will be used
later by support devices.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 accel/kvm/kvm-all.c |  1 +
 include/sysemu/kvm_int.h|  2 ++
 include/sysemu/kvm_xen.h| 20 +
 target/i386/kvm/kvm.c   | 59 +
 target/i386/kvm/meson.build |  2 ++
 target/i386/kvm/xen-emu.c   | 58 
 target/i386/kvm/xen-emu.h   | 19 
 7 files changed, 161 insertions(+)
 create mode 100644 include/sysemu/kvm_xen.h
 create mode 100644 target/i386/kvm/xen-emu.c
 create mode 100644 target/i386/kvm/xen-emu.h

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index e86c33e0e6..8ab4da139f 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -3617,6 +3617,7 @@ static void kvm_accel_instance_init(Object *obj)
 s->kvm_dirty_ring_size = 0;
 s->notify_vmexit = NOTIFY_VMEXIT_OPTION_RUN;
 s->notify_window = 0;
+s->xen_version = 0;
 }
 
 /**
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
index 3b4adcdc10..9a8c062609 100644
--- a/include/sysemu/kvm_int.h
+++ b/include/sysemu/kvm_int.h
@@ -110,6 +110,8 @@ struct KVMState
 struct KVMDirtyRingReaper reaper;
 NotifyVmexitOption notify_vmexit;
 uint32_t notify_window;
+uint32_t xen_version;
+uint32_t xen_caps;
 };
 
 void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
diff --git a/include/sysemu/kvm_xen.h b/include/sysemu/kvm_xen.h
new file mode 100644
index 00..296533f2d5
--- /dev/null
+++ b/include/sysemu/kvm_xen.h
@@ -0,0 +1,20 @@
+/*
+ * Xen HVM emulation support in KVM
+ *
+ * Copyright © 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_SYSEMU_KVM_XEN_H
+#define QEMU_SYSEMU_KVM_XEN_H
+
+uint32_t kvm_xen_get_caps(void);
+
+#define kvm_xen_has_cap(cap) (!!(kvm_xen_get_caps() &   \
+ KVM_XEN_HVM_CONFIG_ ## cap))
+
+#endif /* QEMU_SYSEMU_KVM_XEN_H */
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 0ab4e0734a..e6590eb236 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -31,6 +31,7 @@
 #include "sysemu/runstate.h"
 #include "kvm_i386.h"
 #include "sev.h"
+#include "xen-emu.h"
 #include "hyperv.h"
 #include "hyperv-proto.h"
 
@@ -41,6 +42,7 @@
 #include "qemu/error-report.h"
 #include "qemu/memalign.h"
 #include "hw/i386/x86.h"
+#include "hw/i386/pc.h"
 #include "hw/i386/apic.h"
 #include "hw/i386/apic_internal.h"
 #include "hw/i386/apic-msidef.h"
@@ -48,6 +50,8 @@
 #include "hw/i386/x86-iommu.h"
 #include "hw/i386/e820_memory_layout.h"
 
+#include "hw/xen/xen.h"
+
 #include "hw/pci/pci.h"
 #include "hw/pci/msi.h"
 #include "hw/pci/msix.h"
@@ -2513,6 +2517,22 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 }
 }
 
+if (s->xen_version) {
+#ifdef CONFIG_XEN_EMU
+if (!object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE)) {
+error_report("kvm: Xen support only available in PC machine");
+return -ENOTSUP;
+}
+ret = kvm_xen_init(s);
+if (ret < 0) {
+return ret;
+}
+#else
+error_report("kvm: Xen support not enabled in qemu");
+return -ENOTSUP;
+#endif
+}
+
 ret = kvm_get_supported_msrs(s);
 if (ret < 0) {
 return ret;
@@ -5703,6 +5723,36 @@ static void kvm_arch_set_notify_window(Object *obj, 
Visitor *v,
 s->notify_window = value;
 }
 
+static void kvm_arch_get_xen_version(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+KVMState *s = KVM_STATE(obj);
+uint32_t value = s->xen_version;
+
+visit_type_uint32(v, name, &value, errp);
+}
+
+static void kvm_arch_set_xen_version(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+KVMState *s = KVM_STATE(obj);
+Error *error = NULL;
+uint32_t value;
+
+visit_type_uint32(v, name, &value, &error);
+if (error) {
+error_propagate(errp, error);
+return;
+}
+
+s->xen_version = value;
+if (value && xen_mode == XEN_DISABLED) {
+xen_mode = XEN_EMULATE;
+}
+}
+
 void kvm_arch_accel_class_init(ObjectClass *oc)
 {
 object_class_property_add_enum(oc, "notify-vmexit", "NotifyVMex

[PATCH v6 20/51] i386/xen: handle VCPUOP_register_vcpu_info

2023-01-10 Thread David Woodhouse
From: Joao Martins 

Handle the hypercall to set a per vcpu info, and also wire up the default
vcpu_info in the shared_info page for the first 32 vCPUs.

To avoid deadlock within KVM a vCPU thread must set its *own* vcpu_info
rather than it being set from the context in which the hypercall is
invoked.

Add the vcpu_info (and default) GPA to the vmstate_x86_cpu for migration,
and restore it in kvm_arch_put_registers() appropriately.

Signed-off-by: Joao Martins 
Signed-off-by: David Woodhouse 
---
 target/i386/cpu.h|   2 +
 target/i386/kvm/kvm.c|  17 
 target/i386/kvm/trace-events |   1 +
 target/i386/kvm/xen-emu.c| 152 ++-
 target/i386/kvm/xen-emu.h|   2 +
 target/i386/machine.c|  19 +
 6 files changed, 190 insertions(+), 3 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index c6c57baed5..109b2e5669 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1788,6 +1788,8 @@ typedef struct CPUArchState {
 #endif
 #if defined(CONFIG_KVM)
 struct kvm_nested_state *nested_state;
+uint64_t xen_vcpu_info_gpa;
+uint64_t xen_vcpu_info_default_gpa;
 #endif
 #if defined(CONFIG_HVF)
 HVFX86LazyFlags hvf_lflags;
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 7cbfbed492..fa08cb6574 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -4734,6 +4734,15 @@ int kvm_arch_put_registers(CPUState *cpu, int level)
 kvm_arch_set_tsc_khz(cpu);
 }
 
+#ifdef CONFIG_XEN_EMU
+if (xen_mode == XEN_EMULATE && level == KVM_PUT_FULL_STATE) {
+ret = kvm_put_xen_state(cpu);
+if (ret < 0) {
+return ret;
+}
+}
+#endif
+
 ret = kvm_getput_regs(x86_cpu, 1);
 if (ret < 0) {
 return ret;
@@ -4833,6 +4842,14 @@ int kvm_arch_get_registers(CPUState *cs)
 if (ret < 0) {
 goto out;
 }
+#ifdef CONFIG_XEN_EMU
+if (xen_mode == XEN_EMULATE) {
+ret = kvm_get_xen_state(cs);
+if (ret < 0) {
+goto out;
+}
+}
+#endif
 ret = 0;
  out:
 cpu_sync_bndcs_hflags(&cpu->env);
diff --git a/target/i386/kvm/trace-events b/target/i386/kvm/trace-events
index 0a47c26e80..14e54dfca5 100644
--- a/target/i386/kvm/trace-events
+++ b/target/i386/kvm/trace-events
@@ -9,3 +9,4 @@ kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
 # xen-emu.c
 kvm_xen_hypercall(int cpu, uint8_t cpl, uint64_t input, uint64_t a0, uint64_t 
a1, uint64_t a2, uint64_t ret) "xen_hypercall: cpu %d cpl %d input %" PRIu64 " 
a0 0x%" PRIx64 " a1 0x%" PRIx64 " a2 0x%" PRIx64" ret 0x%" PRIx64
 kvm_xen_set_shared_info(uint64_t gfn) "shared info at gfn 0x%" PRIx64
+kvm_xen_set_vcpu_attr(int cpu, int type, uint64_t gpa) "vcpu attr cpu %d type 
%d gpa 0x%" PRIx64
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index e95a2aee35..dc0dbffa40 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -118,6 +118,8 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr)
 
 int kvm_xen_init_vcpu(CPUState *cs)
 {
+X86CPU *cpu = X86_CPU(cs);
+CPUX86State *env = &cpu->env;
 int err;
 
 /*
@@ -141,6 +143,9 @@ int kvm_xen_init_vcpu(CPUState *cs)
 }
 }
 
+env->xen_vcpu_info_gpa = INVALID_GPA;
+env->xen_vcpu_info_default_gpa = INVALID_GPA;
+
 return 0;
 }
 
@@ -186,10 +191,58 @@ static bool kvm_xen_hcall_xen_version(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 return true;
 }
 
+static int kvm_xen_set_vcpu_attr(CPUState *cs, uint16_t type, uint64_t gpa)
+{
+struct kvm_xen_vcpu_attr xhsi;
+
+xhsi.type = type;
+xhsi.u.gpa = gpa;
+
+trace_kvm_xen_set_vcpu_attr(cs->cpu_index, type, gpa);
+
+return kvm_vcpu_ioctl(cs, KVM_XEN_VCPU_SET_ATTR, &xhsi);
+}
+
+static void do_set_vcpu_info_default_gpa(CPUState *cs, run_on_cpu_data data)
+{
+X86CPU *cpu = X86_CPU(cs);
+CPUX86State *env = &cpu->env;
+
+env->xen_vcpu_info_default_gpa = data.host_ulong;
+
+/* Changing the default does nothing if a vcpu_info was explicitly set. */
+if (env->xen_vcpu_info_gpa == INVALID_GPA) {
+kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO,
+  env->xen_vcpu_info_default_gpa);
+}
+}
+
+static void do_set_vcpu_info_gpa(CPUState *cs, run_on_cpu_data data)
+{
+X86CPU *cpu = X86_CPU(cs);
+CPUX86State *env = &cpu->env;
+
+env->xen_vcpu_info_gpa = data.host_ulong;
+
+kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO,
+  env->xen_vcpu_info_gpa);
+}
+
+static void do_vcpu_soft_reset(CPUState *cs, run_on_cpu_data data)
+{
+X86CPU *cpu = X86_CPU(cs);
+CPUX86State *env = &cpu->env;
+
+env->xen_vcpu_info_gpa = INVALID_GPA;
+env->xen_vcpu_info_default_gpa = INVALID_GPA;
+
+kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO, INVALID_GPA);
+}
+
 static int xen_set_shared_info(uint64_t gfn)
 {
 uint64_t gpa = gfn << TARGET_PAGE_BITS;
-int err;
+

[PATCH v6 12/51] i386/xen: Implement SCHEDOP_poll and SCHEDOP_yield

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

They both do the same thing and just call sched_yield. This is enough to
stop the Linux guest panicking when running on a host kernel which doesn't
intercept SCHEDOP_poll and lets it reach userspace.

Signed-off-by: David Woodhouse 
---
 target/i386/kvm/xen-emu.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 5f2b55ef10..80005ea527 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -227,6 +227,18 @@ static bool kvm_xen_hcall_sched_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 err = schedop_shutdown(cs, arg);
 break;
 
+case SCHEDOP_poll:
+/*
+ * Linux will panic if this doesn't work. Just yield; it's not
+ * worth overthinking it because wWith event channel handling
+ * in KVM, the kernel will intercept this and it will never
+ * reach QEMU anyway.
+ */
+case SCHEDOP_yield:
+sched_yield();
+err = 0;
+break;
+
 default:
 return false;
 }
-- 
2.35.3




[PATCH v6 11/51] i386/xen: implement HYPERVISOR_sched_op, SCHEDOP_shutdown

2023-01-10 Thread David Woodhouse
From: Joao Martins 

It allows to shutdown itself via hypercall with any of the 3 reasons:
  1) self-reboot
  2) shutdown
  3) crash

Implementing SCHEDOP_shutdown sub op let us handle crashes gracefully rather
than leading to triple faults if it remains unimplemented.

In addition, the SHUTDOWN_soft_reset reason is used for kexec, to reset
Xen shared pages and other enlightenments and leave a clean slate for the
new kernel without the hypervisor helpfully writing information at
unexpected addresses.

Signed-off-by: Joao Martins 
[dwmw2: Ditch sched_op_compat which was never available for HVM guests,
Add SCHEDOP_soft_reset]
Signed-off-by: David Woodhouse 
---
 target/i386/kvm/xen-emu.c | 68 +++
 1 file changed, 68 insertions(+)

diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 1dea6feb90..5f2b55ef10 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -17,8 +17,10 @@
 #include "exec/address-spaces.h"
 #include "xen-emu.h"
 #include "trace.h"
+#include "sysemu/runstate.h"
 
 #include "standard-headers/xen/version.h"
+#include "standard-headers/xen/sched.h"
 
 static int kvm_gva_rw(CPUState *cs, uint64_t gva, void *_buf, size_t sz,
   bool is_write)
@@ -170,6 +172,69 @@ static bool kvm_xen_hcall_xen_version(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 return true;
 }
 
+static int kvm_xen_soft_reset(void)
+{
+/* Nothing to reset... yet. */
+return 0;
+}
+
+static int schedop_shutdown(CPUState *cs, uint64_t arg)
+{
+struct sched_shutdown shutdown;
+int ret = 0;
+
+/* No need for 32/64 compat handling */
+qemu_build_assert(sizeof(shutdown) == 4);
+
+if (kvm_copy_from_gva(cs, arg, &shutdown, sizeof(shutdown))) {
+return -EFAULT;
+}
+
+switch (shutdown.reason) {
+case SHUTDOWN_crash:
+cpu_dump_state(cs, stderr, CPU_DUMP_CODE);
+qemu_system_guest_panicked(NULL);
+break;
+
+case SHUTDOWN_reboot:
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+break;
+
+case SHUTDOWN_poweroff:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+break;
+
+case SHUTDOWN_soft_reset:
+ret = kvm_xen_soft_reset();
+break;
+
+default:
+ret = -EINVAL;
+break;
+}
+
+return ret;
+}
+
+static bool kvm_xen_hcall_sched_op(struct kvm_xen_exit *exit, X86CPU *cpu,
+   int cmd, uint64_t arg)
+{
+CPUState *cs = CPU(cpu);
+int err = -ENOSYS;
+
+switch (cmd) {
+case SCHEDOP_shutdown:
+err = schedop_shutdown(cs, arg);
+break;
+
+default:
+return false;
+}
+
+exit->u.hcall.result = err;
+return true;
+}
+
 static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
 {
 uint16_t code = exit->u.hcall.input;
@@ -180,6 +245,9 @@ static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct 
kvm_xen_exit *exit)
 }
 
 switch (code) {
+case __HYPERVISOR_sched_op:
+return kvm_xen_hcall_sched_op(exit, cpu, exit->u.hcall.params[0],
+  exit->u.hcall.params[1]);
 case __HYPERVISOR_xen_version:
 return kvm_xen_hcall_xen_version(exit, cpu, exit->u.hcall.params[0],
  exit->u.hcall.params[1]);
-- 
2.35.3




[PATCH v6 36/51] hw/xen: Implement EVTCHNOP_bind_vcpu

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c  | 40 +++
 hw/i386/kvm/xen_evtchn.h  |  2 ++
 target/i386/kvm/xen-emu.c | 12 
 3 files changed, 54 insertions(+)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 511d52a31d..ad75cddc5e 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -782,6 +782,46 @@ int xen_evtchn_unmask_op(struct evtchn_unmask *unmask)
 return ret;
 }
 
+int xen_evtchn_bind_vcpu_op(struct evtchn_bind_vcpu *vcpu)
+{
+XenEvtchnState *s = xen_evtchn_singleton;
+XenEvtchnPort *p;
+int ret = -EINVAL;
+
+if (!s) {
+return -ENOTSUP;
+}
+
+if (!valid_port(vcpu->port)) {
+return -EINVAL;
+}
+
+if (!valid_vcpu(vcpu->vcpu)) {
+return -ENOENT;
+}
+
+qemu_mutex_lock(&s->port_lock);
+
+p = &s->port_table[vcpu->port];
+
+if (p->type == EVTCHNSTAT_interdomain ||
+p->type == EVTCHNSTAT_unbound ||
+p->type == EVTCHNSTAT_pirq ||
+(p->type == EVTCHNSTAT_virq && virq_is_global(p->type_val))) {
+/*
+ * unmask_port() with do_unmask==false will just raise the event
+ * on the new vCPU if the port was already pending.
+ */
+p->vcpu = vcpu->vcpu;
+unmask_port(s, vcpu->port, false);
+ret = 0;
+}
+
+qemu_mutex_unlock(&s->port_lock);
+
+return ret;
+}
+
 int xen_evtchn_bind_virq_op(struct evtchn_bind_virq *virq)
 {
 XenEvtchnState *s = xen_evtchn_singleton;
diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h
index 1ebc7580eb..486b031c82 100644
--- a/hw/i386/kvm/xen_evtchn.h
+++ b/hw/i386/kvm/xen_evtchn.h
@@ -23,6 +23,7 @@ struct evtchn_bind_ipi;
 struct evtchn_send;
 struct evtchn_alloc_unbound;
 struct evtchn_bind_interdomain;
+struct evtchn_bind_vcpu;
 int xen_evtchn_status_op(struct evtchn_status *status);
 int xen_evtchn_close_op(struct evtchn_close *close);
 int xen_evtchn_unmask_op(struct evtchn_unmask *unmask);
@@ -31,5 +32,6 @@ int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi);
 int xen_evtchn_send_op(struct evtchn_send *send);
 int xen_evtchn_alloc_unbound_op(struct evtchn_alloc_unbound *alloc);
 int xen_evtchn_bind_interdomain_op(struct evtchn_bind_interdomain 
*interdomain);
+int xen_evtchn_bind_vcpu_op(struct evtchn_bind_vcpu *vcpu);
 
 #endif /* QEMU_XEN_EVTCHN_H */
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 2471a4f703..afc6d28357 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -938,6 +938,18 @@ static bool kvm_xen_hcall_evtchn_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 }
 break;
 }
+case EVTCHNOP_bind_vcpu: {
+struct evtchn_bind_vcpu vcpu;
+
+qemu_build_assert(sizeof(vcpu) == 8);
+if (kvm_copy_from_gva(cs, arg, &vcpu, sizeof(vcpu))) {
+err = -EFAULT;
+break;
+}
+
+err = xen_evtchn_bind_vcpu_op(&vcpu);
+break;
+}
 default:
 return false;
 }
-- 
2.35.3




[PATCH v6 44/51] i386/xen: Implement HYPERVISOR_grant_table_op and GNTTABOP_[gs]et_verson

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_gnttab.c  | 31 
 hw/i386/kvm/xen_gnttab.h  |  5 
 target/i386/kvm/xen-emu.c | 60 +++
 3 files changed, 96 insertions(+)

diff --git a/hw/i386/kvm/xen_gnttab.c b/hw/i386/kvm/xen_gnttab.c
index 311f48bfdb..cdcfea5be3 100644
--- a/hw/i386/kvm/xen_gnttab.c
+++ b/hw/i386/kvm/xen_gnttab.c
@@ -186,3 +186,34 @@ int xen_gnttab_map_page(uint64_t idx, uint64_t gfn)
 return 0;
 }
 
+int xen_gnttab_set_version_op(struct gnttab_set_version *set)
+{
+int ret;
+
+switch (set->version) {
+case 1:
+ret = 0;
+break;
+
+case 2:
+/* Behave as before set_version was introduced. */
+ret = -ENOSYS;
+break;
+
+default:
+ret = -EINVAL;
+}
+
+set->version = 1;
+return ret;
+}
+
+int xen_gnttab_get_version_op(struct gnttab_get_version *get)
+{
+if (get->dom != DOMID_SELF && get->dom != xen_domid) {
+return -ESRCH;
+}
+
+get->version = 1;
+return 0;
+}
diff --git a/hw/i386/kvm/xen_gnttab.h b/hw/i386/kvm/xen_gnttab.h
index a7caa94c83..79579677ba 100644
--- a/hw/i386/kvm/xen_gnttab.h
+++ b/hw/i386/kvm/xen_gnttab.h
@@ -15,4 +15,9 @@
 void xen_gnttab_create(void);
 int xen_gnttab_map_page(uint64_t idx, uint64_t gfn);
 
+struct gnttab_set_version;
+struct gnttab_get_version;
+int xen_gnttab_set_version_op(struct gnttab_set_version *set);
+int xen_gnttab_get_version_op(struct gnttab_get_version *get);
+
 #endif /* QEMU_XEN_GNTTAB_H */
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 6570c65ea6..8895f91d8b 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -33,6 +33,7 @@
 #include "standard-headers/xen/hvm/params.h"
 #include "standard-headers/xen/vcpu.h"
 #include "standard-headers/xen/event_channel.h"
+#include "standard-headers/xen/grant_table.h"
 
 #include "xen-compat.h"
 
@@ -1124,6 +1125,61 @@ static bool kvm_xen_hcall_sched_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 return true;
 }
 
+static bool kvm_xen_hcall_gnttab_op(struct kvm_xen_exit *exit, X86CPU *cpu,
+int cmd, uint64_t arg, int count)
+{
+CPUState *cs = CPU(cpu);
+int err;
+
+switch (cmd) {
+case GNTTABOP_set_version: {
+struct gnttab_set_version set;
+
+qemu_build_assert(sizeof(set) == 4);
+if (kvm_copy_from_gva(cs, arg, &set, sizeof(set))) {
+err = -EFAULT;
+break;
+}
+
+err = xen_gnttab_set_version_op(&set);
+if (!err && kvm_copy_to_gva(cs, arg, &set, sizeof(set))) {
+err = -EFAULT;
+}
+break;
+}
+case GNTTABOP_get_version: {
+struct gnttab_get_version get;
+
+qemu_build_assert(sizeof(get) == 8);
+if (kvm_copy_from_gva(cs, arg, &get, sizeof(get))) {
+err = -EFAULT;
+break;
+}
+
+err = xen_gnttab_get_version_op(&get);
+if (!err && kvm_copy_to_gva(cs, arg, &get, sizeof(get))) {
+err = -EFAULT;
+}
+break;
+}
+case GNTTABOP_query_size:
+case GNTTABOP_setup_table:
+case GNTTABOP_copy:
+case GNTTABOP_map_grant_ref:
+case GNTTABOP_unmap_grant_ref:
+case GNTTABOP_swap_grant_ref:
+return false;
+
+default:
+/* Xen explicitly returns -ENOSYS to HVM guests for all others */
+err = -ENOSYS;
+break;
+}
+
+exit->u.hcall.result = err;
+return true;
+}
+
 static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
 {
 uint16_t code = exit->u.hcall.input;
@@ -1134,6 +1190,10 @@ static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct 
kvm_xen_exit *exit)
 }
 
 switch (code) {
+case __HYPERVISOR_grant_table_op:
+return kvm_xen_hcall_gnttab_op(exit, cpu, exit->u.hcall.params[0],
+   exit->u.hcall.params[1],
+   exit->u.hcall.params[2]);
 case __HYPERVISOR_sched_op:
 return kvm_xen_hcall_sched_op(exit, cpu, exit->u.hcall.params[0],
   exit->u.hcall.params[1]);
-- 
2.35.3




[PATCH v6 49/51] hw/xen: Add backend implementation of interdomain event channel support

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

The provides the QEMU side of interdomain event channels, allowing events
to be sent to/from the guest.

The API mirrors libxenevtchn, and in time both this and the real Xen one
will be available through ops structures so that the PV backend drivers
can use the correct one as appropriate.

For now, this implementation can be used directly by our XenStore which
will be for emulated mode only.

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c | 340 ++-
 hw/i386/kvm/xen_evtchn.h |  19 +++
 2 files changed, 352 insertions(+), 7 deletions(-)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 9b9a10fa43..39ad3eec77 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -37,6 +37,7 @@
 #include "sysemu/kvm.h"
 #include "sysemu/kvm_xen.h"
 #include 
+#include 
 
 #include "standard-headers/xen/memory.h"
 #include "standard-headers/xen/hvm/params.h"
@@ -87,6 +88,13 @@ struct compat_shared_info {
 
 #define COMPAT_EVTCHN_2L_NR_CHANNELS1024
 
+/* Local private implementation of struct xenevtchn_handle */
+struct xenevtchn_handle {
+evtchn_port_t be_port;
+evtchn_port_t guest_port; /* Or zero for unbound */
+int fd;
+};
+
 /*
  * For unbound/interdomain ports there are only two possible remote
  * domains; self and QEMU. Use a single high bit in type_val for that,
@@ -108,6 +116,8 @@ struct XenEvtchnState {
 uint32_t nr_ports;
 XenEvtchnPort port_table[EVTCHN_2L_NR_CHANNELS];
 qemu_irq gsis[GSI_NUM_PINS];
+
+struct xenevtchn_handle *be_handles[EVTCHN_2L_NR_CHANNELS];
 };
 
 struct XenEvtchnState *xen_evtchn_singleton;
@@ -115,6 +125,18 @@ struct XenEvtchnState *xen_evtchn_singleton;
 /* Top bits of callback_param are the type (HVM_PARAM_CALLBACK_TYPE_xxx) */
 #define CALLBACK_VIA_TYPE_SHIFT 56
 
+static void unbind_backend_ports(XenEvtchnState *s);
+
+static int xen_evtchn_pre_load(void *opaque)
+{
+XenEvtchnState *s = opaque;
+
+/* Unbind all the backend-side ports; they need to rebind */
+unbind_backend_ports(s);
+
+return 0;
+}
+
 static int xen_evtchn_post_load(void *opaque, int version_id)
 {
 XenEvtchnState *s = opaque;
@@ -148,6 +170,7 @@ static const VMStateDescription xen_evtchn_vmstate = {
 .version_id = 1,
 .minimum_version_id = 1,
 .needed = xen_evtchn_is_needed,
+.pre_load = xen_evtchn_pre_load,
 .post_load = xen_evtchn_post_load,
 .fields = (VMStateField[]) {
 VMSTATE_UINT64(callback_param, XenEvtchnState),
@@ -362,6 +385,20 @@ static int assign_kernel_port(uint16_t type, evtchn_port_t 
port,
 return kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &ha);
 }
 
+static int assign_kernel_eventfd(uint16_t type, evtchn_port_t port, int fd)
+{
+struct kvm_xen_hvm_attr ha;
+
+ha.type = KVM_XEN_ATTR_TYPE_EVTCHN;
+ha.u.evtchn.send_port = port;
+ha.u.evtchn.type = type;
+ha.u.evtchn.flags = 0;
+ha.u.evtchn.deliver.eventfd.port = 0;
+ha.u.evtchn.deliver.eventfd.fd = fd;
+
+return kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &ha);
+}
+
 static bool valid_port(evtchn_port_t port)
 {
 if (!port) {
@@ -380,6 +417,32 @@ static bool valid_vcpu(uint32_t vcpu)
 return !!qemu_get_cpu(vcpu);
 }
 
+static void unbind_backend_ports(XenEvtchnState *s)
+{
+XenEvtchnPort *p;
+int i;
+
+for (i = 1; i < s->nr_ports; i++) {
+p = &s->port_table[i];
+if (p->type == EVTCHNSTAT_interdomain &&
+(p->type_val & PORT_INFO_TYPEVAL_REMOTE_QEMU) ) {
+evtchn_port_t be_port = p->type_val & 
PORT_INFO_TYPEVAL_REMOTE_PORT_MASK;
+
+if (s->be_handles[be_port]) {
+/* This part will be overwritten on the load anyway. */
+p->type = EVTCHNSTAT_unbound;
+p->type_val = PORT_INFO_TYPEVAL_REMOTE_QEMU;
+
+/* Leave the backend port open and unbound too. */
+if (kvm_xen_has_cap(EVTCHN_SEND)) {
+deassign_kernel_port(i);
+}
+s->be_handles[be_port]->guest_port = 0;
+}
+}
+}
+}
+
 int xen_evtchn_status_op(struct evtchn_status *status)
 {
 XenEvtchnState *s = xen_evtchn_singleton;
@@ -815,7 +878,14 @@ static int close_port(XenEvtchnState *s, evtchn_port_t 
port)
 
 case EVTCHNSTAT_interdomain:
 if (p->type_val & PORT_INFO_TYPEVAL_REMOTE_QEMU) {
-/* Not yet implemented. This can't happen! */
+uint16_t be_port = p->type_val & ~PORT_INFO_TYPEVAL_REMOTE_QEMU;
+struct xenevtchn_handle *xc = s->be_handles[be_port];
+if (xc) {
+if (kvm_xen_has_cap(EVTCHN_SEND)) {
+deassign_kernel_port(port);
+}
+xc->guest_port = 0;
+}
 } else {
 /* Loopback interdomain */
 XenEvtchnPort *rp = &s->port_table[p->type_val];
@@ -1047,8 +1117,27 @@ int xen_evtchn_b

[RFC PATCH v1 09/15] hw/xen: Rename xen_common.h to xen_native.h

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

This header is now only for native Xen code, not PV backends that may be
used in Xen emulation. Since the toolstack libraries may depend on the
specific version of Xen headers that they pull in (and will set the
__XEN_TOOLS__ macro to enable internal definitions that they depend on),
the rule is that xen_native.h (and thus the toolstack library headers)
must be included *before* any of the headers in standard-headers/xen.

Signed-off-by: David Woodhouse 
---
 accel/xen/xen-all.c   |  1 +
 hw/9pfs/xen-9p-backend.c  |  1 +
 hw/block/dataplane/xen-block.c|  3 ++-
 hw/block/xen-block.c  |  1 -
 hw/i386/xen/xen-hvm.c |  6 ++---
 hw/i386/xen/xen-mapcache.c|  2 +-
 hw/i386/xen/xen_platform.c|  7 +++---
 hw/xen/trace-events   |  2 +-
 hw/xen/xen-operations.c   |  2 +-
 hw/xen/xen_pt.c   |  2 +-
 hw/xen/xen_pt.h   |  2 +-
 hw/xen/xen_pt_config_init.c   |  2 +-
 hw/xen/xen_pt_msi.c   |  4 ++--
 include/hw/xen/xen.h  | 22 ---
 include/hw/xen/{xen_common.h => xen_native.h} | 10 ++---
 include/hw/xen/xen_pvdev.h|  3 ++-
 16 files changed, 42 insertions(+), 28 deletions(-)
 rename include/hw/xen/{xen_common.h => xen_native.h} (98%)

diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c
index 514bc9eea4..fcdc8364bf 100644
--- a/accel/xen/xen-all.c
+++ b/accel/xen/xen-all.c
@@ -12,6 +12,7 @@
 #include "qemu/error-report.h"
 #include "qemu/module.h"
 #include "qapi/error.h"
+#include "hw/xen/xen_native.h"
 #include "hw/xen/xen-legacy-backend.h"
 #include "hw/xen/xen_pt.h"
 #include "chardev/char.h"
diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index d8bb0e847c..74f3a05f88 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -22,6 +22,7 @@
 #include "qemu/config-file.h"
 #include "qemu/main-loop.h"
 #include "qemu/option.h"
+#include "qemu/iov.h"
 #include "fsdev/qemu-fsdev.h"
 
 #define VERSIONS "1"
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
index 8322a1de82..d44e39e2a1 100644
--- a/hw/block/dataplane/xen-block.c
+++ b/hw/block/dataplane/xen-block.c
@@ -23,8 +23,9 @@
 #include "qemu/main-loop.h"
 #include "qemu/memalign.h"
 #include "qapi/error.h"
-#include "hw/xen/xen_common.h"
 #include "hw/block/xen_blkif.h"
+#include "hw/xen/xen.h"
+#include "hw/xen/interface/io/ring.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/iothread.h"
 #include "xen-block.h"
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index 345b284d70..87299615e3 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -19,7 +19,6 @@
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qstring.h"
 #include "qom/object_interfaces.h"
-#include "hw/xen/xen_common.h"
 #include "hw/block/xen_blkif.h"
 #include "hw/qdev-properties.h"
 #include "hw/xen/xen-block.h"
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 38146efb5a..779d923e10 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -18,8 +18,8 @@
 #include "hw/irq.h"
 #include "hw/hw.h"
 #include "hw/i386/apic-msidef.h"
+#include "hw/xen/xen_native.h"
 #include "hw/xen/xen_backend_ops.h"
-#include "hw/xen/xen_common.h"
 #include "hw/xen/xen-legacy-backend.h"
 #include "hw/xen/xen-bus.h"
 #include "hw/xen/xen-x86.h"
@@ -54,8 +54,8 @@ static bool xen_in_migration;
 /* Compatibility with older version */
 
 /* This allows QEMU to build on a system that has Xen 4.5 or earlier
- * installed.  This here (not in hw/xen/xen_common.h) because xen/hvm/ioreq.h
- * needs to be included before this block and hw/xen/xen_common.h needs to
+ * installed.  This here (not in hw/xen/xen_native.h) because xen/hvm/ioreq.h
+ * needs to be included before this block and hw/xen/xen_native.h needs to
  * be included before xen/hvm/ioreq.h
  */
 #ifndef IOREQ_TYPE_VMWARE_PORT
diff --git a/hw/i386/xen/xen-mapcache.c b/hw/i386/xen/xen-mapcache.c
index a2f93096e7..30cea6ee42 100644
--- a/hw/i386/xen/xen-mapcache.c
+++ b/hw/i386/xen/xen-mapcache.c
@@ -14,7 +14,7 @@
 
 #include 
 
-#include "hw/xen/xen-legacy-backend.h"
+#include "hw/xen/xen_native.h"
 #include "qemu/bitmap.h"
 
 #include "sysemu/runstate.h"
diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
index 00f0527b30..a5fb1c96d0 100644
--- a/hw/i386/xen/xen_platform.c
+++ b/hw/i386/xen/xen_platform.c
@@ -29,7 +29,6 @@
 #include "hw/ide/pci.h"
 #include "hw/pci/pci.h"
 #include "migration/vmstate.h"
-#include "hw/xen/xen.h"
 #include "net/net.h"
 #include "trace.h"
 #include "sysemu/xen.h"
@@ -39,10 +38,12 @@
 #include "qom/object.h"
 
 #ifdef CONFIG_XEN
-#include "hw/xen/xen_common.h"
-#include "hw/xen/xen-legacy-backend.h"
+#include "hw/xen/xen_native.h"
 #endif
 
+/* The r

[PATCH v6 40/51] hw/xen: Support HVM_PARAM_CALLBACK_TYPE_PCI_INTX callback

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

The guest is permitted to specify an arbitrary domain/bus/device/function
and INTX pin from which the callback IRQ shall appear to have come.

In QEMU we can only easily do this for devices that actually exist, and
even that requires us "knowing" that it's a PCMachine in order to find
the PCI root bus — although that's OK really because it's always true.

We also don't get to get notified of INTX routing changes, because we
can't do that as a passive observer; if we try to register a notifier
it will overwrite any existing notifier callback on the device.

But in practice, guests using PCI_INTX will only ever use pin A on the
Xen platform device, and won't swizzle the INTX routing after they set
it up. So this is just fine.

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c  | 73 +--
 target/i386/kvm/xen-emu.c | 32 +
 2 files changed, 94 insertions(+), 11 deletions(-)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 0f3492710b..c82fac69a2 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -27,6 +27,8 @@
 #include "hw/sysbus.h"
 #include "hw/xen/xen.h"
 #include "hw/i386/x86.h"
+#include "hw/i386/pc.h"
+#include "hw/pci/pci.h"
 #include "hw/irq.h"
 
 #include "xen_evtchn.h"
@@ -100,6 +102,7 @@ struct XenEvtchnState {
 
 uint64_t callback_param;
 bool evtchn_in_kernel;
+uint32_t callback_gsi;
 
 QemuMutex port_lock;
 uint32_t nr_ports;
@@ -205,20 +208,44 @@ static void xen_evtchn_register_types(void)
 
 type_init(xen_evtchn_register_types)
 
+static int set_callback_pci_intx(XenEvtchnState *s, uint64_t param)
+{
+PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+uint8_t pin = param & 3;
+uint8_t devfn = (param >> 8) & 0xff;
+uint16_t bus = (param >> 16) & 0x;
+uint16_t domain = (param >> 32) & 0x;
+PCIDevice *pdev;
+PCIINTxRoute r;
+
+if (domain || !pcms) {
+return 0;
+}
+
+pdev = pci_find_device(pcms->bus, bus, devfn);
+if (!pdev) {
+return 0;
+}
+
+r = pci_device_route_intx_to_irq(pdev, pin);
+if (r.mode != PCI_INTX_ENABLED) {
+return 0;
+}
+
+/*
+ * Hm, can we be notified of INTX routing changes? Not without
+ * *owning* the device and being allowed to overwrite its own
+ * ->intx_routing_notifier, AFAICT. So let's not.
+ */
+return r.irq;
+}
+
 void xen_evtchn_set_callback_level(int level)
 {
 XenEvtchnState *s = xen_evtchn_singleton;
 
-if (s) {
-uint32_t param = (uint32_t)s->callback_param;
-
-switch (s->callback_param >> CALLBACK_VIA_TYPE_SHIFT) {
-case HVM_PARAM_CALLBACK_TYPE_GSI:
-if (param < GSI_NUM_PINS) {
-qemu_set_irq(s->gsis[param], level);
-}
-break;
-}
+if (s && s->callback_gsi && s->callback_gsi < GSI_NUM_PINS) {
+qemu_set_irq(s->gsis[s->callback_gsi], level);
 }
 }
 
@@ -226,6 +253,8 @@ int xen_evtchn_set_callback_param(uint64_t param)
 {
 XenEvtchnState *s = xen_evtchn_singleton;
 bool in_kernel = false;
+uint32_t gsi = 0;
+int type = param >> CALLBACK_VIA_TYPE_SHIFT;
 int ret;
 
 if (!s) {
@@ -234,7 +263,7 @@ int xen_evtchn_set_callback_param(uint64_t param)
 
 qemu_mutex_lock(&s->port_lock);
 
-switch (param >> CALLBACK_VIA_TYPE_SHIFT) {
+switch (type) {
 case HVM_PARAM_CALLBACK_TYPE_VECTOR: {
 struct kvm_xen_hvm_attr xa = {
 .type = KVM_XEN_ATTR_TYPE_UPCALL_VECTOR,
@@ -245,10 +274,17 @@ int xen_evtchn_set_callback_param(uint64_t param)
 if (!ret && kvm_xen_has_cap(EVTCHN_SEND)) {
 in_kernel = true;
 }
+gsi = 0;
 break;
 }
 
+case HVM_PARAM_CALLBACK_TYPE_PCI_INTX:
+gsi = set_callback_pci_intx(s, param);
+ret = gsi ? 0 : -EINVAL;
+break;
+
 case HVM_PARAM_CALLBACK_TYPE_GSI:
+gsi = (uint32_t)param;
 ret = 0;
 break;
 
@@ -260,6 +296,21 @@ int xen_evtchn_set_callback_param(uint64_t param)
 if (!ret) {
 s->callback_param = param;
 s->evtchn_in_kernel = in_kernel;
+
+if (gsi != s->callback_gsi) {
+struct vcpu_info *vi = kvm_xen_get_vcpu_info_hva(0);
+
+xen_evtchn_set_callback_level(0);
+s->callback_gsi = gsi;
+
+if (gsi && vi && vi->evtchn_upcall_pending) {
+/*
+ * The vCPU code needs to do it because it needs to set the
+ * flag in the right order to avoid races with clearing.
+ */
+kvm_xen_inject_vcpu_callback_vector(0, type);
+}
+}
 }
 
 qemu_mutex_unlock(&s->port_lock);
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 8a9c3cc828..677e9cac56 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -130,6 +130,38 @@ int kvm_xen_init(K

[RFC PATCH v1 08/15] hw/xen: Use XEN_PAGE_SIZE in PV backend drivers

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

XC_PAGE_SIZE comes from the actual Xen libraries, while XEN_PAGE_SIZE is
provided by QEMU itself in xen_backend_ops.h. For backends which may be
built for emulation mode, use the latter.

Signed-off-by: David Woodhouse 
---
 hw/block/dataplane/xen-block.c |  8 
 hw/display/xenfb.c | 12 ++--
 hw/net/xen_nic.c   | 12 ++--
 hw/usb/xen-usb.c   |  8 
 4 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
index e55b713002..8322a1de82 100644
--- a/hw/block/dataplane/xen-block.c
+++ b/hw/block/dataplane/xen-block.c
@@ -101,9 +101,9 @@ static XenBlockRequest 
*xen_block_start_request(XenBlockDataPlane *dataplane)
  * re-use requests, allocate the memory once here. It will be freed
  * xen_block_dataplane_destroy() when the request list is freed.
  */
-request->buf = qemu_memalign(XC_PAGE_SIZE,
+request->buf = qemu_memalign(XEN_PAGE_SIZE,
  BLKIF_MAX_SEGMENTS_PER_REQUEST *
- XC_PAGE_SIZE);
+ XEN_PAGE_SIZE);
 dataplane->requests_total++;
 qemu_iovec_init(&request->v, 1);
 } else {
@@ -185,7 +185,7 @@ static int xen_block_parse_request(XenBlockRequest *request)
 goto err;
 }
 if (request->req.seg[i].last_sect * dataplane->sector_size >=
-XC_PAGE_SIZE) {
+XEN_PAGE_SIZE) {
 error_report("error: page crossing");
 goto err;
 }
@@ -740,7 +740,7 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane,
 
 dataplane->protocol = protocol;
 
-ring_size = XC_PAGE_SIZE * dataplane->nr_ring_ref;
+ring_size = XEN_PAGE_SIZE * dataplane->nr_ring_ref;
 switch (dataplane->protocol) {
 case BLKIF_PROTOCOL_NATIVE:
 {
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 2c4016fcbd..0074a9b6f8 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -489,13 +489,13 @@ static int xenfb_map_fb(struct XenFB *xenfb)
 }
 
 if (xenfb->pixels) {
-munmap(xenfb->pixels, xenfb->fbpages * XC_PAGE_SIZE);
+munmap(xenfb->pixels, xenfb->fbpages * XEN_PAGE_SIZE);
 xenfb->pixels = NULL;
 }
 
-xenfb->fbpages = DIV_ROUND_UP(xenfb->fb_len, XC_PAGE_SIZE);
+xenfb->fbpages = DIV_ROUND_UP(xenfb->fb_len, XEN_PAGE_SIZE);
 n_fbdirs = xenfb->fbpages * mode / 8;
-n_fbdirs = DIV_ROUND_UP(n_fbdirs, XC_PAGE_SIZE);
+n_fbdirs = DIV_ROUND_UP(n_fbdirs, XEN_PAGE_SIZE);
 
 pgmfns = g_new0(xen_pfn_t, n_fbdirs);
 fbmfns = g_new0(xen_pfn_t, xenfb->fbpages);
@@ -528,8 +528,8 @@ static int xenfb_configure_fb(struct XenFB *xenfb, size_t 
fb_len_lim,
 {
 size_t mfn_sz = sizeof_field(struct xenfb_page, pd[0]);
 size_t pd_len = sizeof_field(struct xenfb_page, pd) / mfn_sz;
-size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;
-size_t fb_len_max = fb_pages * XC_PAGE_SIZE;
+size_t fb_pages = pd_len * XEN_PAGE_SIZE / mfn_sz;
+size_t fb_len_max = fb_pages * XEN_PAGE_SIZE;
 int max_width, max_height;
 
 if (fb_len_lim > fb_len_max) {
@@ -930,7 +930,7 @@ static void fb_disconnect(struct XenLegacyDevice *xendev)
  *   instead.  This releases the guest pages and keeps qemu happy.
  */
 qemu_xen_foreignmem_unmap(fb->pixels, fb->fbpages);
-fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE,
+fb->pixels = mmap(fb->pixels, fb->fbpages * XEN_PAGE_SIZE,
   PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON,
   -1, 0);
 if (fb->pixels == MAP_FAILED) {
diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c
index 166d03787d..9bbf6599fc 100644
--- a/hw/net/xen_nic.c
+++ b/hw/net/xen_nic.c
@@ -145,7 +145,7 @@ static void net_tx_packets(struct XenNetDev *netdev)
 continue;
 }
 
-if ((txreq.offset + txreq.size) > XC_PAGE_SIZE) {
+if ((txreq.offset + txreq.size) > XEN_PAGE_SIZE) {
 xen_pv_printf(&netdev->xendev, 0, "error: page crossing\n");
 net_tx_error(netdev, &txreq, rc);
 continue;
@@ -171,7 +171,7 @@ static void net_tx_packets(struct XenNetDev *netdev)
 if (txreq.flags & NETTXF_csum_blank) {
 /* have read-only mapping -> can't fill checksum in-place */
 if (!tmpbuf) {
-tmpbuf = g_malloc(XC_PAGE_SIZE);
+tmpbuf = g_malloc(XEN_PAGE_SIZE);
 }
 memcpy(tmpbuf, page + txreq.offset, txreq.size);
 net_checksum_calculate(tmpbuf, txreq.size, CSUM_ALL);
@@ -243,9 +243,9 @@ static ssize_t net_rx_packet(NetClientState *nc, const 
uint8_t *buf, size_t size
 if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {
 return 0;
 }
-if (size > XC_PAGE_SIZE - NET_I

[PATCH v6 23/51] i386/xen: implement HYPERVISOR_event_channel_op

2023-01-10 Thread David Woodhouse
From: Joao Martins 

Additionally set XEN_INTERFACE_VERSION to most recent in order to
exercise the "new" event_channel_op.

Signed-off-by: Joao Martins 
[dwmw2: Ditch event_channel_op_compat which was never available to HVM guests]
Signed-off-by: David Woodhouse 
---
 target/i386/kvm/xen-emu.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 7803e4a7a7..ff093328d7 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -27,6 +27,7 @@
 #include "standard-headers/xen/memory.h"
 #include "standard-headers/xen/hvm/hvm_op.h"
 #include "standard-headers/xen/vcpu.h"
+#include "standard-headers/xen/event_channel.h"
 
 #include "xen-compat.h"
 
@@ -585,6 +586,24 @@ static bool kvm_xen_hcall_vcpu_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 return true;
 }
 
+static bool kvm_xen_hcall_evtchn_op(struct kvm_xen_exit *exit,
+int cmd, uint64_t arg)
+{
+int err = -ENOSYS;
+
+switch (cmd) {
+case EVTCHNOP_init_control:
+err = -ENOSYS;
+break;
+
+default:
+return false;
+}
+
+exit->u.hcall.result = err;
+return true;
+}
+
 static int kvm_xen_soft_reset(void)
 {
 CPUState *cpu;
@@ -684,6 +703,9 @@ static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct 
kvm_xen_exit *exit)
 case __HYPERVISOR_sched_op:
 return kvm_xen_hcall_sched_op(exit, cpu, exit->u.hcall.params[0],
   exit->u.hcall.params[1]);
+case __HYPERVISOR_event_channel_op:
+return kvm_xen_hcall_evtchn_op(exit, exit->u.hcall.params[0],
+   exit->u.hcall.params[1]);
 case __HYPERVISOR_vcpu_op:
 return kvm_xen_hcall_vcpu_op(exit, cpu,
  exit->u.hcall.params[0],
-- 
2.35.3




[PATCH v6 26/51] hw/xen: Add xen_evtchn device for event channel emulation

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Include basic support for setting HVM_PARAM_CALLBACK_IRQ to the global
vector method HVM_PARAM_CALLBACK_TYPE_VECTOR, which is handled in-kernel
by raising the vector whenever the vCPU's vcpu_info->evtchn_upcall_pending
flag is set.

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/meson.build   |   5 +-
 hw/i386/kvm/xen_evtchn.c  | 148 ++
 hw/i386/kvm/xen_evtchn.h  |  18 +
 hw/i386/pc.c  |   2 +
 target/i386/kvm/xen-emu.c |  10 +++
 5 files changed, 182 insertions(+), 1 deletion(-)
 create mode 100644 hw/i386/kvm/xen_evtchn.c
 create mode 100644 hw/i386/kvm/xen_evtchn.h

diff --git a/hw/i386/kvm/meson.build b/hw/i386/kvm/meson.build
index 6165cbf019..cab64df339 100644
--- a/hw/i386/kvm/meson.build
+++ b/hw/i386/kvm/meson.build
@@ -4,6 +4,9 @@ i386_kvm_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c'))
 i386_kvm_ss.add(when: 'CONFIG_I8254', if_true: files('i8254.c'))
 i386_kvm_ss.add(when: 'CONFIG_I8259', if_true: files('i8259.c'))
 i386_kvm_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic.c'))
-i386_kvm_ss.add(when: 'CONFIG_XEN_EMU', if_true: files('xen_overlay.c'))
+i386_kvm_ss.add(when: 'CONFIG_XEN_EMU', if_true: files(
+  'xen_overlay.c',
+  'xen_evtchn.c',
+  ))
 
 i386_ss.add_all(when: 'CONFIG_KVM', if_true: i386_kvm_ss)
diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
new file mode 100644
index 00..018f4ef4da
--- /dev/null
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -0,0 +1,148 @@
+/*
+ * QEMU Xen emulation: Event channel support
+ *
+ * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Authors: David Woodhouse 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
+#include "qemu/module.h"
+#include "qemu/main-loop.h"
+#include "qapi/error.h"
+#include "qom/object.h"
+#include "exec/target_page.h"
+#include "exec/address-spaces.h"
+#include "migration/vmstate.h"
+
+#include "hw/sysbus.h"
+#include "hw/xen/xen.h"
+#include "xen_evtchn.h"
+
+#include "sysemu/kvm.h"
+#include "sysemu/kvm_xen.h"
+#include 
+
+#include "standard-headers/xen/memory.h"
+#include "standard-headers/xen/hvm/params.h"
+
+#define TYPE_XEN_EVTCHN "xen-evtchn"
+OBJECT_DECLARE_SIMPLE_TYPE(XenEvtchnState, XEN_EVTCHN)
+
+struct XenEvtchnState {
+/*< private >*/
+SysBusDevice busdev;
+/*< public >*/
+
+uint64_t callback_param;
+bool evtchn_in_kernel;
+
+QemuMutex port_lock;
+};
+
+struct XenEvtchnState *xen_evtchn_singleton;
+
+/* Top bits of callback_param are the type (HVM_PARAM_CALLBACK_TYPE_xxx) */
+#define CALLBACK_VIA_TYPE_SHIFT 56
+
+static int xen_evtchn_post_load(void *opaque, int version_id)
+{
+XenEvtchnState *s = opaque;
+
+if (s->callback_param) {
+xen_evtchn_set_callback_param(s->callback_param);
+}
+
+return 0;
+}
+
+static bool xen_evtchn_is_needed(void *opaque)
+{
+return xen_mode == XEN_EMULATE;
+}
+
+static const VMStateDescription xen_evtchn_vmstate = {
+.name = "xen_evtchn",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = xen_evtchn_is_needed,
+.post_load = xen_evtchn_post_load,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64(callback_param, XenEvtchnState),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void xen_evtchn_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->vmsd = &xen_evtchn_vmstate;
+}
+
+static const TypeInfo xen_evtchn_info = {
+.name  = TYPE_XEN_EVTCHN,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XenEvtchnState),
+.class_init= xen_evtchn_class_init,
+};
+
+void xen_evtchn_create(void)
+{
+XenEvtchnState *s = XEN_EVTCHN(sysbus_create_simple(TYPE_XEN_EVTCHN,
+-1, NULL));
+xen_evtchn_singleton = s;
+
+qemu_mutex_init(&s->port_lock);
+}
+
+static void xen_evtchn_register_types(void)
+{
+type_register_static(&xen_evtchn_info);
+}
+
+type_init(xen_evtchn_register_types)
+
+int xen_evtchn_set_callback_param(uint64_t param)
+{
+XenEvtchnState *s = xen_evtchn_singleton;
+bool in_kernel = false;
+int ret;
+
+if (!s) {
+return -ENOTSUP;
+}
+
+qemu_mutex_lock(&s->port_lock);
+
+switch (param >> CALLBACK_VIA_TYPE_SHIFT) {
+case HVM_PARAM_CALLBACK_TYPE_VECTOR: {
+struct kvm_xen_hvm_attr xa = {
+.type = KVM_XEN_ATTR_TYPE_UPCALL_VECTOR,
+.u.vector = (uint8_t)param,
+};
+
+ret = kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &xa);
+if (!ret && kvm_xen_has_cap(EVTCHN_SEND)) {
+in_kernel = true;
+}
+break;
+}
+default:
+ret = -ENOSYS;
+break;
+}
+
+if (!ret) {
+s->callback_param = param;
+s->evtchn_in_kernel = in_kernel;

[RFC PATCH v1 06/15] hw/xen: Add xenstore operations to allow redirection to internal emulation

2023-01-10 Thread David Woodhouse
From: Paul Durrant 

Signed-off-by: Paul Durrant 
Signed-off-by: David Woodhouse 
---
 accel/xen/xen-all.c |  11 +-
 hw/char/xen_console.c   |   2 +-
 hw/xen/xen-bus-helper.c |  61 +++
 hw/xen/xen-bus.c| 258 
 hw/xen/xen-legacy-backend.c | 121 +++--
 hw/xen/xen-operations.c | 189 
 hw/xen/xen_devconfig.c  |   4 +-
 hw/xen/xen_pt_graphics.c|   1 -
 hw/xen/xen_pvdev.c  |  49 +-
 include/hw/xen/xen-bus-helper.h |  25 ++-
 include/hw/xen/xen-bus.h|  17 +-
 include/hw/xen/xen-legacy-backend.h |   6 +-
 include/hw/xen/xen_backend_ops.h| 155 +
 include/hw/xen/xen_common.h |   1 -
 include/hw/xen/xen_pvdev.h  |   2 +-
 softmmu/globals.c   |   1 +
 16 files changed, 502 insertions(+), 401 deletions(-)

diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c
index 2329556595..6df7b4ff34 100644
--- a/accel/xen/xen-all.c
+++ b/accel/xen/xen-all.c
@@ -100,12 +100,15 @@ void xenstore_store_pv_console_info(int i, Chardev *chr)
 }
 
 
-static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
+static void xenstore_record_dm_state(const char *state)
 {
+struct xs_handle *xs;
 char path[50];
 
+/* We now have everything we need to set the xenstore entry. */
+xs = xs_open(0);
 if (xs == NULL) {
-error_report("xenstore connection not initialized");
+fprintf(stderr, "Could not contact XenStore\n");
 exit(1);
 }
 
@@ -119,6 +122,8 @@ static void xenstore_record_dm_state(struct xs_handle *xs, 
const char *state)
 error_report("error recording dm state");
 exit(1);
 }
+
+xs_close(xs);
 }
 
 
@@ -127,7 +132,7 @@ static void xen_change_state_handler(void *opaque, bool 
running,
 {
 if (running) {
 /* record state running */
-xenstore_record_dm_state(xenstore, "running");
+xenstore_record_dm_state("running");
 }
 }
 
diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
index e9cef3e1ef..ad8638a86d 100644
--- a/hw/char/xen_console.c
+++ b/hw/char/xen_console.c
@@ -181,7 +181,7 @@ static int con_init(struct XenLegacyDevice *xendev)
 const char *output;
 
 /* setup */
-dom = xs_get_domain_path(xenstore, con->xendev.dom);
+dom = qemu_xen_xs_get_domain_path(xenstore, con->xendev.dom);
 if (!xendev->dev) {
 snprintf(con->console, sizeof(con->console), "%s/console", dom);
 } else {
diff --git a/hw/xen/xen-bus-helper.c b/hw/xen/xen-bus-helper.c
index 5a1e12b374..db1e64e0fb 100644
--- a/hw/xen/xen-bus-helper.c
+++ b/hw/xen/xen-bus-helper.c
@@ -10,6 +10,7 @@
 #include "hw/xen/xen-bus.h"
 #include "hw/xen/xen-bus-helper.h"
 #include "qapi/error.h"
+#include "trace.h"
 
 #include 
 
@@ -46,34 +47,28 @@ const char *xs_strstate(enum xenbus_state state)
 return "INVALID";
 }
 
-void xs_node_create(struct xs_handle *xsh, xs_transaction_t tid,
-const char *node, struct xs_permissions perms[],
-unsigned int nr_perms, Error **errp)
+void xs_node_create(struct qemu_xs_handle *h, xs_transaction_t tid,
+const char *node, unsigned int owner, unsigned int domid,
+unsigned int perms, Error **errp)
 {
 trace_xs_node_create(node);
 
-if (!xs_write(xsh, tid, node, "", 0)) {
+if (!qemu_xen_xs_create(h, tid, owner, domid, perms, node)) {
 error_setg_errno(errp, errno, "failed to create node '%s'", node);
-return;
-}
-
-if (!xs_set_permissions(xsh, tid, node, perms, nr_perms)) {
-error_setg_errno(errp, errno, "failed to set node '%s' permissions",
- node);
 }
 }
 
-void xs_node_destroy(struct xs_handle *xsh, xs_transaction_t tid,
+void xs_node_destroy(struct qemu_xs_handle *h, xs_transaction_t tid,
  const char *node, Error **errp)
 {
 trace_xs_node_destroy(node);
 
-if (!xs_rm(xsh, tid, node)) {
+if (!qemu_xen_xs_destroy(h, tid, node)) {
 error_setg_errno(errp, errno, "failed to destroy node '%s'", node);
 }
 }
 
-void xs_node_vprintf(struct xs_handle *xsh, xs_transaction_t tid,
+void xs_node_vprintf(struct qemu_xs_handle *h, xs_transaction_t tid,
  const char *node, const char *key, Error **errp,
  const char *fmt, va_list ap)
 {
@@ -86,7 +81,7 @@ void xs_node_vprintf(struct xs_handle *xsh, xs_transaction_t 
tid,
 
 trace_xs_node_vprintf(path, value);
 
-if (!xs_write(xsh, tid, path, value, len)) {
+if (!qemu_xen_xs_write(h, tid, path, value, len)) {
 error_setg_errno(errp, errno, "failed to write '%s' to '%s'",
  value, path);
 }
@@ -95,18 +90,18 @@ void xs_node_vprintf(struct xs_handle *xsh, 
xs_transaction_t tid,
 g_free(path);
 }
 
-void xs_node_printf(struct xs_han

[PATCH v6 02/51] xen: add CONFIG_XENFV_MACHINE and CONFIG_XEN_EMU options for Xen emulation

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

The XEN_EMU option will cover core Xen support in target/, which exists
only for x86 with KVM today but could theoretically also be implemented
on Arm/Aarch64 and with TCG or other accelerators. It will also cover
the support for architecture-independent grant table and event channel
support which will be added in hw/i386/kvm/ (on the basis that the
non-KVM support is very theoretical and making it not use KVM directly
seems like gratuitous overengineering at this point).

The XENFV_MACHINE option is for the xenfv platform support, which will
now be used both by XEN_EMU and by real Xen.

The XEN option remains dependent on the Xen runtime libraries, and covers
support for real Xen. Some code which currently resides under CONFIG_XEN
will be moving to CONFIG_XENFV_MACHINE over time.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 hw/Kconfig  | 1 +
 hw/i386/Kconfig | 5 +
 hw/xen/Kconfig  | 3 +++
 meson.build | 1 +
 4 files changed, 10 insertions(+)
 create mode 100644 hw/xen/Kconfig

diff --git a/hw/Kconfig b/hw/Kconfig
index 38233bbb0f..ba62ff6417 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -41,6 +41,7 @@ source tpm/Kconfig
 source usb/Kconfig
 source virtio/Kconfig
 source vfio/Kconfig
+source xen/Kconfig
 source watchdog/Kconfig
 
 # arch Kconfig
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index d22ac4a4b9..c9fd577997 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -137,3 +137,8 @@ config VMPORT
 config VMMOUSE
 bool
 depends on VMPORT
+
+config XEN_EMU
+bool
+default y
+depends on KVM && (I386 || X86_64)
diff --git a/hw/xen/Kconfig b/hw/xen/Kconfig
new file mode 100644
index 00..755c8b1faf
--- /dev/null
+++ b/hw/xen/Kconfig
@@ -0,0 +1,3 @@
+config XENFV_MACHINE
+bool
+default y if (XEN || XEN_EMU)
diff --git a/meson.build b/meson.build
index 4c6f8a674a..6fbff38c24 100644
--- a/meson.build
+++ b/meson.build
@@ -3828,6 +3828,7 @@ if have_system
   if xen.found()
 summary_info += {'xen ctrl version':  xen.version()}
   endif
+  summary_info += {'Xen emulation': config_all.has_key('CONFIG_XEN_EMU')}
 endif
 summary_info += {'TCG support':   config_all.has_key('CONFIG_TCG')}
 if config_all.has_key('CONFIG_TCG')
-- 
2.35.3




[RFC PATCH v1 15/15] i386/xen: Initialize XenBus and legacy backends from pc_init1()

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Now that we're close to being able to use the PV backends without actual
Xen, move the bus instantiation out from xen_hvm_init_pc() to pc_init1().

However, still only do it for (xen_mode == XEN_ATTACH) (i.e. when running
on true Xen) because we don't have XenStore ops for emulation yet, and
the XenBus instantiation failure is fatal. Once we have a functional
XenStore for emulated mode, this will become (xen_mode != XEN_DISABLED).

Signed-off-by: David Woodhouse 
---
 hw/i386/pc_piix.c | 17 +
 hw/i386/xen/xen-hvm.c | 11 ---
 2 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index b48047f50c..5678112dc2 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -57,6 +57,10 @@
 #include 
 #include "hw/xen/xen_pt.h"
 #endif
+#ifdef CONFIG_XENFV_MACHINE
+#include "hw/xen/xen-legacy-backend.h"
+#include "hw/xen/xen-bus.h"
+#endif
 #include "migration/global_state.h"
 #include "migration/misc.h"
 #include "sysemu/numa.h"
@@ -157,6 +161,19 @@ static void pc_init1(MachineState *machine,
 }
 }
 
+#ifdef CONFIG_XENFV_MACHINE
+if (xen_mode == XEN_ATTACH) {
+/* Initialize backend core & drivers */
+xen_bus_init();
+
+if (xen_be_init() != 0) {
+error_report("xen backend core setup failed");
+exit(1);
+}
+xen_be_register_common();
+}
+#endif
+
 pc_machine_init_sgx_epc(pcms);
 x86_cpus_init(x86ms, pcmc->default_cpu_version);
 
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 779d923e10..48f289f8ee 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -20,8 +20,6 @@
 #include "hw/i386/apic-msidef.h"
 #include "hw/xen/xen_native.h"
 #include "hw/xen/xen_backend_ops.h"
-#include "hw/xen/xen-legacy-backend.h"
-#include "hw/xen/xen-bus.h"
 #include "hw/xen/xen-x86.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-migration.h"
@@ -1505,15 +1503,6 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion 
**ram_memory)
 QLIST_INIT(&state->dev_list);
 device_listener_register(&state->device_listener);
 
-xen_bus_init();
-
-/* Initialize backend core & drivers */
-if (xen_be_init() != 0) {
-error_report("xen backend core setup failed");
-goto err;
-}
-xen_be_register_common();
-
 QLIST_INIT(&xen_physmap);
 xen_read_physmap(state);
 
-- 
2.35.3




[PATCH v6 19/51] i386/xen: implement HYPERVISOR_vcpu_op

2023-01-10 Thread David Woodhouse
From: Joao Martins 

This is simply when guest tries to register a vcpu_info
and since vcpu_info placement is optional in the minimum ABI
therefore we can just fail with -ENOSYS

Signed-off-by: Joao Martins 
Signed-off-by: David Woodhouse 
---
 target/i386/kvm/xen-emu.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 5005bf848f..e95a2aee35 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -26,6 +26,7 @@
 #include "standard-headers/xen/sched.h"
 #include "standard-headers/xen/memory.h"
 #include "standard-headers/xen/hvm/hvm_op.h"
+#include "standard-headers/xen/vcpu.h"
 
 #include "xen-compat.h"
 
@@ -360,6 +361,25 @@ static bool kvm_xen_hcall_hvm_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 }
 }
 
+static bool kvm_xen_hcall_vcpu_op(struct kvm_xen_exit *exit, X86CPU *cpu,
+  int cmd, int vcpu_id, uint64_t arg)
+{
+int err;
+
+switch (cmd) {
+case VCPUOP_register_vcpu_info:
+/* no vcpu info placement for now */
+err = -ENOSYS;
+break;
+
+default:
+return false;
+}
+
+exit->u.hcall.result = err;
+return true;
+}
+
 static int kvm_xen_soft_reset(void)
 {
 int err;
@@ -454,6 +474,11 @@ static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct 
kvm_xen_exit *exit)
 case __HYPERVISOR_sched_op:
 return kvm_xen_hcall_sched_op(exit, cpu, exit->u.hcall.params[0],
   exit->u.hcall.params[1]);
+case __HYPERVISOR_vcpu_op:
+return kvm_xen_hcall_vcpu_op(exit, cpu,
+ exit->u.hcall.params[0],
+ exit->u.hcall.params[1],
+ exit->u.hcall.params[2]);
 case __HYPERVISOR_hvm_op:
 return kvm_xen_hcall_hvm_op(exit, cpu, exit->u.hcall.params[0],
 exit->u.hcall.params[1]);
-- 
2.35.3




[PATCH v6 15/51] i386/xen: manage and save/restore Xen guest long_mode setting

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Xen will "latch" the guest's 32-bit or 64-bit ("long mode") setting when
the guest writes the MSR to fill in the hypercall page, or when the guest
sets the event channel callback in HVM_PARAM_CALLBACK_IRQ.

KVM handles the former and sets the kernel's long_mode flag accordingly.
The latter will be handled in userspace. Keep them in sync by noticing
when a hypercall is made in a mode that doesn't match qemu's idea of
the guest mode, and resyncing from the kernel. Do that same sync right
before serialization too, in case the guest has set the hypercall page
but hasn't yet made a system call.

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_overlay.c | 65 +++
 hw/i386/kvm/xen_overlay.h |  4 +++
 target/i386/kvm/xen-emu.c | 12 
 3 files changed, 81 insertions(+)

diff --git a/hw/i386/kvm/xen_overlay.c b/hw/i386/kvm/xen_overlay.c
index 3e85bf912f..6fd63ff906 100644
--- a/hw/i386/kvm/xen_overlay.c
+++ b/hw/i386/kvm/xen_overlay.c
@@ -44,6 +44,7 @@ struct XenOverlayState {
 MemoryRegion shinfo_mem;
 void *shinfo_ptr;
 uint64_t shinfo_gpa;
+bool long_mode;
 };
 
 struct XenOverlayState *xen_overlay_singleton;
@@ -96,9 +97,21 @@ static void xen_overlay_realize(DeviceState *dev, Error 
**errp)
 
 s->shinfo_ptr = memory_region_get_ram_ptr(&s->shinfo_mem);
 s->shinfo_gpa = INVALID_GPA;
+s->long_mode = false;
 memset(s->shinfo_ptr, 0, XEN_PAGE_SIZE);
 }
 
+static int xen_overlay_pre_save(void *opaque)
+{
+/*
+ * Fetch the kernel's idea of long_mode to avoid the race condition
+ * where the guest has set the hypercall page up in 64-bit mode but
+ * not yet made a hypercall by the time migration happens, so qemu
+ * hasn't yet noticed.
+ */
+return xen_sync_long_mode();
+}
+
 static int xen_overlay_post_load(void *opaque, int version_id)
 {
 XenOverlayState *s = opaque;
@@ -107,6 +120,9 @@ static int xen_overlay_post_load(void *opaque, int 
version_id)
 xen_overlay_map_page_locked(&s->shinfo_mem, s->shinfo_gpa);
 xen_overlay_set_be_shinfo(s->shinfo_gpa >> XEN_PAGE_SHIFT);
 }
+if (s->long_mode) {
+xen_set_long_mode(true);
+}
 
 return 0;
 }
@@ -121,9 +137,11 @@ static const VMStateDescription xen_overlay_vmstate = {
 .version_id = 1,
 .minimum_version_id = 1,
 .needed = xen_overlay_is_needed,
+.pre_save = xen_overlay_pre_save,
 .post_load = xen_overlay_post_load,
 .fields = (VMStateField[]) {
 VMSTATE_UINT64(shinfo_gpa, XenOverlayState),
+VMSTATE_BOOL(long_mode, XenOverlayState),
 VMSTATE_END_OF_LIST()
 }
 };
@@ -198,3 +216,50 @@ void *xen_overlay_get_shinfo_ptr(void)
 
 return s->shinfo_ptr;
 }
+
+int xen_sync_long_mode(void)
+{
+int ret;
+struct kvm_xen_hvm_attr xa = {
+.type = KVM_XEN_ATTR_TYPE_LONG_MODE,
+};
+
+if (!xen_overlay_singleton) {
+return -ENOENT;
+}
+
+ret = kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_GET_ATTR, &xa);
+if (!ret) {
+xen_overlay_singleton->long_mode = xa.u.long_mode;
+}
+
+return ret;
+}
+
+int xen_set_long_mode(bool long_mode)
+{
+int ret;
+struct kvm_xen_hvm_attr xa = {
+.type = KVM_XEN_ATTR_TYPE_LONG_MODE,
+.u.long_mode = long_mode,
+};
+
+if (!xen_overlay_singleton) {
+return -ENOENT;
+}
+
+ret = kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &xa);
+if (!ret) {
+xen_overlay_singleton->long_mode = xa.u.long_mode;
+}
+
+return ret;
+}
+
+bool xen_is_long_mode(void)
+{
+if (xen_overlay_singleton) {
+return xen_overlay_singleton->long_mode;
+}
+return false;
+}
diff --git a/hw/i386/kvm/xen_overlay.h b/hw/i386/kvm/xen_overlay.h
index 00cff05bb0..5c46a0b036 100644
--- a/hw/i386/kvm/xen_overlay.h
+++ b/hw/i386/kvm/xen_overlay.h
@@ -17,4 +17,8 @@ void xen_overlay_create(void);
 int xen_overlay_map_shinfo_page(uint64_t gpa);
 void *xen_overlay_get_shinfo_ptr(void);
 
+int xen_sync_long_mode(void);
+int xen_set_long_mode(bool long_mode);
+bool xen_is_long_mode(void);
+
 #endif /* QEMU_XEN_OVERLAY_H */
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 80005ea527..80f09f33df 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -19,6 +19,8 @@
 #include "trace.h"
 #include "sysemu/runstate.h"
 
+#include "hw/i386/kvm/xen_overlay.h"
+
 #include "standard-headers/xen/version.h"
 #include "standard-headers/xen/sched.h"
 
@@ -274,6 +276,16 @@ int kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit 
*exit)
 return -1;
 }
 
+/*
+ * The kernel latches the guest 32/64 mode when the MSR is used to fill
+ * the hypercall page. So if we see a hypercall in a mode that doesn't
+ * match our own idea of the guest mode, fetch the kernel's idea of the
+ * "long mode" to remain in sync.
+ */
+if (exit->u.hcall.longmode != xen_is_long_mode()) {
+xen_sync_long_mode()

[PATCH v6 51/51] hw/xen: Add basic ring handling to xenstore

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Extract requests, return ENOSYS to all of them. This is enough to allow
older Linux guests to boot, as they need *something* back but it doesn't
matter much what.

In the first instance we're likely to wire this up over a UNIX socket to
an actual xenstored implementation, but in the fullness of time it would
be nice to have a fully single-tenant "virtual" xenstore within qemu.

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_xenstore.c | 223 -
 1 file changed, 220 insertions(+), 3 deletions(-)

diff --git a/hw/i386/kvm/xen_xenstore.c b/hw/i386/kvm/xen_xenstore.c
index bb3346f4e3..6369e29f59 100644
--- a/hw/i386/kvm/xen_xenstore.c
+++ b/hw/i386/kvm/xen_xenstore.c
@@ -188,18 +188,235 @@ uint16_t xen_xenstore_get_port(void)
 return s->guest_port;
 }
 
+static bool req_pending(XenXenstoreState *s)
+{
+struct xsd_sockmsg *req = (struct xsd_sockmsg *)s->req_data;
+
+return s->req_offset == XENSTORE_HEADER_SIZE + req->len;
+}
+
+static void reset_req(XenXenstoreState *s)
+{
+memset(s->req_data, 0, sizeof(s->req_data));
+s->req_offset = 0;
+}
+
+static void reset_rsp(XenXenstoreState *s)
+{
+s->rsp_pending = false;
+
+memset(s->rsp_data, 0, sizeof(s->rsp_data));
+s->rsp_offset = 0;
+}
+
+static void process_req(XenXenstoreState *s)
+{
+struct xsd_sockmsg *req = (struct xsd_sockmsg *)s->req_data;
+struct xsd_sockmsg *rsp = (struct xsd_sockmsg *)s->rsp_data;
+const char enosys[] = "ENOSYS";
+
+assert(req_pending(s));
+   assert(!s->rsp_pending);
+
+rsp->type = XS_ERROR;
+rsp->req_id = req->req_id;
+rsp->tx_id = req->tx_id;
+rsp->len = sizeof(enosys);
+memcpy((void *)&rsp[1], enosys, sizeof(enosys));
+
+s->rsp_pending = true;
+reset_req(s);
+}
+
+static unsigned int copy_from_ring(XenXenstoreState *s, uint8_t *ptr, unsigned 
int len)
+{
+if (!len)
+return 0;
+
+XENSTORE_RING_IDX prod = qatomic_read(&s->xs->req_prod);
+XENSTORE_RING_IDX cons = qatomic_read(&s->xs->req_cons);
+unsigned int copied = 0;
+
+smp_mb();
+
+while (len) {
+unsigned int avail = prod - cons;
+unsigned int offset = MASK_XENSTORE_IDX(cons);
+unsigned int copylen = avail;
+
+if (avail > XENSTORE_RING_SIZE) {
+error_report("XenStore ring handling error");
+s->fatal_error = true;
+break;
+} else if (avail == 0)
+break;
+
+if (copylen > len) {
+copylen = len;
+}
+if (copylen > XENSTORE_RING_SIZE - offset) {
+copylen = XENSTORE_RING_SIZE - offset;
+}
+
+memcpy(ptr, &s->xs->req[offset], copylen);
+copied += copylen;
+
+ptr += copylen;
+len -= copylen;
+
+cons += copylen;
+}
+
+smp_mb();
+
+qatomic_set(&s->xs->req_cons, cons);
+
+return copied;
+}
+
+static unsigned int copy_to_ring(XenXenstoreState *s, uint8_t *ptr, unsigned 
int len)
+{
+if (!len)
+return 0;
+
+XENSTORE_RING_IDX cons = qatomic_read(&s->xs->rsp_cons);
+XENSTORE_RING_IDX prod = qatomic_read(&s->xs->rsp_prod);
+unsigned int copied = 0;
+
+smp_mb();
+
+while (len) {
+unsigned int avail = cons + XENSTORE_RING_SIZE - prod;
+unsigned int offset = MASK_XENSTORE_IDX(prod);
+unsigned int copylen = len;
+
+if (avail > XENSTORE_RING_SIZE) {
+error_report("XenStore ring handling error");
+s->fatal_error = true;
+break;
+} else if (avail == 0)
+break;
+
+if (copylen > avail) {
+copylen = avail;
+}
+if (copylen > XENSTORE_RING_SIZE - offset) {
+copylen = XENSTORE_RING_SIZE - offset;
+}
+
+
+memcpy(&s->xs->rsp[offset], ptr, copylen);
+copied += copylen;
+
+ptr += copylen;
+len -= copylen;
+
+prod += copylen;
+}
+
+smp_mb();
+
+qatomic_set(&s->xs->rsp_prod, prod);
+
+return copied;
+}
+
+static unsigned int get_req(XenXenstoreState *s)
+{
+unsigned int copied = 0;
+
+if (s->fatal_error)
+return 0;
+
+assert(!req_pending(s));
+
+if (s->req_offset < XENSTORE_HEADER_SIZE) {
+void *ptr = s->req_data + s->req_offset;
+unsigned int len = XENSTORE_HEADER_SIZE;
+unsigned int copylen = copy_from_ring(s, ptr, len);
+
+copied += copylen;
+s->req_offset += copylen;
+}
+
+if (s->req_offset >= XENSTORE_HEADER_SIZE) {
+struct xsd_sockmsg *req = (struct xsd_sockmsg *)s->req_data;
+
+if (req->len > (uint32_t)XENSTORE_PAYLOAD_MAX) {
+error_report("Illegal XenStore request");
+s->fatal_error = true;
+return 0;
+}
+
+void *ptr = s->req_data + s->req_offset;
+unsigned int len = XENSTORE_HEADER_SIZE + req->len - s->req_offset;
+unsigned int copylen = copy_from_ring(s, ptr, 

[PATCH v6 14/51] i386/xen: add pc_machine_kvm_type to initialize XEN_EMULATE mode

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

The xen_overlay device (and later similar devices for event channels and
grant tables) need to be instantiated. Do this from a kvm_type method on
the PC machine derivatives, since KVM is only way to support Xen emulation
for now.

Signed-off-by: David Woodhouse 
---
 hw/i386/pc.c | 11 +++
 include/hw/i386/pc.h |  3 +++
 2 files changed, 14 insertions(+)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d489ecc0d1..0ddae2f6ad 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -89,6 +89,7 @@
 #include "hw/virtio/virtio-iommu.h"
 #include "hw/virtio/virtio-pmem-pci.h"
 #include "hw/virtio/virtio-mem-pci.h"
+#include "hw/i386/kvm/xen_overlay.h"
 #include "hw/mem/memory-device.h"
 #include "sysemu/replay.h"
 #include "target/i386/cpu.h"
@@ -1844,6 +1845,16 @@ static void pc_machine_initfn(Object *obj)
 cxl_machine_init(obj, &pcms->cxl_devices_state);
 }
 
+int pc_machine_kvm_type(MachineState *machine, const char *kvm_type)
+{
+#ifdef CONFIG_XEN_EMU
+if (xen_mode == XEN_EMULATE) {
+xen_overlay_create();
+}
+#endif
+return 0;
+}
+
 static void pc_machine_reset(MachineState *machine, ShutdownCause reason)
 {
 CPUState *cs;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 991f905f5d..b866567b7b 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -293,12 +293,15 @@ extern const size_t pc_compat_1_5_len;
 extern GlobalProperty pc_compat_1_4[];
 extern const size_t pc_compat_1_4_len;
 
+extern int pc_machine_kvm_type(MachineState *machine, const char *vm_type);
+
 #define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \
 static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \
 { \
 MachineClass *mc = MACHINE_CLASS(oc); \
 optsfn(mc); \
 mc->init = initfn; \
+mc->kvm_type = pc_machine_kvm_type; \
 } \
 static const TypeInfo pc_machine_type_##suffix = { \
 .name   = namestr TYPE_MACHINE_SUFFIX, \
-- 
2.35.3




[PATCH v6 03/51] xen: Add XEN_DISABLED mode and make it default

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Also set XEN_ATTACH mode in xen_init() to reflect the truth; not that
anyone ever cared before. It was *only* ever checked in xen_init_pv()
before.

Suggested-by: Paolo Bonzini 
Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 accel/xen/xen-all.c  | 2 ++
 include/hw/xen/xen.h | 5 +++--
 softmmu/globals.c| 2 +-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c
index 69aa7d018b..2329556595 100644
--- a/accel/xen/xen-all.c
+++ b/accel/xen/xen-all.c
@@ -181,6 +181,8 @@ static int xen_init(MachineState *ms)
  * opt out of system RAM being allocated by generic code
  */
 mc->default_ram_id = NULL;
+
+xen_mode = XEN_ATTACH;
 return 0;
 }
 
diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
index 4d412fd4b2..b3873c581b 100644
--- a/include/hw/xen/xen.h
+++ b/include/hw/xen/xen.h
@@ -22,8 +22,9 @@
 
 /* xen-machine.c */
 enum xen_mode {
-XEN_EMULATE = 0,  // xen emulation, using xenner (default)
-XEN_ATTACH// attach to xen domain created by libxl
+XEN_DISABLED = 0, // xen support disabled (default)
+XEN_ATTACH,   // attach to xen domain created by libxl
+XEN_EMULATE,
 };
 
 extern uint32_t xen_domid;
diff --git a/softmmu/globals.c b/softmmu/globals.c
index 527edbefdd..0a4405614e 100644
--- a/softmmu/globals.c
+++ b/softmmu/globals.c
@@ -63,5 +63,5 @@ QemuUUID qemu_uuid;
 bool qemu_uuid_set;
 
 uint32_t xen_domid;
-enum xen_mode xen_mode = XEN_EMULATE;
+enum xen_mode xen_mode = XEN_DISABLED;
 bool xen_domid_restrict;
-- 
2.35.3




Re: [PATCH v14 02/11] s390x/cpu topology: add topology entries on CPU hotplug

2023-01-10 Thread Thomas Huth

On 05/01/2023 15.53, Pierre Morel wrote:

The topology information are attributes of the CPU and are
specified during the CPU device creation.

On hot plug, we gather the topology information on the core,
creates a list of topology entries, each entry contains a single
core mask of each core with identical topology and finaly we
orders the list in topological order.
The topological order is, from higher to lower priority:
- physical topology
 - drawer
 - book
 - socket
 - core origin, offset in 64bit increment from core 0.
- modifier attributes
 - CPU type
 - polarization entitlement
 - dedication

The possibility to insert a CPU in a mask is dependent on the
number of cores allowed in a socket, a book or a drawer, the
checking is done during the hot plug of the CPU to have an
immediate answer.

If the complete topology is not specified, the core is added
in the physical topology based on its core ID and it gets
defaults values for the modifier attributes.

This way, starting QEMU without specifying the topology can
still get some adventage of the CPU topology.


s/adventage/advantage/


Signed-off-by: Pierre Morel 
---
  include/hw/s390x/cpu-topology.h |  48 ++
  hw/s390x/cpu-topology.c | 293 
  hw/s390x/s390-virtio-ccw.c  |  10 ++
  hw/s390x/meson.build|   1 +
  4 files changed, 352 insertions(+)
  create mode 100644 hw/s390x/cpu-topology.c

diff --git a/include/hw/s390x/cpu-topology.h b/include/hw/s390x/cpu-topology.h
index d945b57fc3..b3fd752d8d 100644
--- a/include/hw/s390x/cpu-topology.h
+++ b/include/hw/s390x/cpu-topology.h
@@ -10,7 +10,11 @@
  #ifndef HW_S390X_CPU_TOPOLOGY_H
  #define HW_S390X_CPU_TOPOLOGY_H
  
+#include "qemu/queue.h"

+#include "hw/boards.h"
+
  #define S390_TOPOLOGY_CPU_IFL   0x03
+#define S390_TOPOLOGY_MAX_ORIGIN ((63 + S390_MAX_CPUS) / 64)
  
  #define S390_TOPOLOGY_POLARITY_HORIZONTAL  0x00

  #define S390_TOPOLOGY_POLARITY_VERTICAL_LOW0x01
@@ -20,4 +24,48 @@
  #define S390_TOPOLOGY_SHARED0x00
  #define S390_TOPOLOGY_DEDICATED 0x01
  
+typedef union s390_topology_id {

+uint64_t id;
+struct {
+uint64_t level_6:8; /* byte 0 BE */
+uint64_t level_5:8; /* byte 1 BE */
+uint64_t drawer:8;  /* byte 2 BE */
+uint64_t book:8;/* byte 3 BE */
+uint64_t socket:8;  /* byte 4 BE */
+uint64_t rsrv:5;
+uint64_t d:1;
+uint64_t p:2;   /* byte 5 BE */
+uint64_t type:8;/* byte 6 BE */
+uint64_t origin:2;
+uint64_t core:6;/* byte 7 BE */
+};
+} s390_topology_id;


Bitmasks are OK for code that will definitely only ever work with KVM ... 
but this will certainly fail completely if we ever try to get it running 
with TCG later. Do we care? ... if so, you should certainly avoid a bitfield 
here. Especially since most of the fields are 8-bit anyway and could easily 
be represented by a "uint8_t" variable. Otherwise, just ignore my comment.



+#define TOPO_CPU_MASK   0x003fUL
+
+typedef struct S390TopologyEntry {
+s390_topology_id id;
+QTAILQ_ENTRY(S390TopologyEntry) next;
+uint64_t mask;
+} S390TopologyEntry;
+
+typedef struct S390Topology {
+QTAILQ_HEAD(, S390TopologyEntry) list;
+uint8_t *sockets;


So this "uint8_t" basically is a hidden limit of a maximum of 256 sockets 
that can be used for per book? Do we check that limit somewhere? (I looked 
for it, but I didn't spot such a check)



+CpuTopology *smp;
+} S390Topology;
+
+#ifdef CONFIG_KVM
+bool s390_has_topology(void);
+void s390_topology_set_cpu(MachineState *ms, S390CPU *cpu, Error **errp);
+#else
+static inline bool s390_has_topology(void)
+{
+   return false;
+}
+static inline void s390_topology_set_cpu(MachineState *ms,
+ S390CPU *cpu,
+ Error **errp) {}
+#endif
+extern S390Topology s390_topology;
+
  #endif
diff --git a/hw/s390x/cpu-topology.c b/hw/s390x/cpu-topology.c
new file mode 100644
index 00..438055c612
--- /dev/null
+++ b/hw/s390x/cpu-topology.c
@@ -0,0 +1,293 @@
+/*
+ * CPU Topology
+ *
+ * Copyright IBM Corp. 2022


Want to update to 2023 now?


+ * Author(s): Pierre Morel 
+
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "hw/qdev-properties.h"
+#include "hw/boards.h"
+#include "qemu/typedefs.h"
+#include "target/s390x/cpu.h"
+#include "hw/s390x/s390-virtio-ccw.h"
+#include "hw/s390x/cpu-topology.h"
+
+/*
+ * s390_topology is used to keep the topology information.
+ * .list: queue the topology entries inside which
+ *we keep the information on the CPU topology.
+ *
+ * .smp: keeps track of the machine topology.
+ *
+ * .socket: tracks information on the count o

[PATCH v6 07/51] xen-platform: exclude vfio-pci from the PCI platform unplug

2023-01-10 Thread David Woodhouse
From: Joao Martins 

Such that PCI passthrough devices work for Xen emulated guests.

Signed-off-by: Joao Martins 
Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 hw/i386/xen/xen_platform.c | 18 +++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
index 7db0d94ec2..50174c2269 100644
--- a/hw/i386/xen/xen_platform.c
+++ b/hw/i386/xen/xen_platform.c
@@ -109,12 +109,25 @@ static void log_writeb(PCIXenPlatformState *s, char val)
 #define _UNPLUG_NVME_DISKS 3
 #define UNPLUG_NVME_DISKS (1u << _UNPLUG_NVME_DISKS)
 
+static bool pci_device_is_passthrough(PCIDevice *d)
+{
+if (!strcmp(d->name, "xen-pci-passthrough")) {
+return true;
+}
+
+if (xen_mode == XEN_EMULATE && !strcmp(d->name, "vfio-pci")) {
+return true;
+}
+
+return false;
+}
+
 static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
 {
 /* We have to ignore passthrough devices */
 if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
 PCI_CLASS_NETWORK_ETHERNET
-&& strcmp(d->name, "xen-pci-passthrough") != 0) {
+&& !pci_device_is_passthrough(d)) {
 object_unparent(OBJECT(d));
 }
 }
@@ -187,9 +200,8 @@ static void unplug_disks(PCIBus *b, PCIDevice *d, void 
*opaque)
 !(flags & UNPLUG_IDE_SCSI_DISKS);
 
 /* We have to ignore passthrough devices */
-if (!strcmp(d->name, "xen-pci-passthrough")) {
+if (pci_device_is_passthrough(d))
 return;
-}
 
 switch (pci_get_word(d->config + PCI_CLASS_DEVICE)) {
 case PCI_CLASS_STORAGE_IDE:
-- 
2.35.3




[PATCH v6 30/51] hw/xen: Implement EVTCHNOP_unmask

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

This finally comes with a mechanism for actually injecting events into
the guest vCPU, with all the atomic-test-and-set that's involved in
setting the bit in the shinfo, then the index in the vcpu_info, and
injecting either the lapic vector as MSI, or letting KVM inject the
bare vector.

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c  | 175 ++
 hw/i386/kvm/xen_evtchn.h  |   2 +
 target/i386/kvm/xen-emu.c |  12 +++
 3 files changed, 189 insertions(+)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index a74d95d024..0e5b33e417 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -217,6 +217,13 @@ int xen_evtchn_set_callback_param(uint64_t param)
 return ret;
 }
 
+static void inject_callback(XenEvtchnState *s, uint32_t vcpu)
+{
+int type = s->callback_param >> CALLBACK_VIA_TYPE_SHIFT;
+
+kvm_xen_inject_vcpu_callback_vector(vcpu, type);
+}
+
 static bool valid_port(evtchn_port_t port)
 {
 if (!port) {
@@ -287,6 +294,152 @@ int xen_evtchn_status_op(struct evtchn_status *status)
 return 0;
 }
 
+/*
+ * Never thought I'd hear myself say this, but C++ templates would be
+ * kind of nice here.
+ *
+ * template static int do_unmask_port(T *shinfo, ...);
+ */
+static int do_unmask_port_lm(XenEvtchnState *s, evtchn_port_t port,
+ bool do_unmask, struct shared_info *shinfo,
+ struct vcpu_info *vcpu_info)
+{
+const int bits_per_word = BITS_PER_BYTE * 
sizeof(shinfo->evtchn_pending[0]);
+typeof(shinfo->evtchn_pending[0]) mask;
+int idx = port / bits_per_word;
+int offset = port % bits_per_word;
+
+mask = 1UL << offset;
+
+if (idx >= bits_per_word) {
+return -EINVAL;
+}
+
+if (do_unmask) {
+/*
+ * If this is a true unmask operation, clear the mask bit. If
+ * it was already unmasked, we have nothing further to do.
+ */
+if (!((qatomic_fetch_and(&shinfo->evtchn_mask[idx], ~mask) & mask))) {
+return 0;
+}
+} else {
+/*
+ * This is a pseudo-unmask for affinity changes. We don't
+ * change the mask bit, and if it's *masked* we have nothing
+ * else to do.
+ */
+if (qatomic_fetch_or(&shinfo->evtchn_mask[idx], 0) & mask) {
+return 0;
+}
+}
+
+/* If the event was not pending, we're done. */
+if (!(qatomic_fetch_or(&shinfo->evtchn_pending[idx], 0) & mask)) {
+return 0;
+}
+
+/* Now on to the vcpu_info evtchn_pending_sel index... */
+mask = 1UL << idx;
+
+/* If a port in this word was already pending for this vCPU, all done. */
+if (qatomic_fetch_or(&vcpu_info->evtchn_pending_sel, mask) & mask) {
+return 0;
+}
+
+/* Set evtchn_upcall_pending for this vCPU */
+if (qatomic_fetch_or(&vcpu_info->evtchn_upcall_pending, 1)) {
+return 0;
+}
+
+inject_callback(s, s->port_table[port].vcpu);
+
+return 0;
+}
+
+static int do_unmask_port_compat(XenEvtchnState *s, evtchn_port_t port,
+ bool do_unmask,
+ struct compat_shared_info *shinfo,
+ struct compat_vcpu_info *vcpu_info)
+{
+const int bits_per_word = BITS_PER_BYTE * 
sizeof(shinfo->evtchn_pending[0]);
+typeof(shinfo->evtchn_pending[0]) mask;
+int idx = port / bits_per_word;
+int offset = port % bits_per_word;
+
+mask = 1UL << offset;
+
+if (idx >= bits_per_word) {
+return -EINVAL;
+}
+
+if (do_unmask) {
+/*
+ * If this is a true unmask operation, clear the mask bit. If
+ * it was already unmasked, we have nothing further to do.
+ */
+if (!((qatomic_fetch_and(&shinfo->evtchn_mask[idx], ~mask) & mask))) {
+return 0;
+}
+} else {
+/*
+ * This is a pseudo-unmask for affinity changes. We don't
+ * change the mask bit, and if it's *masked* we have nothing
+ * else to do.
+ */
+if (qatomic_fetch_or(&shinfo->evtchn_mask[idx], 0) & mask) {
+return 0;
+}
+}
+
+/* If the event was not pending, we're done. */
+if (!(qatomic_fetch_or(&shinfo->evtchn_pending[idx], 0) & mask)) {
+return 0;
+}
+
+/* Now on to the vcpu_info evtchn_pending_sel index... */
+mask = 1UL << idx;
+
+/* If a port in this word was already pending for this vCPU, all done. */
+if (qatomic_fetch_or(&vcpu_info->evtchn_pending_sel, mask) & mask) {
+return 0;
+}
+
+/* Set evtchn_upcall_pending for this vCPU */
+if (qatomic_fetch_or(&vcpu_info->evtchn_upcall_pending, 1)) {
+return 0;
+}
+
+inject_callback(s, s->port_table[port].vcpu);
+
+return 0;
+}
+
+static int unmask_port(XenEvtchnState *s, evtchn_port_t port, bool do_unmask)
+{
+void *vcpu_info, *shinfo;

[RFC PATCH v1 10/15] hw/xen: Build PV backend drivers for XENFV_MACHINE

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

Now that we have the redirectable Xen backend operations we can build the
PV backends even without the Xen libraries.

Signed-off-by: David Woodhouse 
---
 hw/9pfs/meson.build| 2 +-
 hw/block/dataplane/meson.build | 2 +-
 hw/block/meson.build   | 2 +-
 hw/char/meson.build| 2 +-
 hw/display/meson.build | 2 +-
 hw/usb/meson.build | 2 +-
 hw/xen/meson.build | 5 -
 7 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/hw/9pfs/meson.build b/hw/9pfs/meson.build
index 12443b6ad5..ac5f37f229 100644
--- a/hw/9pfs/meson.build
+++ b/hw/9pfs/meson.build
@@ -15,7 +15,7 @@ fs_ss.add(files(
 ))
 fs_ss.add(when: 'CONFIG_LINUX', if_true: files('9p-util-linux.c'))
 fs_ss.add(when: 'CONFIG_DARWIN', if_true: files('9p-util-darwin.c'))
-fs_ss.add(when: 'CONFIG_XEN', if_true: files('xen-9p-backend.c'))
+fs_ss.add(when: 'CONFIG_XENFV_MACHINE', if_true: files('xen-9p-backend.c'))
 softmmu_ss.add_all(when: 'CONFIG_FSDEV_9P', if_true: fs_ss)
 
 specific_ss.add(when: 'CONFIG_VIRTIO_9P', if_true: files('virtio-9p-device.c'))
diff --git a/hw/block/dataplane/meson.build b/hw/block/dataplane/meson.build
index 12c6a264f1..ca7b62fdc6 100644
--- a/hw/block/dataplane/meson.build
+++ b/hw/block/dataplane/meson.build
@@ -1,2 +1,2 @@
 specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c'))
-specific_ss.add(when: 'CONFIG_XEN', if_true: files('xen-block.c'))
+specific_ss.add(when: 'CONFIG_XENFV_MACHINE', if_true: files('xen-block.c'))
diff --git a/hw/block/meson.build b/hw/block/meson.build
index b434d5654c..c51539970b 100644
--- a/hw/block/meson.build
+++ b/hw/block/meson.build
@@ -14,7 +14,7 @@ softmmu_ss.add(when: 'CONFIG_PFLASH_CFI02', if_true: 
files('pflash_cfi02.c'))
 softmmu_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80.c'))
 softmmu_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80_sfdp.c'))
 softmmu_ss.add(when: 'CONFIG_SWIM', if_true: files('swim.c'))
-softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen-block.c'))
+softmmu_ss.add(when: 'CONFIG_XENFV_MACHINE', if_true: files('xen-block.c'))
 softmmu_ss.add(when: 'CONFIG_TC58128', if_true: files('tc58128.c'))
 
 specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c', 
'virtio-blk-common.c'))
diff --git a/hw/char/meson.build b/hw/char/meson.build
index 7b594f51b8..d6ef21bfe1 100644
--- a/hw/char/meson.build
+++ b/hw/char/meson.build
@@ -18,7 +18,7 @@ softmmu_ss.add(when: 'CONFIG_SERIAL_PCI', if_true: 
files('serial-pci.c'))
 softmmu_ss.add(when: 'CONFIG_SERIAL_PCI_MULTI', if_true: 
files('serial-pci-multi.c'))
 softmmu_ss.add(when: 'CONFIG_SHAKTI_UART', if_true: files('shakti_uart.c'))
 softmmu_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: 
files('virtio-console.c'))
-softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen_console.c'))
+softmmu_ss.add(when: 'CONFIG_XENFV_MACHINE', if_true: files('xen_console.c'))
 softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_uartlite.c'))
 
 softmmu_ss.add(when: 'CONFIG_AVR_USART', if_true: files('avr_usart.c'))
diff --git a/hw/display/meson.build b/hw/display/meson.build
index 7a725ed80e..5c8da687b7 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -14,7 +14,7 @@ softmmu_ss.add(when: 'CONFIG_PL110', if_true: 
files('pl110.c'))
 softmmu_ss.add(when: 'CONFIG_SII9022', if_true: files('sii9022.c'))
 softmmu_ss.add(when: 'CONFIG_SSD0303', if_true: files('ssd0303.c'))
 softmmu_ss.add(when: 'CONFIG_SSD0323', if_true: files('ssd0323.c'))
-softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xenfb.c'))
+softmmu_ss.add(when: 'CONFIG_XENFV_MACHINE', if_true: files('xenfb.c'))
 
 softmmu_ss.add(when: 'CONFIG_VGA_PCI', if_true: files('vga-pci.c'))
 softmmu_ss.add(when: 'CONFIG_VGA_ISA', if_true: files('vga-isa.c'))
diff --git a/hw/usb/meson.build b/hw/usb/meson.build
index 793df42e21..440df35028 100644
--- a/hw/usb/meson.build
+++ b/hw/usb/meson.build
@@ -84,6 +84,6 @@ if libusb.found()
   hw_usb_modules += {'host': usbhost_ss}
 endif
 
-softmmu_ss.add(when: ['CONFIG_USB', 'CONFIG_XEN', libusb], if_true: 
files('xen-usb.c'))
+softmmu_ss.add(when: ['CONFIG_USB', 'CONFIG_XENFV_MACHINE', libusb], if_true: 
files('xen-usb.c'))
 
 modules += { 'hw-usb': hw_usb_modules }
diff --git a/hw/xen/meson.build b/hw/xen/meson.build
index f195bbd25c..0d1eddbca6 100644
--- a/hw/xen/meson.build
+++ b/hw/xen/meson.build
@@ -1,10 +1,13 @@
-softmmu_ss.add(when: ['CONFIG_XEN', xen], if_true: files(
+softmmu_ss.add(when: ['CONFIG_XENFV_MACHINE'], if_true: files(
   'xen-backend.c',
   'xen-bus-helper.c',
   'xen-bus.c',
   'xen-legacy-backend.c',
   'xen_devconfig.c',
   'xen_pvdev.c',
+))
+
+softmmu_ss.add(when: ['CONFIG_XEN', xen], if_true: files(
   'xen-operations.c',
 ))
 
-- 
2.35.3




[PATCH v6 27/51] i386/xen: Add support for Xen event channel delivery to vCPU

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

The kvm_xen_inject_vcpu_callback_vector() function will either deliver
the per-vCPU local APIC vector (as an MSI), or just kick the vCPU out
of the kernel to trigger KVM's automatic delivery of the global vector.
Support for asserting the GSI/PCI_INTX callbacks will come later.

Also add kvm_xen_get_vcpu_info_hva() which returns the vcpu_info of
a given vCPU.

Signed-off-by: David Woodhouse 
---
 include/sysemu/kvm_xen.h  |  2 +
 target/i386/cpu.h |  2 +
 target/i386/kvm/xen-emu.c | 86 ---
 3 files changed, 84 insertions(+), 6 deletions(-)

diff --git a/include/sysemu/kvm_xen.h b/include/sysemu/kvm_xen.h
index 3e43cd7843..ee53294deb 100644
--- a/include/sysemu/kvm_xen.h
+++ b/include/sysemu/kvm_xen.h
@@ -17,6 +17,8 @@
 #define INVALID_GFN UINT64_MAX
 
 uint32_t kvm_xen_get_caps(void);
+void *kvm_xen_get_vcpu_info_hva(uint32_t vcpu_id);
+void kvm_xen_inject_vcpu_callback_vector(uint32_t vcpu_id, int type);
 
 #define kvm_xen_has_cap(cap) (!!(kvm_xen_get_caps() &   \
  KVM_XEN_HVM_CONFIG_ ## cap))
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 938a1b9c8b..c9b12e7476 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1788,6 +1788,8 @@ typedef struct CPUArchState {
 #endif
 #if defined(CONFIG_KVM)
 struct kvm_nested_state *nested_state;
+MemoryRegion *xen_vcpu_info_mr;
+void *xen_vcpu_info_hva;
 uint64_t xen_vcpu_info_gpa;
 uint64_t xen_vcpu_info_default_gpa;
 uint64_t xen_vcpu_time_info_gpa;
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 42e65573de..eced4bce5c 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -20,6 +20,8 @@
 #include "trace.h"
 #include "sysemu/runstate.h"
 
+#include "hw/pci/msi.h"
+#include "hw/i386/apic-msidef.h"
 #include "hw/i386/kvm/xen_overlay.h"
 #include "hw/i386/kvm/xen_evtchn.h"
 
@@ -247,6 +249,35 @@ static void do_set_vcpu_callback_vector(CPUState *cs, 
run_on_cpu_data data)
 }
 }
 
+static int set_vcpu_info(CPUState *cs, uint64_t gpa)
+{
+X86CPU *cpu = X86_CPU(cs);
+CPUX86State *env = &cpu->env;
+MemoryRegionSection mrs;
+int ret;
+
+ret = kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO, gpa);
+if (ret || gpa == INVALID_GPA) {
+fail:
+if (env->xen_vcpu_info_mr) {
+memory_region_unref(env->xen_vcpu_info_mr);
+env->xen_vcpu_info_mr = NULL;
+}
+env->xen_vcpu_info_hva = NULL;
+return ret;
+}
+
+mrs = memory_region_find(get_system_memory(), gpa, sizeof(struct 
vcpu_info));
+if (!mrs.mr || !mrs.mr->ram_block || mrs.size < sizeof(struct vcpu_info) ||
+!(env->xen_vcpu_info_hva = qemu_map_ram_ptr(mrs.mr->ram_block,
+
mrs.offset_within_region))) {
+ret = -EINVAL;
+goto fail;
+}
+env->xen_vcpu_info_mr = mrs.mr;
+return 0;
+}
+
 static void do_set_vcpu_info_default_gpa(CPUState *cs, run_on_cpu_data data)
 {
 X86CPU *cpu = X86_CPU(cs);
@@ -256,8 +287,7 @@ static void do_set_vcpu_info_default_gpa(CPUState *cs, 
run_on_cpu_data data)
 
 /* Changing the default does nothing if a vcpu_info was explicitly set. */
 if (env->xen_vcpu_info_gpa == INVALID_GPA) {
-kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO,
-  env->xen_vcpu_info_default_gpa);
+set_vcpu_info(cs, env->xen_vcpu_info_default_gpa);
 }
 }
 
@@ -268,8 +298,52 @@ static void do_set_vcpu_info_gpa(CPUState *cs, 
run_on_cpu_data data)
 
 env->xen_vcpu_info_gpa = data.host_ulong;
 
-kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO,
-  env->xen_vcpu_info_gpa);
+set_vcpu_info(cs, env->xen_vcpu_info_gpa);
+}
+
+void *kvm_xen_get_vcpu_info_hva(uint32_t vcpu_id)
+{
+CPUState *cs = qemu_get_cpu(vcpu_id);
+if (!cs) {
+return NULL;
+}
+
+return X86_CPU(cs)->env.xen_vcpu_info_hva;
+}
+
+void kvm_xen_inject_vcpu_callback_vector(uint32_t vcpu_id, int type)
+{
+CPUState *cs = qemu_get_cpu(vcpu_id);
+uint8_t vector;
+
+if (!cs) {
+return;
+}
+
+vector = X86_CPU(cs)->env.xen_vcpu_callback_vector;
+if (vector) {
+/*
+ * The per-vCPU callback vector injected via lapic. Just
+ * deliver it as an MSI.
+ */
+MSIMessage msg = {
+.address = APIC_DEFAULT_ADDRESS | X86_CPU(cs)->apic_id,
+.data = vector | (1UL << MSI_DATA_LEVEL_SHIFT),
+};
+kvm_irqchip_send_msi(kvm_state, msg);
+return;
+}
+
+switch (type) {
+case HVM_PARAM_CALLBACK_TYPE_VECTOR:
+/*
+ * If the evtchn_upcall_pending field in the vcpu_info is set, then
+ * KVM will automatically deliver the vector on entering the vCPU
+ * so all we have to do is kick it out.
+ */
+qemu_cpu_kick(cs);
+br

Re: [PATCH v2 0/5] tsan fixes

2023-01-10 Thread Alex Bennée


Emilio Cota  writes:

> Changes since v1:
>
> - call g_free_rcu on tb_jmp_cache directly, and call
>   tcg_exec_unrealizefn after calling cpu_list_remove(cpu)
>
> - add patch to de-const qemu_spin_destroy
>
> - remove wrappers for qht_do_if_first_in_stripe
>
> Thanks,
>   Emilio

Queued to plugins/next, as there is some intersection with plugins.

Richard,

Please shout if you want to pull this stuff in directly.

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro



[RFC PATCH v1 03/15] hw/xen: Add gnttab operations to allow redirection to internal emulation

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

In emulation, mapping more than one grant ref to be virtually contiguous
would be fairly difficult. The best way to do it might be to make the
ram_block mappings actually backed by a file (shmem or a deleted file,
perhaps) so that we can have multiple *shared* mappings of it. But that
would be fairly intrusive.

Making the backend drivers cope with page *lists* instead of expecting
the mapping to be contiguous is also non-trivial, since some structures
would actually *cross* page boundaries (e.g. the 32-bit blkif responses
which are 12 bytes).

So for now, we'll support only single-page mappings in emulation.

Signed-off-by: David Woodhouse 
Signed-off-by: Paul Durrant 
---
 hw/xen/xen-bus.c| 112 ++--
 hw/xen/xen-legacy-backend.c | 125 ++
 hw/xen/xen-operations.c | 157 
 hw/xen/xen_pvdev.c  |   2 +-
 include/hw/xen/xen-bus.h|   3 +-
 include/hw/xen/xen-legacy-backend.h |  13 +--
 include/hw/xen/xen_backend_ops.h|  93 
 include/hw/xen/xen_common.h |  39 ---
 softmmu/globals.c   |   1 +
 9 files changed, 273 insertions(+), 272 deletions(-)

diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index e93df75d4f..ecdce3b98b 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -946,7 +946,7 @@ static void xen_device_frontend_destroy(XenDevice *xendev)
 void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
Error **errp)
 {
-if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) {
+if (qemu_xen_gnttab_set_max_grants(xendev->xgth, nr_refs)) {
 error_setg_errno(errp, errno, "xengnttab_set_max_grants failed");
 }
 }
@@ -955,9 +955,8 @@ void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t 
*refs,
 unsigned int nr_refs, int prot,
 Error **errp)
 {
-void *map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs,
-xendev->frontend_id, refs,
-prot);
+void *map = qemu_xen_gnttab_map_refs(xendev->xgth, nr_refs,
+ xendev->frontend_id, refs, prot);
 
 if (!map) {
 error_setg_errno(errp, errno,
@@ -970,109 +969,17 @@ void *xen_device_map_grant_refs(XenDevice *xendev, 
uint32_t *refs,
 void xen_device_unmap_grant_refs(XenDevice *xendev, void *map,
  unsigned int nr_refs, Error **errp)
 {
-if (xengnttab_unmap(xendev->xgth, map, nr_refs)) {
+if (qemu_xen_gnttab_unmap(xendev->xgth, map, nr_refs)) {
 error_setg_errno(errp, errno, "xengnttab_unmap failed");
 }
 }
 
-static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain,
-   XenDeviceGrantCopySegment segs[],
-   unsigned int nr_segs, Error **errp)
-{
-uint32_t *refs = g_new(uint32_t, nr_segs);
-int prot = to_domain ? PROT_WRITE : PROT_READ;
-void *map;
-unsigned int i;
-
-for (i = 0; i < nr_segs; i++) {
-XenDeviceGrantCopySegment *seg = &segs[i];
-
-refs[i] = to_domain ? seg->dest.foreign.ref :
-seg->source.foreign.ref;
-}
-
-map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs,
-  xendev->frontend_id, refs,
-  prot);
-if (!map) {
-error_setg_errno(errp, errno,
- "xengnttab_map_domain_grant_refs failed");
-goto done;
-}
-
-for (i = 0; i < nr_segs; i++) {
-XenDeviceGrantCopySegment *seg = &segs[i];
-void *page = map + (i * XC_PAGE_SIZE);
-
-if (to_domain) {
-memcpy(page + seg->dest.foreign.offset, seg->source.virt,
-   seg->len);
-} else {
-memcpy(seg->dest.virt, page + seg->source.foreign.offset,
-   seg->len);
-}
-}
-
-if (xengnttab_unmap(xendev->xgth, map, nr_segs)) {
-error_setg_errno(errp, errno, "xengnttab_unmap failed");
-}
-
-done:
-g_free(refs);
-}
-
 void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
 XenDeviceGrantCopySegment segs[],
 unsigned int nr_segs, Error **errp)
 {
-xengnttab_grant_copy_segment_t *xengnttab_segs;
-unsigned int i;
-
-if (!xendev->feature_grant_copy) {
-compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp);
-return;
-}
-
-xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
-
-for (i = 0; i < nr_segs; i++) {
-XenDeviceGrantCopySegment *seg = &segs[i];
-xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
-
-if (to_domain) {
-

[PATCH v6 08/51] xen-platform: allow its creation with XEN_EMULATE mode

2023-01-10 Thread David Woodhouse
From: Joao Martins 

The only thing we need to handle on KVM side is to change the
pfn from R/W to R/O.

Signed-off-by: Joao Martins 
Signed-off-by: David Woodhouse 
---
 hw/i386/xen/meson.build|  5 -
 hw/i386/xen/xen_platform.c | 39 +-
 2 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build
index be84130300..79d75cc927 100644
--- a/hw/i386/xen/meson.build
+++ b/hw/i386/xen/meson.build
@@ -2,6 +2,9 @@ i386_ss.add(when: 'CONFIG_XEN', if_true: files(
   'xen-hvm.c',
   'xen-mapcache.c',
   'xen_apic.c',
-  'xen_platform.c',
   'xen_pvdevice.c',
 ))
+
+i386_ss.add(when: 'CONFIG_XENFV_MACHINE', if_true: files(
+  'xen_platform.c',
+))
diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
index 50174c2269..00f0527b30 100644
--- a/hw/i386/xen/xen_platform.c
+++ b/hw/i386/xen/xen_platform.c
@@ -28,9 +28,9 @@
 #include "hw/ide.h"
 #include "hw/ide/pci.h"
 #include "hw/pci/pci.h"
-#include "hw/xen/xen_common.h"
 #include "migration/vmstate.h"
-#include "hw/xen/xen-legacy-backend.h"
+#include "hw/xen/xen.h"
+#include "net/net.h"
 #include "trace.h"
 #include "sysemu/xen.h"
 #include "sysemu/block-backend.h"
@@ -38,6 +38,11 @@
 #include "qemu/module.h"
 #include "qom/object.h"
 
+#ifdef CONFIG_XEN
+#include "hw/xen/xen_common.h"
+#include "hw/xen/xen-legacy-backend.h"
+#endif
+
 //#define DEBUG_PLATFORM
 
 #ifdef DEBUG_PLATFORM
@@ -280,18 +285,26 @@ static void platform_fixed_ioport_writeb(void *opaque, 
uint32_t addr, uint32_t v
 PCIXenPlatformState *s = opaque;
 
 switch (addr) {
-case 0: /* Platform flags */ {
-hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
-HVMMEM_ram_ro : HVMMEM_ram_rw;
-if (xen_set_mem_type(xen_domid, mem_type, 0xc0, 0x40)) {
-DPRINTF("unable to change ro/rw state of ROM memory area!\n");
-} else {
+case 0: /* Platform flags */
+if (xen_mode == XEN_EMULATE) {
+/* XX: Use i440gx/q35 PAM setup to do this? */
 s->flags = val & PFFLAG_ROM_LOCK;
-DPRINTF("changed ro/rw state of ROM memory area. now is %s 
state.\n",
-(mem_type == HVMMEM_ram_ro ? "ro":"rw"));
+#ifdef CONFIG_XEN
+} else {
+hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
+HVMMEM_ram_ro : HVMMEM_ram_rw;
+
+if (xen_set_mem_type(xen_domid, mem_type, 0xc0, 0x40)) {
+DPRINTF("unable to change ro/rw state of ROM memory area!\n");
+} else {
+s->flags = val & PFFLAG_ROM_LOCK;
+DPRINTF("changed ro/rw state of ROM memory area. now is %s 
state.\n",
+(mem_type == HVMMEM_ram_ro ? "ro" : "rw"));
+}
+#endif
 }
 break;
-}
+
 case 2:
 log_writeb(s, val);
 break;
@@ -509,8 +522,8 @@ static void xen_platform_realize(PCIDevice *dev, Error 
**errp)
 uint8_t *pci_conf;
 
 /* Device will crash on reset if xen is not initialized */
-if (!xen_enabled()) {
-error_setg(errp, "xen-platform device requires the Xen accelerator");
+if (xen_mode == XEN_DISABLED) {
+error_setg(errp, "xen-platform device requires a Xen guest");
 return;
 }
 
-- 
2.35.3




[PATCH v4 3/8] configure: replace Perl usage with sed

2023-01-10 Thread marcandre . lureau
From: Marc-André Lureau 

Let's try to reduce our Perl usage during config/build-time.

Note: this patch might be dropped if "configure: remove
backwards-compatibility code" is merged earlier.

Signed-off-by: Marc-André Lureau 
Tested-by: Thomas Huth 
---
 configure | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/configure b/configure
index 2281892657..9a944698b4 100755
--- a/configure
+++ b/configure
@@ -2571,11 +2571,9 @@ else
   if test -f meson-private/cmd_line.txt; then
 # Adjust old command line options whose type was changed
 # Avoids having to use "setup --wipe" when Meson is upgraded
-perl -i -ne '
-  s/^gettext = true$/gettext = auto/;
-  s/^gettext = false$/gettext = disabled/;
-  /^b_staticpic/ && next;
-  print;' meson-private/cmd_line.txt
+sed -i.bak -e 's/^gettext = true$/gettext = auto/g' \
+  -e 's/^gettext = false$/gettext = disabled/g' \
+  -e '/^b_staticpic/d' meson-private/cmd_line.txt
   fi
 fi
 
-- 
2.39.0




[PATCH v6 24/51] i386/xen: implement HVMOP_set_evtchn_upcall_vector

2023-01-10 Thread David Woodhouse
From: Ankur Arora 

The HVMOP_set_evtchn_upcall_vector hypercall sets the per-vCPU upcall
vector, to be delivered to the local APIC just like an MSI (with an EOI).

This takes precedence over the system-wide delivery method set by the
HVMOP_set_param hypercall with HVM_PARAM_CALLBACK_IRQ. It's used by
Windows and Xen (PV shim) guests but normally not by Linux.

Signed-off-by: Ankur Arora 
Signed-off-by: Joao Martins 
[dwmw2: Rework for upstream kernel changes and split from HVMOP_set_param]
Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 target/i386/cpu.h|  1 +
 target/i386/kvm/trace-events |  1 +
 target/i386/kvm/xen-emu.c| 84 ++--
 target/i386/machine.c|  1 +
 4 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index bf44a87ddb..938a1b9c8b 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1792,6 +1792,7 @@ typedef struct CPUArchState {
 uint64_t xen_vcpu_info_default_gpa;
 uint64_t xen_vcpu_time_info_gpa;
 uint64_t xen_vcpu_runstate_gpa;
+uint8_t xen_vcpu_callback_vector;
 #endif
 #if defined(CONFIG_HVF)
 HVFX86LazyFlags hvf_lflags;
diff --git a/target/i386/kvm/trace-events b/target/i386/kvm/trace-events
index 14e54dfca5..6133f6dd9e 100644
--- a/target/i386/kvm/trace-events
+++ b/target/i386/kvm/trace-events
@@ -10,3 +10,4 @@ kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
 kvm_xen_hypercall(int cpu, uint8_t cpl, uint64_t input, uint64_t a0, uint64_t 
a1, uint64_t a2, uint64_t ret) "xen_hypercall: cpu %d cpl %d input %" PRIu64 " 
a0 0x%" PRIx64 " a1 0x%" PRIx64 " a2 0x%" PRIx64" ret 0x%" PRIx64
 kvm_xen_set_shared_info(uint64_t gfn) "shared info at gfn 0x%" PRIx64
 kvm_xen_set_vcpu_attr(int cpu, int type, uint64_t gpa) "vcpu attr cpu %d type 
%d gpa 0x%" PRIx64
+kvm_xen_set_vcpu_callback(int cpu, int vector) "callback vcpu %d vector %d"
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index ff093328d7..d56d63b02e 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -26,6 +26,7 @@
 #include "standard-headers/xen/sched.h"
 #include "standard-headers/xen/memory.h"
 #include "standard-headers/xen/hvm/hvm_op.h"
+#include "standard-headers/xen/hvm/params.h"
 #include "standard-headers/xen/vcpu.h"
 #include "standard-headers/xen/event_channel.h"
 
@@ -192,7 +193,8 @@ static bool kvm_xen_hcall_xen_version(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 fi.submap |= 1 << XENFEAT_writable_page_tables |
  1 << XENFEAT_writable_descriptor_tables |
  1 << XENFEAT_auto_translated_physmap |
- 1 << XENFEAT_supervisor_mode_kernel;
+ 1 << XENFEAT_supervisor_mode_kernel |
+ 1 << XENFEAT_hvm_callback_vector;
 }
 
 err = kvm_copy_to_gva(CPU(cpu), arg, &fi, sizeof(fi));
@@ -219,6 +221,31 @@ static int kvm_xen_set_vcpu_attr(CPUState *cs, uint16_t 
type, uint64_t gpa)
 return kvm_vcpu_ioctl(cs, KVM_XEN_VCPU_SET_ATTR, &xhsi);
 }
 
+static int kvm_xen_set_vcpu_callback_vector(CPUState *cs)
+{
+uint8_t vector = X86_CPU(cs)->env.xen_vcpu_callback_vector;
+struct kvm_xen_vcpu_attr xva;
+
+xva.type = KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR;
+xva.u.vector = vector;
+
+trace_kvm_xen_set_vcpu_callback(cs->cpu_index, vector);
+
+return kvm_vcpu_ioctl(cs, KVM_XEN_HVM_SET_ATTR, &xva);
+}
+
+static void do_set_vcpu_callback_vector(CPUState *cs, run_on_cpu_data data)
+{
+X86CPU *cpu = X86_CPU(cs);
+CPUX86State *env = &cpu->env;
+
+env->xen_vcpu_callback_vector = data.host_int;
+
+if (kvm_xen_has_cap(EVTCHN_SEND)) {
+kvm_xen_set_vcpu_callback_vector(cs);
+}
+}
+
 static void do_set_vcpu_info_default_gpa(CPUState *cs, run_on_cpu_data data)
 {
 X86CPU *cpu = X86_CPU(cs);
@@ -275,12 +302,16 @@ static void do_vcpu_soft_reset(CPUState *cs, 
run_on_cpu_data data)
 env->xen_vcpu_info_default_gpa = INVALID_GPA;
 env->xen_vcpu_time_info_gpa = INVALID_GPA;
 env->xen_vcpu_runstate_gpa = INVALID_GPA;
+env->xen_vcpu_callback_vector = 0;
 
 kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO, INVALID_GPA);
 kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO,
   INVALID_GPA);
 kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR,
   INVALID_GPA);
+if (kvm_xen_has_cap(EVTCHN_SEND)) {
+kvm_xen_set_vcpu_callback_vector(cs);
+}
 
 }
 
@@ -455,17 +486,53 @@ static bool kvm_xen_hcall_memory_op(struct kvm_xen_exit 
*exit, X86CPU *cpu,
 return true;
 }
 
+static int kvm_xen_hcall_evtchn_upcall_vector(struct kvm_xen_exit *exit,
+  X86CPU *cpu, uint64_t arg)
+{
+struct xen_hvm_evtchn_upcall_vector up;
+CPUState *target_cs;
+
+/* No need for 32/64 compat handling */
+qemu_build_assert(sizeof(u

[PATCH v6 28/51] hw/xen: Implement EVTCHNOP_status

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

This adds the basic structure for maintaining the port table and reporting
the status of ports therein.

Signed-off-by: David Woodhouse 
---
 hw/i386/kvm/xen_evtchn.c  | 104 ++
 hw/i386/kvm/xen_evtchn.h  |   3 ++
 include/sysemu/kvm_xen.h  |   3 ++
 target/i386/kvm/xen-emu.c |  20 +++-
 4 files changed, 128 insertions(+), 2 deletions(-)

diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 018f4ef4da..ff143a8134 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -22,6 +22,7 @@
 #include "hw/sysbus.h"
 #include "hw/xen/xen.h"
 #include "xen_evtchn.h"
+#include "xen_overlay.h"
 
 #include "sysemu/kvm.h"
 #include "sysemu/kvm_xen.h"
@@ -33,6 +34,22 @@
 #define TYPE_XEN_EVTCHN "xen-evtchn"
 OBJECT_DECLARE_SIMPLE_TYPE(XenEvtchnState, XEN_EVTCHN)
 
+typedef struct XenEvtchnPort {
+uint32_t vcpu;  /* Xen/ACPI vcpu_id */
+uint16_t type;  /* EVTCHNSTAT_ */
+uint16_t type_val;  /* pirq# / virq# / remote port according to type */
+} XenEvtchnPort;
+
+#define COMPAT_EVTCHN_2L_NR_CHANNELS1024
+
+/*
+ * For unbound/interdomain ports there are only two possible remote
+ * domains; self and QEMU. Use a single high bit in type_val for that,
+ * and the low bits for the remote port number (or 0 for unbound).
+ */
+#define PORT_INFO_TYPEVAL_REMOTE_QEMU   0x8000
+#define PORT_INFO_TYPEVAL_REMOTE_PORT_MASK  0x7FFF
+
 struct XenEvtchnState {
 /*< private >*/
 SysBusDevice busdev;
@@ -42,6 +59,8 @@ struct XenEvtchnState {
 bool evtchn_in_kernel;
 
 QemuMutex port_lock;
+uint32_t nr_ports;
+XenEvtchnPort port_table[EVTCHN_2L_NR_CHANNELS];
 };
 
 struct XenEvtchnState *xen_evtchn_singleton;
@@ -65,6 +84,18 @@ static bool xen_evtchn_is_needed(void *opaque)
 return xen_mode == XEN_EMULATE;
 }
 
+static const VMStateDescription xen_evtchn_port_vmstate = {
+.name = "xen_evtchn_port",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(vcpu, XenEvtchnPort),
+VMSTATE_UINT16(type, XenEvtchnPort),
+VMSTATE_UINT16(type_val, XenEvtchnPort),
+VMSTATE_END_OF_LIST()
+}
+};
+
 static const VMStateDescription xen_evtchn_vmstate = {
 .name = "xen_evtchn",
 .version_id = 1,
@@ -73,6 +104,9 @@ static const VMStateDescription xen_evtchn_vmstate = {
 .post_load = xen_evtchn_post_load,
 .fields = (VMStateField[]) {
 VMSTATE_UINT64(callback_param, XenEvtchnState),
+VMSTATE_UINT32(nr_ports, XenEvtchnState),
+VMSTATE_STRUCT_VARRAY_UINT32(port_table, XenEvtchnState, nr_ports, 1,
+ xen_evtchn_port_vmstate, XenEvtchnPort),
 VMSTATE_END_OF_LIST()
 }
 };
@@ -146,3 +180,73 @@ int xen_evtchn_set_callback_param(uint64_t param)
 
 return ret;
 }
+
+static bool valid_port(evtchn_port_t port)
+{
+if (!port) {
+return false;
+}
+
+if (xen_is_long_mode()) {
+return port < EVTCHN_2L_NR_CHANNELS;
+} else {
+return port < COMPAT_EVTCHN_2L_NR_CHANNELS;
+}
+}
+
+int xen_evtchn_status_op(struct evtchn_status *status)
+{
+XenEvtchnState *s = xen_evtchn_singleton;
+XenEvtchnPort *p;
+
+if (!s) {
+return -ENOTSUP;
+}
+
+if (status->dom != DOMID_SELF && status->dom != xen_domid) {
+return -ESRCH;
+}
+
+if (!valid_port(status->port)) {
+return -EINVAL;
+}
+
+qemu_mutex_lock(&s->port_lock);
+
+p = &s->port_table[status->port];
+
+status->status = p->type;
+status->vcpu = p->vcpu;
+
+switch (p->type) {
+case EVTCHNSTAT_unbound:
+if (p->type_val & PORT_INFO_TYPEVAL_REMOTE_QEMU) {
+status->u.unbound.dom = DOMID_QEMU;
+} else {
+status->u.unbound.dom = xen_domid;
+}
+break;
+
+case EVTCHNSTAT_interdomain:
+if (p->type_val & PORT_INFO_TYPEVAL_REMOTE_QEMU) {
+status->u.interdomain.dom = DOMID_QEMU;
+} else {
+status->u.interdomain.dom = xen_domid;
+}
+
+status->u.interdomain.port = p->type_val &
+PORT_INFO_TYPEVAL_REMOTE_PORT_MASK;
+break;
+
+case EVTCHNSTAT_pirq:
+status->u.pirq = p->type_val;
+break;
+
+case EVTCHNSTAT_virq:
+status->u.virq = p->type_val;
+break;
+}
+
+qemu_mutex_unlock(&s->port_lock);
+return 0;
+}
diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h
index c9b7f9d11f..76467636ee 100644
--- a/hw/i386/kvm/xen_evtchn.h
+++ b/hw/i386/kvm/xen_evtchn.h
@@ -15,4 +15,7 @@
 void xen_evtchn_create(void);
 int xen_evtchn_set_callback_param(uint64_t param);
 
+struct evtchn_status;
+int xen_evtchn_status_op(struct evtchn_status *status);
+
 #endif /* QEMU_XEN_EVTCHN_H */
diff --git a/include/sysemu/kvm_xen.h b/include/sysemu/kvm_xen.h
index ee53294deb..2192ceea10 100644
--- a/include/sysemu/kvm_xen.h
+++ 

Re: [RFC PATCH v2 13/19] tests: do not run test-hmp on all machines for ARM KVM-only

2023-01-10 Thread Fabiano Rosas
Thomas Huth  writes:

> On 09/01/2023 23.42, Fabiano Rosas wrote:
>> From: Claudio Fontana 
>> 
>> on ARM we currently list and build all machines, even when
>> building KVM-only, without TCG.
>> 
>> Until we fix this (and we only list and build machines that are
>> compatible with KVM), only test specifically using the "virt"
>> machine in this case.
>
> Why don't you fix it immediately? ... 

My idea was to have in this series the minimum to unbreak the
--disable-tcg build and later bring the rest of the changes
incrementally.

(plus the cpregs code movement which conflicts with everything, so I'd
rather merge it sooner)

> it shouldn't be too hard to add some 
> "depends on TCG" statements to the machine entries in hw/arm/Kconfig, should 
> it?

I havent't looked into it yet. If it turns out to be simple I can do it
now.

> Anyway, if that's not possible (yet), I suggest to add your hack to 
> qtest_cb_for_every_machine() instead, so you could change this in one 
> central place instead of adding a hack to each and every test that uses this 
> function.

Good idea.

>
>   Thomas



[PATCH v4 1/8] build-sys: fix crlf-ending C code

2023-01-10 Thread marcandre . lureau
From: Marc-André Lureau 

On msys2, the shader-to-C script produces bad C:
./ui/shader/texture-blit-vert.h:2:5: error: missing terminating " character 
[-Werror]

Fix it by changing the line ending from crlf to lf, and convert the
script to Python (qemu build seems perl-free after that).

Signed-off-by: Marc-André Lureau 
Acked-by: Thomas Huth 
---
 meson.build  |  2 +-
 scripts/shaderinclude.pl | 16 
 scripts/shaderinclude.py | 26 ++
 3 files changed, 27 insertions(+), 17 deletions(-)
 delete mode 100644 scripts/shaderinclude.pl
 create mode 100644 scripts/shaderinclude.py

diff --git a/meson.build b/meson.build
index 175517eafd..b3c6db8343 100644
--- a/meson.build
+++ b/meson.build
@@ -2781,7 +2781,7 @@ config_host_data.set('CONFIG_SLIRP', slirp.found())
 genh += configure_file(output: 'config-host.h', configuration: 
config_host_data)
 
 hxtool = find_program('scripts/hxtool')
-shaderinclude = find_program('scripts/shaderinclude.pl')
+shaderinclude = find_program('scripts/shaderinclude.py')
 qapi_gen = find_program('scripts/qapi-gen.py')
 qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
  meson.current_source_dir() / 'scripts/qapi/commands.py',
diff --git a/scripts/shaderinclude.pl b/scripts/shaderinclude.pl
deleted file mode 100644
index cd3bb40b12..00
--- a/scripts/shaderinclude.pl
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env perl
-use strict;
-use warnings;
-
-my $file = shift;
-open FILE, "<", $file or die "open $file: $!";
-my $name = $file;
-$name =~ s|.*/||;
-$name =~ s/[-.]/_/g;
-print "static GLchar ${name}_src[] =\n";
-while () {
-chomp;
-printf "\"%s\\n\"\n", $_;
-}
-print "\"\\n\";\n";
-close FILE;
diff --git a/scripts/shaderinclude.py b/scripts/shaderinclude.py
new file mode 100644
index 00..ab2aade2cd
--- /dev/null
+++ b/scripts/shaderinclude.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 Red Hat, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import sys
+import os
+
+
+def main(args):
+file_path = args[1]
+basename = os.path.basename(file_path)
+varname = basename.replace('-', '_').replace('.', '_')
+
+with os.fdopen(sys.stdout.fileno(), "wt", closefd=False, newline='\n') as 
stdout:
+with open(file_path, "r", encoding='utf-8') as file:
+print(f'static GLchar {varname}_src[] =', file=stdout)
+for line in file:
+line = line.rstrip()
+print(f'"{line}\\n"', file=stdout)
+print('"\\n";', file=stdout)
+
+
+if __name__ == '__main__':
+sys.exit(main(sys.argv))
-- 
2.39.0




[RFC PATCH v1 00/15] Xen PV backend support for KVM/Xen guests

2023-01-10 Thread David Woodhouse
This is a very early preview of phase 2, in which we make the PV backend 
drivers build. Mostly by providing operations tables that can be backed 
either by the true Xen toolstack libraries, or by the internal emulated 
versions. But also a bunch of untangling of headers to keep things sane.

Some parts of it are relatively straightforward; others less so. In
particular, it looks really hard to provide a contiguous virtual mapping
of multiple potentially discontiguous pages granted by the guest. To
fix that we might actually need the guest memory blocks to be backed
by real files (perhaps deleted or shmem) in order that they can be mapped
again in at a different virtual address. So for now we'll limit the
back ends to mapping a single grant ref at a time.

https://git.infradead.org/users/dwmw2/qemu.git/shortlog/refs/heads/xenfv-kvm-backends-1

David Woodhouse (14):
  hw/xen: Add evtchn operations to allow redirection to internal emulation
  hw/xen: Add emulated evtchn ops
  hw/xen: Add gnttab operations to allow redirection to internal emulation
  hw/xen: Pass grant ref to gnttab unmap
  hw/xen: Add foreignmem operations to allow redirection to internal 
emulation
  hw/xen: Move xenstore_store_pv_console_info to xen_console.c
  hw/xen: Use XEN_PAGE_SIZE in PV backend drivers
  hw/xen: Rename xen_common.h to xen_native.h
  hw/xen: Build PV backend drivers for XENFV_MACHINE
  hw/xen: Map guest XENSTORE_PFN grant in emulated Xenstore
  hw/xen: Add backend implementation of grant table operations
  hw/xen: Implement soft reset for emulated gnttab
  hw/xen: Remove old version of Xen headers
  i386/xen: Initialize XenBus and legacy backends from pc_init1()

Paul Durrant (1):
  hw/xen: Add xenstore operations to allow redirection to internal emulation

 accel/xen/xen-all.c   |   69 +-
 hw/9pfs/meson.build   |2 +-
 hw/9pfs/xen-9p-backend.c  |   32 +-
 hw/9pfs/xen-9pfs.h|4 +-
 hw/block/dataplane/meson.build|2 +-
 hw/block/dataplane/xen-block.c|   12 +-
 hw/block/meson.build  |2 +-
 hw/block/xen-block.c  |1 -
 hw/block/xen_blkif.h  |5 +-
 hw/char/meson.build   |2 +-
 hw/char/xen_console.c |   59 +-
 hw/display/meson.build|2 +-
 hw/display/xenfb.c|   38 +-
 hw/i386/kvm/xen_evtchn.c  |   15 +
 hw/i386/kvm/xen_gnttab.c  |  320 +++-
 hw/i386/kvm/xen_gnttab.h  |1 +
 hw/i386/kvm/xen_xenstore.c|   13 +-
 hw/i386/pc_piix.c |   17 +
 hw/i386/xen/xen-hvm.c |   45 +-
 hw/i386/xen/xen-mapcache.c|2 +-
 hw/i386/xen/xen_platform.c|7 +-
 hw/net/xen_nic.c  |   27 +-
 hw/usb/meson.build|2 +-
 hw/usb/xen-usb.c  |   31 +-
 hw/xen/meson.build|6 +-
 hw/xen/trace-events   |2 +-
 hw/xen/xen-bus-helper.c   |   61 +-
 hw/xen/xen-bus.c  |  394 ++
 hw/xen/xen-legacy-backend.c   |  256 ++-
 hw/xen/xen-operations.c   |  487 
 hw/xen/xen_devconfig.c|4 +-
 hw/xen/xen_pt.c   |2 +-
 hw/xen/xen_pt.h   |2 +-
 hw/xen/xen_pt_config_init.c   |2 +-
 hw/xen/xen_pt_graphics.c  |1 -
 hw/xen/xen_pt_msi.c   |4 +-
 hw/xen/xen_pvdev.c|   63 +-
 include/hw/xen/interface/grant_table.h|   36 -
 include/hw/xen/interface/io/blkif.h   |  712 -
 include/hw/xen/interface/io/console.h |   46 --
 include/hw/xen/interface/io/fbif.h|  156 
 include/hw/xen/interface/io/kbdif.h   |  566 --
 include/hw/xen/interface/io/netif.h   | 1010 -
 include/hw/xen/interface/io/protocols.h   |   42 -
 include/hw/xen/interface/io/ring.h|  474 
 include/hw/xen/interface/io/usbif.h   |  254 ---
 include/hw/xen/interface/io/xenbus.h  |   70 --
 include/hw/xen/xen-bus-helper.h   |   25 +-
 include/hw/xen/xen-bus.h  |   21 +-
 include/hw/xen/xen-legacy-backend.h   |   24 +-
 include/hw/xen/xen.h  |   24 +-
 include/hw/xen/xen_backend_ops.h  |  393 ++
 include/hw/xen/{xen_common.h => xen_native.h} |   75 +-
 include/hw/xen/xen_pvdev.h  

[RFC PATCH v1 07/15] hw/xen: Move xenstore_store_pv_console_info to xen_console.c

2023-01-10 Thread David Woodhouse
From: David Woodhouse 

There's no need for this to be in the Xen accel code, and as we want to
use the Xen console support with KVM-emulated Xen we'll want to have a
platform-agnostic version of it. Make it use GString to build up the
path while we're at it.

Signed-off-by: David Woodhouse 
---
 accel/xen/xen-all.c   | 61 ---
 hw/char/xen_console.c | 45 +--
 include/hw/xen/xen.h  |  2 --
 3 files changed, 43 insertions(+), 65 deletions(-)

diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c
index 6df7b4ff34..514bc9eea4 100644
--- a/accel/xen/xen-all.c
+++ b/accel/xen/xen-all.c
@@ -39,67 +39,6 @@ xc_interface *xen_xc;
 xenforeignmemory_handle *xen_fmem;
 xendevicemodel_handle *xen_dmod;
 
-static int store_dev_info(int domid, Chardev *cs, const char *string)
-{
-struct xs_handle *xs = NULL;
-char *path = NULL;
-char *newpath = NULL;
-char *pts = NULL;
-int ret = -1;
-
-/* Only continue if we're talking to a pty. */
-if (!CHARDEV_IS_PTY(cs)) {
-return 0;
-}
-pts = cs->filename + 4;
-
-/* We now have everything we need to set the xenstore entry. */
-xs = xs_open(0);
-if (xs == NULL) {
-fprintf(stderr, "Could not contact XenStore\n");
-goto out;
-}
-
-path = xs_get_domain_path(xs, domid);
-if (path == NULL) {
-fprintf(stderr, "xs_get_domain_path() error\n");
-goto out;
-}
-newpath = realloc(path, (strlen(path) + strlen(string) +
-strlen("/tty") + 1));
-if (newpath == NULL) {
-fprintf(stderr, "realloc error\n");
-goto out;
-}
-path = newpath;
-
-strcat(path, string);
-strcat(path, "/tty");
-if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
-fprintf(stderr, "xs_write for '%s' fail", string);
-goto out;
-}
-ret = 0;
-
-out:
-free(path);
-xs_close(xs);
-
-return ret;
-}
-
-void xenstore_store_pv_console_info(int i, Chardev *chr)
-{
-if (i == 0) {
-store_dev_info(xen_domid, chr, "/console");
-} else {
-char buf[32];
-snprintf(buf, sizeof(buf), "/device/console/%d", i);
-store_dev_info(xen_domid, chr, buf);
-}
-}
-
-
 static void xenstore_record_dm_state(const char *state)
 {
 struct xs_handle *xs;
diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
index ad8638a86d..c7a19c0e7c 100644
--- a/hw/char/xen_console.c
+++ b/hw/char/xen_console.c
@@ -173,6 +173,48 @@ static void xencons_send(struct XenConsole *con)
 
 /*  */
 
+static int store_con_info(struct XenConsole *con)
+{
+Chardev *cs = qemu_chr_fe_get_driver(&con->chr);
+char *pts = NULL;
+char *dom_path;
+GString *path;
+int ret = -1;
+
+/* Only continue if we're talking to a pty. */
+if (!CHARDEV_IS_PTY(cs)) {
+return 0;
+}
+pts = cs->filename + 4;
+
+dom_path = qemu_xen_xs_get_domain_path(xenstore, xen_domid);
+if (!dom_path) {
+return 0;
+}
+
+path = g_string_new(dom_path);
+free(dom_path);
+
+if (con->xendev.dev) {
+g_string_append_printf(path, "/device/console/%d", con->xendev.dev);
+} else {
+g_string_append(path, "/console");
+}
+g_string_append(path, "/tty");
+
+if (xenstore_write_str(con->console, path->str, pts)) {
+fprintf(stderr, "xenstore_write_str for '%s' fail", path->str);
+goto out;
+}
+ret = 0;
+
+out:
+g_string_free(path, true);
+free(path);
+
+return ret;
+}
+
 static int con_init(struct XenLegacyDevice *xendev)
 {
 struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
@@ -215,8 +257,7 @@ static int con_init(struct XenLegacyDevice *xendev)
  &error_abort);
 }
 
-xenstore_store_pv_console_info(con->xendev.dev,
-   qemu_chr_fe_get_driver(&con->chr));
+store_con_info(con);
 
 out:
 g_free(type);
diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
index b3873c581b..fcc6c5b522 100644
--- a/include/hw/xen/xen.h
+++ b/include/hw/xen/xen.h
@@ -39,8 +39,6 @@ int xen_is_pirq_msi(uint32_t msi_data);
 
 qemu_irq *xen_interrupt_controller_init(void);
 
-void xenstore_store_pv_console_info(int i, Chardev *chr);
-
 void xen_register_framebuffer(struct MemoryRegion *mr);
 
 #endif /* QEMU_HW_XEN_H */
-- 
2.35.3




[PATCH v4 4/8] meson: replace Perl usage with Python

2023-01-10 Thread marcandre . lureau
From: Marc-André Lureau 

Let's try to remove Perl usage during build time.

Signed-off-by: Marc-André Lureau 
---
 tests/qapi-schema/meson.build | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build
index 9dfe98bc9a..d85b14f28c 100644
--- a/tests/qapi-schema/meson.build
+++ b/tests/qapi-schema/meson.build
@@ -259,22 +259,23 @@ if build_docs
   # Fix possible inconsistency in line endings in generated output and
   # in the golden reference (which could otherwise cause test failures
   # on Windows hosts). Unfortunately diff --strip-trailing-cr
-  # is GNU-diff only. The odd-looking perl is because we must avoid
+  # is GNU-diff only. The odd-looking python is because we must avoid
   # using an explicit '\' character in the command arguments to
   # a custom_target(), as Meson will unhelpfully replace it with a '/'
   # (https://github.com/mesonbuild/meson/issues/1564)
+  remove_cr = [python, '-c', 'import 
sys;[sys.stdout.write(line.replace(chr(13), "")) for line in sys.stdin]']
   qapi_doc_out_nocr = custom_target('QAPI rST doc newline-sanitized',
 output: ['doc-good.txt.nocr'],
 input: qapi_doc_out[0],
 build_by_default: true,
-command: ['perl', '-pe', '$x = chr 13; 
s/$x$//', '@INPUT@'],
+command: [remove_cr, '@INPUT@'],
 capture: true)
 
   qapi_doc_ref_nocr = custom_target('QAPI rST doc reference newline-sanitized',
 output: ['doc-good.ref.nocr'],
 input: files('doc-good.txt'),
 build_by_default: true,
-command: ['perl', '-pe', '$x = chr 13; 
s/$x$//', '@INPUT@'],
+command: [remove_cr, '@INPUT@'],
 capture: true)
 
   test('QAPI rST doc', diff, args: ['-u', qapi_doc_ref_nocr[0], 
qapi_doc_out_nocr[0]],
-- 
2.39.0




Re: [RFC PATCH 0/4] qom: Introduce object_class_property_deprecate()

2023-01-10 Thread Kevin Wolf
Am 09.01.2023 um 23:54 hat Philippe Mathieu-Daudé geschrieben:
> Hi,
> 
> There will always be a need to deprecate things. Here I'm
> tackling the QOM (class) properties, since they can be set
> from some CLI options (-object -device -global ...).
> 
> As an experiment, we add object_class_property_deprecate()
> to register a class property as deprecated (since some version),
> then we deprecate the TYPE_PFLASH_CFI02 'width' property, and
> finally as a bonus we emit a warning when the deprecation period
> is over, as a reminder. (For that we introduce few 'versions'
> helpers).

The last part means that increasing the version number (i.e. the commit
that opens the development tree for the next release) can change the
output, and this is turn can break test cases.

If we are happy to introduce breakage with a version number change that
will require future commits to open the development tree less trivial
than they are today because they need to fix the breakage, too, why not
make it a build error instead of a different warning message at runtime?

Kevin




  1   2   3   4   >