Re: [PATCH v4] hw/nvme: Use ioeventfd to handle doorbell updates

2022-07-06 Thread Klaus Jensen
On Jul  6 19:34, Jinhao Fan wrote:
> at 2:43 AM, Keith Busch  wrote:
> 
> > On Tue, Jul 05, 2022 at 07:11:36PM +0200, Klaus Jensen wrote:
> >> On Jul  5 22:24, Jinhao Fan wrote:
> >>> @@ -1374,7 +1374,14 @@ static void nvme_enqueue_req_completion(NvmeCQueue 
> >>> *cq, NvmeRequest *req)
> >>> 
> >>> QTAILQ_REMOVE(>sq->out_req_list, req, entry);
> >>> QTAILQ_INSERT_TAIL(>req_list, req, entry);
> >>> -timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
> >>> +
> >>> +if (req->sq->ioeventfd_enabled) {
> >>> +/* Post CQE directly since we are in main loop thread */
> >>> +nvme_post_cqes(cq);
> >>> +} else {
> >>> +/* Schedule the timer to post CQE later since we are in vcpu 
> >>> thread */
> >>> +timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 
> >>> 500);
> >>> +}
> >> 
> >> Actually, we are only in the vcpu thread if we come here from
> >> nvme_process_db that in very rare circumstances may enqueue the
> >> completion of an AER due to an invalid doorbell write.
> >> 
> >> In general, nvme_enqueue_req_completion is only ever called from the
> >> main iothread. Which actually causes me to wonder why we defer this work
> >> in the first place. It does have the benefit that we queue up several
> >> completions before posting them in one go and raising the interrupt.
> >> But I wonder if that could be handled better.
> > 
> > I think the timer is used because of the cq_full condition. We need to 
> > restart
> > completions when it becomes not full, which requires a doorbell write. 
> > Having
> > everyone from the main iothread use the same timer as the doorbell handler 
> > just
> > ensures single threaded list access.
> 
> Could we let nvme_process_aers register another timer/BH to trigger
> nvme_enqueue_req_completion in the iothread? In this way we won’t need the
> timer_mod in nvme_enqueue_req_completion.

Yes, we could have process_aers in a timer. Which would probably be
preferable in order to limit the amount of work the mmio handler is
doing in that rare case. However, its such a rare case (only misbehaving
drivers) that it's probably not worth optimizing for.

> We can also avoid some potential currency problems because CQ is only
> modified in the iothread.
> 

There are currently no concurrency problems because of the Big QEMU
Lock. When the mmio handler is running, the vcpu holds the BQL (and
whenever the main iothread is running, it is holding the BQL).

> BTW, are there any reason that we must use timers (not BH) here? Also why do
> we choose to delay for 500ns?

No particular reason. do not see any reason why this could not be bottom
halfs. This will likely change into bhs when we add iothread support
anyway.


signature.asc
Description: PGP signature


Re: [PATCH] hw/pci/pci_bridge: ensure PCIe slots have only one slot

2022-07-06 Thread Michael S. Tsirkin
On Mon, Jul 04, 2022 at 01:25:14PM +0300, Roman Kagan wrote:
> It's possible to create non-working configurations by attaching a device
> to a derivative of PCIe slot (pcie-root-port, ioh3420, etc) and
> specifying a slot number other that zero, e.g.:
> 
> -device pcie-root-port,id=s0,... \
> -device virtio-blk-pci,bus=s0,addr=4,...
> 
> Make QEMU reject such configurations and only allow addr=0 on the
> secondary bus of a PCIe slot.
> 
> Signed-off-by: Roman Kagan 
> ---
>  hw/pci/pci_bridge.c | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
> index da34c8ebcd..8b38d5ad3d 100644
> --- a/hw/pci/pci_bridge.c
> +++ b/hw/pci/pci_bridge.c
> @@ -33,6 +33,7 @@
>  #include "qemu/units.h"
>  #include "hw/pci/pci_bridge.h"
>  #include "hw/pci/pci_bus.h"
> +#include "hw/pci/pcie_port.h"
>  #include "qemu/module.h"
>  #include "qemu/range.h"
>  #include "qapi/error.h"
> @@ -386,6 +387,10 @@ void pci_bridge_initfn(PCIDevice *dev, const char 
> *typename)
>  br->windows = pci_bridge_region_init(br);
>  QLIST_INIT(_bus->child);
>  QLIST_INSERT_HEAD(>child, sec_bus, sibling);
> +
> +if (PCIE_SLOT(dev)) {
> +sec_bus->slot_reserved_mask = ~1u;
> +}


Please add comments explaining what's going on.

>  }
>  
>  /* default qdev clean up function for PCI-to-PCI bridge */
> -- 
> 2.36.1




Re: [PATCH] hw/pci/pci_bridge: ensure PCIe slots have only one slot

2022-07-06 Thread Michael S. Tsirkin
On Wed, Jul 06, 2022 at 10:43:12PM +0300, Roman Kagan wrote:
> On Wed, Jul 06, 2022 at 09:38:39PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> > On 7/4/22 13:25, Roman Kagan wrote:
> > > It's possible to create non-working configurations by attaching a device
> > > to a derivative of PCIe slot (pcie-root-port, ioh3420, etc) and
> > > specifying a slot number other that zero, e.g.:
> > > 
> > >  -device pcie-root-port,id=s0,... \
> > >  -device virtio-blk-pci,bus=s0,addr=4,...
> > > 
> > > Make QEMU reject such configurations and only allow addr=0 on the
> > > secondary bus of a PCIe slot.
> > > 
> > > Signed-off-by: Roman Kagan 
> > > ---
> > >   hw/pci/pci_bridge.c | 5 +
> > >   1 file changed, 5 insertions(+)
> > > 
> > > diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
> > > index da34c8ebcd..8b38d5ad3d 100644
> > > --- a/hw/pci/pci_bridge.c
> > > +++ b/hw/pci/pci_bridge.c
> > > @@ -33,6 +33,7 @@
> > >   #include "qemu/units.h"
> > >   #include "hw/pci/pci_bridge.h"
> > >   #include "hw/pci/pci_bus.h"
> > > +#include "hw/pci/pcie_port.h"
> > >   #include "qemu/module.h"
> > >   #include "qemu/range.h"
> > >   #include "qapi/error.h"
> > > @@ -386,6 +387,10 @@ void pci_bridge_initfn(PCIDevice *dev, const char 
> > > *typename)
> > >   br->windows = pci_bridge_region_init(br);
> > >   QLIST_INIT(_bus->child);
> > >   QLIST_INSERT_HEAD(>child, sec_bus, sibling);
> > > +
> > > +if (PCIE_SLOT(dev)) {
> > 
> > Hmm, wouldn't PCIE_SLOT just crash if dev is not pcie slot? As I 
> > understand, PCIE_SLOT is finally an OBJECT_CHECK(), which say:
> > 
> >  * If an invalid object is passed to this function, a run time assert will 
> > be
> >  * generated.
> 
> Well, the assertion is there only if configured with
> --enable-qom-cast-debug which is off by default, that's why it even
> passed make check.  As it stands, it's just a typecast which is a no-op
> here, and basically it makes every bridge have only a single slot, which
> is wrong of course.
> 
> Will rework, thanks!
> Roman.

Which probably means it was not actually tested that the patch
rejects the invalid configuration, was it?

-- 
MST




[PATCH v3 13/13] iotests: fix copy-before-write for macOS and FreeBSD

2022-07-06 Thread John Snow
From: Vladimir Sementsov-Ogievskiy 

Do not merge: this is a copy of Vladimir's fix that will be taken in
through the iotests tree.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
Signed-off-by: John Snow 
---
 tests/qemu-iotests/tests/copy-before-write | 5 +
 1 file changed, 5 insertions(+)

diff --git a/tests/qemu-iotests/tests/copy-before-write 
b/tests/qemu-iotests/tests/copy-before-write
index 16efebbf8f0..56937b9dfff 100755
--- a/tests/qemu-iotests/tests/copy-before-write
+++ b/tests/qemu-iotests/tests/copy-before-write
@@ -192,6 +192,11 @@ read 1048576/1048576 bytes at offset 0
 
 def test_timeout_break_guest(self):
 log = self.do_cbw_timeout('break-guest-write')
+# macOS and FreeBSD tend to represent ETIMEDOUT as
+# "Operation timed out", when Linux prefer
+# "Connection timed out"
+log = log.replace('Operation timed out',
+  'Connection timed out')
 self.assertEqual(log, """\
 wrote 524288/524288 bytes at offset 0
 512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-- 
2.34.3




[PATCH v3 03/13] tests/vm: switch CentOS 8 to CentOS 8 Stream

2022-07-06 Thread John Snow
The old CentOS image didn't work anymore because it was already EOL at
the beginning of 2022.

Signed-off-by: John Snow 
Reviewed-by: Thomas Huth 
---
 tests/vm/centos | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/vm/centos b/tests/vm/centos
index be4f6ff2f14..3a527c47b3d 100755
--- a/tests/vm/centos
+++ b/tests/vm/centos
@@ -1,8 +1,8 @@
 #!/usr/bin/env python3
 #
-# CentOS image
+# CentOS 8 Stream image
 #
-# Copyright 2018 Red Hat Inc.
+# Copyright 2018, 2022 Red Hat Inc.
 #
 # Authors:
 #  Fam Zheng 
@@ -32,7 +32,7 @@ class CentosVM(basevm.BaseVM):
 """
 
 def build_image(self, img):
-cimg = 
self._download_with_cache("https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.3.2011-20201204.2.x86_64.qcow2;)
+cimg = 
self._download_with_cache("https://cloud.centos.org/centos/8-stream/x86_64/images/CentOS-Stream-GenericCloud-8-20220125.1.x86_64.qcow2;)
 img_tmp = img + ".tmp"
 subprocess.check_call(['cp', '-f', cimg, img_tmp])
 self.exec_qemu_img("resize", img_tmp, "50G")
-- 
2.34.3




[PATCH v3 10/13] tests/vm: Remove docker cross-compile test from CentOS VM

2022-07-06 Thread John Snow
The fedora container has since been split apart, so there's no suitable
nearby target that would support "test-mingw" as it requires both x32
and x64 support -- so either fedora-cross-win32 nor fedora-cross-win64
would be truly suitable.

Just remove this test as superfluous with our current CI infrastructure.

Signed-off-by: John Snow 
---
 tests/vm/centos | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/vm/centos b/tests/vm/centos
index 3a527c47b3d..097a9ca14d3 100755
--- a/tests/vm/centos
+++ b/tests/vm/centos
@@ -28,7 +28,6 @@ class CentosVM(basevm.BaseVM):
 tar -xf $SRC_ARCHIVE;
 make docker-test-block@centos8 {verbose} J={jobs} NETWORK=1;
 make docker-test-quick@centos8 {verbose} J={jobs} NETWORK=1;
-make docker-test-mingw@fedora  {verbose} J={jobs} NETWORK=1;
 """
 
 def build_image(self, img):
-- 
2.34.3




[PATCH v3 12/13] tests/qemu-iotests: skip 108 when FUSE is not loaded

2022-07-06 Thread John Snow
Do not merge: Staged in Hanna's branch.

Signed-off-by: John Snow 
---
 tests/qemu-iotests/108 | 5 +
 1 file changed, 5 insertions(+)

diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
index 9e923d6a59f..54e935acf28 100755
--- a/tests/qemu-iotests/108
+++ b/tests/qemu-iotests/108
@@ -60,6 +60,11 @@ if sudo -n losetup &>/dev/null; then
 else
 loopdev=false
 
+# Check for usable FUSE in the host environment:
+if test ! -c "/dev/fuse"; then
+_notrun 'No passwordless sudo nor usable /dev/fuse'
+fi
+
 # QSD --export fuse will either yield "Parameter 'id' is missing"
 # or "Invalid parameter 'fuse'", depending on whether there is
 # FUSE support or not.
-- 
2.34.3




[PATCH v3 05/13] tests/vm: update sha256sum for ubuntu.aarch64

2022-07-06 Thread John Snow
This checksum changes weekly; use a fixed point image and update the
checksum so we don't have to re-download it quite so much.

Note: Just like the centos.aarch64 test, this test currently seems very
flaky when run as a TCG test.

Signed-off-by: John Snow 
---
 tests/vm/ubuntu.aarch64 | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tests/vm/ubuntu.aarch64 b/tests/vm/ubuntu.aarch64
index b291945a7e9..fc9c2ce22ff 100755
--- a/tests/vm/ubuntu.aarch64
+++ b/tests/vm/ubuntu.aarch64
@@ -32,9 +32,13 @@ DEFAULT_CONFIG = {
 class UbuntuAarch64VM(ubuntuvm.UbuntuVM):
 name = "ubuntu.aarch64"
 arch = "aarch64"
+# NOTE: The Ubuntu 18.04 cloud images are updated weekly. The
+# release below has been chosen as the latest at time of writing.
+# Using the rolling latest release means the SHA will be wrong
+# within a week.
 image_name = "ubuntu-18.04-server-cloudimg-arm64.img"
-image_link = "https://cloud-images.ubuntu.com/releases/18.04/release/; + 
image_name
-
image_sha256="0fdcba761965735a8a903d8b88df8e47f156f48715c00508e4315c506d7d3cb1"
+image_link = 
"https://cloud-images.ubuntu.com/releases/bionic/release-20220610/; + image_name
+
image_sha256="0eacc5142238788365576b15f1d0b6f23dda6d3e545ee22f5306af7bd6ec47bd"
 BUILD_SCRIPT = """
 set -e;
 cd $(mktemp -d);
-- 
2.34.3




[PATCH v3 09/13] tests/vm: upgrade Ubuntu 18.04 VM to 20.04

2022-07-06 Thread John Snow
18.04 has fallen out of our support window, so move ubuntu.aarch64
forward to ubuntu 20.04, which is now our oldest supported Ubuntu
release.

Signed-off-by: John Snow 
---
 tests/vm/ubuntu.aarch64 | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tests/vm/ubuntu.aarch64 b/tests/vm/ubuntu.aarch64
index fc9c2ce22ff..666947393bd 100755
--- a/tests/vm/ubuntu.aarch64
+++ b/tests/vm/ubuntu.aarch64
@@ -32,13 +32,13 @@ DEFAULT_CONFIG = {
 class UbuntuAarch64VM(ubuntuvm.UbuntuVM):
 name = "ubuntu.aarch64"
 arch = "aarch64"
-# NOTE: The Ubuntu 18.04 cloud images are updated weekly. The
-# release below has been chosen as the latest at time of writing.
-# Using the rolling latest release means the SHA will be wrong
-# within a week.
-image_name = "ubuntu-18.04-server-cloudimg-arm64.img"
-image_link = 
"https://cloud-images.ubuntu.com/releases/bionic/release-20220610/; + image_name
-
image_sha256="0eacc5142238788365576b15f1d0b6f23dda6d3e545ee22f5306af7bd6ec47bd"
+# NOTE: The Ubuntu 20.04 cloud images are periodically updated. The
+# fixed image chosen below is the latest release at time of
+# writing. Using a rolling latest instead would mean that the SHA
+# would be incorrect at an indeterminate point in the future.
+image_name = "focal-server-cloudimg-arm64.img"
+image_link = "https://cloud-images.ubuntu.com/focal/20220615/; + image_name
+
image_sha256="95a027336e197debe88c92ff2e554598e23c409139e1e750b71b3b820b514832"
 BUILD_SCRIPT = """
 set -e;
 cd $(mktemp -d);
-- 
2.34.3




[PATCH v3 01/13] qga: treat get-guest-fsinfo as "best effort"

2022-07-06 Thread John Snow
In some container environments, there may be references to block devices
witnessable from a container through /proc/self/mountinfo that reference
devices we simply don't have access to in the container, and cannot
provide information about.

Instead of failing the entire fsinfo command, return stub information
for these failed lookups.

This allows test-qga to pass under docker tests, which are in turn used
by the CentOS VM tests.

Signed-off-by: John Snow 
---
 qga/commands-posix.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 0469dc409d4..950c9d72fe7 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -1207,7 +1207,12 @@ static void build_guest_fsinfo_for_device(char const 
*devpath,
 
 syspath = realpath(devpath, NULL);
 if (!syspath) {
-error_setg_errno(errp, errno, "realpath(\"%s\")", devpath);
+if (errno == ENOENT) {
+/* This devpath may not exist because of container config, etc. */
+fs->name = g_path_get_basename(devpath);
+} else {
+error_setg_errno(errp, errno, "realpath(\"%s\")", devpath);
+}
 return;
 }
 
-- 
2.34.3




[PATCH v3 02/13] tests/vm: use 'cp' instead of 'ln' for temporary vm images

2022-07-06 Thread John Snow
If the initial setup fails, you've permanently altered the state of the
downloaded image in an unknowable way. Use 'cp' like our other test
setup scripts do.

Signed-off-by: John Snow 
Reviewed-by: Thomas Huth 
---
 tests/vm/centos | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/vm/centos b/tests/vm/centos
index 5c7bc1c1a9a..be4f6ff2f14 100755
--- a/tests/vm/centos
+++ b/tests/vm/centos
@@ -34,7 +34,7 @@ class CentosVM(basevm.BaseVM):
 def build_image(self, img):
 cimg = 
self._download_with_cache("https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.3.2011-20201204.2.x86_64.qcow2;)
 img_tmp = img + ".tmp"
-subprocess.check_call(["ln", "-f", cimg, img_tmp])
+subprocess.check_call(['cp', '-f', cimg, img_tmp])
 self.exec_qemu_img("resize", img_tmp, "50G")
 self.boot(img_tmp, extra_args = ["-cdrom", self.gen_cloud_init_iso()])
 self.wait_ssh()
-- 
2.34.3




[PATCH v3 11/13] tests/qemu-iotests: hotfix for 307, 223 output

2022-07-06 Thread John Snow
Do not merge; staged in Hanna's branch.

Signed-off-by: John Snow 
---
 tests/qemu-iotests/223.out | 4 ++--
 tests/qemu-iotests/307.out | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
index 06479415312..26fb347c5da 100644
--- a/tests/qemu-iotests/223.out
+++ b/tests/qemu-iotests/223.out
@@ -93,7 +93,7 @@ exports available: 3
  export: 'n2'
   description: some text
   size:  4194304
-  flags: 0xced ( flush fua trim zeroes df cache fast-zero )
+  flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
   min block: 1
   opt block: 4096
   max block: 33554432
@@ -212,7 +212,7 @@ exports available: 3
  export: 'n2'
   description: some text
   size:  4194304
-  flags: 0xced ( flush fua trim zeroes df cache fast-zero )
+  flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
   min block: 1
   opt block: 4096
   max block: 33554432
diff --git a/tests/qemu-iotests/307.out b/tests/qemu-iotests/307.out
index ec8d2be0e0a..390f05d1b78 100644
--- a/tests/qemu-iotests/307.out
+++ b/tests/qemu-iotests/307.out
@@ -83,7 +83,7 @@ exports available: 2
  export: 'export1'
   description: This is the writable second export
   size:  67108864
-  flags: 0xced ( flush fua trim zeroes df cache fast-zero )
+  flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
   min block: XXX
   opt block: XXX
   max block: XXX
@@ -109,7 +109,7 @@ exports available: 1
  export: 'export1'
   description: This is the writable second export
   size:  67108864
-  flags: 0xced ( flush fua trim zeroes df cache fast-zero )
+  flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
   min block: XXX
   opt block: XXX
   max block: XXX
-- 
2.34.3




[PATCH v3 00/13] Improve reliability of VM tests

2022-07-06 Thread John Snow
Note: patches 11-13 are included for testing simplicity, they shouldn't
be merged. They will be included in a forthcoming block PR.

This patch series attempts to improve the reliability of several of the
VM test targets. In particular, both CentOS 8 tests are non-functional
because CentOS 8 was EOL at the beginning of this calendar year, with
repositories and mirrors going offline.

I also remove the ubuntu.i386 test because we no longer support Ubuntu
18.04 nor do we have explicit need of an i386 build test.

After this series, I am able to successfully run every VM target on an
x86_64 host, except:

- ubuntu.aarch64: Hangs often during testing, see below.
- centos.aarch64: Hangs often during testing, see below.
- haiku.x86_64: Build failures not addressed by this series, see
  https://lists.gnu.org/archive/html/qemu-devel/2022-06/msg02103.html

The unit tests that I see fail most often under aarch64 are:

- virtio-net-failover: Seems to like to hang on openbsd
- migration-test: Tends to hang under aarch64 tcg

Future work (next version? next series?);

- Try to get centos.aarch64 working reliably under TCG
- Upgrade ubuntu.aarch64 to 20.04 after fixing centos.aarch64
- Fix the Haiku build test, if possible.
- Ensure I can reliably run and pass "make vm-build-all".
  (Remove VMs from this recipe if necessary.)

John Snow (12):
  qga: treat get-guest-fsinfo as "best effort"
  tests/vm: use 'cp' instead of 'ln' for temporary vm images
  tests/vm: switch CentOS 8 to CentOS 8 Stream
  tests/vm: switch centos.aarch64 to CentOS 8 Stream
  tests/vm: update sha256sum for ubuntu.aarch64
  tests/vm: remove ubuntu.i386 VM test
  tests/vm: remove duplicate 'centos' VM test
  tests/vm: add 1GB extra memory per core
  tests/vm: upgrade Ubuntu 18.04 VM to 20.04
  tests/vm: Remove docker cross-compile test from CentOS VM
  tests/qemu-iotests: hotfix for 307, 223 output
  tests/qemu-iotests: skip 108 when FUSE is not loaded

Vladimir Sementsov-Ogievskiy (1):
  iotests: fix copy-before-write for macOS and FreeBSD

 qga/commands-posix.c   |   7 +-
 tests/qemu-iotests/108 |   5 +
 tests/qemu-iotests/223.out |   4 +-
 tests/qemu-iotests/307.out |   4 +-
 tests/qemu-iotests/tests/copy-before-write |   5 +
 tests/vm/Makefile.include  |   5 +-
 tests/vm/basevm.py |   5 +
 tests/vm/centos|   9 +-
 tests/vm/centos.aarch64| 174 +++--
 tests/vm/ubuntu.aarch64|  10 +-
 tests/vm/ubuntu.i386   |  40 -
 11 files changed, 62 insertions(+), 206 deletions(-)
 delete mode 100755 tests/vm/ubuntu.i386

-- 
2.34.3





[PATCH v3 08/13] tests/vm: add 1GB extra memory per core

2022-07-06 Thread John Snow
If you try to run a 16 or 32 threaded test, you're going to run out of
memory very quickly with qom-test and a few others. Bump the memory
limit to try to scale with larger-core machines.

Granted, this means that a 16 core processor is going to ask for 16GB,
but you *probably* meet that requirement if you have such a machine.

512MB per core didn't seem to be enough to avoid ENOMEM and SIGABRTs in
the test cases in practice on a six core machine; so I bumped it up to
1GB which seemed to help.

Add this magic in early to the configuration process so that the
config file, if provided, can still override it.

Signed-off-by: John Snow 
---
 tests/vm/basevm.py | 5 +
 1 file changed, 5 insertions(+)

diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index d7d0413df35..4fd9af10b7f 100644
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -99,6 +99,11 @@ def __init__(self, args, config=None):
 self._source_path = args.source_path
 # Allow input config to override defaults.
 self._config = DEFAULT_CONFIG.copy()
+
+# 1GB per core, minimum of 4. This is only a default.
+mem = max(4, args.jobs)
+self._config['memory'] = f"{mem}G"
+
 if config != None:
 self._config.update(config)
 self.validate_ssh_keys()
-- 
2.34.3




[PATCH v3 07/13] tests/vm: remove duplicate 'centos' VM test

2022-07-06 Thread John Snow
This is listed twice by accident; we require genisoimage to run the
test, so remove the unconditional entry.

Signed-off-by: John Snow 
Reviewed-by: Thomas Huth 
---
 tests/vm/Makefile.include | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index a94f0ebf7f1..8d2a164552d 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -15,7 +15,7 @@ endif
 
 EFI_AARCH64 = $(wildcard $(BUILD_DIR)/pc-bios/edk2-aarch64-code.fd)
 
-X86_IMAGES := freebsd netbsd openbsd centos fedora haiku.x86_64
+X86_IMAGES := freebsd netbsd openbsd fedora haiku.x86_64
 ifneq ($(GENISOIMAGE),)
 X86_IMAGES += centos
 ifneq ($(EFI_AARCH64),)
-- 
2.34.3




[PATCH v3 06/13] tests/vm: remove ubuntu.i386 VM test

2022-07-06 Thread John Snow
Ubuntu 18.04 is out of our support window, and Ubuntu 20.04 does not
support i386 anymore. The debian project does, but they do not provide
any cloud images for it, a new expect-style script would have to be
written.

Since we have i386 cross-compiler tests hosted on GitLab CI, we don't
need to support this VM test anymore.

Signed-off-by: John Snow 
Reviewed-by: Thomas Huth 
---
 tests/vm/Makefile.include |  3 +--
 tests/vm/ubuntu.i386  | 40 ---
 2 files changed, 1 insertion(+), 42 deletions(-)
 delete mode 100755 tests/vm/ubuntu.i386

diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index 5f5b1fbfe68..a94f0ebf7f1 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -17,7 +17,7 @@ EFI_AARCH64 = $(wildcard 
$(BUILD_DIR)/pc-bios/edk2-aarch64-code.fd)
 
 X86_IMAGES := freebsd netbsd openbsd centos fedora haiku.x86_64
 ifneq ($(GENISOIMAGE),)
-X86_IMAGES += ubuntu.i386 centos
+X86_IMAGES += centos
 ifneq ($(EFI_AARCH64),)
 ARM64_IMAGES += ubuntu.aarch64 centos.aarch64
 endif
@@ -48,7 +48,6 @@ vm-help vm-test:
@echo "  vm-build-fedora - Build QEMU in Fedora VM"
 ifneq ($(GENISOIMAGE),)
@echo "  vm-build-centos - Build QEMU in CentOS VM, 
with Docker"
-   @echo "  vm-build-ubuntu.i386- Build QEMU in ubuntu i386 VM"
 ifneq ($(EFI_AARCH64),)
@echo "  vm-build-ubuntu.aarch64 - Build QEMU in ubuntu aarch64 
VM"
@echo "  vm-build-centos.aarch64 - Build QEMU in CentOS aarch64 
VM"
diff --git a/tests/vm/ubuntu.i386 b/tests/vm/ubuntu.i386
deleted file mode 100755
index 47681b6f87d..000
--- a/tests/vm/ubuntu.i386
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-#
-# Ubuntu i386 image
-#
-# Copyright 2017 Red Hat Inc.
-#
-# Authors:
-#  Fam Zheng 
-#
-# This code is licensed under the GPL version 2 or later.  See
-# the COPYING file in the top-level directory.
-#
-
-import sys
-import basevm
-import ubuntuvm
-
-DEFAULT_CONFIG = {
-'install_cmds' : "apt-get update,"\
- "apt-get build-dep -y qemu,"\
- "apt-get install -y libfdt-dev language-pack-en 
ninja-build",
-}
-
-class UbuntuX86VM(ubuntuvm.UbuntuVM):
-name = "ubuntu.i386"
-arch = "i386"
-image_link="https://cloud-images.ubuntu.com/releases/bionic/"\
-   "release-20191114/ubuntu-18.04-server-cloudimg-i386.img"
-
image_sha256="28969840626d1ea80bb249c08eef1a4533e8904aa51a327b40f37ac4b4ff04ef"
-BUILD_SCRIPT = """
-set -e;
-cd $(mktemp -d);
-sudo chmod a+r /dev/vdb;
-tar -xf /dev/vdb;
-./configure {configure_opts};
-make --output-sync {target} -j{jobs} {verbose};
-"""
-
-if __name__ == "__main__":
-sys.exit(basevm.main(UbuntuX86VM, DEFAULT_CONFIG))
-- 
2.34.3




[PATCH v2 6/7] hw/ide/piix: Ignore writes of hardwired PCI command register bits

2022-07-06 Thread Lev Kujawski
One method to enable PCI bus mastering for IDE controllers, often used
by x86 firmware, is to write 0x7 to the PCI command register.  Neither
the PIIX3 specification nor actual hardware (a Tyan S1686D system)
permit modification of the Memory Space Enable (MSE) bit, 1, and thus
the command register would be left in an unspecified state without
this patch.

* hw/ide/piix.c
  a) Add a reference to the PIIX4 data sheet.
  b) Mask the MSE bit using the QEMU PCI device wmask field.
* tests/qtest/ide-test.c
  Use the command_disabled field of the QPCIDevice testing model to
  indicate that PCI_COMMAND_MEMORY is hardwired in the PIIX3/4 IDE
  controller.

Signed-off-by: Lev Kujawski 
---
 hw/ide/piix.c  | 15 +++
 tests/qtest/ide-test.c |  1 +
 2 files changed, 16 insertions(+)

diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index de1f4f0efb..64620c5778 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -25,6 +25,8 @@
  * References:
  *  [1] 82371FB (PIIX) AND 82371SB (PIIX3) PCI ISA IDE XCELERATOR,
  *  290550-002, Intel Corporation, April 1997.
+ *  [2] 82371AB PCI-TO-ISA / IDE XCELERATOR (PIIX4), 290562-001,
+ *  Intel Corporation, April 1997.
  */
 
 #include "qemu/osdep.h"
@@ -160,6 +162,19 @@ static void pci_piix_ide_realize(PCIDevice *dev, Error 
**errp)
 uint8_t *pci_conf = dev->config;
 int rc;
 
+/*
+ * Mask all IDE PCI command register bits except for Bus Master
+ * Function Enable (bit 2) and I/O Space Enable (bit 1), as the
+ * remainder are hardwired to 0 [1, p.48] [2, p.89-90].
+ *
+ * NOTE: According to the PIIX3 datasheet [1], the Memory Space
+ * Enable (MSE bit) is hardwired to 1, but this is contradicted by
+ * actual PIIX3 hardware, the datasheet itself (viz., Default
+ * Value: h), and the PIIX4 datasheet [2].
+ */
+pci_set_word(dev->wmask + PCI_COMMAND,
+ PCI_COMMAND_MASTER | PCI_COMMAND_IO);
+
 pci_conf[PCI_CLASS_PROG] = 0x80; // legacy ATA mode
 
 bmdma_setup_bar(d);
diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c
index dfcf59cee8..728e8ce00f 100644
--- a/tests/qtest/ide-test.c
+++ b/tests/qtest/ide-test.c
@@ -176,6 +176,7 @@ static QPCIDevice *get_pci_device(QTestState *qts, QPCIBar 
*bmdma_bar,
 
 *ide_bar = qpci_legacy_iomap(dev, IDE_BASE);
 
+dev->command_disabled = PCI_COMMAND_MEMORY;
 qpci_device_enable(dev);
 
 return dev;
-- 
2.34.1




[PATCH v2 7/7] hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command

2022-07-06 Thread Lev Kujawski
CHS-based disk utilities and operating systems may adjust the logical
geometry of a hard drive to cope with the expectations or limitations
of software using the ATA INITIALIZE_DEVICE_PARAMETERS command.

Prior to this patch, INITIALIZE_DEVICE_PARAMETERS was a nop that
always returned success, raising the possibility of data loss or
corruption if the CHS<->LBA translation redirected a write to the
wrong sector.

* hw/ide/core.c
ide_reset():
  Reset the logical CHS geometry of the hard disk when the power-on
  defaults feature is enabled.
cmd_specify():
  a) New function implementing INITIALIZE_DEVICE_PARAMETERS.
  b) Ignore calls for empty or ATAPI devices.
cmd_set_features():
  Implement the power-on defaults enable and disable features.
struct ide_cmd_table:
  Switch WIN_SPECIFY from cmd_nop() to cmd_specify().
ide_init_drive():
  Set new fields 'drive_heads' and 'drive_sectors' based upon the
  actual disk geometry.

* include/hw/ide/internal.h
struct IDEState:
a) Store the actual drive CHS values within the new fields
   'drive_heads' and 'drive_sectors.'
b) Track whether a soft IDE reset should also reset the logical CHS
   geometry of the hard disk within the new field 'reset_reverts'.

Signed-off-by: Lev Kujawski 
---
 hw/ide/core.c | 29 ++---
 include/hw/ide/internal.h |  3 +++
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index b747191ebf..39afdc0006 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1340,6 +1340,11 @@ static void ide_reset(IDEState *s)
 s->pio_aiocb = NULL;
 }
 
+if (s->reset_reverts) {
+s->reset_reverts = false;
+s->heads = s->drive_heads;
+s->sectors   = s->drive_sectors;
+}
 if (s->drive_kind == IDE_CFATA)
 s->mult_sectors = 0;
 else
@@ -1618,6 +1623,20 @@ static bool cmd_check_power_mode(IDEState *s, uint8_t 
cmd)
 return true;
 }
 
+/* INITIALIZE DEVICE PARAMETERS */
+static bool cmd_specify(IDEState *s, uint8_t cmd)
+{
+if (s->blk && s->drive_kind != IDE_CD) {
+s->heads = (s->select & (ATA_DEV_HS)) + 1;
+s->sectors = s->nsector;
+ide_set_irq(s->bus);
+} else {
+ide_abort_command(s);
+}
+
+return true;
+}
+
 static bool cmd_set_features(IDEState *s, uint8_t cmd)
 {
 uint16_t *identify_data;
@@ -1641,7 +1660,11 @@ static bool cmd_set_features(IDEState *s, uint8_t cmd)
 ide_flush_cache(s);
 return false;
 case 0xcc: /* reverting to power-on defaults enable */
+s->reset_reverts = true;
+return true;
 case 0x66: /* reverting to power-on defaults disable */
+s->reset_reverts = false;
+return true;
 case 0xaa: /* read look-ahead enable */
 case 0x55: /* read look-ahead disable */
 case 0x05: /* set advanced power management mode */
@@ -2051,7 +2074,7 @@ static const struct {
 [WIN_SEEK]= { cmd_seek, HD_CFA_OK | SET_DSC },
 [CFA_TRANSLATE_SECTOR]= { cmd_cfa_translate_sector, CFA_OK },
 [WIN_DIAGNOSE]= { cmd_exec_dev_diagnostic, ALL_OK },
-[WIN_SPECIFY] = { cmd_nop, HD_CFA_OK | SET_DSC },
+[WIN_SPECIFY] = { cmd_specify, HD_CFA_OK | SET_DSC },
 [WIN_STANDBYNOW2] = { cmd_nop, HD_CFA_OK },
 [WIN_IDLEIMMEDIATE2]  = { cmd_nop, HD_CFA_OK },
 [WIN_STANDBY2]= { cmd_nop, HD_CFA_OK },
@@ -2541,8 +2564,8 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, 
IDEDriveKind kind,
 
 blk_get_geometry(blk, _sectors);
 s->cylinders = cylinders;
-s->heads = heads;
-s->sectors = secs;
+s->heads = s->drive_heads = heads;
+s->sectors = s->drive_sectors = secs;
 s->chs_trans = chs_trans;
 s->nb_sectors = nb_sectors;
 s->wwn = wwn;
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index 97e7e59dc5..b17f36df95 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -375,6 +375,7 @@ struct IDEState {
 uint8_t unit;
 /* ide config */
 IDEDriveKind drive_kind;
+int drive_heads, drive_sectors;
 int cylinders, heads, sectors, chs_trans;
 int64_t nb_sectors;
 int mult_sectors;
@@ -401,6 +402,8 @@ struct IDEState {
 uint8_t select;
 uint8_t status;
 
+bool reset_reverts;
+
 /* set for lba48 access */
 uint8_t lba48;
 BlockBackend *blk;
-- 
2.34.1




[PATCH v2 4/7] tests/qtest/ide-test: Verify that DIAGNOSTIC clears DEV to zero

2022-07-06 Thread Lev Kujawski
Verify correction of EXECUTE DEVICE DIAGNOSTIC introduced in commit
72423831c3 (hw/ide/core: Clear LBA and drive bits for EXECUTE DEVICE
DIAGNOSTIC, 2022-05-28).

Signed-off-by: Lev Kujawski 
---
 tests/qtest/ide-test.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c
index 1ff707d2cd..dfcf59cee8 100644
--- a/tests/qtest/ide-test.c
+++ b/tests/qtest/ide-test.c
@@ -90,6 +90,7 @@ enum {
 
 enum {
 CMD_DSM = 0x06,
+CMD_DIAGNOSE= 0x90,
 CMD_READ_DMA= 0xc8,
 CMD_WRITE_DMA   = 0xca,
 CMD_FLUSH_CACHE = 0xe7,
@@ -616,6 +617,36 @@ static void test_identify(void)
 free_pci_device(dev);
 }
 
+static void test_diagnostic(void)
+{
+QTestState *qts;
+QPCIDevice *dev;
+QPCIBar bmdma_bar, ide_bar;
+uint8_t data;
+
+qts = ide_test_start(
+"-blockdev driver=file,node-name=hda,filename=%s "
+"-blockdev driver=file,node-name=hdb,filename=%s "
+"-device ide-hd,drive=hda,bus=ide.0,unit=0 "
+"-device ide-hd,drive=hdb,bus=ide.0,unit=1 ",
+tmp_path[0], tmp_path[1]);
+
+dev = get_pci_device(qts, _bar, _bar);
+
+/* DIAGNOSE command on device 1 */
+qpci_io_writeb(dev, ide_bar, reg_device, DEV);
+data = qpci_io_readb(dev, ide_bar, reg_device);
+g_assert_cmphex(data & DEV, ==, DEV);
+qpci_io_writeb(dev, ide_bar, reg_command, CMD_DIAGNOSE);
+
+/* Verify that DEVICE is now 0 */
+data = qpci_io_readb(dev, ide_bar, reg_device);
+g_assert_cmphex(data & DEV, ==, 0);
+
+ide_test_quit(qts);
+free_pci_device(dev);
+}
+
 /*
  * Write sector 1 with random data to make IDE storage dirty
  * Needed for flush tests so that flushes actually go though the block layer
@@ -1037,6 +1068,8 @@ int main(int argc, char **argv)
 
 qtest_add_func("/ide/identify", test_identify);
 
+qtest_add_func("/ide/diagnostic", test_diagnostic);
+
 qtest_add_func("/ide/bmdma/simple_rw", test_bmdma_simple_rw);
 qtest_add_func("/ide/bmdma/trim", test_bmdma_trim);
 qtest_add_func("/ide/bmdma/various_prdts", test_bmdma_various_prdts);
-- 
2.34.1




[PATCH v2 3/7] hw/ide/core: Clear LBA and drive bits for EXECUTE DEVICE DIAGNOSTIC

2022-07-06 Thread Lev Kujawski
Prior to this patch, cmd_exec_dev_diagnostic relied upon
ide_set_signature to clear the device register.  While the
preservation of the drive bit by ide_set_signature is necessary for
the DEVICE RESET, IDENTIFY DEVICE, and READ SECTOR commands,
ATA/ATAPI-6 specifies that "DEV shall be cleared to zero" for EXECUTE
DEVICE DIAGNOSTIC.

This deviation was uncovered by the ATACT Device Testing Program
written by Hale Landis.

Signed-off-by: Lev Kujawski 
---
 hw/ide/core.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 7cbc0a54a7..b747191ebf 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1704,8 +1704,14 @@ static bool cmd_identify_packet(IDEState *s, uint8_t cmd)
 return false;
 }
 
+/* EXECUTE DEVICE DIAGNOSTIC */
 static bool cmd_exec_dev_diagnostic(IDEState *s, uint8_t cmd)
 {
+/*
+ * Clear the device register per the ATA (v6) specification,
+ * because ide_set_signature does not clear LBA or drive bits.
+ */
+s->select = (ATA_DEV_ALWAYS_ON);
 ide_set_signature(s);
 
 if (s->drive_kind == IDE_CD) {
-- 
2.34.1




[PATCH v2 5/7] qpci_device_enable: Allow for command bits hardwired to 0

2022-07-06 Thread Lev Kujawski
Devices like the PIIX3/4 IDE controller do not support certain modes
of operation, such as memory space accesses, and indicate this lack of
support by hardwiring the applicable bits to zero.  Extend the QEMU
PCI device testing framework to accommodate such devices.

* tests/qtest/libqos/pci.h: Add the command_disabled word to indicate
  bits hardwired to 0.
* tests/qtest/libqos/pci.c: Verify that hardwired bits are actually
  hardwired.

Signed-off-by: Lev Kujawski 
---
 tests/qtest/libqos/pci.c | 13 +++--
 tests/qtest/libqos/pci.h |  1 +
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c
index b23d72346b..4f3d28d8d9 100644
--- a/tests/qtest/libqos/pci.c
+++ b/tests/qtest/libqos/pci.c
@@ -220,18 +220,19 @@ int qpci_secondary_buses_init(QPCIBus *bus)
 
 void qpci_device_enable(QPCIDevice *dev)
 {
-uint16_t cmd;
+const uint16_t enable_bits =
+PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+uint16_t cmd, new_cmd;
 
 /* FIXME -- does this need to be a bus callout? */
 cmd = qpci_config_readw(dev, PCI_COMMAND);
-cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+cmd |= enable_bits;
 qpci_config_writew(dev, PCI_COMMAND, cmd);
 
 /* Verify the bits are now set. */
-cmd = qpci_config_readw(dev, PCI_COMMAND);
-g_assert_cmphex(cmd & PCI_COMMAND_IO, ==, PCI_COMMAND_IO);
-g_assert_cmphex(cmd & PCI_COMMAND_MEMORY, ==, PCI_COMMAND_MEMORY);
-g_assert_cmphex(cmd & PCI_COMMAND_MASTER, ==, PCI_COMMAND_MASTER);
+new_cmd = qpci_config_readw(dev, PCI_COMMAND);
+new_cmd &= enable_bits;
+g_assert_cmphex(new_cmd, ==, enable_bits & ~dev->command_disabled);
 }
 
 /**
diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
index 8389614523..eaedb98588 100644
--- a/tests/qtest/libqos/pci.h
+++ b/tests/qtest/libqos/pci.h
@@ -68,6 +68,7 @@ struct QPCIDevice
 bool msix_enabled;
 QPCIBar msix_table_bar, msix_pba_bar;
 uint64_t msix_table_off, msix_pba_off;
+uint16_t command_disabled;
 };
 
 struct QPCIAddress {
-- 
2.34.1




[PATCH v2 2/7] tests/qtest/ide-test.c: Create disk image for use as a secondary

2022-07-06 Thread Lev Kujawski
Change 'tmp_path' into an array of two members to accommodate another
disk image of size TEST_IMAGE_SIZE.  This facilitates testing ATA
protocol aspects peculiar to secondary devices on the same controller.

Signed-off-by: Lev Kujawski 
---
 tests/qtest/ide-test.c | 38 +++---
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c
index 5bcb75a7e5..1ff707d2cd 100644
--- a/tests/qtest/ide-test.c
+++ b/tests/qtest/ide-test.c
@@ -121,7 +121,9 @@ enum {
 static QPCIBus *pcibus = NULL;
 static QGuestAllocator guest_malloc;
 
-static char tmp_path[] = "/tmp/qtest.XX";
+#define TMP_PATH_LEN 18
+
+static char tmp_path[2][TMP_PATH_LEN];
 static char debug_path[] = "/tmp/qtest-blkdebug.XX";
 
 static QTestState *ide_test_start(const char *cmdline_fmt, ...)
@@ -310,7 +312,7 @@ static QTestState *test_bmdma_setup(void)
 qts = ide_test_start(
 "-drive file=%s,if=ide,cache=writeback,format=raw "
 "-global ide-hd.serial=%s -global ide-hd.ver=%s",
-tmp_path, "testdisk", "version");
+tmp_path[0], "testdisk", "version");
 qtest_irq_intercept_in(qts, "ioapic");
 
 return qts;
@@ -574,7 +576,7 @@ static void test_identify(void)
 qts = ide_test_start(
 "-drive file=%s,if=ide,cache=writeback,format=raw "
 "-global ide-hd.serial=%s -global ide-hd.ver=%s",
-tmp_path, "testdisk", "version");
+tmp_path[0], "testdisk", "version");
 
 dev = get_pci_device(qts, _bar, _bar);
 
@@ -662,7 +664,7 @@ static void test_flush(void)
 
 qts = ide_test_start(
 "-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw",
-tmp_path);
+tmp_path[0]);
 
 dev = get_pci_device(qts, _bar, _bar);
 
@@ -713,7 +715,7 @@ static void test_pci_retry_flush(void)
 qts = ide_test_start(
 "-drive file=blkdebug:%s:%s,if=ide,cache=writeback,format=raw,"
 "rerror=stop,werror=stop",
-debug_path, tmp_path);
+debug_path, tmp_path[0]);
 
 dev = get_pci_device(qts, _bar, _bar);
 
@@ -892,14 +894,14 @@ static void cdrom_pio_impl(int nblocks)
 
 /* Prepopulate the CDROM with an interesting pattern */
 generate_pattern(pattern, patt_len, ATAPI_BLOCK_SIZE);
-fh = fopen(tmp_path, "w+");
+fh = fopen(tmp_path[0], "w+");
 ret = fwrite(pattern, ATAPI_BLOCK_SIZE, patt_blocks, fh);
 g_assert_cmpint(ret, ==, patt_blocks);
 fclose(fh);
 
 qts = ide_test_start(
 "-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 "
-"-device ide-cd,drive=sr0,bus=ide.0", tmp_path);
+"-device ide-cd,drive=sr0,bus=ide.0", tmp_path[0]);
 dev = get_pci_device(qts, _bar, _bar);
 qtest_irq_intercept_in(qts, "ioapic");
 
@@ -985,7 +987,7 @@ static void test_cdrom_dma(void)
 
 qts = ide_test_start(
 "-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 "
-"-device ide-cd,drive=sr0,bus=ide.0", tmp_path);
+"-device ide-cd,drive=sr0,bus=ide.0", tmp_path[0]);
 qtest_irq_intercept_in(qts, "ioapic");
 
 guest_buf = guest_alloc(_malloc, len);
@@ -993,7 +995,7 @@ static void test_cdrom_dma(void)
 prdt[0].size = cpu_to_le32(len | PRDT_EOT);
 
 generate_pattern(pattern, ATAPI_BLOCK_SIZE * 16, ATAPI_BLOCK_SIZE);
-fh = fopen(tmp_path, "w+");
+fh = fopen(tmp_path[0], "w+");
 ret = fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh);
 g_assert_cmpint(ret, ==, 16);
 fclose(fh);
@@ -1011,6 +1013,7 @@ static void test_cdrom_dma(void)
 
 int main(int argc, char **argv)
 {
+int i;
 int fd;
 int ret;
 
@@ -1020,11 +1023,14 @@ int main(int argc, char **argv)
 close(fd);
 
 /* Create a temporary raw image */
-fd = mkstemp(tmp_path);
-g_assert(fd >= 0);
-ret = ftruncate(fd, TEST_IMAGE_SIZE);
-g_assert(ret == 0);
-close(fd);
+for (i = 0; i < 2; ++i) {
+strncpy(tmp_path[i], "/tmp/qtest.XX", TMP_PATH_LEN);
+fd = mkstemp(tmp_path[i]);
+g_assert(fd >= 0);
+ret = ftruncate(fd, TEST_IMAGE_SIZE);
+g_assert(ret == 0);
+close(fd);
+}
 
 /* Run the tests */
 g_test_init(, , NULL);
@@ -1048,7 +1054,9 @@ int main(int argc, char **argv)
 ret = g_test_run();
 
 /* Cleanup */
-unlink(tmp_path);
+for (i = 0; i < 2; ++i) {
+unlink(tmp_path[i]);
+}
 unlink(debug_path);
 
 return ret;
-- 
2.34.1




[PATCH v2 1/7] piix_ide_reset: Use pci_set_* functions instead of direct access

2022-07-06 Thread Lev Kujawski
Eliminate the remaining TODOs in hw/ide/piix.c by:
* Using pci_set_{size} functions to write the PIIX PCI configuration
  space instead of manipulating it directly as an array; and
* Documenting the default register values by reference to the
  controlling specification.

Signed-off-by: Lev Kujawski 
---
 hw/ide/piix.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 9a9b28078e..de1f4f0efb 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -21,6 +21,10 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
+ *
+ * References:
+ *  [1] 82371FB (PIIX) AND 82371SB (PIIX3) PCI ISA IDE XCELERATOR,
+ *  290550-002, Intel Corporation, April 1997.
  */
 
 #include "qemu/osdep.h"
@@ -114,14 +118,11 @@ static void piix_ide_reset(DeviceState *dev)
 ide_bus_reset(>bus[i]);
 }
 
-/* TODO: this is the default. do not override. */
-pci_conf[PCI_COMMAND] = 0x00;
-/* TODO: this is the default. do not override. */
-pci_conf[PCI_COMMAND + 1] = 0x00;
-/* TODO: use pci_set_word */
-pci_conf[PCI_STATUS] = PCI_STATUS_FAST_BACK;
-pci_conf[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_MEDIUM >> 8;
-pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */
+/* PCI command register default value (h) per [1, p.48].  */
+pci_set_word(pci_conf + PCI_COMMAND, 0x);
+pci_set_word(pci_conf + PCI_STATUS,
+ PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_FAST_BACK);
+pci_set_byte(pci_conf + 0x20, 0x01);  /* BMIBA: 20-23h */
 }
 
 static int pci_piix_init_ports(PCIIDEState *d)
-- 
2.34.1




Re: [PULL 00/34] ppc queue

2022-07-06 Thread Richard Henderson

On 7/7/22 01:39, Daniel Henrique Barboza wrote:

The following changes since commit 180c2f24d5e8eada41e012a3899d29bb695aae06:

   Merge tag 'net-pull-request' of https://github.com/jasowang/qemu into 
staging (2022-07-06 10:41:34 +0530)

are available in the Git repository at:

   https://gitlab.com/danielhb/qemu.git tags/pull-ppc-20220706

for you to fetch changes up to 0b83377f46042529adbbf3a77f7ffb6f1e8a0aaa:

   target/ppc: Fix MPC8555 and MPC8560 core type to e500v1 (2022-07-06 10:30:01 
-0300)


ppc patch queue for 2022-07-06:

This queue consists of improvements and bug fixes in TCG, powernv and
pSeries, with some fixes in other areas as well.

- tcg and target/ppc: BCDA and mffscdrn implementations, Remove CONFIG_INT128
conditional code
- fix '-cpu max' alias
- remove '-cpu default' alias
- spapr: fixes in DDW handling, H_WATCHDOG support
- powernv: cleanups in the pnv-phb3/4 models
- fix core type of MPC8555 and MPC8560 models


Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/7.1 as 
appropriate.


r~





Alexey Kardashevskiy (4):
   spapr/ddw: Reset DMA when the last non-default window is removed
   spapr/ddw: Implement 64bit query extension
   ppc: Define SETFIELD for the ppc target
   ppc/spapr: Implement H_WATCHDOG

Daniel Henrique Barboza (8):
   ppc/pnv: move root port attach to pnv_phb4_realize()
   ppc/pnv: attach phb3/phb4 root ports in QOM tree
   ppc/pnv: assign pnv-phb-root-port chassis/slot earlier
   ppc/pnv: make pnv_ics_get() use the chip8->phbs[] array
   ppc/pnv: make pnv_ics_resend() use chip8->phbs[]
   ppc/pnv: make pnv_chip_power8_pic_print_info() use chip8->phbs[]
   ppc/pnv: remove 'INTERFACE_PCIE_DEVICE' from phb3 root bus
   ppc/pnv: remove 'INTERFACE_PCIE_DEVICE' from phb4 root bus

Matheus Ferst (11):
   target/ppc: use int128.h methods in vpmsumd
   target/ppc: use int128.h methods in vadduqm
   target/ppc: use int128.h methods in vaddecuq and vaddeuqm
   target/ppc: use int128.h methods in vaddcuq
   target/ppc: use int128.h methods in vsubuqm
   target/ppc: use int128.h methods in vsubecuq and vsubeuqm
   target/ppc: use int128.h methods in vsubcuq
   target/ppc: Add flag for ISA v2.06 BCDA instructions
   target/ppc: implement addg6s
   target/ppc: implement cbcdtd
   target/ppc: implement cdtbcd

Murilo Opsfelder Araujo (1):
   target/ppc: Return default CPU for max CPU

Pali Rohár (1):
   target/ppc: Fix MPC8555 and MPC8560 core type to e500v1

Thomas Huth (1):
   target/ppc/cpu-models: Remove the "default" CPU alias

Víctor Colombo (8):
   target/ppc: Change FPSCR_* to follow POWER ISA numbering convention
   target/ppc: Fix insn32.decode style issues
   target/ppc: Move mffscrn[i] to decodetree
   target/ppc: Move mffsce to decodetree
   target/ppc: Move mffsl to decodetree
   target/ppc: Move mffs[.] to decodetree
   target/ppc: Implement mffscdrn[i] instructions
   tests/tcg/ppc64: Add mffsce test

  hw/intc/pnv_xive.c |  20 ---
  hw/intc/pnv_xive2.c|  20 ---
  hw/pci-host/pnv_phb3.c |  22 +--
  hw/pci-host/pnv_phb4.c |  40 +
  hw/pci-host/pnv_phb4_pec.c |   3 -
  hw/ppc/pnv.c   | 102 +--
  hw/ppc/spapr.c |   4 +
  hw/ppc/spapr_iommu.c   |   3 +-
  hw/ppc/spapr_pci.c |   6 +-
  hw/ppc/spapr_rtas_ddw.c|  34 +++-
  hw/watchdog/meson.build|   1 +
  hw/watchdog/spapr_watchdog.c   | 274 +
  hw/watchdog/trace-events   |   7 +
  include/hw/pci-host/pnv_phb3_regs.h|  16 --
  include/hw/ppc/pnv.h   |   3 +-
  include/hw/ppc/spapr.h |  26 ++-
  target/ppc/cpu-models.c|  17 +-
  target/ppc/cpu-models.h|  14 +-
  target/ppc/cpu.h   |  89 ++
  target/ppc/cpu_init.c  |  29 ++-
  target/ppc/dfp_helper.c|  65 +++
  target/ppc/helper.h|  20 ++-
  target/ppc/insn32.decode   |  71 ++--
  target/ppc/int_helper.c| 229 
  target/ppc/internal.h  |   3 -
  target/ppc/translate/fixedpoint-impl.c.inc |  51 ++
  target/ppc/translate/fp-impl.c.inc | 203 +++--
  target/ppc/translate/fp-ops.c.inc  |   9 -
  target/ppc/translate/vmx-impl.c.inc|  32 ++--
  target/ppc/translate/vmx-ops.c.inc |   9 +-
  tests/tcg/ppc64/Makefile.target|   1 +
  tests/tcg/ppc6

[PATCH v2] hw: m25p80: Add Block Protect and Top Bottom bits for write protect

2022-07-06 Thread Iris Chen
Signed-off-by: Iris Chen 
---
Addressing all comments. 
In reponse to this comment:
"Something wrong will occur if all block_protect[0123] are zeroes",
the code actually ignores num_protected_sectors when block_protect_value = 0
which happens when block_protect[0123] are zeroes.
 
You can refer to the bottom block in v1, where we only look at cases when 
block_protect_value > 0 so it is actually handled.
Regardless, since we were setting num_protected_sectors
in either case, I have refactored the code to make it more clear. 

 hw/block/m25p80.c | 103 --
 1 file changed, 91 insertions(+), 12 deletions(-)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 50b523e5b1..bddea9853b 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -38,21 +38,19 @@
 #include "trace.h"
 #include "qom/object.h"
 
-/* Fields for FlashPartInfo->flags */
-
-/* erase capabilities */
-#define ER_4K 1
-#define ER_32K 2
-/* set to allow the page program command to write 0s back to 1. Useful for
- * modelling EEPROM with SPI flash command set
- */
-#define EEPROM 0x100
-
 /* 16 MiB max in 3 byte address mode */
 #define MAX_3BYTES_SIZE 0x100
-
 #define SPI_NOR_MAX_ID_LEN 6
 
+/* Fields for FlashPartInfo->flags */
+enum spi_option_flags {
+ER_4K  = BIT(0),
+ER_32K = BIT(1),
+EEPROM = BIT(2),
+HAS_SR_TB  = BIT(3),
+HAS_SR_BP3_BIT6= BIT(4),
+};
+
 typedef struct FlashPartInfo {
 const char *part_name;
 /*
@@ -253,7 +251,8 @@ static const FlashPartInfo known_devices[] = {
 { INFO("n25q512a11",  0x20bb20,  0,  64 << 10, 1024, ER_4K) },
 { INFO("n25q512a13",  0x20ba20,  0,  64 << 10, 1024, ER_4K) },
 { INFO("n25q128", 0x20ba18,  0,  64 << 10, 256, 0) },
-{ INFO("n25q256a",0x20ba19,  0,  64 << 10, 512, ER_4K) },
+{ INFO("n25q256a",0x20ba19,  0,  64 << 10, 512,
+   ER_4K | HAS_SR_BP3_BIT6 | HAS_SR_TB) },
 { INFO("n25q512a",0x20ba20,  0,  64 << 10, 1024, ER_4K) },
 { INFO("n25q512ax3",  0x20ba20,  0x1000,  64 << 10, 1024, ER_4K) },
 { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K) },
@@ -480,6 +479,11 @@ struct Flash {
 bool reset_enable;
 bool quad_enable;
 bool aai_enable;
+bool block_protect0;
+bool block_protect1;
+bool block_protect2;
+bool block_protect3;
+bool top_bottom_bit;
 bool status_register_write_disabled;
 uint8_t ear;
 
@@ -626,11 +630,36 @@ void flash_write8(Flash *s, uint32_t addr, uint8_t data)
 uint32_t page = addr / s->pi->page_size;
 uint8_t prev = s->storage[s->cur_addr];
 
+uint32_t block_protect_value = (s->block_protect3 << 3) |
+   (s->block_protect2 << 2) |
+   (s->block_protect1 << 1) |
+   (s->block_protect0 << 0);
+
 if (!s->write_enable) {
 qemu_log_mask(LOG_GUEST_ERROR, "M25P80: write with write protect!\n");
 return;
 }
 
+if (block_protect_value > 0) {
+uint32_t num_protected_sectors = 1 << (block_protect_value - 1);
+uint32_t sector = addr / s->pi->sector_size;
+
+/* top_bottom_bit == 0 means TOP */
+if (!s->top_bottom_bit) {
+if (s->pi->n_sectors <= sector + num_protected_sectors) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "M25P80: write with write protect!\n");
+return;
+}
+} else {
+if (sector < num_protected_sectors) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "M25P80: write with write protect!\n");
+return;
+}
+}
+}
+
 if ((prev ^ data) & data) {
 trace_m25p80_programming_zero_to_one(s, addr, prev, data);
 }
@@ -728,6 +757,15 @@ static void complete_collecting_data(Flash *s)
 break;
 case WRSR:
 s->status_register_write_disabled = extract32(s->data[0], 7, 1);
+s->block_protect0 = extract32(s->data[0], 2, 1);
+s->block_protect1 = extract32(s->data[0], 3, 1);
+s->block_protect2 = extract32(s->data[0], 4, 1);
+if (s->pi->flags & HAS_SR_TB) {
+s->top_bottom_bit = extract32(s->data[0], 5, 1);
+}
+if (s->pi->flags & HAS_SR_BP3_BIT6) {
+s->block_protect3 = extract32(s->data[0], 6, 1);
+}
 
 switch (get_man(s)) {
 case MAN_SPANSION:
@@ -1213,6 +1251,15 @@ static void decode_new_cmd(Flash *s, uint32_t value)
 case RDSR:
 s->data[0] = (!!s->write_enable) << 1;
 s->data[0] |= (!!s->status_register_write_disabled) << 7;
+s->data[0] |= (!!s->block_protect0) << 2;
+s->data[0] |= (!!s->block_protect1) << 3;
+s->data[0] |= (!!s->block_protect2) << 4;
+if (s->pi->flags & HAS_SR_TB) {
+s->data[0] |= 

vhost-user-test failure

2022-07-06 Thread Richard Henderson

Seen on my ubuntu 22.04 laptop:

 86/591 qemu:qtest+qtest-i386 / qtest-i386/qos-test   ERROR 
   10.74s   killed by signal 6 SIGABRT




# child process (/i386/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-net-pci/virti

o-net/virtio-net-tests/vhost-user/reconnect/subprocess [1677921]) stderr: "qemu-

system-i386: -chardev socket,id=chr-reconnect,path=/tmp/vhost-test-MdgDF8/reconn

ect.sock,server=on: info: QEMU waiting for connection on: disconnected:unix:/tmp

/vhost-test-MdgDF8/reconnect.sock,server=on\nqemu-system-i386: Failed to set msg

 fds.\nqemu-system-i386: vhost VQ 0 ring restore failed: -22: Invalid argument (

22)\nqemu-system-i386: Failed to set msg fds.\nqemu-system-i386: vhost VQ 1 ring

 restore failed: -22: Invalid argument (22)\n**\nERROR:../src/tests/qtest/vhost-

user-test.c:809:wait_for_rings_started: assertion failed (ctpop64(s->rings) == c

ount): (1 == 2)\n"

Bail out! ERROR:../src/tests/qtest/qos-test.c:189:subprocess_run_one_test: child

 process (/i386/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-net-pci/virtio-net/v

irtio-net-tests/vhost-user/reconnect/subprocess [1677921]) failed unexpectedly

stderr:

**

ERROR:../src/tests/qtest/qos-test.c:189:subprocess_run_one_test: child process 
(/i386/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-net-pci/virtio-net/virtio-net-tests/vhost-user/reconnect/subprocess 
[1677921]) failed unexpectedly




The failure appears to be timeout related, so it's not consistent, but some of the error 
messages embedded in that block suggest the test never really got started correctly?



r~



[PATCH v4 1/2] qapi: Avoid generating C identifier 'linux'

2022-07-06 Thread zhenwei pi
'linux' is not usable as identifier, because C compilers targeting
Linux predefine it as a macro expanding to 1.  Add it to
@polluted_words. 'unix' is already there.

Suggested-by: Markus Armbruster 
Reviewed-by: Marc-André Lureau 
Signed-off-by: zhenwei pi 
---
 scripts/qapi/common.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 489273574a..737b059e62 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -114,7 +114,7 @@ def c_name(name: str, protect: bool = True) -> str:
  'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
  'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
 # namespace pollution:
-polluted_words = set(['unix', 'errno', 'mips', 'sparc', 'i386'])
+polluted_words = set(['unix', 'errno', 'mips', 'sparc', 'i386', 'linux'])
 name = re.sub(r'[^A-Za-z0-9_]', '_', name)
 if protect and (name in (c89_words | c99_words | c11_words | gcc_words
  | cpp_words | polluted_words)
-- 
2.20.1




Re: [PATCH] hw/riscv: virt: pass random seed to fdt

2022-07-06 Thread Jason A. Donenfeld
Hey Alistair,

On Tue, Jul 05, 2022 at 03:09:09AM +0200, Jason A. Donenfeld wrote:
> Hi Alistair,
> 
> On Wed, Jun 29, 2022 at 4:09 AM Alistair Francis  wrote:
> > I have a Linux 5.8 test case that is failing due to this patch.
> 
> Before I started fixing things in random.c, there were a lot of early
> boot bugs with the RNG in Linux. I backported the fixes for these to
> all stable kernels. It's a bummer that risc-v got hit by these bugs,
> but I think that's just the way things go unfortunately.
> 
> Jason
> 

By the way, I still can't find this in your github tree. I was hoping we
could get this in for 7.1.

As for your 5.8 issue, I've been trying to reproduce that to understand
more about it, but I'm unable to. I've been trying with
nommu_virt_defconfig using my patch ontop of qemu master. Maybe it's
possible in testing this out you were testing the wrong branch? Anyway,
it'd be nice to get this queued up...

Jason



[PATCH v4 0/2] qga: add command 'guest-get-cpustats'

2022-07-06 Thread zhenwei pi
v3 -> v4:
- Separate qapi script change from qga.

v2 -> v3:
- Rename 'GuestOsType' to 'GuestCpuStatsType'.
- Add 'linux' into polluted_words, rename 'linuxos' to 'linux'. Remove
  'windows' from 'GuestCpuStatsType', because currently we don't use it.

v1 -> v2:
- Konstantin & Marc-André pointed out that the structure 'GuestCpuStats'
  is too *linux style*, so re-define it to 'GuestLinuxCpuStats', and use
  an union type of 'GuestCpuStats'.

- Modify comment info from 'man proc', also add linux version infomation.

- Test sscanf return value by '(i == EOF)' (To Marc-André: name is declared
  as 'char name[64];', so we can't test '!name').

- Suggested by Marc-André, use 'int clk_tck = sysconf(_SC_CLK_TCK);'
  instead of hard code.

v1:
- Implement guest agent command 'guest-get-cpustats'

Zhenwei Pi (2):
  qapi: Avoid generating C identifier 'linux'
  qga: add command 'guest-get-cpustats'

 qga/commands-posix.c   | 89 ++
 qga/commands-win32.c   |  6 +++
 qga/qapi-schema.json   | 81 ++
 scripts/qapi/common.py |  2 +-
 4 files changed, 177 insertions(+), 1 deletion(-)

-- 
2.20.1




Re: [PATCH] configure: Restrict TCG to emulation

2022-07-06 Thread Richard Henderson

On 7/6/22 21:08, Thomas Huth wrote:

From: Philippe Mathieu-Daudé

If we don't need to emulate any target, we certainly don't need TCG.

This should also help to compile again with
  ".../configure --enable-tools --disable-system --disable-user"
on systems that do not have a TCG backend.

Signed-off-by: Philippe Mathieu-Daudé
[thuth: Re-arranged the code, remove check-softfloat from buildtest.yml]
Signed-off-by: Thomas Huth
---
  configure  | 20 ++--
  .gitlab-ci.d/buildtest.yml |  2 +-
  2 files changed, 15 insertions(+), 7 deletions(-)


Reviewed-by: Richard Henderson 

r~



[PATCH v4 2/2] qga: add command 'guest-get-cpustats'

2022-07-06 Thread zhenwei pi
A vCPU thread always reaches 100% utilization when:
- guest uses idle=poll
- disable HLT vm-exit
- enable MWAIT

Add new guest agent command 'guest-get-cpustats' to get guest CPU
statistics, we can know the guest workload and how busy the CPU is.

Reviewed-by: Marc-André Lureau 
Signed-off-by: zhenwei pi 
---
 qga/commands-posix.c | 89 
 qga/commands-win32.c |  6 +++
 qga/qapi-schema.json | 81 
 3 files changed, 176 insertions(+)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 0469dc409d..f18530d85f 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2893,6 +2893,90 @@ GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error 
**errp)
 return guest_get_diskstats(errp);
 }
 
+GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
+{
+GuestCpuStatsList *head = NULL, **tail = 
+const char *cpustats = "/proc/stat";
+int clk_tck = sysconf(_SC_CLK_TCK);
+FILE *fp;
+size_t n;
+char *line = NULL;
+
+fp = fopen(cpustats, "r");
+if (fp  == NULL) {
+error_setg_errno(errp, errno, "open(\"%s\")", cpustats);
+return NULL;
+}
+
+while (getline(, , fp) != -1) {
+GuestCpuStats *cpustat = NULL;
+GuestLinuxCpuStats *linuxcpustat;
+int i;
+unsigned long user, system, idle, iowait, irq, softirq, steal, guest;
+unsigned long nice, guest_nice;
+char name[64];
+
+i = sscanf(line, "%s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+   name, , , , , , , ,
+   , , _nice);
+
+/* drop "cpu 1 2 3 ...", get "cpuX 1 2 3 ..." only */
+if ((i == EOF) || strncmp(name, "cpu", 3) || (name[3] == '\0')) {
+continue;
+}
+
+if (i < 5) {
+slog("Parsing cpu stat from %s failed, see \"man proc\"", 
cpustats);
+break;
+}
+
+cpustat = g_new0(GuestCpuStats, 1);
+cpustat->type = GUEST_CPU_STATS_TYPE_LINUX;
+
+linuxcpustat = >u.q_linux;
+linuxcpustat->cpu = atoi([3]);
+linuxcpustat->user = user * 1000 / clk_tck;
+linuxcpustat->nice = nice * 1000 / clk_tck;
+linuxcpustat->system = system * 1000 / clk_tck;
+linuxcpustat->idle = idle * 1000 / clk_tck;
+
+if (i > 5) {
+linuxcpustat->has_iowait = true;
+linuxcpustat->iowait = iowait * 1000 / clk_tck;
+}
+
+if (i > 6) {
+linuxcpustat->has_irq = true;
+linuxcpustat->irq = irq * 1000 / clk_tck;
+linuxcpustat->has_softirq = true;
+linuxcpustat->softirq = softirq * 1000 / clk_tck;
+}
+
+if (i > 8) {
+linuxcpustat->has_steal = true;
+linuxcpustat->steal = steal * 1000 / clk_tck;
+}
+
+if (i > 9) {
+linuxcpustat->has_guest = true;
+linuxcpustat->guest = guest * 1000 / clk_tck;
+}
+
+if (i > 10) {
+linuxcpustat->has_guest = true;
+linuxcpustat->guest = guest * 1000 / clk_tck;
+linuxcpustat->has_guestnice = true;
+linuxcpustat->guestnice = guest_nice * 1000 / clk_tck;
+}
+
+QAPI_LIST_APPEND(tail, cpustat);
+}
+
+free(line);
+fclose(fp);
+return head;
+}
+
 #else /* defined(__linux__) */
 
 void qmp_guest_suspend_disk(Error **errp)
@@ -3247,6 +3331,11 @@ GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error 
**errp)
 return NULL;
 }
 
+GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
 
 #endif /* CONFIG_FSFREEZE */
 
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 36f94c0f9c..7ed7664715 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2543,3 +2543,9 @@ GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error 
**errp)
 error_setg(errp, QERR_UNSUPPORTED);
 return NULL;
 }
+
+GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 9fa20e791b..869399ea1a 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1576,3 +1576,84 @@
 { 'command': 'guest-get-diskstats',
   'returns': ['GuestDiskStatsInfo']
 }
+
+##
+# @GuestCpuStatsType:
+#
+# An enumeration of OS type
+#
+# Since: 7.1
+##
+{ 'enum': 'GuestCpuStatsType',
+  'data': [ 'linux' ] }
+
+
+##
+# @GuestLinuxCpuStats:
+#
+# CPU statistics of Linux
+#
+# @cpu: CPU index in guest OS
+#
+# @user: Time spent in user mode
+#
+# @nice: Time spent in user mode with low priority (nice)
+#
+# @system: Time spent in system mode
+#
+# @idle: Time spent in the idle task
+#
+# @iowait: Time waiting for I/O to complete (since Linux 2.5.41)
+#
+# @irq: Time servicing interrupts (since Linux 2.6.0-test4)
+#
+# @softirq: Time servicing softirqs (since Linux 2.6.0-test4)
+#
+# @steal: 

Re: [PATCH] ui/cocoa: Fix switched_to_fullscreen warning

2022-07-06 Thread Peter Delevoryas
On Sat, Jul 02, 2022 at 11:30:16PM +0900, Akihiko Odaki wrote:
> Reviewed-by: Akihiko Odaki 

Just checking in on the status of this: do I need to submit a pull request?
Or will this patch be picked up in a miscellaneous pull queue eventually?

> 
> On 2022/07/02 13:43, Peter Delevoryas wrote:
> > I noticed this error while building QEMU on Mac OS X:
> > 
> >  [1040/1660] Compiling Objective-C object libcommon.fa.p/ui_cocoa.m.o
> >  ../ui/cocoa.m:803:17: warning: variable 'switched_to_fullscreen' set 
> > but not used [-Wunused-but-set-variable]
> >  static bool switched_to_fullscreen = false;
> >  ^
> >  1 warning generated.
> > 
> > I think the behavior is fine if you remove "switched_to_fullscreen", I can
> > still switch in and out of mouse grabbed mode and fullscreen mode with this
> > change, and Command keycodes will only be passed to the guest if the mouse
> > is grabbed, which I think is the right behavior. I'm not sure why a static
> > piece of state was needed to handle that in the first place. Perhaps the
> > refactoring of the flags-state-change fixed that by toggling the Command
> > keycode on.
> > 
> > I tested this with an Ubuntu core image on macOS 12.4
> > 
> >  wget 
> > https://cdimage.ubuntu.com/ubuntu-core/18/stable/current/ubuntu-core-18-i386.img.xz
> >  xz -d ubuntu-core-18-i386.img.xz
> >  qemu-system-x86_64 -drive file=ubuntu-core-18.i386.img,format=raw
> > 
> > Fixes: 6d73bb643aa7 ("ui/cocoa: Clear modifiers whenever possible")
> > Signed-off-by: Peter Delevoryas 
> > ---
> >   ui/cocoa.m | 8 
> >   1 file changed, 8 deletions(-)
> > 
> > diff --git a/ui/cocoa.m b/ui/cocoa.m
> > index 84c84e98fc..13e208b037 100644
> > --- a/ui/cocoa.m
> > +++ b/ui/cocoa.m
> > @@ -800,7 +800,6 @@ - (bool) handleEventLocked:(NSEvent *)event
> >   int buttons = 0;
> >   int keycode = 0;
> >   bool mouse_event = false;
> > -static bool switched_to_fullscreen = false;
> >   // Location of event in virtual screen coordinates
> >   NSPoint p = [self screenLocationOfEvent:event];
> >   NSUInteger modifiers = [event modifierFlags];
> > @@ -952,13 +951,6 @@ - (bool) handleEventLocked:(NSEvent *)event
> >   // forward command key combos to the host UI unless the mouse 
> > is grabbed
> >   if (!isMouseGrabbed && ([event modifierFlags] & 
> > NSEventModifierFlagCommand)) {
> > -/*
> > - * Prevent the command key from being stuck down in the 
> > guest
> > - * when using Command-F to switch to full screen mode.
> > - */
> > -if (keycode == Q_KEY_CODE_F) {
> > -switched_to_fullscreen = true;
> > -}
> >   return false;
> >   }
> 



Re: [PATCH v5 19/45] target/arm: Implement SME MOVA

2022-07-06 Thread Richard Henderson

On 7/6/22 22:17, Peter Maydell wrote:

On Wed, 6 Jul 2022 at 10:11, Richard Henderson
 wrote:


We can reuse the SVE functions for implementing moves to/from
horizontal tile slices, but we need new ones for moves to/from
vertical tile slices.

Signed-off-by: Richard Henderson 




+/*
+ * Move Zreg vector to ZArray column.
+ */
+#define DO_MOVA_C(NAME, TYPE, H)\
+void HELPER(NAME)(void *za, void *vn, void *vg, uint32_t desc)  \
+{   \
+int i, oprsz = simd_oprsz(desc);\
+for (i = 0; i < oprsz; ) {  \
+uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
+do {\
+if (pg & 1) {   \
+*(TYPE *)(za + tile_vslice_offset(i)) = *(TYPE *)(vn + H(i)); \
+}   \
+i += sizeof(TYPE);  \
+pg >>= sizeof(TYPE);\
+} while (i & 15);   \
+}   \
+}
+
+DO_MOVA_C(sme_mova_cz_b, uint8_t, H1)
+DO_MOVA_C(sme_mova_cz_h, uint16_t, H2)
+DO_MOVA_C(sme_mova_cz_s, uint32_t, H4)


i is a byte offset in this loop, so shouldn't these be using H1_2 and H1_4 ?


Oops, yes.


r~



Re: [PATCH] avocado: Fix BUILD_DIR if it's equal to SOURCE_DIR

2022-07-06 Thread Peter Delevoryas
On Sat, Jul 02, 2022 at 11:56:04AM -0700, Peter Delevoryas wrote:
> I like to build QEMU from the root source directory, rather than cd'ing
> into the build directory. This code may as well include a search path
> for that, so that you can run avocado tests individually without
> specifying "-p qemu_bin=build/qemu-system-arm" manually.

Pinging this thread since I didn't get a response.

> 
> Signed-off-by: Peter Delevoryas 
> ---
>  tests/avocado/avocado_qemu/__init__.py | 17 +
>  1 file changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/tests/avocado/avocado_qemu/__init__.py 
> b/tests/avocado/avocado_qemu/__init__.py
> index b656a70c55..ed4853c805 100644
> --- a/tests/avocado/avocado_qemu/__init__.py
> +++ b/tests/avocado/avocado_qemu/__init__.py
> @@ -120,14 +120,15 @@ def pick_default_qemu_bin(bin_prefix='qemu-system-', 
> arch=None):
>  # qemu binary path does not match arch for powerpc, handle it
>  if 'ppc64le' in arch:
>  arch = 'ppc64'
> -qemu_bin_relative_path = os.path.join(".", bin_prefix + arch)
> -if is_readable_executable_file(qemu_bin_relative_path):
> -return qemu_bin_relative_path
> -
> -qemu_bin_from_bld_dir_path = os.path.join(BUILD_DIR,
> -  qemu_bin_relative_path)
> -if is_readable_executable_file(qemu_bin_from_bld_dir_path):
> -return qemu_bin_from_bld_dir_path
> +qemu_bin_name = bin_prefix + arch
> +qemu_bin_paths = [
> +os.path.join(".", qemu_bin_name),
> +os.path.join(BUILD_DIR, qemu_bin_name),
> +os.path.join(BUILD_DIR, "build", qemu_bin_name),

Thinking about how to write this last line again, maybe it should actually
be "os.path.join(SOURCE_DIR, "build", qemu_bin_name)"?

> +]
> +for path in qemu_bin_paths:
> +if is_readable_executable_file(path):
> +return path
>  return None
>  
>  
> -- 
> 2.37.0
> 
> 



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

2022-07-06 Thread Peter Delevoryas
On Wed, Jul 06, 2022 at 09:46:48AM -0700, Peter Delevoryas wrote:
> On Wed, Jul 06, 2022 at 09:02:14AM +0100, Daniel P. Berrangé wrote:
> > On Tue, Jul 05, 2022 at 02:46:59PM -0700, Peter Delevoryas wrote:
> > > I noticed that I can't run any avocado tests on macOS because the QMP
> > > unix socket path is too long:
> > 
> > 
> > > I think the path limit for unix sockets on macOS might be 104 [1]
> > 
> > All platforms have a very limited path limit, so it isn't really
> > a macOS specific problem, rather
> > 
> > > 
> > > /*
> > >  * [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) */
> > > };
> > > 
> > > The path we're using is exactly 105 characters:
> > > 
> > > $ python
> > > Python 2.7.10 (default, Jan 19 2016, 22:24:01)
> > > [GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
> > > Type "help", "copyright", "credits" or "license" for more information.
> > > >>> len('/var/folders/d7/rz20f6hd709c1ty8f6_6y_z4gn/T/avo_qemu_sock_uh3w_dgc/qemu-37331-10bacf110-monitor.sock')
> > 
> > It is a problem related to where the test suite is creating the
> > paths.
> > 
> > /var/folders/d7/rz20f6hd709c1ty8f6_6y_z4gn/T/avo_qemu_sock_uh3w_dgc/
> > 
> > is way too deep a directory location.
> 
> That's a good point.
> 
> > 
> > It seems we just create this location using 'tempfile.TemporyDirectory'
> > to get a standard tmp dir.
> > 
> > Do you know why python is choosing
> > 
> >   /var/folders/d7/rz20f6hd709c1ty8f6_6y_z4gn/T/
> > 
> > as the temp dir ? Is that a standard location on macOS or is it
> > from some env variable you have set ?
> 
> Hmmm yeah it is odd, I'm not really sure why it's created there or if
> standard glibc tmpfile creation goes there too, I'll go experiment and
> report back. And yeah, maybe I'll double check any environment variables or
> other things.
> 
> The macOS system I use happens to be a Facebook work laptop, which could
> also be related now that I think about it.

Hmmm yeah looks like this is because my TMPDIR is weird.

$ echo $TMPDIR
/var/folders/d7/rz20f6hd709c1ty8f6_6y_z4gn/T/

I didn't think to check this cause I wasn't familiar with TMPDIR. 路

Thanks for responding, I'll just use TMPDIR=/tmp for now. It's probably
something wrong with the Facebook development environment.

Peter

> 
> > 
> > > diff --git a/python/qemu/machine/machine.py 
> > > b/python/qemu/machine/machine.py
> > > index 37191f433b..93451774e3 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"{os.getpid()}{id(self):02x}"
> > 
> > I don't think this is the right fix really, because IMHO the problem
> > is the hugely long path, rather than the final socket name.
> 
> True, yeah let me try to investigate the directory placement.
> 
> > 
> > That said, there is redundancy in the path - avocado is passing in
> > a dierctory created using 'tempfile.TemporyDirectory' so there is no
> > reason why we need to add more entropy via the POD and the 'id(self)'
> > hex string.
> 
> Oh good point, I hadn't thought about that.
> 
> > 
> > IMHO avocado should pass in the 'name' parameter explicitly, using a
> > plain name and thus get a shorter string.
> 
> I see, yeah that makes sense. Maybe I can include a couple patches for this,
> one fixing the directory location, and one refactoring the temporary file
> name template (If I'm understanding your suggestion correctly).
> 
> Thanks for the review! I really appreciate it.
> Peter
> 
> > 
> > >  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}.sock"
> > >  )
> > >  
> > >  self._console_log_path = console_log
> > > -- 
> > > 2.37.0
> > > 
> > > 
> > 
> > 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: [PULL 0/2] M68k for 7.1 patches

2022-07-06 Thread Richard Henderson

On 7/6/22 17:10, Laurent Vivier wrote:

The following changes since commit 180c2f24d5e8eada41e012a3899d29bb695aae06:

   Merge tag 'net-pull-request' of https://github.com/jasowang/qemu into 
staging (2022-07-06 10:41:34 +0530)

are available in the Git repository at:

   https://github.com/vivier/qemu-m68k.git tags/m68k-for-7.1-pull-request

for you to fetch changes up to a988465d0eb7e2ee31a3679bbe3fbe71681820da:

   m68k: virt: pass RNG seed via bootinfo block (2022-07-06 12:30:41 +0200)


Pull request m68k 20220706

pass RNG seed via bootinfo block


Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/7.1 as 
appropriate.


r~






Jason A. Donenfeld (2):
   m68k: use correct variable name in boot info string macro
   m68k: virt: pass RNG seed via bootinfo block

  hw/m68k/bootinfo.h | 18 +-
  .../standard-headers/asm-m68k/bootinfo-virt.h  |  1 +
  hw/m68k/virt.c |  7 +++
  3 files changed, 25 insertions(+), 1 deletion(-)






[PATCH v2 1/2] hw/i386/postcard.c: New ISA POST card device

2022-07-06 Thread Lev Kujawski
Relocate the ioport80 functionality within hw/i386/pc.c into a new ISA
POST card device (postcard.c) that is capable of being instantiated at
different ports as well, such as for the following platforms [1]:
  0x84  for COMPAQ
  0x90  for PS/2 (ISA)
  0x300 for AWARD BIOS
  0x680 for PS/2 (MCA)

Emulate i440FX hardware by storing the value written to the port, a
behavior relied upon by firmware for these systems (e.g., AMIBIOS) to
track the state of the boot process.  Despite the name of this device,
said behavior does not rely upon the presence of an installed POST
card, as the chipset provides an extraneous DMA page register at the
POST address.

To aid firmware debugging, allow for tracing POST card values,
mimicking the [new value, old value] display format of physical cards.

Reference platform:
  TYAN S1686D (i440FX system board)

References:
  [1] F. v. Gilluwe, The Undocumented PC. Boston, MA: Addison-Wesley,
  1997, p. 800-801.

Signed-off-by: Lev Kujawski 
---
 (v2) No functional changes. Add myself as the maintainer of this device,
  per checkpatch; add technical details and references to commit log.

 MAINTAINERS|   5 ++
 hw/i386/Kconfig|   5 ++
 hw/i386/meson.build|   1 +
 hw/i386/pc.c   |  25 +--
 hw/i386/postcard.c | 149 +
 hw/i386/trace-events   |   3 +
 include/hw/i386/postcard.h |  35 +
 7 files changed, 200 insertions(+), 23 deletions(-)
 create mode 100644 hw/i386/postcard.c
 create mode 100644 include/hw/i386/postcard.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 450abd0252..33b13583b7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1719,6 +1719,11 @@ F: include/sysemu/numa.h
 F: tests/unit/test-smp-parse.c
 T: git https://gitlab.com/ehabkost/qemu.git machine-next
 
+ISA POST card
+M: Lev Kujawski 
+S: Supported
+F: hw/i386/postcard.c
+
 Xtensa Machines
 ---
 sim
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index d22ac4a4b9..17979e5c0d 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -10,6 +10,10 @@ config SGX
 bool
 depends on KVM
 
+config POST_CARD
+bool
+depends on ISA_BUS
+
 config PC
 bool
 imply APPLESMC
@@ -40,6 +44,7 @@ config PC
 select PCSPK
 select I8257
 select MC146818RTC
+select POST_CARD
 # For ACPI builder:
 select SERIAL_ISA
 select ACPI_PCI
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 213e2e82b3..c883e8ec9a 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -28,6 +28,7 @@ i386_ss.add(when: 'CONFIG_PC', if_true: files(
   'port92.c'))
 i386_ss.add(when: 'CONFIG_X86_FW_OVMF', if_true: files('pc_sysfw_ovmf.c'),
 if_false: 
files('pc_sysfw_ovmf-stubs.c'))
+i386_ss.add(when: 'CONFIG_POST_CARD', if_true: files('postcard.c'))
 
 subdir('kvm')
 subdir('xen')
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 774cb2bf07..c179e38a61 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -32,6 +32,7 @@
 #include "hw/i386/topology.h"
 #include "hw/i386/fw_cfg.h"
 #include "hw/i386/vmport.h"
+#include "hw/i386/postcard.h"
 #include "sysemu/cpus.h"
 #include "hw/block/fdc.h"
 #include "hw/ide.h"
@@ -403,16 +404,6 @@ GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled)
 return s;
 }
 
-static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
-   unsigned size)
-{
-}
-
-static uint64_t ioport80_read(void *opaque, hwaddr addr, unsigned size)
-{
-return 0xULL;
-}
-
 /* MSDOS compatibility mode FPU exception support */
 static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
unsigned size)
@@ -1059,16 +1050,6 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus 
*pci_bus)
 return dev;
 }
 
-static const MemoryRegionOps ioport80_io_ops = {
-.write = ioport80_write,
-.read = ioport80_read,
-.endianness = DEVICE_NATIVE_ENDIAN,
-.impl = {
-.min_access_size = 1,
-.max_access_size = 1,
-},
-};
-
 static const MemoryRegionOps ioportF0_io_ops = {
 .write = ioportF0_write,
 .read = ioportF0_read,
@@ -1139,12 +1120,10 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 qemu_irq pit_alt_irq = NULL;
 qemu_irq rtc_irq = NULL;
 ISADevice *pit = NULL;
-MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
 MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
 X86MachineState *x86ms = X86_MACHINE(pcms);
 
-memory_region_init_io(ioport80_io, NULL, _io_ops, NULL, 
"ioport80", 1);
-memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
+(void)post_card_init(isa_bus, POST_CARD_PORT_DEFAULT);
 
 memory_region_init_io(ioportF0_io, NULL, _io_ops, NULL, 
"ioportF0", 1);
 memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
diff --git a/hw/i386/postcard.c b/hw/i386/postcard.c
new file mode 100644
index 00..c9fa263510
--- 

[PATCH v2 2/2] hw/i386/postcard: New test suite for the ISA POST card device

2022-07-06 Thread Lev Kujawski
Verify that port 0x80 behavior corresponds with i440FX hardware.
Despite the name of the device, said behavior is implemented by the
system board and does not depend upon the actual presence of a POST
card.

In particular:
 a) Writes to port 0x80 are retained and may be read afterwards.
 b) Word and double word reads return a repeated sequence of the
written octet.

Reference platform:
 TYAN S1686D (i440FX system board)

Signed-off-by: Lev Kujawski 
---
 (v2) First revision of test suite.

 MAINTAINERS |   1 +
 tests/qtest/meson.build |   1 +
 tests/qtest/postcard-test.c | 122 
 3 files changed, 124 insertions(+)
 create mode 100644 tests/qtest/postcard-test.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 33b13583b7..801494d955 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1723,6 +1723,7 @@ ISA POST card
 M: Lev Kujawski 
 S: Supported
 F: hw/i386/postcard.c
+F: tests/qtest/postcard-test.c
 
 Xtensa Machines
 ---
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 31287a9173..0718bdb394 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -47,6 +47,7 @@ qtests_i386 = \
   (config_all_devices.has_key('CONFIG_ISA_IPMI_KCS') ? ['ipmi-kcs-test'] : []) 
+\
   (config_host.has_key('CONFIG_LINUX') and 
 \
config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + 
 \
+  (config_all_devices.has_key('CONFIG_POST_CARD') ? ['postcard-test'] : []) +  
 \
   (config_all_devices.has_key('CONFIG_WDT_IB700') ? ['wdt_ib700-test'] : []) + 
 \
   (config_all_devices.has_key('CONFIG_PVPANIC_ISA') ? ['pvpanic-test'] : []) + 
 \
   (config_all_devices.has_key('CONFIG_PVPANIC_PCI') ? ['pvpanic-pci-test'] : 
[]) +  \
diff --git a/tests/qtest/postcard-test.c b/tests/qtest/postcard-test.c
new file mode 100644
index 00..2e04876d4a
--- /dev/null
+++ b/tests/qtest/postcard-test.c
@@ -0,0 +1,122 @@
+/*
+ * Test Suite for the ISA POST Card
+ *
+ * Copyright (c) 2022 Lev Kujawski
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation; either version 2 of the
+ *  License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+#include "hw/i386/postcard.h"
+
+
+/* I/O helper functions */
+static void
+post_card_write(uint8_t val)
+{
+outb(POST_CARD_PORT_DEFAULT, val);
+}
+
+static uint8_t
+post_card_readb(void)
+{
+return inb(POST_CARD_PORT_DEFAULT);
+}
+
+static uint16_t
+post_card_readw(void)
+{
+return inw(POST_CARD_PORT_DEFAULT);
+}
+
+static uint32_t
+post_card_readl(void)
+{
+return inl(POST_CARD_PORT_DEFAULT);
+}
+
+
+/* Testing framework */
+static QTestState *qts;
+
+static void
+test_setup(void)
+{
+assert(qts == NULL);
+qts = qtest_start("-machine pc");
+assert(qts != NULL);
+}
+
+static void
+test_teardown(void)
+{
+assert(qts != NULL);
+qtest_quit(qts);
+qts = NULL;
+}
+
+
+/* Test cases */
+static void
+test_initial_state(void)
+{
+test_setup();
+g_assert_cmphex(post_card_readb(), ==, 0x00);
+test_teardown();
+}
+
+static void
+test_retain_write(void)
+{
+test_setup();
+g_assert_cmphex(post_card_readb(), ==, 0x00);
+post_card_write(0xaa);
+g_assert_cmphex(post_card_readb(), ==, 0xaa);
+test_teardown();
+}
+
+static void
+test_read_word(void)
+{
+test_setup();
+g_assert_cmphex(post_card_readb(), ==, 0x00);
+post_card_write(0xa5);
+g_assert_cmphex(post_card_readw(), ==, 0xa5a5);
+test_teardown();
+}
+
+static void
+test_read_double_word(void)
+{
+test_setup();
+g_assert_cmphex(post_card_readb(), ==, 0x00);
+post_card_write(0xa5);
+g_assert_cmphex(post_card_readl(), ==, 0xa5a5a5a5);
+test_teardown();
+}
+
+
+int
+main(int argc, char **argv)
+{
+g_test_init(, , NULL);
+
+qtest_add_func("/postcard/initial_state", test_initial_state);
+qtest_add_func("/postcard/retain_write", test_retain_write);
+qtest_add_func("/postcard/read_word", test_read_word);
+qtest_add_func("/postcard/read_double_word", test_read_double_word);
+
+return g_test_run();
+}
-- 
2.34.1




Re: [PATCH] scripts: check if .git exists before checking submodule status

2022-07-06 Thread Philippe Mathieu-Daudé via

On 29/6/22 18:08, Daniel P. Berrangé wrote:

Currently we check status of each submodule, before actually checking
if we're in a git repo. These status commands will all fail, but we
are hiding their output so we don't see it currently.

Signed-off-by: Daniel P. Berrangé 
---
  scripts/git-submodule.sh | 12 ++--
  1 file changed, 6 insertions(+), 6 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v9 14/21] jobs: protect job.aio_context with BQL and job_mutex

2022-07-06 Thread Emanuele Giuseppe Esposito
In order to make it thread safe, implement a "fake rwlock",
where we allow reads under BQL *or* job_mutex held, but
writes only under BQL *and* job_mutex.

The only write we have is in child_job_set_aio_ctx, which always
happens under drain (so the job is paused).
For this reason, introduce job_set_aio_context and make sure that
the context is set under BQL, job_mutex and drain.
Also make sure all other places where the aiocontext is read
are protected.

Note: at this stage, job_{lock/unlock} and job lock guard macros
are *nop*.

Suggested-by: Paolo Bonzini 
Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
---
 block/replication.c |  6 --
 blockjob.c  |  3 ++-
 include/qemu/job.h  | 19 ++-
 job.c   | 12 
 4 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/block/replication.c b/block/replication.c
index 55c8f894aa..2189863df1 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -148,8 +148,10 @@ static void replication_close(BlockDriverState *bs)
 }
 if (s->stage == BLOCK_REPLICATION_FAILOVER) {
 commit_job = >commit_job->job;
-assert(commit_job->aio_context == qemu_get_current_aio_context());
-job_cancel_sync(commit_job, false);
+WITH_JOB_LOCK_GUARD() {
+assert(commit_job->aio_context == qemu_get_current_aio_context());
+job_cancel_sync_locked(commit_job, false);
+}
 }
 
 if (s->mode == REPLICATION_MODE_SECONDARY) {
diff --git a/blockjob.c b/blockjob.c
index bce05a9096..0d120ed126 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -166,12 +166,13 @@ static void child_job_set_aio_ctx(BdrvChild *c, 
AioContext *ctx,
 bdrv_set_aio_context_ignore(sibling->bs, ctx, ignore);
 }
 
-job->job.aio_context = ctx;
+job_set_aio_context(>job, ctx);
 }
 
 static AioContext *child_job_get_parent_aio_context(BdrvChild *c)
 {
 BlockJob *job = c->opaque;
+assert(qemu_in_main_thread());
 
 return job->job.aio_context;
 }
diff --git a/include/qemu/job.h b/include/qemu/job.h
index 5709e8d4a8..c144aabefc 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -77,7 +77,12 @@ typedef struct Job {
 
 /** Protected by AioContext lock */
 
-/** AioContext to run the job coroutine in */
+/**
+ * AioContext to run the job coroutine in.
+ * This field can be read when holding either the BQL (so we are in
+ * the main loop) or the job_mutex.
+ * It can be only written when we hold *both* BQL and job_mutex.
+ */
 AioContext *aio_context;
 
 /** Reference count of the block job */
@@ -741,4 +746,16 @@ int job_finish_sync(Job *job, void (*finish)(Job *, Error 
**errp),
 int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
Error **errp);
 
+/**
+ * Sets the @job->aio_context.
+ * Called with job_mutex *not* held.
+ *
+ * This function must run in the main thread to protect against
+ * concurrent read in job_finish_sync_locked(),
+ * takes the job_mutex lock to protect against the read in
+ * job_do_yield_locked(), and must be called when the coroutine
+ * is quiescent.
+ */
+void job_set_aio_context(Job *job, AioContext *ctx);
+
 #endif
diff --git a/job.c b/job.c
index 405f39566b..66cae82593 100644
--- a/job.c
+++ b/job.c
@@ -394,6 +394,17 @@ Job *job_get(const char *id)
 return job_get_locked(id);
 }
 
+void job_set_aio_context(Job *job, AioContext *ctx)
+{
+/* protect against read in job_finish_sync_locked and job_start */
+assert(qemu_in_main_thread());
+/* protect against read in job_do_yield_locked */
+JOB_LOCK_GUARD();
+/* ensure the coroutine is quiescent while the AioContext is changed */
+assert(job->pause_count > 0);
+job->aio_context = ctx;
+}
+
 /* Called with job_mutex *not* held. */
 static void job_sleep_timer_cb(void *opaque)
 {
@@ -1380,6 +1391,7 @@ int job_finish_sync_locked(Job *job,
 {
 Error *local_err = NULL;
 int ret;
+assert(qemu_in_main_thread());
 
 job_ref_locked(job);
 
-- 
2.31.1




Re: [PATCH v8 17/20] job.c: enable job lock/unlock and remove Aiocontext locks

2022-07-06 Thread Emanuele Giuseppe Esposito



Am 05/07/2022 um 15:07 schrieb Stefan Hajnoczi:
> On Wed, Jun 29, 2022 at 10:15:35AM -0400, Emanuele Giuseppe Esposito wrote:
>> Change the job_{lock/unlock} and macros to use job_mutex.
>>
>> Now that they are not nop anymore, remove the aiocontext
>> to avoid deadlocks.
>>
>> Therefore:
>> - when possible, remove completely the aiocontext lock/unlock pair
>> - if it is used by some other function too, reduce the locking
>> section as much as possible, leaving the job API outside.
>>
>> There is only one JobDriver callback, ->free() that assumes that
>> the aiocontext lock is held (because it calls bdrv_unref), so for
>> now keep that under aiocontext lock.
> 
> This discussion shouldn't hold up the patch series, it's a separate
> issue:
> 
> Why does bdrv_unref() need the AioContext lock? The reference count
> itself is protected by the BQL (bdrv_ref() is GS too). I/O requests
> should be using fine-grained locks now, so I'm not sure if we still need
> to hold the AioContext lock to drain them?

If I remove the AioContex lock/unlock in job_unref_locked, I see that
test 200 and test-bdrv-drain are failing.

The reason is that job->free() is calling block_job_free and then we
eventually get to bdrv_detach_child claling bdrv_try_set_aio_context
from the main loop, on a node that is in another AioContext lock.

So it isn't really about bdrv_unref, but more bdrv_try_set_aio_context.
Until we don't find a solution to that, we can't get rid of this
aiocontext lock.

That's the shared call stack from both tests:

#0  __pthread_kill_implementation (threadid=,
signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x766a64a3 in __pthread_kill_internal (signo=6,
threadid=) at pthread_kill.c:78
#2  0x76659d06 in __GI_raise (sig=sig@entry=6)
at ../sysdeps/posix/raise.c:26
#3  0x7662c7d3 in __GI_abort () at abort.c:79
#4  0x55d6411f in error_exit (err=,
msg=msg@entry=0x55f49b30 <__func__.20> "qemu_mutex_unlock_impl")
at ../util/qemu-thread-posix.c:38
--Type  for more, q to quit, c to continue without paging--
#5  0x55d64965 in qemu_mutex_unlock_impl (mutex=0x568d0620,
file=, line=)
at ../util/qemu-thread-posix.c:118
#6  0x55c39c06 in bdrv_set_aio_context_ignore (bs=0x575133e0,
new_context=0x566a2ad0, ignore=0x7fffd110) at ../block.c:7399
#7  0x55c3a100 in bdrv_child_try_set_aio_context (
bs=bs@entry=0x575133e0, ctx=ctx@entry=0x566a2ad0,
ignore_child=ignore_child@entry=0x0, errp=errp@entry=0x0)
at ../block.c:7493
#8  0x55c3a1f6 in bdrv_try_set_aio_context (errp=0x0,
--Type  for more, q to quit, c to continue without paging--
ctx=0x566a2ad0, bs=0x575133e0) at ../block.c:7503
#9  bdrv_detach_child (childp=0x7fffd168) at ../block.c:3130
#10 bdrv_root_unref_child (child=,
child@entry=0x5732dc00)
at ../block.c:3228
#11 0x55c4265f in block_job_remove_all_bdrv (job=0x575b6a30)
at ../blockjob.c:195
#12 0x55c426b5 in block_job_free (job=0x575b6a30)
at ../blockjob.c:76
#13 0x55c4472e in job_unref_locked (job=0x575b6a30)
at ../job.c:464
--Type  for more, q to quit, c to continue without paging--
#14 job_unref_locked (job=0x575b6a30) at ../job.c:450

> 
> Reviewed-by: Stefan Hajnoczi 
> 




[PATCH v9 15/21] job.c: enable job lock/unlock and remove Aiocontext locks

2022-07-06 Thread Emanuele Giuseppe Esposito
Change the job_{lock/unlock} and macros to use job_mutex.

Now that they are not nop anymore, remove the aiocontext
to avoid deadlocks.

Therefore:
- when possible, remove completely the aiocontext lock/unlock pair
- if it is used by some other function too, reduce the locking
  section as much as possible, leaving the job API outside.
- change AIO_WAIT_WHILE in AIO_WAIT_WHILE_UNLOCKED, since we
  are not using the aiocontext lock anymore

There is only one JobDriver callback, ->free() that assumes that
the aiocontext lock is held (because it calls bdrv_unref), so for
now keep that under aiocontext lock.

Also remove real_job_{lock/unlock}, as they are replaced by the
public functions.

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
---
 blockdev.c   | 74 ---
 include/qemu/job.h   | 22 
 job-qmp.c| 46 +++--
 job.c| 86 +++-
 tests/unit/test-bdrv-drain.c |  4 +-
 tests/unit/test-block-iothread.c |  2 +-
 tests/unit/test-blockjob.c   | 13 ++---
 7 files changed, 53 insertions(+), 194 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 5b79093155..2cd84d206c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -155,12 +155,7 @@ void blockdev_mark_auto_del(BlockBackend *blk)
 for (job = block_job_next_locked(NULL); job;
  job = block_job_next_locked(job)) {
 if (block_job_has_bdrv(job, blk_bs(blk))) {
-AioContext *aio_context = job->job.aio_context;
-aio_context_acquire(aio_context);
-
 job_cancel_locked(>job, false);
-
-aio_context_release(aio_context);
 }
 }
 
@@ -1836,14 +1831,7 @@ static void drive_backup_abort(BlkActionState *common)
 DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
 
 if (state->job) {
-AioContext *aio_context;
-
-aio_context = bdrv_get_aio_context(state->bs);
-aio_context_acquire(aio_context);
-
 job_cancel_sync(>job->job, true);
-
-aio_context_release(aio_context);
 }
 }
 
@@ -1937,14 +1925,7 @@ static void blockdev_backup_abort(BlkActionState *common)
 BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, 
common);
 
 if (state->job) {
-AioContext *aio_context;
-
-aio_context = bdrv_get_aio_context(state->bs);
-aio_context_acquire(aio_context);
-
 job_cancel_sync(>job->job, true);
-
-aio_context_release(aio_context);
 }
 }
 
@@ -3306,19 +3287,14 @@ out:
 }
 
 /*
- * Get a block job using its ID and acquire its AioContext.
- * Called with job_mutex held.
+ * Get a block job using its ID. Called with job_mutex held.
  */
-static BlockJob *find_block_job_locked(const char *id,
-   AioContext **aio_context,
-   Error **errp)
+static BlockJob *find_block_job_locked(const char *id, Error **errp)
 {
 BlockJob *job;
 
 assert(id != NULL);
 
-*aio_context = NULL;
-
 job = block_job_get_locked(id);
 
 if (!job) {
@@ -3327,36 +3303,30 @@ static BlockJob *find_block_job_locked(const char *id,
 return NULL;
 }
 
-*aio_context = block_job_get_aio_context(job);
-aio_context_acquire(*aio_context);
-
 return job;
 }
 
 void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
 {
-AioContext *aio_context;
 BlockJob *job;
 
 JOB_LOCK_GUARD();
-job = find_block_job_locked(device, _context, errp);
+job = find_block_job_locked(device, errp);
 
 if (!job) {
 return;
 }
 
 block_job_set_speed_locked(job, speed, errp);
-aio_context_release(aio_context);
 }
 
 void qmp_block_job_cancel(const char *device,
   bool has_force, bool force, Error **errp)
 {
-AioContext *aio_context;
 BlockJob *job;
 
 JOB_LOCK_GUARD();
-job = find_block_job_locked(device, _context, errp);
+job = find_block_job_locked(device, errp);
 
 if (!job) {
 return;
@@ -3369,22 +3339,19 @@ void qmp_block_job_cancel(const char *device,
 if (job_user_paused_locked(>job) && !force) {
 error_setg(errp, "The block job for device '%s' is currently paused",
device);
-goto out;
+return;
 }
 
 trace_qmp_block_job_cancel(job);
 job_user_cancel_locked(>job, force, errp);
-out:
-aio_context_release(aio_context);
 }
 
 void qmp_block_job_pause(const char *device, Error **errp)
 {
-AioContext *aio_context;
 BlockJob *job;
 
 JOB_LOCK_GUARD();
-job = find_block_job_locked(device, _context, errp);
+job = find_block_job_locked(device, errp);
 
 if (!job) {
 return;
@@ -3392,16 +3359,14 @@ void qmp_block_job_pause(const char *device, Error 
**errp)
 
 trace_qmp_block_job_pause(job);
 job_user_pause_locked(>job, errp);
-

Re: [PATCH] tcg/tci: Remove CONFIG_DEBUG_TCG_INTERPRETER

2022-07-06 Thread Philippe Mathieu-Daudé via

On 5/7/22 10:36, Richard Henderson wrote:

There is nothing in this environment variable that cannot
be done better with -d flags.  There is nothing special
about TCI that warrants this hack.

Moreover, it does not compile -- remove it.

Reported-by: Song Gao 
Signed-off-by: Richard Henderson 
---
  tcg/tci/tcg-target.h | 5 -
  tcg/tci/tcg-target.c.inc | 7 ---
  2 files changed, 12 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v9 10/21] block/mirror.c: use of job helpers in drivers to avoid TOC/TOU

2022-07-06 Thread Emanuele Giuseppe Esposito
Once job lock is used and aiocontext is removed, mirror has
to perform job operations under the same critical section,
using the helpers prepared in previous commit.

Note: at this stage, job_{lock/unlock} and job lock guard macros
are *nop*.

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
---
 block/mirror.c | 19 ++-
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index d8ecb9efa2..b38676e19d 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -654,9 +654,13 @@ static int mirror_exit_common(Job *job)
 BlockDriverState *target_bs;
 BlockDriverState *mirror_top_bs;
 Error *local_err = NULL;
-bool abort = job->ret < 0;
+bool abort;
 int ret = 0;
 
+WITH_JOB_LOCK_GUARD() {
+abort = job->ret < 0;
+}
+
 if (s->prepared) {
 return 0;
 }
@@ -1152,8 +1156,10 @@ static void mirror_complete(Job *job, Error **errp)
 s->should_complete = true;
 
 /* If the job is paused, it will be re-entered when it is resumed */
-if (!job->paused) {
-job_enter(job);
+WITH_JOB_LOCK_GUARD() {
+if (!job->paused) {
+job_enter_cond_locked(job, NULL);
+}
 }
 }
 
@@ -1173,8 +1179,11 @@ static bool mirror_drained_poll(BlockJob *job)
  * from one of our own drain sections, to avoid a deadlock waiting for
  * ourselves.
  */
-if (!s->common.job.paused && !job_is_cancelled(>job) && !s->in_drain) 
{
-return true;
+WITH_JOB_LOCK_GUARD() {
+if (!s->common.job.paused && !job_is_cancelled_locked(>job)
+&& !s->in_drain) {
+return true;
+}
 }
 
 return !!s->in_flight;
-- 
2.31.1




Re: [PATCH] tests/docker/dockerfiles: Add debian-loongarch-cross.docker

2022-07-06 Thread Philippe Mathieu-Daudé via

On 4/7/22 09:08, Richard Henderson wrote:

Use the pre-packaged toolchain provided by Loongson via github.

Signed-off-by: Richard Henderson 
---
  configure |  5 
  tests/docker/Makefile.include |  2 ++
  .../dockerfiles/debian-loongarch-cross.docker | 25 +++
  3 files changed, 32 insertions(+)
  create mode 100644 tests/docker/dockerfiles/debian-loongarch-cross.docker


Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v9 03/21] job.c: API functions not used outside should be static

2022-07-06 Thread Emanuele Giuseppe Esposito
job_event_* functions can all be static, as they are not used
outside job.c.

Same applies for job_txn_add_job().

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 include/qemu/job.h | 18 --
 job.c  | 22 +++---
 2 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/include/qemu/job.h b/include/qemu/job.h
index 876e13d549..4b64eb15f7 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -358,18 +358,6 @@ JobTxn *job_txn_new(void);
  */
 void job_txn_unref(JobTxn *txn);
 
-/**
- * @txn: The transaction (may be NULL)
- * @job: Job to add to the transaction
- *
- * Add @job to the transaction.  The @job must not already be in a transaction.
- * The caller must call either job_txn_unref() or job_completed() to release
- * the reference that is automatically grabbed here.
- *
- * If @txn is NULL, the function does nothing.
- */
-void job_txn_add_job(JobTxn *txn, Job *job);
-
 /**
  * Create a new long-running job and return it.
  *
@@ -431,12 +419,6 @@ void job_progress_set_remaining(Job *job, uint64_t 
remaining);
  */
 void job_progress_increase_remaining(Job *job, uint64_t delta);
 
-/** To be called when a cancelled job is finalised. */
-void job_event_cancelled(Job *job);
-
-/** To be called when a successfully completed job is finalised. */
-void job_event_completed(Job *job);
-
 /**
  * Conditionally enter the job coroutine if the job is ready to run, not
  * already busy and fn() returns true. fn() is called while under the job_lock
diff --git a/job.c b/job.c
index 2b4ffca9d4..cafd597ba4 100644
--- a/job.c
+++ b/job.c
@@ -125,7 +125,17 @@ void job_txn_unref(JobTxn *txn)
 }
 }
 
-void job_txn_add_job(JobTxn *txn, Job *job)
+/**
+ * @txn: The transaction (may be NULL)
+ * @job: Job to add to the transaction
+ *
+ * Add @job to the transaction.  The @job must not already be in a transaction.
+ * The caller must call either job_txn_unref() or job_completed() to release
+ * the reference that is automatically grabbed here.
+ *
+ * If @txn is NULL, the function does nothing.
+ */
+static void job_txn_add_job(JobTxn *txn, Job *job)
 {
 if (!txn) {
 return;
@@ -427,12 +437,18 @@ void job_progress_increase_remaining(Job *job, uint64_t 
delta)
 progress_increase_remaining(>progress, delta);
 }
 
-void job_event_cancelled(Job *job)
+/**
+ * To be called when a cancelled job is finalised.
+ */
+static void job_event_cancelled(Job *job)
 {
 notifier_list_notify(>on_finalize_cancelled, job);
 }
 
-void job_event_completed(Job *job)
+/**
+ * To be called when a successfully completed job is finalised.
+ */
+static void job_event_completed(Job *job)
 {
 notifier_list_notify(>on_finalize_completed, job);
 }
-- 
2.31.1




Re: [PATCH v3 4/4] target/mips: introduce Cavium Octeon CPU model

2022-07-06 Thread Philippe Mathieu-Daudé via

On 4/7/22 12:59, Pavel Dovgalyuk wrote:

ping

This is the only non-reviewed patch in the series.


I've been looking for doc/datasheets but no luck (except the Linux 
kernel comments).


What kind of testing are you doing?


On 20.06.2022 15:05, Pavel Dovgalyuk wrote:

This patch adds Cavium Octeon 68XX vCPU which provides
Octeon-specific instructions.

Signed-off-by: Pavel Dovgalyuk 

--
v3 changes:
  - split the patch to instruction set introduction and new vCPU
    (suggested by Philippe Mathieu-Daudé)
v2 changes:
  - vCPU name changed to Octeon68XX (suggested by Richard Henderson)
---
  target/mips/cpu-defs.c.inc |   28 
  1 file changed, 28 insertions(+)




Re: [PATCH] docs: aspeed: Minor updates

2022-07-06 Thread Peter Delevoryas
On Wed, Jul 06, 2022 at 07:21:31PM +0200, Cédric Le Goater wrote:
> Some more controllers have been modeled recently. Reflect that in the
> list of supported devices. New machines were also added.

Looks good, thanks for this!

Reviewed-by: Peter Delevoryas 

> 
> Signed-off-by: Cédric Le Goater 
> ---
>  docs/system/arm/aspeed.rst | 14 ++
>  1 file changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst
> index 445095690c04..6c5b05128ea8 100644
> --- a/docs/system/arm/aspeed.rst
> +++ b/docs/system/arm/aspeed.rst
> @@ -31,7 +31,10 @@ AST2600 SoC based machines :
>  - ``tacoma-bmc``   OpenPOWER Witherspoon POWER9 AST2600 BMC
>  - ``rainier-bmc``  IBM Rainier POWER10 BMC
>  - ``fuji-bmc`` Facebook Fuji BMC
> +- ``bletchley-bmc``Facebook Bletchley BMC
>  - ``fby35-bmc``Facebook fby35 BMC
> +- ``qcom-dc-scm-v1-bmc``   Qualcomm DC-SCM V1 BMC
> +- ``qcom-firework-bmc``Qualcomm Firework BMC
>  
>  Supported devices
>  -
> @@ -40,7 +43,7 @@ Supported devices
>   * Interrupt Controller (VIC)
>   * Timer Controller
>   * RTC Controller
> - * I2C Controller
> + * I2C Controller, including the new register interface of the AST2600
>   * System Control Unit (SCU)
>   * SRAM mapping
>   * X-DMA Controller (basic interface)
> @@ -57,6 +60,10 @@ Supported devices
>   * LPC Peripheral Controller (a subset of subdevices are supported)
>   * Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
>   * ADC
> + * Secure Boot Controller (AST2600)
> + * eMMC Boot Controller (dummy)
> + * PECI Controller (minimal)
> + * I3C Controller
>  
>  
>  Missing devices
> @@ -68,12 +75,10 @@ Missing devices
>   * Super I/O Controller
>   * PCI-Express 1 Controller
>   * Graphic Display Controller
> - * PECI Controller
>   * MCTP Controller
>   * Mailbox Controller
>   * Virtual UART
>   * eSPI Controller
> - * I3C Controller
>  
>  Boot options
>  
> @@ -154,6 +159,8 @@ Supported devices
>   * LPC Peripheral Controller (a subset of subdevices are supported)
>   * Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
>   * ADC
> + * Secure Boot Controller
> + * PECI Controller (minimal)
>  
>  
>  Missing devices
> @@ -161,7 +168,6 @@ Missing devices
>  
>   * PWM and Fan Controller
>   * Slave GPIO Controller
> - * PECI Controller
>   * Mailbox Controller
>   * Virtual UART
>   * eSPI Controller
> -- 
> 2.35.3
> 
> 



[PATCH v9 04/21] aio-wait.h: introduce AIO_WAIT_WHILE_UNLOCKED

2022-07-06 Thread Emanuele Giuseppe Esposito
Same as AIO_WAIT_WHILE macro, but if we are in the Main loop
do not release and then acquire ctx_ 's aiocontext.

Once all Aiocontext locks go away, this macro will replace
AIO_WAIT_WHILE.

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 include/block/aio-wait.h | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
index 54840f8622..a61f82c617 100644
--- a/include/block/aio-wait.h
+++ b/include/block/aio-wait.h
@@ -59,10 +59,13 @@ typedef struct {
 extern AioWait global_aio_wait;
 
 /**
- * AIO_WAIT_WHILE:
+ * _AIO_WAIT_WHILE:
  * @ctx: the aio context, or NULL if multiple aio contexts (for which the
  *   caller does not hold a lock) are involved in the polling condition.
  * @cond: wait while this conditional expression is true
+ * @unlock: whether to unlock and then lock again @ctx. This apples
+ * only when waiting for another AioContext from the main loop.
+ * Otherwise it's ignored.
  *
  * Wait while a condition is true.  Use this to implement synchronous
  * operations that require event loop activity.
@@ -75,7 +78,7 @@ extern AioWait global_aio_wait;
  * wait on conditions between two IOThreads since that could lead to deadlock,
  * go via the main loop instead.
  */
-#define AIO_WAIT_WHILE(ctx, cond) ({   \
+#define _AIO_WAIT_WHILE(ctx, cond, unlock) ({  \
 bool waited_ = false;  \
 AioWait *wait_ = _aio_wait; \
 AioContext *ctx_ = (ctx);  \
@@ -92,11 +95,11 @@ extern AioWait global_aio_wait;
 assert(qemu_get_current_aio_context() ==   \
qemu_get_aio_context());\
 while ((cond)) {   \
-if (ctx_) {\
+if (unlock && ctx_) {  \
 aio_context_release(ctx_); \
 }  \
 aio_poll(qemu_get_aio_context(), true);\
-if (ctx_) {\
+if (unlock && ctx_) {  \
 aio_context_acquire(ctx_); \
 }  \
 waited_ = true;\
@@ -105,6 +108,12 @@ extern AioWait global_aio_wait;
 qatomic_dec(_->num_waiters);  \
 waited_; })
 
+#define AIO_WAIT_WHILE(ctx, cond)  \
+_AIO_WAIT_WHILE(ctx, cond, true)
+
+#define AIO_WAIT_WHILE_UNLOCKED(ctx, cond) \
+_AIO_WAIT_WHILE(ctx, cond, false)
+
 /**
  * aio_wait_kick:
  * Wake up the main thread if it is waiting on AIO_WAIT_WHILE().  During
-- 
2.31.1




[PATCH v9 20/21] blockjob: remove unused functions

2022-07-06 Thread Emanuele Giuseppe Esposito
These public functions are not used anywhere, thus can be dropped.

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
---
 blockjob.c   | 30 --
 include/block/blockjob.h | 36 +---
 2 files changed, 13 insertions(+), 53 deletions(-)

diff --git a/blockjob.c b/blockjob.c
index 893c8ff08e..bb82e8d04c 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -56,12 +56,6 @@ BlockJob *block_job_next_locked(BlockJob *bjob)
 return job ? container_of(job, BlockJob, job) : NULL;
 }
 
-BlockJob *block_job_next(BlockJob *bjob)
-{
-JOB_LOCK_GUARD();
-return block_job_next_locked(bjob);
-}
-
 BlockJob *block_job_get_locked(const char *id)
 {
 Job *job = job_get_locked(id);
@@ -74,12 +68,6 @@ BlockJob *block_job_get_locked(const char *id)
 }
 }
 
-BlockJob *block_job_get(const char *id)
-{
-JOB_LOCK_GUARD();
-return block_job_get_locked(id);
-}
-
 void block_job_free(Job *job)
 {
 BlockJob *bjob = container_of(job, BlockJob, job);
@@ -312,12 +300,6 @@ bool block_job_set_speed_locked(BlockJob *job, int64_t 
speed, Error **errp)
 return true;
 }
 
-bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
-{
-JOB_LOCK_GUARD();
-return block_job_set_speed_locked(job, speed, errp);
-}
-
 int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n)
 {
 IO_CODE();
@@ -361,12 +343,6 @@ BlockJobInfo *block_job_query_locked(BlockJob *job, Error 
**errp)
 return info;
 }
 
-BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
-{
-JOB_LOCK_GUARD();
-return block_job_query_locked(job, errp);
-}
-
 /* Called with job lock held */
 static void block_job_iostatus_set_err_locked(BlockJob *job, int error)
 {
@@ -532,12 +508,6 @@ void block_job_iostatus_reset_locked(BlockJob *job)
 job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
 }
 
-void block_job_iostatus_reset(BlockJob *job)
-{
-JOB_LOCK_GUARD();
-block_job_iostatus_reset_locked(job);
-}
-
 void block_job_user_resume(Job *job)
 {
 BlockJob *bjob = container_of(job, BlockJob, job);
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index 912e10b083..7cb4ceaf09 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -93,30 +93,26 @@ typedef struct BlockJob {
  */
 
 /**
- * block_job_next:
+ * block_job_next_locked:
  * @job: A block job, or %NULL.
  *
  * Get the next element from the list of block jobs after @job, or the
  * first one if @job is %NULL.
  *
  * Returns the requested job, or %NULL if there are no more jobs left.
+ * Called with job lock held.
  */
-BlockJob *block_job_next(BlockJob *job);
-
-/* Same as block_job_next(), but called with job lock held. */
 BlockJob *block_job_next_locked(BlockJob *job);
 
 /**
- * block_job_get:
+ * block_job_get_locked:
  * @id: The id of the block job.
  *
  * Get the block job identified by @id (which must not be %NULL).
  *
  * Returns the requested job, or %NULL if it doesn't exist.
+ * Called with job lock held.
  */
-BlockJob *block_job_get(const char *id);
-
-/* Same as block_job_get(), but called with job lock held. */
 BlockJob *block_job_get_locked(const char *id);
 
 /**
@@ -152,43 +148,37 @@ void block_job_remove_all_bdrv(BlockJob *job);
 bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs);
 
 /**
- * block_job_set_speed:
+ * block_job_set_speed_locked:
  * @job: The job to set the speed for.
  * @speed: The new value
  * @errp: Error object.
  *
  * Set a rate-limiting parameter for the job; the actual meaning may
  * vary depending on the job type.
- */
-bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
-
-/*
- * Same as block_job_set_speed(), but called with job lock held.
- * Might release the lock temporarily.
+ *
+ * Called with job lock held, but might release it temporarily.
  */
 bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp);
 
 /**
- * block_job_query:
+ * block_job_query_locked:
  * @job: The job to get information about.
  *
  * Return information about a job.
+ *
+ * Called with job lock held.
  */
-BlockJobInfo *block_job_query(BlockJob *job, Error **errp);
-
-/* Same as block_job_query(), but called with job lock held. */
 BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp);
 
 /**
- * block_job_iostatus_reset:
+ * block_job_iostatus_reset_locked:
  * @job: The job whose I/O status should be reset.
  *
  * Reset I/O status on @job and on BlockDriverState objects it uses,
  * other than job->blk.
+ *
+ * Called with job lock held.
  */
-void block_job_iostatus_reset(BlockJob *job);
-
-/* Same as block_job_iostatus_reset(), but called with job lock held. */
 void block_job_iostatus_reset_locked(BlockJob *job);
 
 /*
-- 
2.31.1




[PATCH v9 19/21] blockjob: protect iostatus field in BlockJob struct

2022-07-06 Thread Emanuele Giuseppe Esposito
iostatus is the only field (together with .job) that needs
protection using the job mutex.

It is set in the main loop (GLOBAL_STATE functions) but read
in I/O code (block_job_error_action).

In order to protect it, change block_job_iostatus_set_err
to block_job_iostatus_set_err_locked(), always called under
job lock.

Signed-off-by: Emanuele Giuseppe Esposito 
---
 blockjob.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/blockjob.c b/blockjob.c
index a2559b97a7..893c8ff08e 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -367,7 +367,8 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
 return block_job_query_locked(job, errp);
 }
 
-static void block_job_iostatus_set_err(BlockJob *job, int error)
+/* Called with job lock held */
+static void block_job_iostatus_set_err_locked(BlockJob *job, int error)
 {
 if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
 job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
@@ -586,8 +587,8 @@ BlockErrorAction block_job_error_action(BlockJob *job, 
BlockdevOnError on_err,
  */
 job->job.user_paused = true;
 }
+block_job_iostatus_set_err_locked(job, error);
 }
-block_job_iostatus_set_err(job, error);
 }
 return action;
 }
-- 
2.31.1




[PULL 30/34] target/ppc: implement cbcdtd

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

Implements the Convert Binary Coded Decimal To Declets instruction.
Since libdecnumber doesn't expose the methods for direct conversion
(decDigitsToDPD, BCD2DPD, etc.), the BCD values are converted to
decimal32 format, from which the declets are extracted.

Where the behavior is undefined, we try to match the result observed in
a POWER9 DD2.3.

Reviewed-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
Signed-off-by: Víctor Colombo 
Message-Id: <20220629162904.105060-11-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/dfp_helper.c| 39 ++
 target/ppc/helper.h|  1 +
 target/ppc/insn32.decode   |  4 +++
 target/ppc/translate/fixedpoint-impl.c.inc |  7 
 4 files changed, 51 insertions(+)

diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c
index 0d01ac3de0..db9e994c8c 100644
--- a/target/ppc/dfp_helper.c
+++ b/target/ppc/dfp_helper.c
@@ -1391,3 +1391,42 @@ DFP_HELPER_SHIFT(DSCLI, 64, 1)
 DFP_HELPER_SHIFT(DSCLIQ, 128, 1)
 DFP_HELPER_SHIFT(DSCRI, 64, 0)
 DFP_HELPER_SHIFT(DSCRIQ, 128, 0)
+
+target_ulong helper_CBCDTD(target_ulong s)
+{
+uint64_t res = 0;
+uint32_t dec32;
+uint8_t bcd[6];
+int w, i, offs;
+decNumber a;
+decContext context;
+
+decContextDefault(, DEC_INIT_DECIMAL32);
+
+for (w = 1; w >= 0; w--) {
+res <<= 32;
+decNumberZero();
+/* Extract each BCD field of word "w" */
+for (i = 5; i >= 0; i--) {
+offs = 4 * (5 - i) + 32 * w;
+bcd[i] = extract64(s, offs, 4);
+if (bcd[i] > 9) {
+/*
+ * If the field value is greater than 9, the results are
+ * undefined. We could use a fixed value like 0 or 9, but
+ * an and with 9 seems to better match the hardware behavior.
+ */
+bcd[i] &= 9;
+}
+}
+
+/* Create a decNumber with the BCD values and convert to decimal32 */
+decNumberSetBCD(, bcd, 6);
+decimal32FromNumber((decimal32 *), , );
+
+/* Extract the two declets from the decimal32 value */
+res |= dec32 & 0xf;
+}
+
+return res;
+}
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 84a41d85b0..583c8dd0c2 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -54,6 +54,7 @@ DEF_HELPER_3(sraw, tl, env, tl, tl)
 DEF_HELPER_FLAGS_2(CFUGED, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(PDEPD, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(PEXTD, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_1(CBCDTD, TCG_CALL_NO_RWG_SE, tl, tl)
 #if defined(TARGET_PPC64)
 DEF_HELPER_FLAGS_2(cmpeqb, TCG_CALL_NO_RWG_SE, i32, tl, tl)
 DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index af8ba9ca9b..65bcaf657f 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -87,6 +87,9 @@
 _rc   rt ra rb rc:bool
 @X_rc   .. rt:5 ra:5 rb:5 .. rc:1   _rc
 
+_sa   rs ra
+@X_sa   .. rs:5 ra:5 . .. . _sa
+
 %x_frtp 22:4 !function=times_2
 %x_frap 17:4 !function=times_2
 %x_frbp 12:4 !function=times_2
@@ -314,6 +317,7 @@ PEXTD   01 . . . 001000 -   @X
 ## BCD Assist
 
 ADDG6S  01 . . . - 001001010 -  @X
+CBCDTD  01 . . - 0100111010 -   @X_sa
 
 ### Float-Point Load Instructions
 
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 490e49cfc7..892c9d2568 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -529,3 +529,10 @@ static bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
 
 return true;
 }
+
+static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
+{
+REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
+gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
+return true;
+}
-- 
2.36.1




[PATCH v9 18/21] blockjob: rename notifier callbacks as _locked

2022-07-06 Thread Emanuele Giuseppe Esposito
They all are called with job_lock held, in job_event_*_locked()

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
---
 blockjob.c | 25 +++--
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/blockjob.c b/blockjob.c
index bbd297b583..a2559b97a7 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -254,7 +254,8 @@ int block_job_add_bdrv(BlockJob *job, const char *name, 
BlockDriverState *bs,
 return 0;
 }
 
-static void block_job_on_idle(Notifier *n, void *opaque)
+/* Called with job_mutex lock held. */
+static void block_job_on_idle_locked(Notifier *n, void *opaque)
 {
 aio_wait_kick();
 }
@@ -374,7 +375,8 @@ static void block_job_iostatus_set_err(BlockJob *job, int 
error)
 }
 }
 
-static void block_job_event_cancelled(Notifier *n, void *opaque)
+/* Called with job_mutex lock held. */
+static void block_job_event_cancelled_locked(Notifier *n, void *opaque)
 {
 BlockJob *job = opaque;
 uint64_t progress_current, progress_total;
@@ -393,7 +395,8 @@ static void block_job_event_cancelled(Notifier *n, void 
*opaque)
 job->speed);
 }
 
-static void block_job_event_completed(Notifier *n, void *opaque)
+/* Called with job_mutex lock held. */
+static void block_job_event_completed_locked(Notifier *n, void *opaque)
 {
 BlockJob *job = opaque;
 const char *msg = NULL;
@@ -419,7 +422,8 @@ static void block_job_event_completed(Notifier *n, void 
*opaque)
 msg);
 }
 
-static void block_job_event_pending(Notifier *n, void *opaque)
+/* Called with job_mutex lock held. */
+static void block_job_event_pending_locked(Notifier *n, void *opaque)
 {
 BlockJob *job = opaque;
 
@@ -431,7 +435,8 @@ static void block_job_event_pending(Notifier *n, void 
*opaque)
   job->job.id);
 }
 
-static void block_job_event_ready(Notifier *n, void *opaque)
+/* Called with job_mutex lock held. */
+static void block_job_event_ready_locked(Notifier *n, void *opaque)
 {
 BlockJob *job = opaque;
 uint64_t progress_current, progress_total;
@@ -476,11 +481,11 @@ void *block_job_create(const char *job_id, const 
BlockJobDriver *driver,
 
 ratelimit_init(>limit);
 
-job->finalize_cancelled_notifier.notify = block_job_event_cancelled;
-job->finalize_completed_notifier.notify = block_job_event_completed;
-job->pending_notifier.notify = block_job_event_pending;
-job->ready_notifier.notify = block_job_event_ready;
-job->idle_notifier.notify = block_job_on_idle;
+job->finalize_cancelled_notifier.notify = block_job_event_cancelled_locked;
+job->finalize_completed_notifier.notify = block_job_event_completed_locked;
+job->pending_notifier.notify = block_job_event_pending_locked;
+job->ready_notifier.notify = block_job_event_ready_locked;
+job->idle_notifier.notify = block_job_on_idle_locked;
 
 WITH_JOB_LOCK_GUARD() {
 notifier_list_add(>job.on_finalize_cancelled,
-- 
2.31.1




[PATCH v9 11/21] jobs: group together API calls under the same job lock

2022-07-06 Thread Emanuele Giuseppe Esposito
Now that the API offers also _locked() functions, take advantage
of it and give also the caller control to take the lock and call
_locked functions.

This makes sense especially when we have for loops, because it
makes no sense to have:

for(job = job_next(); ...)

where each job_next() takes the lock internally.
Instead we want

JOB_LOCK_GUARD();
for(job = job_next_locked(); ...)

Note: at this stage, job_{lock/unlock} and job lock guard macros
are *nop*.

Signed-off-by: Emanuele Giuseppe Esposito 
---
 block.c| 20 +++---
 blockdev.c | 12 ---
 blockjob.c | 52 +++---
 job-qmp.c  |  4 +++-
 job.c  |  5 -
 monitor/qmp-cmds.c |  7 +--
 qemu-img.c | 41 +---
 7 files changed, 93 insertions(+), 48 deletions(-)

diff --git a/block.c b/block.c
index 2c0080..d0db104d71 100644
--- a/block.c
+++ b/block.c
@@ -4978,9 +4978,12 @@ static void bdrv_close(BlockDriverState *bs)
 
 void bdrv_close_all(void)
 {
-assert(job_next(NULL) == NULL);
 GLOBAL_STATE_CODE();
 
+WITH_JOB_LOCK_GUARD() {
+assert(job_next_locked(NULL) == NULL);
+}
+
 /* Drop references from requests still in flight, such as canceled block
  * jobs whose AIO context has not been polled yet */
 bdrv_drain_all();
@@ -6165,13 +6168,16 @@ XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp)
 }
 }
 
-for (job = block_job_next(NULL); job; job = block_job_next(job)) {
-GSList *el;
+WITH_JOB_LOCK_GUARD() {
+for (job = block_job_next_locked(NULL); job;
+ job = block_job_next_locked(job)) {
+GSList *el;
 
-xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB,
-   job->job.id);
-for (el = job->nodes; el; el = el->next) {
-xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data);
+xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB,
+job->job.id);
+for (el = job->nodes; el; el = el->next) {
+xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data);
+}
 }
 }
 
diff --git a/blockdev.c b/blockdev.c
index 71f793c4ab..5b79093155 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -150,12 +150,15 @@ void blockdev_mark_auto_del(BlockBackend *blk)
 return;
 }
 
-for (job = block_job_next(NULL); job; job = block_job_next(job)) {
+JOB_LOCK_GUARD();
+
+for (job = block_job_next_locked(NULL); job;
+ job = block_job_next_locked(job)) {
 if (block_job_has_bdrv(job, blk_bs(blk))) {
 AioContext *aio_context = job->job.aio_context;
 aio_context_acquire(aio_context);
 
-job_cancel(>job, false);
+job_cancel_locked(>job, false);
 
 aio_context_release(aio_context);
 }
@@ -3745,7 +3748,10 @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
 BlockJobInfoList *head = NULL, **tail = 
 BlockJob *job;
 
-for (job = block_job_next(NULL); job; job = block_job_next(job)) {
+JOB_LOCK_GUARD();
+
+for (job = block_job_next_locked(NULL); job;
+ job = block_job_next_locked(job)) {
 BlockJobInfo *value;
 AioContext *aio_context;
 
diff --git a/blockjob.c b/blockjob.c
index 0d59aba439..bce05a9096 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -99,7 +99,9 @@ static char *child_job_get_parent_desc(BdrvChild *c)
 static void child_job_drained_begin(BdrvChild *c)
 {
 BlockJob *job = c->opaque;
-job_pause(>job);
+WITH_JOB_LOCK_GUARD() {
+job_pause_locked(>job);
+}
 }
 
 static bool child_job_drained_poll(BdrvChild *c)
@@ -111,8 +113,10 @@ static bool child_job_drained_poll(BdrvChild *c)
 /* An inactive or completed job doesn't have any pending requests. Jobs
  * with !job->busy are either already paused or have a pause point after
  * being reentered, so no job driver code will run before they pause. */
-if (!job->busy || job_is_completed(job)) {
-return false;
+WITH_JOB_LOCK_GUARD() {
+if (!job->busy || job_is_completed_locked(job)) {
+return false;
+}
 }
 
 /* Otherwise, assume that it isn't fully stopped yet, but allow the job to
@@ -127,7 +131,9 @@ static bool child_job_drained_poll(BdrvChild *c)
 static void child_job_drained_end(BdrvChild *c, int *drained_end_counter)
 {
 BlockJob *job = c->opaque;
-job_resume(>job);
+WITH_JOB_LOCK_GUARD() {
+job_resume_locked(>job);
+}
 }
 
 static bool child_job_can_set_aio_ctx(BdrvChild *c, AioContext *ctx,
@@ -475,13 +481,15 @@ void *block_job_create(const char *job_id, const 
BlockJobDriver *driver,
 job->ready_notifier.notify = block_job_event_ready;
 job->idle_notifier.notify = block_job_on_idle;
 
-notifier_list_add(>job.on_finalize_cancelled,
-  

[PATCH v9 01/21] job.c: make job_mutex and job_lock/unlock() public

2022-07-06 Thread Emanuele Giuseppe Esposito
job mutex will be used to protect the job struct elements and list,
replacing AioContext locks.

Right now use a shared lock for all jobs, in order to keep things
simple. Once the AioContext lock is gone, we can introduce per-job
locks.

To simplify the switch from aiocontext to job lock, introduce
*nop* lock/unlock functions and macros.
We want to always call job_lock/unlock outside the AioContext locks,
and not vice-versa, otherwise we might get a deadlock. This is not
straightforward to do, and that's why we start with nop functions.
Once everything is protected by job_lock/unlock, we can change the nop into
an actual mutex and remove the aiocontext lock.

Since job_mutex is already being used, add static
real_job_{lock/unlock} for the existing usage.

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 include/qemu/job.h | 24 
 job.c  | 35 +++
 2 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/include/qemu/job.h b/include/qemu/job.h
index c105b31076..d1192ffd61 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -303,6 +303,30 @@ typedef enum JobCreateFlags {
 JOB_MANUAL_DISMISS = 0x04,
 } JobCreateFlags;
 
+extern QemuMutex job_mutex;
+
+#define JOB_LOCK_GUARD() /* QEMU_LOCK_GUARD(_mutex) */
+
+#define WITH_JOB_LOCK_GUARD() /* WITH_QEMU_LOCK_GUARD(_mutex) */
+
+/**
+ * job_lock:
+ *
+ * Take the mutex protecting the list of jobs and their status.
+ * Most functions called by the monitor need to call job_lock
+ * and job_unlock manually.  On the other hand, function called
+ * by the block jobs themselves and by the block layer will take the
+ * lock for you.
+ */
+void job_lock(void);
+
+/**
+ * job_unlock:
+ *
+ * Release the mutex protecting the list of jobs and their status.
+ */
+void job_unlock(void);
+
 /**
  * Allocate and return a new job transaction. Jobs can be added to the
  * transaction using job_txn_add_job().
diff --git a/job.c b/job.c
index 075c6f3a20..2b4ffca9d4 100644
--- a/job.c
+++ b/job.c
@@ -32,6 +32,12 @@
 #include "trace/trace-root.h"
 #include "qapi/qapi-events-job.h"
 
+/*
+ * job_mutex protects the jobs list, but also makes the
+ * struct job fields thread-safe.
+ */
+QemuMutex job_mutex;
+
 static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs);
 
 /* Job State Transition Table */
@@ -74,17 +80,22 @@ struct JobTxn {
 int refcnt;
 };
 
-/* Right now, this mutex is only needed to synchronize accesses to job->busy
- * and job->sleep_timer, such as concurrent calls to job_do_yield and
- * job_enter. */
-static QemuMutex job_mutex;
+void job_lock(void)
+{
+/* nop */
+}
+
+void job_unlock(void)
+{
+/* nop */
+}
 
-static void job_lock(void)
+static void real_job_lock(void)
 {
 qemu_mutex_lock(_mutex);
 }
 
-static void job_unlock(void)
+static void real_job_unlock(void)
 {
 qemu_mutex_unlock(_mutex);
 }
@@ -450,21 +461,21 @@ void job_enter_cond(Job *job, bool(*fn)(Job *job))
 return;
 }
 
-job_lock();
+real_job_lock();
 if (job->busy) {
-job_unlock();
+real_job_unlock();
 return;
 }
 
 if (fn && !fn(job)) {
-job_unlock();
+real_job_unlock();
 return;
 }
 
 assert(!job->deferred_to_main_loop);
 timer_del(>sleep_timer);
 job->busy = true;
-job_unlock();
+real_job_unlock();
 aio_co_enter(job->aio_context, job->co);
 }
 
@@ -481,13 +492,13 @@ void job_enter(Job *job)
  * called explicitly. */
 static void coroutine_fn job_do_yield(Job *job, uint64_t ns)
 {
-job_lock();
+real_job_lock();
 if (ns != -1) {
 timer_mod(>sleep_timer, ns);
 }
 job->busy = false;
 job_event_idle(job);
-job_unlock();
+real_job_unlock();
 qemu_coroutine_yield();
 
 /* Set by job_enter_cond() before re-entering the coroutine.  */
-- 
2.31.1




[PATCH v9 21/21] job: remove unused functions

2022-07-06 Thread Emanuele Giuseppe Esposito
These public functions are not used anywhere, thus can be dropped.
Also, since this is the final job API that doesn't use AioContext
lock and replaces it with job_lock, adjust all remaining function
documentation to clearly specify if the job lock is taken or not.

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
---
 include/qemu/job.h | 110 +
 job.c  | 119 ++---
 2 files changed, 37 insertions(+), 192 deletions(-)

diff --git a/include/qemu/job.h b/include/qemu/job.h
index 676f69bb2e..3d82b1eaee 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -361,6 +361,8 @@ JobTxn *job_txn_new(void);
 /**
  * Release a reference that was previously acquired with job_txn_add_job or
  * job_txn_new. If it's the last reference to the object, it will be freed.
+ *
+ * Called with job lock *not* held.
  */
 void job_txn_unref(JobTxn *txn);
 
@@ -390,19 +392,17 @@ void *job_create(const char *job_id, const JobDriver 
*driver, JobTxn *txn,
 /**
  * Add a reference to Job refcnt, it will be decreased with job_unref, and then
  * be freed if it comes to be the last reference.
+ *
+ * Called with job lock held.
  */
-void job_ref(Job *job);
-
-/* Same as job_ref(), but called with job lock held. */
 void job_ref_locked(Job *job);
 
 /**
  * Release a reference that was previously acquired with job_ref() or
  * job_create(). If it's the last reference to the object, it will be freed.
+ *
+ * Called with job lock held.
  */
-void job_unref(Job *job);
-
-/* Same as job_unref(), but called with job lock held. */
 void job_unref_locked(Job *job);
 
 /**
@@ -448,12 +448,8 @@ void job_progress_increase_remaining(Job *job, uint64_t 
delta);
  * Conditionally enter the job coroutine if the job is ready to run, not
  * already busy and fn() returns true. fn() is called while under the job_lock
  * critical section.
- */
-void job_enter_cond(Job *job, bool(*fn)(Job *job));
-
-/*
- * Same as job_enter_cond(), but called with job lock held.
- * Might release the lock temporarily.
+ *
+ * Called with job lock held, but might release it temporarily.
  */
 void job_enter_cond_locked(Job *job, bool(*fn)(Job *job));
 
@@ -532,11 +528,8 @@ bool job_cancel_requested(Job *job);
 
 /**
  * Returns whether the job is in a completed state.
- * Called with job_mutex *not* held.
+ * Called with job lock held.
  */
-bool job_is_completed(Job *job);
-
-/* Same as job_is_completed(), but called with job lock held. */
 bool job_is_completed_locked(Job *job);
 
 /**
@@ -552,45 +545,34 @@ bool job_is_ready_locked(Job *job);
  * Request @job to pause at the next pause point. Must be paired with
  * job_resume(). If the job is supposed to be resumed by user action, call
  * job_user_pause() instead.
+ *
+ * Called with job lock held.
  */
-void job_pause(Job *job);
-
-/* Same as job_pause(), but called with job lock held. */
 void job_pause_locked(Job *job);
 
-/** Resumes a @job paused with job_pause. */
-void job_resume(Job *job);
-
-/*
- * Same as job_resume(), but called with job lock held.
- * Might release the lock temporarily.
+/**
+ * Resumes a @job paused with job_pause.
+ * Called with job lock held, but might release it temporarily.
  */
 void job_resume_locked(Job *job);
 
 /**
  * Asynchronously pause the specified @job.
  * Do not allow a resume until a matching call to job_user_resume.
+ * Called with job lock held.
  */
-void job_user_pause(Job *job, Error **errp);
-
-/* Same as job_user_pause(), but called with job lock held. */
 void job_user_pause_locked(Job *job, Error **errp);
 
-/** Returns true if the job is user-paused. */
-bool job_user_paused(Job *job);
-
-/* Same as job_user_paused(), but called with job lock held. */
+/**
+ * Returns true if the job is user-paused.
+ * Called with job lock held.
+ */
 bool job_user_paused_locked(Job *job);
 
 /**
  * Resume the specified @job.
  * Must be paired with a preceding job_user_pause.
- */
-void job_user_resume(Job *job, Error **errp);
-
-/*
- * Same as job_user_resume(), but called with job lock held.
- * Might release the lock temporarily.
+ * Called with job lock held, but might release it temporarily.
  */
 void job_user_resume_locked(Job *job, Error **errp);
 
@@ -599,30 +581,25 @@ void job_user_resume_locked(Job *job, Error **errp);
  * first one if @job is %NULL.
  *
  * Returns the requested job, or %NULL if there are no more jobs left.
+ * Called with job lock held.
  */
-Job *job_next(Job *job);
-
-/* Same as job_next(), but called with job lock held. */
 Job *job_next_locked(Job *job);
 
 /**
  * Get the job identified by @id (which must not be %NULL).
  *
  * Returns the requested job, or %NULL if it doesn't exist.
+ * Called with job lock held.
  */
-Job *job_get(const char *id);
-
-/* Same as job_get(), but called with job lock held. */
 Job *job_get_locked(const char *id);
 
 /**
  * Check whether the verb @verb can be applied to @job in its current 

[PATCH v9 16/21] block_job_query: remove atomic read

2022-07-06 Thread Emanuele Giuseppe Esposito
Not sure what the atomic here was supposed to do, since job.busy
is protected by the job lock. Since the whole function
is called under job_mutex, just remove the atomic.

Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Emanuele Giuseppe Esposito 
---
 blockjob.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/blockjob.c b/blockjob.c
index 0d120ed126..bbd297b583 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -341,7 +341,7 @@ BlockJobInfo *block_job_query_locked(BlockJob *job, Error 
**errp)
 info = g_new0(BlockJobInfo, 1);
 info->type  = g_strdup(job_type_str(>job));
 info->device= g_strdup(job->job.id);
-info->busy  = qatomic_read(>job.busy);
+info->busy  = job->job.busy;
 info->paused= job->job.pause_count > 0;
 info->offset= progress_current;
 info->len   = progress_total;
-- 
2.31.1




[PULL 28/34] target/ppc: Add flag for ISA v2.06 BCDA instructions

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

Adds an insns_flags2 for the BCD assist instructions introduced in
Power ISA 2.06. These instructions are not listed in the manuals for
e5500[1] and e6500[2], so the flag is only added for POWER7/8/9/10
models.

[1] https://www.nxp.com/files-static/32bit/doc/ref_manual/EREF_RM.pdf
[2] https://www.nxp.com/docs/en/reference-manual/E6500RM.pdf

Signed-off-by: Matheus Ferst 
Signed-off-by: Víctor Colombo 
Reviewed-by: Richard Henderson 
Message-Id: <20220629162904.105060-9-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/cpu.h  |  5 -
 target/ppc/cpu_init.c | 10 ++
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index b38c651af4..7aaff9dcc5 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2289,6 +2289,8 @@ enum {
 PPC2_ISA310= 0x0010ULL,
 /*   lwsync instruction  */
 PPC2_MEM_LWSYNC= 0x0020ULL,
+/* ISA 2.06 BCD assist instructions  */
+PPC2_BCDA_ISA206   = 0x0040ULL,
 
 #define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \
 PPC2_ISA205 | PPC2_VSX207 | PPC2_PERM_ISA206 | \
@@ -2297,7 +2299,8 @@ enum {
 PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | \
 PPC2_ALTIVEC_207 | PPC2_ISA207S | PPC2_DFP | \
 PPC2_FP_CVT_S64 | PPC2_TM | PPC2_PM_ISA206 | \
-PPC2_ISA300 | PPC2_ISA310 | PPC2_MEM_LWSYNC)
+PPC2_ISA300 | PPC2_ISA310 | PPC2_MEM_LWSYNC | \
+PPC2_BCDA_ISA206)
 };
 
 /*/
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index c16cb8dbe7..bdfb1a5c6f 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5985,7 +5985,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
 PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 |
 PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 |
 PPC2_FP_TST_ISA206 | PPC2_FP_CVT_S64 |
-PPC2_PM_ISA206 | PPC2_MEM_LWSYNC;
+PPC2_PM_ISA206 | PPC2_MEM_LWSYNC | PPC2_BCDA_ISA206;
 pcc->msr_mask = (1ull << MSR_SF) |
 (1ull << MSR_VR) |
 (1ull << MSR_VSX) |
@@ -6159,7 +6159,8 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
 PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
 PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
 PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
-PPC2_TM | PPC2_PM_ISA206 | PPC2_MEM_LWSYNC;
+PPC2_TM | PPC2_PM_ISA206 | PPC2_MEM_LWSYNC |
+PPC2_BCDA_ISA206;
 pcc->msr_mask = (1ull << MSR_SF) |
 (1ull << MSR_HV) |
 (1ull << MSR_TM) |
@@ -6379,7 +6380,8 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
 PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
 PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
 PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
-PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_MEM_LWSYNC;
+PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_MEM_LWSYNC |
+PPC2_BCDA_ISA206;
 pcc->msr_mask = (1ull << MSR_SF) |
 (1ull << MSR_HV) |
 (1ull << MSR_TM) |
@@ -6597,7 +6599,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
 PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
 PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
 PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_ISA310 |
-PPC2_MEM_LWSYNC;
+PPC2_MEM_LWSYNC | PPC2_BCDA_ISA206;
 pcc->msr_mask = (1ull << MSR_SF) |
 (1ull << MSR_HV) |
 (1ull << MSR_TM) |
-- 
2.36.1




[PATCH v9 05/21] job.c: add job_lock/unlock while keeping job.h intact

2022-07-06 Thread Emanuele Giuseppe Esposito
With "intact" we mean that all job.h functions implicitly
take the lock. Therefore API callers are unmodified.

This means that:
- many static functions that will be always called with job lock held
  become _locked, and call _locked functions
- all public functions take the lock internally if needed, and call _locked
  functions
- all public functions called internally by other functions in job.c will have a
  _locked counterpart (sometimes public), to avoid deadlocks (job lock already 
taken).
  These functions are not used for now.
- some public functions called only from exernal files (not job.c) do not
  have _locked() counterpart and take the lock inside. Others won't need
  the lock at all because use fields only set at initialization and
  never modified.

job_{lock/unlock} is independent from real_job_{lock/unlock}.

Note: at this stage, job_{lock/unlock} and job lock guard macros
are *nop*

Signed-off-by: Emanuele Giuseppe Esposito 
---
 include/qemu/job.h | 138 ++-
 job.c  | 605 -
 2 files changed, 558 insertions(+), 185 deletions(-)

diff --git a/include/qemu/job.h b/include/qemu/job.h
index 4b64eb15f7..5709e8d4a8 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -358,8 +358,15 @@ JobTxn *job_txn_new(void);
  */
 void job_txn_unref(JobTxn *txn);
 
+/*
+ * Same as job_txn_unref(), but called with job lock held.
+ * Might release the lock temporarily.
+ */
+void job_txn_unref_locked(JobTxn *txn);
+
 /**
  * Create a new long-running job and return it.
+ * Called with job_mutex *not* held.
  *
  * @job_id: The id of the newly-created job, or %NULL for internal jobs
  * @driver: The class object for the newly-created job.
@@ -380,17 +387,25 @@ void *job_create(const char *job_id, const JobDriver 
*driver, JobTxn *txn,
  */
 void job_ref(Job *job);
 
+/* Same as job_ref(), but called with job lock held. */
+void job_ref_locked(Job *job);
+
 /**
  * Release a reference that was previously acquired with job_ref() or
  * job_create(). If it's the last reference to the object, it will be freed.
  */
 void job_unref(Job *job);
 
+/* Same as job_unref(), but called with job lock held. */
+void job_unref_locked(Job *job);
+
 /**
  * @job: The job that has made progress
  * @done: How much progress the job made since the last call
  *
  * Updates the progress counter of the job.
+ *
+ * May be called with mutex held or not held.
  */
 void job_progress_update(Job *job, uint64_t done);
 
@@ -401,6 +416,8 @@ void job_progress_update(Job *job, uint64_t done);
  *
  * Sets the expected end value of the progress counter of a job so that a
  * completion percentage can be calculated when the progress is updated.
+ *
+ * May be called with mutex held or not held.
  */
 void job_progress_set_remaining(Job *job, uint64_t remaining);
 
@@ -416,6 +433,8 @@ void job_progress_set_remaining(Job *job, uint64_t 
remaining);
  * length before, and job_progress_update() afterwards.
  * (So the operation acts as a parenthesis in regards to the main job
  * operation running in background.)
+ *
+ * May be called with mutex held or not held.
  */
 void job_progress_increase_remaining(Job *job, uint64_t delta);
 
@@ -426,11 +445,19 @@ void job_progress_increase_remaining(Job *job, uint64_t 
delta);
  */
 void job_enter_cond(Job *job, bool(*fn)(Job *job));
 
+/*
+ * Same as job_enter_cond(), but called with job lock held.
+ * Might release the lock temporarily.
+ */
+void job_enter_cond_locked(Job *job, bool(*fn)(Job *job));
+
 /**
  * @job: A job that has not yet been started.
  *
  * Begins execution of a job.
  * Takes ownership of one reference to the job object.
+ *
+ * Called with job_mutex *not* held.
  */
 void job_start(Job *job);
 
@@ -438,6 +465,7 @@ void job_start(Job *job);
  * @job: The job to enter.
  *
  * Continue the specified job by entering the coroutine.
+ * Called with job_mutex *not* held.
  */
 void job_enter(Job *job);
 
@@ -446,6 +474,8 @@ void job_enter(Job *job);
  *
  * Pause now if job_pause() has been called. Jobs that perform lots of I/O
  * must call this between requests so that the job can be paused.
+ *
+ * Called with job_mutex *not* held.
  */
 void coroutine_fn job_pause_point(Job *job);
 
@@ -453,6 +483,7 @@ void coroutine_fn job_pause_point(Job *job);
  * @job: The job that calls the function.
  *
  * Yield the job coroutine.
+ * Called with job_mutex *not* held.
  */
 void job_yield(Job *job);
 
@@ -463,6 +494,8 @@ void job_yield(Job *job);
  * Put the job to sleep (assuming that it wasn't canceled) for @ns
  * %QEMU_CLOCK_REALTIME nanoseconds.  Canceling the job will immediately
  * interrupt the wait.
+ *
+ * Called with job_mutex *not* held.
  */
 void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
 
@@ -475,21 +508,40 @@ const char *job_type_str(const Job *job);
 /** Returns true if the job should not be visible to the management layer. */
 bool job_is_internal(Job *job);
 
-/** Returns whether the job is 

[PATCH v9 17/21] blockjob.h: categorize fields in struct BlockJob

2022-07-06 Thread Emanuele Giuseppe Esposito
The same job lock is being used also to protect some of blockjob fields.
Categorize them just as done in job.h.

Signed-off-by: Emanuele Giuseppe Esposito 
---
 include/block/blockjob.h | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index 8b65d3949d..912e10b083 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -40,10 +40,16 @@ typedef struct BlockJobDriver BlockJobDriver;
  * Long-running operation on a BlockDriverState.
  */
 typedef struct BlockJob {
-/** Data belonging to the generic Job infrastructure */
+/**
+ * Data belonging to the generic Job infrastructure.
+ * Protected by job mutex.
+ */
 Job job;
 
-/** Status that is published by the query-block-jobs QMP API */
+/**
+ * Status that is published by the query-block-jobs QMP API.
+ * Protected by job mutex.
+ */
 BlockDeviceIoStatus iostatus;
 
 /** Speed that was set with @block_job_set_speed.  */
@@ -55,6 +61,8 @@ typedef struct BlockJob {
 /** Block other operations when block job is running */
 Error *blocker;
 
+/** All notifiers are set once in block_job_create() and never modified. */
+
 /** Called when a cancelled job is finalised. */
 Notifier finalize_cancelled_notifier;
 
@@ -70,7 +78,10 @@ typedef struct BlockJob {
 /** Called when the job coroutine yields or terminates */
 Notifier idle_notifier;
 
-/** BlockDriverStates that are involved in this block job */
+/**
+ * BlockDriverStates that are involved in this block job.
+ * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE)
+ */
 GSList *nodes;
 } BlockJob;
 
-- 
2.31.1




[PULL 26/34] target/ppc: Implement mffscdrn[i] instructions

2022-07-06 Thread Daniel Henrique Barboza
From: Víctor Colombo 

Signed-off-by: Víctor Colombo 
Reviewed-by: Matheus Ferst 
Message-Id: <20220629162904.105060-7-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/insn32.decode   |  5 
 target/ppc/translate/fp-impl.c.inc | 41 ++
 2 files changed, 46 insertions(+)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 7d219f000f..e5770bcc16 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -133,6 +133,9 @@
 _imm2 rt imm
 @X_imm2 .. rt:5 . ... imm:2 .. ._imm2
 
+_imm3 rt imm
+@X_imm3 .. rt:5 . .. imm:3 .. . _imm3
+
 %x_xt   0:1 21:5
 _imm5 xt imm:uint8_t vrb
 @X_imm5 .. . imm:5 vrb:5 .. .   _imm5 
xt=%x_xt
@@ -348,7 +351,9 @@ SETNBCR 01 . . - 00 -   
@X_bi
 MFFS11 . 0 - 1001000111 .   @X_t_rc
 MFFSCE  11 . 1 - 1001000111 -   @X_t
 MFFSCRN 11 . 10110 . 1001000111 -   @X_tb
+MFFSCDRN11 . 10100 . 1001000111 -   @X_tb
 MFFSCRNI11 . 10111 ---.. 1001000111 -   @X_imm2
+MFFSCDRNI   11 . 10101 --... 1001000111 -   @X_imm3
 MFFSL   11 . 11000 - 1001000111 -   @X_t
 
 ### Decimal Floating-Point Arithmetic Instructions
diff --git a/target/ppc/translate/fp-impl.c.inc 
b/target/ppc/translate/fp-impl.c.inc
index d6231358f8..319513d001 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -696,6 +696,27 @@ static bool trans_MFFSCRN(DisasContext *ctx, arg_X_tb *a)
 return true;
 }
 
+static bool trans_MFFSCDRN(DisasContext *ctx, arg_X_tb *a)
+{
+TCGv_i64 t1, fpscr;
+
+REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+REQUIRE_FPU(ctx);
+
+t1 = tcg_temp_new_i64();
+get_fpr(t1, a->rb);
+tcg_gen_andi_i64(t1, t1, FP_DRN);
+
+gen_reset_fpstatus();
+fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
+store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100);
+
+tcg_temp_free_i64(t1);
+tcg_temp_free_i64(fpscr);
+
+return true;
+}
+
 static bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 *a)
 {
 TCGv_i64 t1, fpscr;
@@ -716,6 +737,26 @@ static bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 
*a)
 return true;
 }
 
+static bool trans_MFFSCDRNI(DisasContext *ctx, arg_X_imm3 *a)
+{
+TCGv_i64 t1, fpscr;
+
+REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+REQUIRE_FPU(ctx);
+
+t1 = tcg_temp_new_i64();
+tcg_gen_movi_i64(t1, (uint64_t)a->imm << FPSCR_DRN0);
+
+gen_reset_fpstatus();
+fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
+store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100);
+
+tcg_temp_free_i64(t1);
+tcg_temp_free_i64(fpscr);
+
+return true;
+}
+
 static bool trans_MFFSL(DisasContext *ctx, arg_X_t *a)
 {
 TCGv_i64 fpscr;
-- 
2.36.1




[PATCH v9 07/21] blockjob: introduce block_job _locked() APIs

2022-07-06 Thread Emanuele Giuseppe Esposito
Just as done with job.h, create _locked() functions in blockjob.h

These functions will be later useful when caller has already taken
the lock. All blockjob _locked functions call job _locked functions.

Note: at this stage, job_{lock/unlock} and job lock guard macros
are *nop*.

Signed-off-by: Emanuele Giuseppe Esposito 
---
 blockjob.c   | 52 
 include/block/blockjob.h | 18 ++
 2 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/blockjob.c b/blockjob.c
index 7da59a1f1c..0d59aba439 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -44,21 +44,27 @@ static bool is_block_job(Job *job)
job_type(job) == JOB_TYPE_STREAM;
 }
 
-BlockJob *block_job_next(BlockJob *bjob)
+BlockJob *block_job_next_locked(BlockJob *bjob)
 {
 Job *job = bjob ? >job : NULL;
 GLOBAL_STATE_CODE();
 
 do {
-job = job_next(job);
+job = job_next_locked(job);
 } while (job && !is_block_job(job));
 
 return job ? container_of(job, BlockJob, job) : NULL;
 }
 
-BlockJob *block_job_get(const char *id)
+BlockJob *block_job_next(BlockJob *bjob)
 {
-Job *job = job_get(id);
+JOB_LOCK_GUARD();
+return block_job_next_locked(bjob);
+}
+
+BlockJob *block_job_get_locked(const char *id)
+{
+Job *job = job_get_locked(id);
 GLOBAL_STATE_CODE();
 
 if (job && is_block_job(job)) {
@@ -68,6 +74,12 @@ BlockJob *block_job_get(const char *id)
 }
 }
 
+BlockJob *block_job_get(const char *id)
+{
+JOB_LOCK_GUARD();
+return block_job_get_locked(id);
+}
+
 void block_job_free(Job *job)
 {
 BlockJob *bjob = container_of(job, BlockJob, job);
@@ -256,14 +268,14 @@ static bool job_timer_pending(Job *job)
 return timer_pending(>sleep_timer);
 }
 
-bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
+bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp)
 {
 const BlockJobDriver *drv = block_job_driver(job);
 int64_t old_speed = job->speed;
 
 GLOBAL_STATE_CODE();
 
-if (job_apply_verb(>job, JOB_VERB_SET_SPEED, errp) < 0) {
+if (job_apply_verb_locked(>job, JOB_VERB_SET_SPEED, errp) < 0) {
 return false;
 }
 if (speed < 0) {
@@ -277,7 +289,9 @@ bool block_job_set_speed(BlockJob *job, int64_t speed, 
Error **errp)
 job->speed = speed;
 
 if (drv->set_speed) {
+job_unlock();
 drv->set_speed(job, speed);
+job_lock();
 }
 
 if (speed && speed <= old_speed) {
@@ -285,18 +299,24 @@ bool block_job_set_speed(BlockJob *job, int64_t speed, 
Error **errp)
 }
 
 /* kick only if a timer is pending */
-job_enter_cond(>job, job_timer_pending);
+job_enter_cond_locked(>job, job_timer_pending);
 
 return true;
 }
 
+bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
+{
+JOB_LOCK_GUARD();
+return block_job_set_speed_locked(job, speed, errp);
+}
+
 int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n)
 {
 IO_CODE();
 return ratelimit_calculate_delay(>limit, n);
 }
 
-BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
+BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp)
 {
 BlockJobInfo *info;
 uint64_t progress_current, progress_total;
@@ -320,7 +340,7 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
 info->len   = progress_total;
 info->speed = job->speed;
 info->io_status = job->iostatus;
-info->ready = job_is_ready(>job),
+info->ready = job_is_ready_locked(>job),
 info->status= job->job.status;
 info->auto_finalize = job->job.auto_finalize;
 info->auto_dismiss  = job->job.auto_dismiss;
@@ -333,6 +353,12 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
 return info;
 }
 
+BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
+{
+JOB_LOCK_GUARD();
+return block_job_query_locked(job, errp);
+}
+
 static void block_job_iostatus_set_err(BlockJob *job, int error)
 {
 if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
@@ -478,7 +504,7 @@ fail:
 return NULL;
 }
 
-void block_job_iostatus_reset(BlockJob *job)
+void block_job_iostatus_reset_locked(BlockJob *job)
 {
 GLOBAL_STATE_CODE();
 if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
@@ -488,6 +514,12 @@ void block_job_iostatus_reset(BlockJob *job)
 job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
 }
 
+void block_job_iostatus_reset(BlockJob *job)
+{
+JOB_LOCK_GUARD();
+block_job_iostatus_reset_locked(job);
+}
+
 void block_job_user_resume(Job *job)
 {
 BlockJob *bjob = container_of(job, BlockJob, job);
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index 6525e16fd5..8b65d3949d 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -92,6 +92,9 @@ typedef struct BlockJob {
  */
 BlockJob *block_job_next(BlockJob *job);
 
+/* Same as block_job_next(), but called with job lock held. */
+BlockJob *block_job_next_locked(BlockJob *job);

[PATCH v9 12/21] commit and mirror: create new nodes using bdrv_get_aio_context, and not the job aiocontext

2022-07-06 Thread Emanuele Giuseppe Esposito
We are always using the given bs AioContext, so there is no need
to take the job ones (which is identical anyways).
This also reduces the point we need to check when protecting
job.aio_context field.

Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Emanuele Giuseppe Esposito 
---
 block/commit.c | 4 ++--
 block/mirror.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/block/commit.c b/block/commit.c
index 851d1c557a..336f799172 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -370,7 +370,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
 goto fail;
 }
 
-s->base = blk_new(s->common.job.aio_context,
+s->base = blk_new(bdrv_get_aio_context(bs),
   base_perms,
   BLK_PERM_CONSISTENT_READ
   | BLK_PERM_WRITE_UNCHANGED);
@@ -382,7 +382,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
 s->base_bs = base;
 
 /* Required permissions are already taken with block_job_add_bdrv() */
-s->top = blk_new(s->common.job.aio_context, 0, BLK_PERM_ALL);
+s->top = blk_new(bdrv_get_aio_context(bs), 0, BLK_PERM_ALL);
 ret = blk_insert_bs(s->top, top, errp);
 if (ret < 0) {
 goto fail;
diff --git a/block/mirror.c b/block/mirror.c
index b38676e19d..1977e25171 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1728,7 +1728,7 @@ static BlockJob *mirror_start_job(
 goto fail;
 }
 
-s->target = blk_new(s->common.job.aio_context,
+s->target = blk_new(bdrv_get_aio_context(bs),
 target_perms, target_shared_perms);
 ret = blk_insert_bs(s->target, target, errp);
 if (ret < 0) {
-- 
2.31.1




[PATCH v9 13/21] job: detect change of aiocontext within job coroutine

2022-07-06 Thread Emanuele Giuseppe Esposito
From: Paolo Bonzini 

We want to make sure access of job->aio_context is always done
under either BQL or job_mutex. The problem is that using
aio_co_enter(job->aiocontext, job->co) in job_start and job_enter_cond
makes the coroutine immediately resume, so we can't hold the job lock.
And caching it is not safe either, as it might change.

job_start is under BQL, so it can freely read job->aiocontext, but
job_enter_cond is not. In order to fix this, use aio_co_wake():
the advantage is that it won't use job->aiocontext, but the
main disadvantage is that it won't be able to detect a change of
job AioContext.

Calling bdrv_try_set_aio_context() will issue the following calls
(simplified):
* in terms of  bdrv callbacks:
  .drained_begin -> .set_aio_context -> .drained_end
* in terms of child_job functions:
  child_job_drained_begin -> child_job_set_aio_context -> child_job_drained_end
* in terms of job functions:
  job_pause_locked -> job_set_aio_context -> job_resume_locked

We can see that after setting the new aio_context, job_resume_locked
calls again job_enter_cond, which then invokes aio_co_wake(). But
while job->aiocontext has been set in job_set_aio_context,
job->co->ctx has not changed, so the coroutine would be entering in
the wrong aiocontext.

Using aio_co_schedule in job_resume_locked() might seem as a valid
alternative, but the problem is that the bh resuming the coroutine
is not scheduled immediately, and if in the meanwhile another
bdrv_try_set_aio_context() is run (see test_propagate_mirror() in
test-block-iothread.c), we would have the first schedule in the
wrong aiocontext, and the second set of drains won't even manage
to schedule the coroutine, as job->busy would still be true from
the previous job_resume_locked().

The solution is to stick with aio_co_wake(), but then detect every time
the coroutine resumes back from yielding if job->aio_context
has changed. If so, we can reschedule it to the new context.

Check for the aiocontext change in job_do_yield_locked because:
1) aio_co_reschedule_self requires to be in the running coroutine
2) since child_job_set_aio_context allows changing the aiocontext only
   while the job is paused, this is the exact place where the coroutine
   resumes, before running JobDriver's code.

Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Paolo Bonzini 
---
 job.c | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/job.c b/job.c
index 9c8792c9e8..405f39566b 100644
--- a/job.c
+++ b/job.c
@@ -581,11 +581,12 @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
 return;
 }
 
-assert(!job->deferred_to_main_loop);
 timer_del(>sleep_timer);
 job->busy = true;
 real_job_unlock();
-aio_co_enter(job->aio_context, job->co);
+job_unlock();
+aio_co_wake(job->co);
+job_lock();
 }
 
 void job_enter_cond(Job *job, bool(*fn)(Job *job))
@@ -611,6 +612,8 @@ void job_enter(Job *job)
  */
 static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
 {
+AioContext *next_aio_context;
+
 real_job_lock();
 if (ns != -1) {
 timer_mod(>sleep_timer, ns);
@@ -622,7 +625,20 @@ static void coroutine_fn job_do_yield_locked(Job *job, 
uint64_t ns)
 qemu_coroutine_yield();
 job_lock();
 
-/* Set by job_enter_cond() before re-entering the coroutine.  */
+next_aio_context = job->aio_context;
+/*
+ * Coroutine has resumed, but in the meanwhile the job AioContext
+ * might have changed via bdrv_try_set_aio_context(), so we need to move
+ * the coroutine too in the new aiocontext.
+ */
+while (qemu_get_current_aio_context() != next_aio_context) {
+job_unlock();
+aio_co_reschedule_self(next_aio_context);
+job_lock();
+next_aio_context = job->aio_context;
+}
+
+/* Set by job_enter_cond_locked() before re-entering the coroutine.  */
 assert(job->busy);
 }
 
-- 
2.31.1




[PULL 16/34] target/ppc: use int128.h methods in vsubuqm

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

And also move the insn to decodetree

Signed-off-by: Matheus Ferst 
Reviewed-by: Víctor Colombo 
Message-Id: <20220606150037.338931-6-matheus.fe...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/helper.h |  2 +-
 target/ppc/insn32.decode|  2 ++
 target/ppc/int_helper.c | 19 ++-
 target/ppc/translate/vmx-impl.c.inc |  5 ++---
 target/ppc/translate/vmx-ops.c.inc  |  2 +-
 5 files changed, 8 insertions(+), 22 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index f6b1b2fad2..1c02ad85e5 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -208,7 +208,7 @@ DEF_HELPER_FLAGS_3(VADDUQM, TCG_CALL_NO_RWG, void, avr, 
avr, avr)
 DEF_HELPER_FLAGS_4(VADDECUQ, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_4(VADDEUQM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_3(VADDCUQ, TCG_CALL_NO_RWG, void, avr, avr, avr)
-DEF_HELPER_FLAGS_3(vsubuqm, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(VSUBUQM, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_4(vsubecuq, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_4(vsubeuqm, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_3(vsubcuq, TCG_CALL_NO_RWG, void, avr, avr, avr)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 35252ddd4f..a8d3a5a8a1 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -556,6 +556,8 @@ VADDUQM 000100 . . . 001@VX
 VADDEUQM000100 . . . . 00   @VA
 VADDECUQ000100 . . . . 01   @VA
 
+VSUBUQM 000100 . . . 101@VX
+
 VEXTSB2W000100 . 1 . 1100010@VX_tb
 VEXTSH2W000100 . 10001 . 1100010@VX_tb
 VEXTSB2D000100 . 11000 . 1100010@VX_tb
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 279333a814..159b831d97 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2176,12 +2176,6 @@ VGENERIC_DO(popcntd, u64)
 
 #undef VGENERIC_DO
 
-#if HOST_BIG_ENDIAN
-#define QW_ONE { .u64 = { 0, 1 } }
-#else
-#define QW_ONE { .u64 = { 1, 0 } }
-#endif
-
 #ifndef CONFIG_INT128
 
 static inline void avr_qw_not(ppc_avr_t *t, ppc_avr_t a)
@@ -2245,18 +2239,9 @@ void helper_VADDECUQ(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b, ppc_avr_t *c)
 r->VsrD(1) = carry_out;
 }
 
-void helper_vsubuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
+void helper_VSUBUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-#ifdef CONFIG_INT128
-r->u128 = a->u128 - b->u128;
-#else
-ppc_avr_t tmp;
-ppc_avr_t one = QW_ONE;
-
-avr_qw_not(, *b);
-avr_qw_add(, *a, tmp);
-avr_qw_add(r, tmp, one);
-#endif
+r->s128 = int128_sub(a->s128, b->s128);
 }
 
 void helper_vsubeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
diff --git a/target/ppc/translate/vmx-impl.c.inc 
b/target/ppc/translate/vmx-impl.c.inc
index 8c0e5bcc03..1e665534c3 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -1234,7 +1234,6 @@ GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
 GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
 GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
 GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
-GEN_VXFORM(vsubuqm, 0, 20);
 GEN_VXFORM(vsubcuq, 0, 21);
 GEN_VXFORM3(vsubeuqm, 31, 0);
 GEN_VXFORM3(vsubecuq, 31, 0);
@@ -2858,8 +2857,6 @@ GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \
 bcdus, PPC_NONE, PPC2_ISA300)
 GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
 bcdtrunc, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM_DUAL(vsubuqm, PPC2_ALTIVEC_207, PPC_NONE, \
-bcdtrunc, PPC_NONE, PPC2_ISA300)
 GEN_VXFORM_DUAL(vsubcuq, PPC2_ALTIVEC_207, PPC_NONE, \
 bcdutrunc, PPC_NONE, PPC2_ISA300)
 
@@ -3102,6 +3099,8 @@ TRANS_FLAGS2(ALTIVEC_207, VADDUQM, do_vx_helper, 
gen_helper_VADDUQM)
 
 TRANS_FLAGS2(ALTIVEC_207, VPMSUMD, do_vx_helper, gen_helper_VPMSUMD)
 
+TRANS_FLAGS2(ALTIVEC_207, VSUBUQM, do_vx_helper, gen_helper_VSUBUQM)
+
 static bool do_vx_vmuleo(DisasContext *ctx, arg_VX *a, bool even,
  void (*gen_mul)(TCGv_i64, TCGv_i64, TCGv_i64, 
TCGv_i64))
 {
diff --git a/target/ppc/translate/vmx-ops.c.inc 
b/target/ppc/translate/vmx-ops.c.inc
index 33e05929cb..9feef9afee 100644
--- a/target/ppc/translate/vmx-ops.c.inc
+++ b/target/ppc/translate/vmx-ops.c.inc
@@ -126,7 +126,7 @@ GEN_VXFORM(vsubuws, 0, 26),
 GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_ALTIVEC, PPC2_ISA300),
 GEN_VXFORM(vsubshs, 0, 29),
 GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_DUAL(vsubuqm, bcdtrunc, 0, 20, PPC2_ALTIVEC_207, PPC2_ISA300),
+GEN_VXFORM_300(bcdtrunc, 0, 20),
 GEN_VXFORM_DUAL(vsubcuq, bcdutrunc, 0, 21, PPC2_ALTIVEC_207, PPC2_ISA300),
 GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, 

[PATCH v9 00/21] job: replace AioContext lock with job_mutex

2022-07-06 Thread Emanuele Giuseppe Esposito
In this series, we want to remove the AioContext lock and instead
use the already existent job_mutex to protect the job structures
and list. This is part of the work to get rid of AioContext lock
usage in favour of smaller granularity locks.

In order to simplify reviewer's job, job lock/unlock functions and
macros are added as empty prototypes (nop) in patch 1.
They are converted to use the actual job mutex only in the last
patch. In this way we can freely create locking sections
without worrying about deadlocks with the aiocontext lock.

Patch 2 defines what fields in the job structure need protection.
Patches 3-6 are in preparation to the job locks, moving functions
from global to static and introducing helpers.

Patch 7-9 introduce the (nop) job lock into the job API and
its users, and patches 10-13 categorize respectively locked and
unlocked functions in the job API.

Patches 14-17 take care of protecting job->aio_context, and
finally patch 18 makes the prototypes in patch 1 use the
job_mutex and removes all aiocontext lock at the same time.

Tested this series by running unit tests, qemu-iotests and qtests
(x86_64).

---
v9:
* merge patch 6 and 7 to 5.
* additional "taken with job lock/unlock" added and propagated in callers
* protect iostatus field of BlockJobs
* move all blockjob patches torward the end of the serie

v8:
* reorganize patch ordering according with Vladimir proposal
* minor nitpicks

v7:
* s/temporary/temporarly
* double identical locking comment to the same function
* patch 2: add "Protected by AioContext lock" to better categorize fields in
  job.h
* use same comment style in all function headers ("Just like {funct}, but
  called between job_lock and job_unlock")

v6:
* patch 4 and 6 squashed with patch 19 (enable job lock and
  reduce/remove AioContext lock)
* patch 19: job_unref_locked read the aiocontext inside the
  job lock.

v5:
* just restructured patches a little bit better, as there were
  functions used before they were defined.
* rebased on kwolf/block branch and API split serie

v4:
* move "protected by job_mutex" from patch 2 to 15, where the job_mutex is
  actually added.
* s/aio_co_enter/aio_co_schedule in job.c, and adjust tests accordingly.
* remove job_get_aio_context, add job_set_aio_context. Use "fake rwlock"
  to protect job->aiocontext.
* get rid of useless getters method, namely:
  job_get_status
  job_get_pause_count
  job_get_paused
  job_get_busy
  They are all used only by tests, and such getter is pretty useless.
  Replace with job_lock(); assert(); job_unlock();
* use job lock macros instead of job lock/unlock in unit tests.
* convert also blockjob functions to have _locked
* put the job_lock/unlock patches before the _locked ones
* replace aio_co_enter in job.c and detect change of context

v3:
* add "_locked" suffix to the functions called under job_mutex lock
* rename _job_lock in real_job_lock
* job_mutex is now public, and drivers like monitor use it directly
* introduce and protect job_get_aio_context
* remove mirror-specific APIs and just use WITH_JOB_GUARD
* more extensive use of WITH_JOB_GUARD and JOB_LOCK_GUARD

RFC v2:
* use JOB_LOCK_GUARD and WITH_JOB_LOCK_GUARD
* mu(u)ltiple typos in commit messages
* job API split patches are sent separately in another series
* use of empty job_{lock/unlock} and JOB_LOCK_GUARD/WITH_JOB_LOCK_GUARD
  to avoid deadlocks and simplify the reviewer job
* move patch 11 (block_job_query: remove atomic read) as last

Emanuele Giuseppe Esposito (20):
  job.c: make job_mutex and job_lock/unlock() public
  job.h: categorize fields in struct Job
  job.c: API functions not used outside should be static
  aio-wait.h: introduce AIO_WAIT_WHILE_UNLOCKED
  job.c: add job_lock/unlock while keeping job.h intact
  job: move and update comments from blockjob.c
  blockjob: introduce block_job  _locked() APIs
  jobs: add job lock in find_* functions
  jobs: use job locks also in the unit tests
  block/mirror.c: use of job helpers in drivers to avoid TOC/TOU
  jobs: group together API calls under the same job lock
  commit and mirror: create new nodes using bdrv_get_aio_context, and
not the job aiocontext
  jobs: protect job.aio_context with BQL and job_mutex
  job.c: enable job lock/unlock and remove Aiocontext locks
  block_job_query: remove atomic read
  blockjob.h: categorize fields in struct BlockJob
  blockjob: rename notifier callbacks as _locked
  blockjob: protect iostatus field in BlockJob struct
  blockjob: remove unused functions
  job: remove unused functions

Paolo Bonzini (1):
  job: detect change of aiocontext within job coroutine

 block.c  |  20 +-
 block/commit.c   |   4 +-
 block/mirror.c   |  21 +-
 block/replication.c  |   6 +-
 blockdev.c   | 129 +++---
 blockjob.c   | 131 ---
 include/block/aio-wait.h |  17 +-
 include/block/blockjob.h |  45 ++-
 include/qemu/job.h  

[PATCH v9 02/21] job.h: categorize fields in struct Job

2022-07-06 Thread Emanuele Giuseppe Esposito
Categorize the fields in struct Job to understand which ones
need to be protected by the job mutex and which don't.

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 include/qemu/job.h | 61 +++---
 1 file changed, 36 insertions(+), 25 deletions(-)

diff --git a/include/qemu/job.h b/include/qemu/job.h
index d1192ffd61..876e13d549 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -40,27 +40,52 @@ typedef struct JobTxn JobTxn;
  * Long-running operation.
  */
 typedef struct Job {
+
+/* Fields set at initialization (job_create), and never modified */
+
 /** The ID of the job. May be NULL for internal jobs. */
 char *id;
 
-/** The type of this job. */
+/**
+ * The type of this job.
+ * All callbacks are called with job_mutex *not* held.
+ */
 const JobDriver *driver;
 
-/** Reference count of the block job */
-int refcnt;
-
-/** Current state; See @JobStatus for details. */
-JobStatus status;
-
-/** AioContext to run the job coroutine in */
-AioContext *aio_context;
-
 /**
  * The coroutine that executes the job.  If not NULL, it is reentered when
  * busy is false and the job is cancelled.
+ * Initialized in job_start()
  */
 Coroutine *co;
 
+/** True if this job should automatically finalize itself */
+bool auto_finalize;
+
+/** True if this job should automatically dismiss itself */
+bool auto_dismiss;
+
+/** The completion function that will be called when the job completes.  */
+BlockCompletionFunc *cb;
+
+/** The opaque value that is passed to the completion function.  */
+void *opaque;
+
+/* ProgressMeter API is thread-safe */
+ProgressMeter progress;
+
+
+/** Protected by AioContext lock */
+
+/** AioContext to run the job coroutine in */
+AioContext *aio_context;
+
+/** Reference count of the block job */
+int refcnt;
+
+/** Current state; See @JobStatus for details. */
+JobStatus status;
+
 /**
  * Timer that is used by @job_sleep_ns. Accessed under job_mutex (in
  * job.c).
@@ -112,14 +137,6 @@ typedef struct Job {
 /** Set to true when the job has deferred work to the main loop. */
 bool deferred_to_main_loop;
 
-/** True if this job should automatically finalize itself */
-bool auto_finalize;
-
-/** True if this job should automatically dismiss itself */
-bool auto_dismiss;
-
-ProgressMeter progress;
-
 /**
  * Return code from @run and/or @prepare callback(s).
  * Not final until the job has reached the CONCLUDED status.
@@ -134,12 +151,6 @@ typedef struct Job {
  */
 Error *err;
 
-/** The completion function that will be called when the job completes.  */
-BlockCompletionFunc *cb;
-
-/** The opaque value that is passed to the completion function.  */
-void *opaque;
-
 /** Notifiers called when a cancelled job is finalised */
 NotifierList on_finalize_cancelled;
 
@@ -167,6 +178,7 @@ typedef struct Job {
 
 /**
  * Callbacks and other information about a Job driver.
+ * All callbacks are invoked with job_mutex *not* held.
  */
 struct JobDriver {
 
@@ -472,7 +484,6 @@ void job_yield(Job *job);
  */
 void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
 
-
 /** Returns the JobType of a given Job. */
 JobType job_type(const Job *job);
 
-- 
2.31.1




[PATCH v9 09/21] jobs: use job locks also in the unit tests

2022-07-06 Thread Emanuele Giuseppe Esposito
Add missing job synchronization in the unit tests, with
explicit locks.

We are deliberately using _locked functions wrapped by a guard
instead of a normal call because the normal call will be removed
in future, as the only usage is limited to the tests.

In other words, if a function like job_pause() is/will be only used
in tests to avoid:

WITH_JOB_LOCK_GUARD(){
job_pause_locked();
}

then it is not worth keeping job_pause(), and just use the guard.

Note: at this stage, job_{lock/unlock} and job lock guard macros
are *nop*.

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
---
 tests/unit/test-bdrv-drain.c | 76 +-
 tests/unit/test-block-iothread.c |  8 ++-
 tests/unit/test-blockjob-txn.c   | 24 +---
 tests/unit/test-blockjob.c   | 94 
 4 files changed, 141 insertions(+), 61 deletions(-)

diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
index 36be84ae55..0db056ea63 100644
--- a/tests/unit/test-bdrv-drain.c
+++ b/tests/unit/test-bdrv-drain.c
@@ -943,61 +943,83 @@ static void test_blockjob_common_drain_node(enum 
drain_type drain_type,
 }
 }
 
-g_assert_cmpint(job->job.pause_count, ==, 0);
-g_assert_false(job->job.paused);
-g_assert_true(tjob->running);
-g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
+WITH_JOB_LOCK_GUARD() {
+g_assert_cmpint(job->job.pause_count, ==, 0);
+g_assert_false(job->job.paused);
+g_assert_true(tjob->running);
+g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
+}
 
 do_drain_begin_unlocked(drain_type, drain_bs);
 
-if (drain_type == BDRV_DRAIN_ALL) {
-/* bdrv_drain_all() drains both src and target */
-g_assert_cmpint(job->job.pause_count, ==, 2);
-} else {
-g_assert_cmpint(job->job.pause_count, ==, 1);
+WITH_JOB_LOCK_GUARD() {
+if (drain_type == BDRV_DRAIN_ALL) {
+/* bdrv_drain_all() drains both src and target */
+g_assert_cmpint(job->job.pause_count, ==, 2);
+} else {
+g_assert_cmpint(job->job.pause_count, ==, 1);
+}
+g_assert_true(job->job.paused);
+g_assert_false(job->job.busy); /* The job is paused */
 }
-g_assert_true(job->job.paused);
-g_assert_false(job->job.busy); /* The job is paused */
 
 do_drain_end_unlocked(drain_type, drain_bs);
 
 if (use_iothread) {
-/* paused is reset in the I/O thread, wait for it */
+/*
+ * Here we are waiting for the paused status to change,
+ * so don't bother protecting the read every time.
+ *
+ * paused is reset in the I/O thread, wait for it
+ */
 while (job->job.paused) {
 aio_poll(qemu_get_aio_context(), false);
 }
 }
 
-g_assert_cmpint(job->job.pause_count, ==, 0);
-g_assert_false(job->job.paused);
-g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
+WITH_JOB_LOCK_GUARD() {
+g_assert_cmpint(job->job.pause_count, ==, 0);
+g_assert_false(job->job.paused);
+g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
+}
 
 do_drain_begin_unlocked(drain_type, target);
 
-if (drain_type == BDRV_DRAIN_ALL) {
-/* bdrv_drain_all() drains both src and target */
-g_assert_cmpint(job->job.pause_count, ==, 2);
-} else {
-g_assert_cmpint(job->job.pause_count, ==, 1);
+WITH_JOB_LOCK_GUARD() {
+if (drain_type == BDRV_DRAIN_ALL) {
+/* bdrv_drain_all() drains both src and target */
+g_assert_cmpint(job->job.pause_count, ==, 2);
+} else {
+g_assert_cmpint(job->job.pause_count, ==, 1);
+}
+g_assert_true(job->job.paused);
+g_assert_false(job->job.busy); /* The job is paused */
 }
-g_assert_true(job->job.paused);
-g_assert_false(job->job.busy); /* The job is paused */
 
 do_drain_end_unlocked(drain_type, target);
 
 if (use_iothread) {
-/* paused is reset in the I/O thread, wait for it */
+/*
+ * Here we are waiting for the paused status to change,
+ * so don't bother protecting the read every time.
+ *
+ * paused is reset in the I/O thread, wait for it
+ */
 while (job->job.paused) {
 aio_poll(qemu_get_aio_context(), false);
 }
 }
 
-g_assert_cmpint(job->job.pause_count, ==, 0);
-g_assert_false(job->job.paused);
-g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
+WITH_JOB_LOCK_GUARD() {
+g_assert_cmpint(job->job.pause_count, ==, 0);
+g_assert_false(job->job.paused);
+g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
+}
 
 aio_context_acquire(ctx);
-ret = job_complete_sync(>job, _abort);
+WITH_JOB_LOCK_GUARD() {
+ret = job_complete_sync_locked(>job, 

[PULL 13/34] target/ppc: use int128.h methods in vadduqm

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

And also move the insn to decodetree.

Signed-off-by: Matheus Ferst 
Reviewed-by: Víctor Colombo 
Message-Id: <20220606150037.338931-3-matheus.fe...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/helper.h | 2 +-
 target/ppc/insn32.decode| 2 ++
 target/ppc/int_helper.c | 8 ++--
 target/ppc/translate/vmx-impl.c.inc | 3 ++-
 target/ppc/translate/vmx-ops.c.inc  | 1 -
 5 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 39ad114c97..c6fbe4b6da 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -204,7 +204,7 @@ DEF_HELPER_FLAGS_5(vadduws, TCG_CALL_NO_RWG, void, avr, 
avr, avr, avr, i32)
 DEF_HELPER_FLAGS_5(vsububs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
 DEF_HELPER_FLAGS_5(vsubuhs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
 DEF_HELPER_FLAGS_5(vsubuws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
-DEF_HELPER_FLAGS_3(vadduqm, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(VADDUQM, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_4(vaddecuq, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_4(vaddeuqm, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_3(vaddcuq, TCG_CALL_NO_RWG, void, avr, avr, avr)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 0772729c6e..d6bfc2c768 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -550,6 +550,8 @@ VRLQNM  000100 . . . 00101000101@VX
 
 ## Vector Integer Arithmetic Instructions
 
+VADDUQM 000100 . . . 001@VX
+
 VEXTSB2W000100 . 1 . 1100010@VX_tb
 VEXTSH2W000100 . 10001 . 1100010@VX_tb
 VEXTSB2D000100 . 11000 . 1100010@VX_tb
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 1476e51651..7de69f00b5 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2224,13 +2224,9 @@ static int avr_qw_addc(ppc_avr_t *t, ppc_avr_t a, 
ppc_avr_t b)
 
 #endif
 
-void helper_vadduqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
+void helper_VADDUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-#ifdef CONFIG_INT128
-r->u128 = a->u128 + b->u128;
-#else
-avr_qw_add(r, *a, *b);
-#endif
+r->s128 = int128_add(a->s128, b->s128);
 }
 
 void helper_vaddeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
diff --git a/target/ppc/translate/vmx-impl.c.inc 
b/target/ppc/translate/vmx-impl.c.inc
index 4c2a36405b..3fb48404d9 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -1234,7 +1234,6 @@ GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
 GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
 GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
 GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
-GEN_VXFORM(vadduqm, 0, 4);
 GEN_VXFORM(vaddcuq, 0, 5);
 GEN_VXFORM3(vaddeuqm, 30, 0);
 GEN_VXFORM3(vaddecuq, 30, 0);
@@ -3100,6 +3099,8 @@ static bool do_vx_helper(DisasContext *ctx, arg_VX *a,
 return true;
 }
 
+TRANS_FLAGS2(ALTIVEC_207, VADDUQM, do_vx_helper, gen_helper_VADDUQM)
+
 TRANS_FLAGS2(ALTIVEC_207, VPMSUMD, do_vx_helper, gen_helper_VPMSUMD)
 
 static bool do_vx_vmuleo(DisasContext *ctx, arg_VX *a, bool even,
diff --git a/target/ppc/translate/vmx-ops.c.inc 
b/target/ppc/translate/vmx-ops.c.inc
index 26c1d957ee..065b0ba414 100644
--- a/target/ppc/translate/vmx-ops.c.inc
+++ b/target/ppc/translate/vmx-ops.c.inc
@@ -126,7 +126,6 @@ GEN_VXFORM(vsubuws, 0, 26),
 GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_ALTIVEC, PPC2_ISA300),
 GEN_VXFORM(vsubshs, 0, 29),
 GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_207(vadduqm, 0, 4),
 GEN_VXFORM_207(vaddcuq, 0, 5),
 GEN_VXFORM_DUAL(vaddeuqm, vaddecuq, 30, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
 GEN_VXFORM_DUAL(vsubuqm, bcdtrunc, 0, 20, PPC2_ALTIVEC_207, PPC2_ISA300),
-- 
2.36.1




[PATCH v9 06/21] job: move and update comments from blockjob.c

2022-07-06 Thread Emanuele Giuseppe Esposito
This comment applies more on job, it was left in blockjob as in the past
the whole job logic was implemented there.

Note: at this stage, job_{lock/unlock} and job lock guard macros
are *nop*.

No functional change intended.

Signed-off-by: Emanuele Giuseppe Esposito 
---
 blockjob.c | 20 
 job.c  | 14 ++
 2 files changed, 14 insertions(+), 20 deletions(-)

diff --git a/blockjob.c b/blockjob.c
index 4868453d74..7da59a1f1c 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -36,21 +36,6 @@
 #include "qemu/main-loop.h"
 #include "qemu/timer.h"
 
-/*
- * The block job API is composed of two categories of functions.
- *
- * The first includes functions used by the monitor.  The monitor is
- * peculiar in that it accesses the block job list with block_job_get, and
- * therefore needs consistency across block_job_get and the actual operation
- * (e.g. block_job_set_speed).  The consistency is achieved with
- * aio_context_acquire/release.  These functions are declared in blockjob.h.
- *
- * The second includes functions used by the block job drivers and sometimes
- * by the core block layer.  These do not care about locking, because the
- * whole coroutine runs under the AioContext lock, and are declared in
- * blockjob_int.h.
- */
-
 static bool is_block_job(Job *job)
 {
 return job_type(job) == JOB_TYPE_BACKUP ||
@@ -433,11 +418,6 @@ static void block_job_event_ready(Notifier *n, void 
*opaque)
 }
 
 
-/*
- * API for block job drivers and the block layer.  These functions are
- * declared in blockjob_int.h.
- */
-
 void *block_job_create(const char *job_id, const BlockJobDriver *driver,
JobTxn *txn, BlockDriverState *bs, uint64_t perm,
uint64_t shared_perm, int64_t speed, int flags,
diff --git a/job.c b/job.c
index 37485e162a..de3d368086 100644
--- a/job.c
+++ b/job.c
@@ -32,6 +32,20 @@
 #include "trace/trace-root.h"
 #include "qapi/qapi-events-job.h"
 
+/*
+ * The job API is composed of two categories of functions.
+ *
+ * The first includes functions used by the monitor.  The monitor is
+ * peculiar in that it accesses the block job list with job_get, and
+ * therefore needs consistency across job_get and the actual operation
+ * (e.g. job_user_cancel). To achieve this consistency, the caller
+ * calls job_lock/job_unlock itself around the whole operation.
+ *
+ *
+ * The second includes functions used by the block job drivers and sometimes
+ * by the core block layer. These delegate the locking to the callee instead.
+ */
+
 /*
  * job_mutex protects the jobs list, but also makes the
  * struct job fields thread-safe.
-- 
2.31.1




[PULL 34/34] target/ppc: Fix MPC8555 and MPC8560 core type to e500v1

2022-07-06 Thread Daniel Henrique Barboza
From: Pali Rohár 

Commit 80d11f4467c4 ("Add definitions for Freescale PowerPC implementations")
changed core type of MPC8555 and MPC8560 from e500v1 to e500v2.

But both MPC8555 and MPC8560 have just e500v1 cores, there are no features
of e500v2 cores. It can be verified by reading NXP documentations:
https://www.nxp.com/docs/en/data-sheet/MPC8555EEC.pdf
https://www.nxp.com/docs/en/data-sheet/MPC8560EC.pdf
https://www.nxp.com/docs/en/reference-manual/MPC8555ERM.pdf
https://www.nxp.com/docs/en/reference-manual/MPC8560RM.pdf

Therefore fix core type of MPC8555 and MPC8560 back to e500v1.

Just for completeness, here is list of all Motorola/Freescale/NXP
processors which were released and have e500v1 or e500v2 cores:

e500v1: MPC8540 MPC8541 MPC8555 MPC8560

e500v2: BSC9131 BSC9132
C291 C292 C293
MPC8533 MPC8535 MPC8536 MPC8543 MPC8544 MPC8545 MPC8547
MPC8548 MPC8567 MPC8568 MPC8569 MPC8572
P1010 P1011 P1012 P1013 P1014 P1015 P1016 P1020 P1021
P1022 P1024 P1025 P2010 P2020

Sorted alphabetically; not by release date / generation / feature set.
All this is from public information available on NXP website.

Seems that qemu has support only for some subset of MPC85xx processors.
Historically processors with e500 cores have mpc85xx family codename and
lot of software have them in mpc85xx architecture subdirectory.

Note that GCC uses -mcpu=8540 option for specifying e500v1 core and
-mcpu=8548 option for specifying e500v2 core.

So sometimes (mpc)8540 is alias for e500v1 and (mpc)8548 is alias for
e500v2.

Fixes: 80d11f4467c4 ("Add definitions for Freescale PowerPC implementations")
Signed-off-by: Pali Rohár 
Reviewed-by: Daniel Henrique Barboza 
Message-Id: <20220703195029.23793-1-p...@kernel.org>
[danielhb: added more context in the commit msg]
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/cpu-models.c | 14 +++---
 target/ppc/cpu-models.h | 14 +++---
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 8538493061..912b037c63 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -385,19 +385,19 @@
 POWERPC_DEF_SVR("mpc8548e_v21", "MPC8548E v2.1",
 CPU_POWERPC_MPC8548E_v21, POWERPC_SVR_8548E_v21, e500v2)
 POWERPC_DEF_SVR("mpc8555_v10", "MPC8555 v1.0",
-CPU_POWERPC_MPC8555_v10,  POWERPC_SVR_8555_v10,  e500v2)
+CPU_POWERPC_MPC8555_v10,  POWERPC_SVR_8555_v10,  e500v1)
 POWERPC_DEF_SVR("mpc8555_v11", "MPC8555 v1.1",
-CPU_POWERPC_MPC8555_v11,  POWERPC_SVR_8555_v11,  e500v2)
+CPU_POWERPC_MPC8555_v11,  POWERPC_SVR_8555_v11,  e500v1)
 POWERPC_DEF_SVR("mpc8555e_v10", "MPC8555E v1.0",
-CPU_POWERPC_MPC8555E_v10, POWERPC_SVR_8555E_v10, e500v2)
+CPU_POWERPC_MPC8555E_v10, POWERPC_SVR_8555E_v10, e500v1)
 POWERPC_DEF_SVR("mpc8555e_v11", "MPC8555E v1.1",
-CPU_POWERPC_MPC8555E_v11, POWERPC_SVR_8555E_v11, e500v2)
+CPU_POWERPC_MPC8555E_v11, POWERPC_SVR_8555E_v11, e500v1)
 POWERPC_DEF_SVR("mpc8560_v10", "MPC8560 v1.0",
-CPU_POWERPC_MPC8560_v10,  POWERPC_SVR_8560_v10,  e500v2)
+CPU_POWERPC_MPC8560_v10,  POWERPC_SVR_8560_v10,  e500v1)
 POWERPC_DEF_SVR("mpc8560_v20", "MPC8560 v2.0",
-CPU_POWERPC_MPC8560_v20,  POWERPC_SVR_8560_v20,  e500v2)
+CPU_POWERPC_MPC8560_v20,  POWERPC_SVR_8560_v20,  e500v1)
 POWERPC_DEF_SVR("mpc8560_v21", "MPC8560 v2.1",
-CPU_POWERPC_MPC8560_v21,  POWERPC_SVR_8560_v21,  e500v2)
+CPU_POWERPC_MPC8560_v21,  POWERPC_SVR_8560_v21,  e500v1)
 POWERPC_DEF_SVR("mpc8567", "MPC8567",
 CPU_POWERPC_MPC8567,  POWERPC_SVR_8567,  e500v2)
 POWERPC_DEF_SVR("mpc8567e", "MPC8567E",
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
index 76775a74a9..1326493a9a 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -184,13 +184,13 @@ enum {
 #define CPU_POWERPC_MPC8548E_v11 CPU_POWERPC_e500v2_v11
 #define CPU_POWERPC_MPC8548E_v20 CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8548E_v21 CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8555_v10  CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8555_v11  CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8555E_v10 CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8555E_v11 CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8560_v10  CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8560_v20  CPU_POWERPC_e500v2_v20
-#define CPU_POWERPC_MPC8560_v21  CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8555_v10  CPU_POWERPC_e500v1_v20
+#define CPU_POWERPC_MPC8555_v11  CPU_POWERPC_e500v1_v20
+#define CPU_POWERPC_MPC8555E_v10 CPU_POWERPC_e500v1_v20
+#define CPU_POWERPC_MPC8555E_v11 CPU_POWERPC_e500v1_v20
+#define 

[PULL 12/34] target/ppc: use int128.h methods in vpmsumd

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

Also drop VECTOR_FOR_INORDER_I usage since there is no need to access
the elements in any particular order, and move the instruction to
decodetree.

Signed-off-by: Matheus Ferst 
Reviewed-by: Víctor Colombo 
Message-Id: <20220606150037.338931-2-matheus.fe...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/helper.h |  2 +-
 target/ppc/insn32.decode|  4 +++
 target/ppc/int_helper.c | 48 ++---
 target/ppc/translate/vmx-impl.c.inc |  3 +-
 target/ppc/translate/vmx-ops.c.inc  |  1 -
 5 files changed, 17 insertions(+), 41 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index d627cfe6ed..39ad114c97 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -318,7 +318,7 @@ DEF_HELPER_FLAGS_3(vbpermq, TCG_CALL_NO_RWG, void, avr, 
avr, avr)
 DEF_HELPER_FLAGS_3(vpmsumb, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_3(vpmsumh, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_3(vpmsumw, TCG_CALL_NO_RWG, void, avr, avr, avr)
-DEF_HELPER_FLAGS_3(vpmsumd, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(VPMSUMD, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_2(vextublx, TCG_CALL_NO_RWG, tl, tl, avr)
 DEF_HELPER_FLAGS_2(vextuhlx, TCG_CALL_NO_RWG, tl, tl, avr)
 DEF_HELPER_FLAGS_2(vextuwlx, TCG_CALL_NO_RWG, tl, tl, avr)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 6ea48d5163..0772729c6e 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -426,6 +426,10 @@ DSCLIQ  11 . . .. 00110 .   
@Z22_tap_sh_rc
 DSCRI   111011 . . .. 001100010 .   @Z22_ta_sh_rc
 DSCRIQ  11 . . .. 001100010 .   @Z22_tap_sh_rc
 
+## Vector Exclusive-OR-based Instructions
+
+VPMSUMD 000100 . . . 10011001000@VX
+
 ## Vector Integer Instructions
 
 VCMPEQUB000100 . . . . 000110   @VC
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 3ae03f73d3..1476e51651 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -1484,52 +1484,24 @@ PMSUM(vpmsumb, u8, u16, uint16_t)
 PMSUM(vpmsumh, u16, u32, uint32_t)
 PMSUM(vpmsumw, u32, u64, uint64_t)
 
-void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
+void helper_VPMSUMD(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-
-#ifdef CONFIG_INT128
 int i, j;
-__uint128_t prod[2];
-
-VECTOR_FOR_INORDER_I(i, u64) {
-prod[i] = 0;
-for (j = 0; j < 64; j++) {
-if (a->u64[i] & (1ull << j)) {
-prod[i] ^= (((__uint128_t)b->u64[i]) << j);
+Int128 tmp, prod[2] = {int128_zero(), int128_zero()};
+
+for (j = 0; j < 64; j++) {
+for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
+if (a->VsrD(i) & (1ull << j)) {
+tmp = int128_make64(b->VsrD(i));
+tmp = int128_lshift(tmp, j);
+prod[i] = int128_xor(prod[i], tmp);
 }
 }
 }
 
-r->u128 = prod[0] ^ prod[1];
-
-#else
-int i, j;
-ppc_avr_t prod[2];
-
-VECTOR_FOR_INORDER_I(i, u64) {
-prod[i].VsrD(1) = prod[i].VsrD(0) = 0;
-for (j = 0; j < 64; j++) {
-if (a->u64[i] & (1ull << j)) {
-ppc_avr_t bshift;
-if (j == 0) {
-bshift.VsrD(0) = 0;
-bshift.VsrD(1) = b->u64[i];
-} else {
-bshift.VsrD(0) = b->u64[i] >> (64 - j);
-bshift.VsrD(1) = b->u64[i] << j;
-}
-prod[i].VsrD(1) ^= bshift.VsrD(1);
-prod[i].VsrD(0) ^= bshift.VsrD(0);
-}
-}
-}
-
-r->VsrD(1) = prod[0].VsrD(1) ^ prod[1].VsrD(1);
-r->VsrD(0) = prod[0].VsrD(0) ^ prod[1].VsrD(0);
-#endif
+r->s128 = int128_xor(prod[0], prod[1]);
 }
 
-
 #if HOST_BIG_ENDIAN
 #define PKBIG 1
 #else
diff --git a/target/ppc/translate/vmx-impl.c.inc 
b/target/ppc/translate/vmx-impl.c.inc
index 0b563bed37..4c2a36405b 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -2717,7 +2717,6 @@ GEN_VXFORM_TRANS(vgbbd, 6, 20);
 GEN_VXFORM(vpmsumb, 4, 16)
 GEN_VXFORM(vpmsumh, 4, 17)
 GEN_VXFORM(vpmsumw, 4, 18)
-GEN_VXFORM(vpmsumd, 4, 19)
 
 #define GEN_BCD(op) \
 static void gen_##op(DisasContext *ctx) \
@@ -3101,6 +3100,8 @@ static bool do_vx_helper(DisasContext *ctx, arg_VX *a,
 return true;
 }
 
+TRANS_FLAGS2(ALTIVEC_207, VPMSUMD, do_vx_helper, gen_helper_VPMSUMD)
+
 static bool do_vx_vmuleo(DisasContext *ctx, arg_VX *a, bool even,
  void (*gen_mul)(TCGv_i64, TCGv_i64, TCGv_i64, 
TCGv_i64))
 {
diff --git a/target/ppc/translate/vmx-ops.c.inc 
b/target/ppc/translate/vmx-ops.c.inc
index d7cc57868e..26c1d957ee 100644
--- a/target/ppc/translate/vmx-ops.c.inc
+++ b/target/ppc/translate/vmx-ops.c.inc
@@ -237,7 

[PULL 32/34] target/ppc: Return default CPU for max CPU

2022-07-06 Thread Daniel Henrique Barboza
From: Murilo Opsfelder Araujo 

All ppc CPUs represent hardware that exists in the real world, i.e.: we
do not have a "max" CPU with all possible emulated features enabled.
Return the default CPU type for the machine because that has greater
chance of being useful as the "max" CPU.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1038
Cc: Cédric Le Goater 
Cc: Daniel Henrique Barboza 
Cc: Daniel P. Berrangé 
Cc: Greg Kurz 
Cc: Matheus K. Ferst 
Cc: Thomas Huth 
Signed-off-by: Murilo Opsfelder Araujo 
Signed-off-by: Fabiano Rosas 
Reviewed-by: Víctor Colombo 
Message-Id: <20220628205513.81917-1-muri...@linux.ibm.com>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/cpu-models.c |  1 -
 target/ppc/cpu_init.c   | 19 +++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 976be5e0d1..05589eb21d 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -879,7 +879,6 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
 { "755", "755_v2.8" },
 { "goldfinger", "755_v2.8" },
 { "7400", "7400_v2.9" },
-{ "max", "7400_v2.9" },
 { "g4",  "7400_v2.9" },
 { "7410", "7410_v1.4" },
 { "nitro", "7410_v1.4" },
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index bdfb1a5c6f..86ad28466a 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -47,6 +47,10 @@
 #include "spr_common.h"
 #include "power8-pmu.h"
 
+#ifndef CONFIG_USER_ONLY
+#include "hw/boards.h"
+#endif
+
 /* #define PPC_DEBUG_SPR */
 /* #define USE_APPLE_GDB */
 
@@ -6965,6 +6969,21 @@ static ObjectClass *ppc_cpu_class_by_name(const char 
*name)
 }
 }
 
+/*
+ * All ppc CPUs represent hardware that exists in the real world, i.e.: we
+ * do not have a "max" CPU with all possible emulated features enabled.
+ * Return the default CPU type for the machine because that has greater
+ * chance of being useful as the "max" CPU.
+ */
+#if !defined(CONFIG_USER_ONLY)
+if (strcmp(name, "max") == 0) {
+MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
+if (mc) {
+return object_class_by_name(mc->default_cpu_type);
+}
+}
+#endif
+
 cpu_model = g_ascii_strdown(name, -1);
 p = ppc_cpu_lookup_alias(cpu_model);
 if (p) {
-- 
2.36.1




[PATCH v9 08/21] jobs: add job lock in find_* functions

2022-07-06 Thread Emanuele Giuseppe Esposito
Both blockdev.c and job-qmp.c have TOC/TOU conditions, because
they first search for the job and then perform an action on it.
Therefore, we need to do the search + action under the same
job mutex critical section.

Note: at this stage, job_{lock/unlock} and job lock guard macros
are *nop*.

Signed-off-by: Emanuele Giuseppe Esposito 
Reviewed-by: Stefan Hajnoczi 
---
 blockdev.c | 67 +-
 job-qmp.c  | 57 --
 2 files changed, 86 insertions(+), 38 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 9230888e34..71f793c4ab 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3302,9 +3302,13 @@ out:
 aio_context_release(aio_context);
 }
 
-/* Get a block job using its ID and acquire its AioContext */
-static BlockJob *find_block_job(const char *id, AioContext **aio_context,
-Error **errp)
+/*
+ * Get a block job using its ID and acquire its AioContext.
+ * Called with job_mutex held.
+ */
+static BlockJob *find_block_job_locked(const char *id,
+   AioContext **aio_context,
+   Error **errp)
 {
 BlockJob *job;
 
@@ -3312,7 +3316,7 @@ static BlockJob *find_block_job(const char *id, 
AioContext **aio_context,
 
 *aio_context = NULL;
 
-job = block_job_get(id);
+job = block_job_get_locked(id);
 
 if (!job) {
 error_set(errp, ERROR_CLASS_DEVICE_NOT_ACTIVE,
@@ -3329,13 +,16 @@ static BlockJob *find_block_job(const char *id, 
AioContext **aio_context,
 void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
 {
 AioContext *aio_context;
-BlockJob *job = find_block_job(device, _context, errp);
+BlockJob *job;
+
+JOB_LOCK_GUARD();
+job = find_block_job_locked(device, _context, errp);
 
 if (!job) {
 return;
 }
 
-block_job_set_speed(job, speed, errp);
+block_job_set_speed_locked(job, speed, errp);
 aio_context_release(aio_context);
 }
 
@@ -3343,7 +3350,10 @@ void qmp_block_job_cancel(const char *device,
   bool has_force, bool force, Error **errp)
 {
 AioContext *aio_context;
-BlockJob *job = find_block_job(device, _context, errp);
+BlockJob *job;
+
+JOB_LOCK_GUARD();
+job = find_block_job_locked(device, _context, errp);
 
 if (!job) {
 return;
@@ -3353,14 +3363,14 @@ void qmp_block_job_cancel(const char *device,
 force = false;
 }
 
-if (job_user_paused(>job) && !force) {
+if (job_user_paused_locked(>job) && !force) {
 error_setg(errp, "The block job for device '%s' is currently paused",
device);
 goto out;
 }
 
 trace_qmp_block_job_cancel(job);
-job_user_cancel(>job, force, errp);
+job_user_cancel_locked(>job, force, errp);
 out:
 aio_context_release(aio_context);
 }
@@ -3368,57 +3378,69 @@ out:
 void qmp_block_job_pause(const char *device, Error **errp)
 {
 AioContext *aio_context;
-BlockJob *job = find_block_job(device, _context, errp);
+BlockJob *job;
+
+JOB_LOCK_GUARD();
+job = find_block_job_locked(device, _context, errp);
 
 if (!job) {
 return;
 }
 
 trace_qmp_block_job_pause(job);
-job_user_pause(>job, errp);
+job_user_pause_locked(>job, errp);
 aio_context_release(aio_context);
 }
 
 void qmp_block_job_resume(const char *device, Error **errp)
 {
 AioContext *aio_context;
-BlockJob *job = find_block_job(device, _context, errp);
+BlockJob *job;
+
+JOB_LOCK_GUARD();
+job = find_block_job_locked(device, _context, errp);
 
 if (!job) {
 return;
 }
 
 trace_qmp_block_job_resume(job);
-job_user_resume(>job, errp);
+job_user_resume_locked(>job, errp);
 aio_context_release(aio_context);
 }
 
 void qmp_block_job_complete(const char *device, Error **errp)
 {
 AioContext *aio_context;
-BlockJob *job = find_block_job(device, _context, errp);
+BlockJob *job;
+
+JOB_LOCK_GUARD();
+job = find_block_job_locked(device, _context, errp);
 
 if (!job) {
 return;
 }
 
 trace_qmp_block_job_complete(job);
-job_complete(>job, errp);
+job_complete_locked(>job, errp);
 aio_context_release(aio_context);
 }
 
 void qmp_block_job_finalize(const char *id, Error **errp)
 {
 AioContext *aio_context;
-BlockJob *job = find_block_job(id, _context, errp);
+BlockJob *job;
+
+JOB_LOCK_GUARD();
+job = find_block_job_locked(id, _context, errp);
 
 if (!job) {
 return;
 }
 
 trace_qmp_block_job_finalize(job);
-job_ref(>job);
-job_finalize(>job, errp);
+job_ref_locked(>job);
+job_finalize_locked(>job, errp);
 
 /*
  * Job's context might have changed via job_finalize (and job_txn_apply
@@ -3426,23 +3448,26 @@ void qmp_block_job_finalize(const char *id, Error 
**errp)
  * one.
  */
 aio_context = 

[PULL 29/34] target/ppc: implement addg6s

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

Implements the following Power ISA v2.06 instruction:
addg6s: Add and Generate Sixes

Signed-off-by: Matheus Ferst 
Signed-off-by: Víctor Colombo 
Reviewed-by: Víctor Colombo 
Message-Id: <20220629162904.105060-10-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/insn32.decode   |  4 +++
 target/ppc/translate/fixedpoint-impl.c.inc | 37 ++
 2 files changed, 41 insertions(+)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index e5770bcc16..af8ba9ca9b 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -311,6 +311,10 @@ CNTTZDM 01 . . . 1000111011 -   @X
 PDEPD   01 . . . 0010011100 -   @X
 PEXTD   01 . . . 001000 -   @X
 
+## BCD Assist
+
+ADDG6S  01 . . . - 001001010 -  @X
+
 ### Float-Point Load Instructions
 
 LFS 11 . .  @D
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 1aab32be03..490e49cfc7 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -492,3 +492,40 @@ static bool trans_PEXTD(DisasContext *ctx, arg_X *a)
 #endif
 return true;
 }
+
+static bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
+{
+const uint64_t carry_bits = 0xULL;
+TCGv t0, t1, carry, zero = tcg_constant_tl(0);
+
+REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
+
+t0 = tcg_temp_new();
+t1 = tcg_const_tl(0);
+carry = tcg_const_tl(0);
+
+for (int i = 0; i < 16; i++) {
+tcg_gen_shri_tl(t0, cpu_gpr[a->ra], i * 4);
+tcg_gen_andi_tl(t0, t0, 0xf);
+tcg_gen_add_tl(t1, t1, t0);
+
+tcg_gen_shri_tl(t0, cpu_gpr[a->rb], i * 4);
+tcg_gen_andi_tl(t0, t0, 0xf);
+tcg_gen_add_tl(t1, t1, t0);
+
+tcg_gen_andi_tl(t1, t1, 0x10);
+tcg_gen_setcond_tl(TCG_COND_NE, t1, t1, zero);
+
+tcg_gen_shli_tl(t0, t1, i * 4);
+tcg_gen_or_tl(carry, carry, t0);
+}
+
+tcg_gen_xori_tl(carry, carry, (target_long)carry_bits);
+tcg_gen_muli_tl(cpu_gpr[a->rt], carry, 6);
+
+tcg_temp_free(t0);
+tcg_temp_free(t1);
+tcg_temp_free(carry);
+
+return true;
+}
-- 
2.36.1




[PULL 11/34] spapr/ddw: Implement 64bit query extension

2022-07-06 Thread Daniel Henrique Barboza
From: Alexey Kardashevskiy 

PAPR 2.8 (2018) defines an extension to return 64bit value for
the largest TCE block in "ibm,query-pe-dma-window". Recent Linux kernels
support this already.

This adds the extension and supports the older format.

This advertises a bigger window for the new format as the biggest
window with 2M pages below the start of the 64bit window as it is
the maximum we will see in practice.

Signed-off-by: Alexey Kardashevskiy 
Reviewed-by: Daniel Henrique Barboza 
Message-Id: <20220623073136.1380214-1-...@ozlabs.ru>
Signed-off-by: Daniel Henrique Barboza 
---
 hw/ppc/spapr_pci.c  |  5 +++--
 hw/ppc/spapr_rtas_ddw.c | 19 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 5e95d7940f..67e9d468aa 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -2360,8 +2360,9 @@ int spapr_dt_phb(SpaprMachineState *spapr, SpaprPhbState 
*phb,
 cpu_to_be32(RTAS_IBM_REMOVE_PE_DMA_WINDOW)
 };
 uint32_t ddw_extensions[] = {
-cpu_to_be32(1),
-cpu_to_be32(RTAS_IBM_RESET_PE_DMA_WINDOW)
+cpu_to_be32(2),
+cpu_to_be32(RTAS_IBM_RESET_PE_DMA_WINDOW),
+cpu_to_be32(1), /* 1: ibm,query-pe-dma-window 6 outputs, PAPR 2.8 */
 };
 SpaprTceTable *tcet;
 SpaprDrc *drc;
diff --git a/hw/ppc/spapr_rtas_ddw.c b/hw/ppc/spapr_rtas_ddw.c
index bb7d91b6d1..7ba11382bc 100644
--- a/hw/ppc/spapr_rtas_ddw.c
+++ b/hw/ppc/spapr_rtas_ddw.c
@@ -100,7 +100,7 @@ static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
 uint64_t buid;
 uint32_t avail, addr, pgmask = 0;
 
-if ((nargs != 3) || (nret != 5)) {
+if ((nargs != 3) || ((nret != 5) && (nret != 6))) {
 goto param_error_exit;
 }
 
@@ -118,9 +118,20 @@ static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
 
 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 rtas_st(rets, 1, avail);
-rtas_st(rets, 2, 0x8000); /* The largest window we can possibly have */
-rtas_st(rets, 3, pgmask);
-rtas_st(rets, 4, 0); /* DMA migration mask, not supported */
+if (nret == 6) {
+/*
+ * Set the Max TCE number as 1<<(58-21) = 0x20..
+ * 1<<59 is the huge window start and 21 is 2M page shift.
+ */
+rtas_st(rets, 2, 0x0020);
+rtas_st(rets, 3, 0x);
+rtas_st(rets, 4, pgmask);
+rtas_st(rets, 5, 0); /* DMA migration mask, not supported */
+} else {
+rtas_st(rets, 2, 0x8000);
+rtas_st(rets, 3, pgmask);
+rtas_st(rets, 4, 0); /* DMA migration mask, not supported */
+}
 
 trace_spapr_iommu_ddw_query(buid, addr, avail, 0x8000, pgmask);
 return;
-- 
2.36.1




[PULL 25/34] target/ppc: Move mffs[.] to decodetree

2022-07-06 Thread Daniel Henrique Barboza
From: Víctor Colombo 

Signed-off-by: Víctor Colombo 
Reviewed-by: Matheus Ferst 
Message-Id: <20220629162904.105060-6-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/insn32.decode   |  4 
 target/ppc/translate/fp-impl.c.inc | 35 +++---
 target/ppc/translate/fp-ops.c.inc  |  1 -
 3 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 6b68689357..7d219f000f 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -100,6 +100,9 @@
 _tb   rt rb
 @X_tb   .. rt:5 . rb:5 .. . _tb
 
+_t_rc rt rc:bool
+@X_t_rc .. rt:5 . . .. rc:1 _t_rc
+
 _tb_rcrt rb rc:bool
 @X_tb_rc.. rt:5 . rb:5 .. rc:1  _tb_rc
 
@@ -342,6 +345,7 @@ SETNBCR 01 . . - 00 -   
@X_bi
 
 ### Move To/From FPSCR
 
+MFFS11 . 0 - 1001000111 .   @X_t_rc
 MFFSCE  11 . 1 - 1001000111 -   @X_t
 MFFSCRN 11 . 10110 . 1001000111 -   @X_tb
 MFFSCRNI11 . 10111 ---.. 1001000111 -   @X_imm2
diff --git a/target/ppc/translate/fp-impl.c.inc 
b/target/ppc/translate/fp-impl.c.inc
index 4f4d57c611..d6231358f8 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -615,24 +615,6 @@ static void gen_mcrfs(DisasContext *ctx)
 tcg_temp_free_i64(tnew_fpscr);
 }
 
-/* mffs */
-static void gen_mffs(DisasContext *ctx)
-{
-TCGv_i64 t0;
-if (unlikely(!ctx->fpu_enabled)) {
-gen_exception(ctx, POWERPC_EXCP_FPU);
-return;
-}
-t0 = tcg_temp_new_i64();
-gen_reset_fpstatus();
-tcg_gen_extu_tl_i64(t0, cpu_fpscr);
-set_fpr(rD(ctx->opcode), t0);
-if (unlikely(Rc(ctx->opcode))) {
-gen_set_cr1_from_fpscr(ctx);
-}
-tcg_temp_free_i64(t0);
-}
-
 static TCGv_i64 place_from_fpscr(int rt, uint64_t mask)
 {
 TCGv_i64 fpscr = tcg_temp_new_i64();
@@ -660,6 +642,23 @@ static void store_fpscr_masked(TCGv_i64 fpscr, uint64_t 
clear_mask,
 tcg_temp_free_i64(fpscr_masked);
 }
 
+static bool trans_MFFS(DisasContext *ctx, arg_X_t_rc *a)
+{
+TCGv_i64 fpscr;
+
+REQUIRE_FPU(ctx);
+
+gen_reset_fpstatus();
+fpscr = place_from_fpscr(a->rt, UINT64_MAX);
+if (a->rc) {
+gen_set_cr1_from_fpscr(ctx);
+}
+
+tcg_temp_free_i64(fpscr);
+
+return true;
+}
+
 static bool trans_MFFSCE(DisasContext *ctx, arg_X_t *a)
 {
 TCGv_i64 fpscr;
diff --git a/target/ppc/translate/fp-ops.c.inc 
b/target/ppc/translate/fp-ops.c.inc
index f8c35124ae..1b65f5ab73 100644
--- a/target/ppc/translate/fp-ops.c.inc
+++ b/target/ppc/translate/fp-ops.c.inc
@@ -74,7 +74,6 @@ GEN_HANDLER_E(fcpsgn, 0x3F, 0x08, 0x00, 0x, PPC_NONE, 
PPC2_ISA205),
 GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x0001, PPC_NONE, PPC2_VSX207),
 GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x0001, PPC_NONE, PPC2_VSX207),
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
-GEN_HANDLER_E_2(mffs, 0x3F, 0x07, 0x12, 0x00, 0x, PPC_FLOAT, PPC_NONE),
 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x, PPC_FLOAT),
-- 
2.36.1




[PULL 33/34] target/ppc/cpu-models: Remove the "default" CPU alias

2022-07-06 Thread Daniel Henrique Barboza
From: Thomas Huth 

QEMU emulates a *lot* of PowerPC-based machines - having a CPU
that is named "default" and cannot be used with most of those
machines sounds just wrong. Thus let's remove this old and confusing
alias now.

Signed-off-by: Thomas Huth 
Reviewed-by: Greg Kurz 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220705151030.662140-1-th...@redhat.com>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/cpu-models.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 05589eb21d..8538493061 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -917,6 +917,6 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
 #endif
 { "ppc32", "604" },
 { "ppc", "604" },
-{ "default", "604" },
+
 { NULL, NULL }
 };
-- 
2.36.1




[PULL 10/34] spapr/ddw: Reset DMA when the last non-default window is removed

2022-07-06 Thread Daniel Henrique Barboza
From: Alexey Kardashevskiy 

PAPR+/LoPAPR says:
===
The platform must restore the default DMA window for the PE on a call
to the ibm,remove-pe-dma-window RTAS call when all of the following
are true:
 a. The call removes the last DMA window remaining for the PE.
 b. The DMA window being removed is not the default window

===

This resets DMA as PAPR mandates.

Signed-off-by: Alexey Kardashevskiy 
Reviewed-by: Daniel Henrique Barboza 
Message-Id: <20220622052955.1069903-1-...@ozlabs.ru>
Signed-off-by: Daniel Henrique Barboza 
---
 hw/ppc/spapr_iommu.c|  3 ++-
 hw/ppc/spapr_pci.c  |  1 +
 hw/ppc/spapr_rtas_ddw.c | 15 +++
 include/hw/ppc/spapr.h  |  1 +
 4 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 81e5a1aea3..63e34d457a 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -279,7 +279,7 @@ static const VMStateDescription vmstate_spapr_tce_table_ex 
= {
 
 static const VMStateDescription vmstate_spapr_tce_table = {
 .name = "spapr_iommu",
-.version_id = 2,
+.version_id = 3,
 .minimum_version_id = 2,
 .pre_save = spapr_tce_table_pre_save,
 .post_load = spapr_tce_table_post_load,
@@ -292,6 +292,7 @@ static const VMStateDescription vmstate_spapr_tce_table = {
 VMSTATE_BOOL(bypass, SpaprTceTable),
 VMSTATE_VARRAY_UINT32_ALLOC(mig_table, SpaprTceTable, mig_nb_table, 0,
 vmstate_info_uint64, uint64_t),
+VMSTATE_BOOL_V(def_win, SpaprTceTable, 3),
 
 VMSTATE_END_OF_LIST()
 },
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index b2f5fbef0c..5e95d7940f 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -2067,6 +2067,7 @@ void spapr_phb_dma_reset(SpaprPhbState *sphb)
 tcet = spapr_tce_find_by_liobn(sphb->dma_liobn[0]);
 spapr_tce_table_enable(tcet, SPAPR_TCE_PAGE_SHIFT, sphb->dma_win_addr,
sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT);
+tcet->def_win = true;
 }
 
 static void spapr_phb_reset(DeviceState *qdev)
diff --git a/hw/ppc/spapr_rtas_ddw.c b/hw/ppc/spapr_rtas_ddw.c
index 13d339c807..bb7d91b6d1 100644
--- a/hw/ppc/spapr_rtas_ddw.c
+++ b/hw/ppc/spapr_rtas_ddw.c
@@ -215,6 +215,7 @@ static void rtas_ibm_remove_pe_dma_window(PowerPCCPU *cpu,
 SpaprPhbState *sphb;
 SpaprTceTable *tcet;
 uint32_t liobn;
+bool def_win_removed;
 
 if ((nargs != 1) || (nret != 1)) {
 goto param_error_exit;
@@ -231,9 +232,23 @@ static void rtas_ibm_remove_pe_dma_window(PowerPCCPU *cpu,
 goto param_error_exit;
 }
 
+def_win_removed = tcet->def_win;
 spapr_tce_table_disable(tcet);
 trace_spapr_iommu_ddw_remove(liobn);
 
+/*
+ * PAPR+/LoPAPR says:
+ * The platform must restore the default DMA window for the PE on a call
+ * to the ibm,remove-pe-dma-window RTAS call when all of the following
+ * are true:
+ * a. The call removes the last DMA window remaining for the PE.
+ * b. The DMA window being removed is not the default window
+ */
+if (spapr_phb_get_active_win_num(sphb) == 0 && !def_win_removed) {
+spapr_phb_dma_reset(sphb);
+trace_spapr_iommu_ddw_reset(sphb->buid, 0);
+}
+
 rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 return;
 
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 072dda2c72..4ba2b27b8c 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -902,6 +902,7 @@ struct SpaprTceTable {
 bool bypass;
 bool need_vfio;
 bool skipping_replay;
+bool def_win;
 int fd;
 MemoryRegion root;
 IOMMUMemoryRegion iommu;
-- 
2.36.1




[PULL 22/34] target/ppc: Move mffscrn[i] to decodetree

2022-07-06 Thread Daniel Henrique Barboza
From: Víctor Colombo 

Signed-off-by: Víctor Colombo 
Reviewed-by: Matheus Ferst 
Message-Id: <20220629162904.105060-3-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/insn32.decode   |  8 +++
 target/ppc/internal.h  |  3 --
 target/ppc/translate/fp-impl.c.inc | 83 +++---
 target/ppc/translate/fp-ops.c.inc  |  4 --
 4 files changed, 50 insertions(+), 48 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 1a425ab28f..f63098d024 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -124,6 +124,9 @@
 _bfl  bf l:bool ra rb
 @X_bfl  .. bf:3 . l:1 ra:5 rb:5 .. ._bfl
 
+_imm2 rt imm
+@X_imm2 .. rt:5 . ... imm:2 .. ._imm2
+
 %x_xt   0:1 21:5
 _imm5 xt imm:uint8_t vrb
 @X_imm5 .. . imm:5 vrb:5 .. .   _imm5 
xt=%x_xt
@@ -334,6 +337,11 @@ SETBCR  01 . . - 011010 -   
@X_bi
 SETNBC  01 . . - 011100 -   @X_bi
 SETNBCR 01 . . - 00 -   @X_bi
 
+### Move To/From FPSCR
+
+MFFSCRN 11 . 10110 . 1001000111 -   @X_tb
+MFFSCRNI11 . 10111 ---.. 1001000111 -   @X_imm2
+
 ### Decimal Floating-Point Arithmetic Instructions
 
 DADD111011 . . . 10 .   @X_rc
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 2add128cd1..467f3046c8 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -159,9 +159,6 @@ EXTRACT_HELPER(FPL, 25, 1);
 EXTRACT_HELPER(FPFLM, 17, 8);
 EXTRACT_HELPER(FPW, 16, 1);
 
-/* mffscrni */
-EXTRACT_HELPER(RM, 11, 2);
-
 /* addpcis */
 EXTRACT_HELPER_SPLIT_3(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0)
 #if defined(TARGET_PPC64)
diff --git a/target/ppc/translate/fp-impl.c.inc 
b/target/ppc/translate/fp-impl.c.inc
index f9b58b844e..bcb7ec2689 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -685,71 +685,72 @@ static void gen_mffsce(DisasContext *ctx)
 tcg_temp_free_i64(t0);
 }
 
-static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
+static TCGv_i64 place_from_fpscr(int rt, uint64_t mask)
 {
-TCGv_i64 t0 = tcg_temp_new_i64();
-TCGv_i32 mask = tcg_const_i32(0x0001);
+TCGv_i64 fpscr = tcg_temp_new_i64();
+TCGv_i64 fpscr_masked = tcg_temp_new_i64();
 
-gen_reset_fpstatus();
-tcg_gen_extu_tl_i64(t0, cpu_fpscr);
-tcg_gen_andi_i64(t0, t0, FP_DRN | FP_ENABLES | FP_RN);
-set_fpr(rD(ctx->opcode), t0);
+tcg_gen_extu_tl_i64(fpscr, cpu_fpscr);
+tcg_gen_andi_i64(fpscr_masked, fpscr, mask);
+set_fpr(rt, fpscr_masked);
 
-/* Mask FPSCR value to clear RN.  */
-tcg_gen_andi_i64(t0, t0, ~FP_RN);
+tcg_temp_free_i64(fpscr_masked);
 
-/* Merge RN into FPSCR value.  */
-tcg_gen_or_i64(t0, t0, t1);
+return fpscr;
+}
 
-gen_helper_store_fpscr(cpu_env, t0, mask);
+static void store_fpscr_masked(TCGv_i64 fpscr, uint64_t clear_mask,
+   TCGv_i64 set_mask, uint32_t store_mask)
+{
+TCGv_i64 fpscr_masked = tcg_temp_new_i64();
+TCGv_i32 st_mask = tcg_constant_i32(store_mask);
 
-tcg_temp_free_i32(mask);
-tcg_temp_free_i64(t0);
+tcg_gen_andi_i64(fpscr_masked, fpscr, ~clear_mask);
+tcg_gen_or_i64(fpscr_masked, fpscr_masked, set_mask);
+gen_helper_store_fpscr(cpu_env, fpscr_masked, st_mask);
+
+tcg_temp_free_i64(fpscr_masked);
 }
 
-/* mffscrn */
-static void gen_mffscrn(DisasContext *ctx)
+static bool trans_MFFSCRN(DisasContext *ctx, arg_X_tb *a)
 {
-TCGv_i64 t1;
+TCGv_i64 t1, fpscr;
 
-if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
-return gen_mffs(ctx);
-}
-
-if (unlikely(!ctx->fpu_enabled)) {
-gen_exception(ctx, POWERPC_EXCP_FPU);
-return;
-}
+REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+REQUIRE_FPU(ctx);
 
 t1 = tcg_temp_new_i64();
-get_fpr(t1, rB(ctx->opcode));
-/* Mask FRB to get just RN.  */
+get_fpr(t1, a->rb);
 tcg_gen_andi_i64(t1, t1, FP_RN);
 
-gen_helper_mffscrn(ctx, t1);
+gen_reset_fpstatus();
+fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
+store_fpscr_masked(fpscr, FP_RN, t1, 0x0001);
 
 tcg_temp_free_i64(t1);
+tcg_temp_free_i64(fpscr);
+
+return true;
 }
 
-/* mffscrni */
-static void gen_mffscrni(DisasContext *ctx)
+static bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 *a)
 {
-TCGv_i64 t1;
-
-if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
-return gen_mffs(ctx);
-}
+TCGv_i64 t1, fpscr;
 
-if (unlikely(!ctx->fpu_enabled)) {
-gen_exception(ctx, POWERPC_EXCP_FPU);
-return;
-}
+REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+REQUIRE_FPU(ctx);
 
-t1 = tcg_const_i64((uint64_t)RM(ctx->opcode));
+t1 = tcg_temp_new_i64();
+tcg_gen_movi_i64(t1, a->imm);
 
-

[PULL 23/34] target/ppc: Move mffsce to decodetree

2022-07-06 Thread Daniel Henrique Barboza
From: Víctor Colombo 

Signed-off-by: Víctor Colombo 
Reviewed-by: Matheus Ferst 
Message-Id: <20220629162904.105060-4-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/insn32.decode   |  4 +++
 target/ppc/translate/fp-impl.c.inc | 46 +++---
 target/ppc/translate/fp-ops.c.inc  |  2 --
 3 files changed, 20 insertions(+), 32 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index f63098d024..7cb7faabac 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -94,6 +94,9 @@
 
 @X_tp_a_bp_rc   .. 0 ra:5 0 .. rc:1 _rc 
rt=%x_frtp rb=%x_frbp
 
+_trt
+@X_t.. rt:5 . . .. ._t
+
 _tb   rt rb
 @X_tb   .. rt:5 . rb:5 .. . _tb
 
@@ -339,6 +342,7 @@ SETNBCR 01 . . - 00 -   
@X_bi
 
 ### Move To/From FPSCR
 
+MFFSCE  11 . 1 - 1001000111 -   @X_t
 MFFSCRN 11 . 10110 . 1001000111 -   @X_tb
 MFFSCRNI11 . 10111 ---.. 1001000111 -   @X_imm2
 
diff --git a/target/ppc/translate/fp-impl.c.inc 
b/target/ppc/translate/fp-impl.c.inc
index bcb7ec2689..64e26b9b42 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -655,36 +655,6 @@ static void gen_mffsl(DisasContext *ctx)
 tcg_temp_free_i64(t0);
 }
 
-/* mffsce */
-static void gen_mffsce(DisasContext *ctx)
-{
-TCGv_i64 t0;
-TCGv_i32 mask;
-
-if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
-return gen_mffs(ctx);
-}
-
-if (unlikely(!ctx->fpu_enabled)) {
-gen_exception(ctx, POWERPC_EXCP_FPU);
-return;
-}
-
-t0 = tcg_temp_new_i64();
-
-gen_reset_fpstatus();
-tcg_gen_extu_tl_i64(t0, cpu_fpscr);
-set_fpr(rD(ctx->opcode), t0);
-
-/* Clear exception enable bits in the FPSCR.  */
-tcg_gen_andi_i64(t0, t0, ~FP_ENABLES);
-mask = tcg_const_i32(0x0003);
-gen_helper_store_fpscr(cpu_env, t0, mask);
-
-tcg_temp_free_i32(mask);
-tcg_temp_free_i64(t0);
-}
-
 static TCGv_i64 place_from_fpscr(int rt, uint64_t mask)
 {
 TCGv_i64 fpscr = tcg_temp_new_i64();
@@ -712,6 +682,22 @@ static void store_fpscr_masked(TCGv_i64 fpscr, uint64_t 
clear_mask,
 tcg_temp_free_i64(fpscr_masked);
 }
 
+static bool trans_MFFSCE(DisasContext *ctx, arg_X_t *a)
+{
+TCGv_i64 fpscr;
+
+REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+REQUIRE_FPU(ctx);
+
+gen_reset_fpstatus();
+fpscr = place_from_fpscr(a->rt, UINT64_MAX);
+store_fpscr_masked(fpscr, FP_ENABLES, tcg_constant_i64(0), 0x0003);
+
+tcg_temp_free_i64(fpscr);
+
+return true;
+}
+
 static bool trans_MFFSCRN(DisasContext *ctx, arg_X_tb *a)
 {
 TCGv_i64 t1, fpscr;
diff --git a/target/ppc/translate/fp-ops.c.inc 
b/target/ppc/translate/fp-ops.c.inc
index a27a1be9f5..a76943b8bf 100644
--- a/target/ppc/translate/fp-ops.c.inc
+++ b/target/ppc/translate/fp-ops.c.inc
@@ -75,8 +75,6 @@ GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x0001, PPC_NONE, 
PPC2_VSX207),
 GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x0001, PPC_NONE, PPC2_VSX207),
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
 GEN_HANDLER_E_2(mffs, 0x3F, 0x07, 0x12, 0x00, 0x, PPC_FLOAT, PPC_NONE),
-GEN_HANDLER_E_2(mffsce, 0x3F, 0x07, 0x12, 0x01, 0x, PPC_FLOAT,
-PPC2_ISA300),
 GEN_HANDLER_E_2(mffsl, 0x3F, 0x07, 0x12, 0x18, 0x, PPC_FLOAT,
 PPC2_ISA300),
 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
-- 
2.36.1




[PULL 31/34] target/ppc: implement cdtbcd

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

Implements the Convert Declets To Binary Coded Decimal instruction.
Since libdecnumber doesn't expose the methods for direct conversion
(decDigitsFromDPD, DPD2BCD, etc), a positive decimal32 with zero
exponent is used as an intermediate value to convert the declets.

Reviewed-by: Richard Henderson 
Signed-off-by: Matheus Ferst 
Signed-off-by: Víctor Colombo 
Message-Id: <20220629162904.105060-12-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/dfp_helper.c| 26 ++
 target/ppc/helper.h|  1 +
 target/ppc/insn32.decode   |  1 +
 target/ppc/translate/fixedpoint-impl.c.inc |  7 ++
 4 files changed, 35 insertions(+)

diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c
index db9e994c8c..5ba74b2124 100644
--- a/target/ppc/dfp_helper.c
+++ b/target/ppc/dfp_helper.c
@@ -1392,6 +1392,32 @@ DFP_HELPER_SHIFT(DSCLIQ, 128, 1)
 DFP_HELPER_SHIFT(DSCRI, 64, 0)
 DFP_HELPER_SHIFT(DSCRIQ, 128, 0)
 
+target_ulong helper_CDTBCD(target_ulong s)
+{
+uint64_t res = 0;
+uint32_t dec32, declets;
+uint8_t bcd[6];
+int i, w, sh;
+decNumber a;
+
+for (w = 1; w >= 0; w--) {
+res <<= 32;
+declets = extract64(s, 32 * w, 20);
+if (declets) {
+/* decimal32 with zero exponent and word "w" declets */
+dec32 = (0x225ULL << 20) | declets;
+decimal32ToNumber((decimal32 *), );
+decNumberGetBCD(, bcd);
+for (i = 0; i < a.digits; i++) {
+sh = 4 * (a.digits - 1 - i);
+res |= (uint64_t)bcd[i] << sh;
+}
+}
+}
+
+return res;
+}
+
 target_ulong helper_CBCDTD(target_ulong s)
 {
 uint64_t res = 0;
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 583c8dd0c2..ed0641a234 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -54,6 +54,7 @@ DEF_HELPER_3(sraw, tl, env, tl, tl)
 DEF_HELPER_FLAGS_2(CFUGED, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(PDEPD, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(PEXTD, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_1(CDTBCD, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(CBCDTD, TCG_CALL_NO_RWG_SE, tl, tl)
 #if defined(TARGET_PPC64)
 DEF_HELPER_FLAGS_2(cmpeqb, TCG_CALL_NO_RWG_SE, i32, tl, tl)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 65bcaf657f..f7653ef9d5 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -317,6 +317,7 @@ PEXTD   01 . . . 001000 -   @X
 ## BCD Assist
 
 ADDG6S  01 . . . - 001001010 -  @X
+CDTBCD  01 . . - 0100011010 -   @X_sa
 CBCDTD  01 . . - 0100111010 -   @X_sa
 
 ### Float-Point Load Instructions
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 892c9d2568..cb0097bedb 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -530,6 +530,13 @@ static bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
 return true;
 }
 
+static bool trans_CDTBCD(DisasContext *ctx, arg_X_sa *a)
+{
+REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
+gen_helper_CDTBCD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
+return true;
+}
+
 static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
 {
 REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
-- 
2.36.1




[PULL 21/34] target/ppc: Fix insn32.decode style issues

2022-07-06 Thread Daniel Henrique Barboza
From: Víctor Colombo 

Some lines in insn32.decode have inconsistent alignment when compared
to others.
Fix this by changing the alignment of some lines, making it more
consistent throughout the file.

Signed-off-by: Víctor Colombo 
Reviewed-by: Richard Henderson 
Message-Id: <20220629162904.105060-2-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/insn32.decode | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 65a6a42f78..1a425ab28f 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -21,11 +21,11 @@
 @A  .. frt:5 fra:5 frb:5 frc:5 . rc:1   
 
   rt ra si:int64_t
-@D  .. rt:5 ra:5 si:s16 
+@D  .. rt:5 ra:5 si:s16 
 
 _bf   bf l:bool ra imm
-@D_bfs  .. bf:3 - l:1 ra:5 imm:s16  _bf
-@D_bfu  .. bf:3 - l:1 ra:5 imm:16   _bf
+@D_bfs  .. bf:3 . l:1 ra:5 imm:s16  _bf
+@D_bfu  .. bf:3 . l:1 ra:5 imm:16   _bf
 
 %dq_si  4:s12  !function=times_16
 %dq_rtp 22:4   !function=times_2
@@ -38,7 +38,7 @@
 @DQ_TSXP.. . ra:5    si=%dq_si 
rt=%rt_tsxp
 
 %ds_si  2:s14  !function=times_4
-@DS .. rt:5 ra:5 .. ..   si=%ds_si
+@DS .. rt:5 ra:5 .. ..   si=%ds_si
 
 %ds_rtp 22:4   !function=times_2
 @DS_rtp .. 0 ra:5 .. ..  rt=%ds_rtp 
si=%ds_si
@@ -49,10 +49,10 @@
 
  rt d
 %dx_d   6:s10 16:5 0:1
-@DX .. rt:5  . .. . .d=%dx_d
+@DX .. rt:5  . .. . .d=%dx_d
 
  vrt vra vrb rc
-@VA .. vrt:5 vra:5 vrb:5 rc:5 ..
+@VA .. vrt:5 vra:5 vrb:5 rc:5 ..
 
  vrt vra vrb rc:bool
 @VC .. vrt:5 vra:5 vrb:5 rc:1 ..
@@ -61,7 +61,7 @@
 @VN .. vrt:5 vra:5 vrb:5 .. sh:3 .. 
 
  vrt vra vrb
-@VX .. vrt:5 vra:5 vrb:5 .. .   
+@VX .. vrt:5 vra:5 vrb:5 .. .   
 
 _bf  bf vra vrb
 @VX_bf  .. bf:3 .. vra:5 vrb:5 ...  _bf
@@ -76,13 +76,13 @@
 @VX_tb_rc   .. vrt:5 . vrb:5 rc:1 .._tb_rc
 
 _uim4vrt uim vrb
-@VX_uim4.. vrt:5 . uim:4 vrb:5 ...  _uim4
+@VX_uim4.. vrt:5 . uim:4 vrb:5 ...  _uim4
 
 _tb  vrt vrb
-@VX_tb  .. vrt:5 . vrb:5 ..._tb
+@VX_tb  .. vrt:5 . vrb:5 ..._tb
 
   rt ra rb
-@X  .. rt:5 ra:5 rb:5 .. .  
+@X  .. rt:5 ra:5 rb:5 .. .  
 
 _rc   rt ra rb rc:bool
 @X_rc   .. rt:5 ra:5 rb:5 .. rc:1   _rc
@@ -107,7 +107,7 @@
 @X_t_bp_rc  .. rt:5 . 0 .. rc:1 _tb_rc 
rb=%x_frbp
 
 _bi   rt bi
-@X_bi   .. rt:5 bi:5 - .. - _bi
+@X_bi   .. rt:5 bi:5 . .. . _bi
 
 _bf   bf ra rb
 @X_bf   .. bf:3 .. ra:5 rb:5 .. .   _bf
@@ -122,7 +122,7 @@
 @X_bf_uim_bp.. bf:3 . uim:6 0 .. .  _bf_uim 
rb=%x_frbp
 
 _bfl  bf l:bool ra rb
-@X_bfl  .. bf:3 - l:1 ra:5 rb:5 ..- _bfl
+@X_bfl  .. bf:3 . l:1 ra:5 rb:5 .. ._bfl
 
 %x_xt   0:1 21:5
 _imm5 xt imm:uint8_t vrb
-- 
2.36.1




[PULL 08/34] ppc/pnv: remove 'INTERFACE_PCIE_DEVICE' from phb4 root bus

2022-07-06 Thread Daniel Henrique Barboza
It's unneeded. No other PCIE_BUS implements this interface.

Reviewed-by: Frederic Barrat 
Fixes: 4f9924c4d4cf ("ppc/pnv: Add models for POWER9 PHB4 PCIe Host bridge")
Signed-off-by: Daniel Henrique Barboza 
Message-Id: <20220621173436.165912-9-danielhb...@gmail.com>
---
 hw/pci-host/pnv_phb4.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 725b3d740b..d225ab5b0f 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1752,10 +1752,6 @@ static const TypeInfo pnv_phb4_root_bus_info = {
 .name = TYPE_PNV_PHB4_ROOT_BUS,
 .parent = TYPE_PCIE_BUS,
 .class_init = pnv_phb4_root_bus_class_init,
-.interfaces = (InterfaceInfo[]) {
-{ INTERFACE_PCIE_DEVICE },
-{ }
-},
 };
 
 static void pnv_phb4_root_port_reset(DeviceState *dev)
-- 
2.36.1




[PULL 19/34] ppc: Define SETFIELD for the ppc target

2022-07-06 Thread Daniel Henrique Barboza
From: Alexey Kardashevskiy 

It keeps repeating, move it to the header. This uses __builtin_ffsll() to
allow using the macros in #define.

This is not using the QEMU's FIELD macros as this would require changing
all such macros found in skiboot (the PPC PowerNV firmware).

Signed-off-by: Alexey Kardashevskiy 
Reviewed-by: Daniel Henrique Barboza 
Message-Id: <20220628080544.1509428-1-...@ozlabs.ru>
Signed-off-by: Daniel Henrique Barboza 
---
 hw/intc/pnv_xive.c  | 20 
 hw/intc/pnv_xive2.c | 20 
 hw/pci-host/pnv_phb4.c  | 16 
 include/hw/pci-host/pnv_phb3_regs.h | 16 
 target/ppc/cpu.h| 12 
 5 files changed, 12 insertions(+), 72 deletions(-)

diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index 1ce1d7b07d..c7b75ed12e 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -66,26 +66,6 @@ static const XiveVstInfo vst_infos[] = {
 qemu_log_mask(LOG_GUEST_ERROR, "XIVE[%x] - " fmt "\n",  \
   (xive)->chip->chip_id, ## __VA_ARGS__);
 
-/*
- * QEMU version of the GETFIELD/SETFIELD macros
- *
- * TODO: It might be better to use the existing extract64() and
- * deposit64() but this means that all the register definitions will
- * change and become incompatible with the ones found in skiboot.
- *
- * Keep it as it is for now until we find a common ground.
- */
-static inline uint64_t GETFIELD(uint64_t mask, uint64_t word)
-{
-return (word & mask) >> ctz64(mask);
-}
-
-static inline uint64_t SETFIELD(uint64_t mask, uint64_t word,
-uint64_t value)
-{
-return (word & ~mask) | ((value << ctz64(mask)) & mask);
-}
-
 /*
  * When PC_TCTXT_CHIPID_OVERRIDE is configured, the PC_TCTXT_CHIPID
  * field overrides the hardwired chip ID in the Powerbus operations
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index f31c53c28d..f22ce5ca59 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -75,26 +75,6 @@ static const XiveVstInfo vst_infos[] = {
 qemu_log_mask(LOG_GUEST_ERROR, "XIVE[%x] - " fmt "\n",  \
   (xive)->chip->chip_id, ## __VA_ARGS__);
 
-/*
- * QEMU version of the GETFIELD/SETFIELD macros
- *
- * TODO: It might be better to use the existing extract64() and
- * deposit64() but this means that all the register definitions will
- * change and become incompatible with the ones found in skiboot.
- *
- * Keep it as it is for now until we find a common ground.
- */
-static inline uint64_t GETFIELD(uint64_t mask, uint64_t word)
-{
-return (word & mask) >> ctz64(mask);
-}
-
-static inline uint64_t SETFIELD(uint64_t mask, uint64_t word,
-uint64_t value)
-{
-return (word & ~mask) | ((value << ctz64(mask)) & mask);
-}
-
 /*
  * TODO: Document block id override
  */
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index d225ab5b0f..67ddde4a6e 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -31,22 +31,6 @@
 qemu_log_mask(LOG_GUEST_ERROR, "phb4_pec[%d:%d]: " fmt "\n",\
   (pec)->chip_id, (pec)->index, ## __VA_ARGS__)
 
-/*
- * QEMU version of the GETFIELD/SETFIELD macros
- *
- * These are common with the PnvXive model.
- */
-static inline uint64_t GETFIELD(uint64_t mask, uint64_t word)
-{
-return (word & mask) >> ctz64(mask);
-}
-
-static inline uint64_t SETFIELD(uint64_t mask, uint64_t word,
-uint64_t value)
-{
-return (word & ~mask) | ((value << ctz64(mask)) & mask);
-}
-
 static PCIDevice *pnv_phb4_find_cfg_dev(PnvPHB4 *phb)
 {
 PCIHostState *pci = PCI_HOST_BRIDGE(phb);
diff --git a/include/hw/pci-host/pnv_phb3_regs.h 
b/include/hw/pci-host/pnv_phb3_regs.h
index a174ef1f70..38f8ce9d74 100644
--- a/include/hw/pci-host/pnv_phb3_regs.h
+++ b/include/hw/pci-host/pnv_phb3_regs.h
@@ -12,22 +12,6 @@
 
 #include "qemu/host-utils.h"
 
-/*
- * QEMU version of the GETFIELD/SETFIELD macros
- *
- * These are common with the PnvXive model.
- */
-static inline uint64_t GETFIELD(uint64_t mask, uint64_t word)
-{
-return (word & mask) >> ctz64(mask);
-}
-
-static inline uint64_t SETFIELD(uint64_t mask, uint64_t word,
-uint64_t value)
-{
-return (word & ~mask) | ((value << ctz64(mask)) & mask);
-}
-
 /*
  * PBCQ XSCOM registers
  */
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index e109b5902b..b38c651af4 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -47,6 +47,18 @@
  PPC_BIT32(bs))
 #define PPC_BITMASK8(bs, be)((PPC_BIT8(bs) - PPC_BIT8(be)) | PPC_BIT8(bs))
 
+/*
+ * QEMU version of the GETFIELD/SETFIELD macros from skiboot
+ *
+ * It might be better to use the existing extract64() and
+ * deposit64() but this means that all the register definitions will
+ * change and become incompatible with the ones found in skiboot.
+ */
+#define 

[PULL 24/34] target/ppc: Move mffsl to decodetree

2022-07-06 Thread Daniel Henrique Barboza
From: Víctor Colombo 

Signed-off-by: Víctor Colombo 
Reviewed-by: Matheus Ferst 
Message-Id: <20220629162904.105060-5-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/insn32.decode   |  1 +
 target/ppc/translate/fp-impl.c.inc | 38 +-
 target/ppc/translate/fp-ops.c.inc  |  2 --
 3 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 7cb7faabac..6b68689357 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -345,6 +345,7 @@ SETNBCR 01 . . - 00 -   
@X_bi
 MFFSCE  11 . 1 - 1001000111 -   @X_t
 MFFSCRN 11 . 10110 . 1001000111 -   @X_tb
 MFFSCRNI11 . 10111 ---.. 1001000111 -   @X_imm2
+MFFSL   11 . 11000 - 1001000111 -   @X_t
 
 ### Decimal Floating-Point Arithmetic Instructions
 
diff --git a/target/ppc/translate/fp-impl.c.inc 
b/target/ppc/translate/fp-impl.c.inc
index 64e26b9b42..4f4d57c611 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -633,28 +633,6 @@ static void gen_mffs(DisasContext *ctx)
 tcg_temp_free_i64(t0);
 }
 
-/* mffsl */
-static void gen_mffsl(DisasContext *ctx)
-{
-TCGv_i64 t0;
-
-if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
-return gen_mffs(ctx);
-}
-
-if (unlikely(!ctx->fpu_enabled)) {
-gen_exception(ctx, POWERPC_EXCP_FPU);
-return;
-}
-t0 = tcg_temp_new_i64();
-gen_reset_fpstatus();
-tcg_gen_extu_tl_i64(t0, cpu_fpscr);
-/* Mask everything except mode, status, and enables.  */
-tcg_gen_andi_i64(t0, t0, FP_DRN | FP_STATUS | FP_ENABLES | FP_RN);
-set_fpr(rD(ctx->opcode), t0);
-tcg_temp_free_i64(t0);
-}
-
 static TCGv_i64 place_from_fpscr(int rt, uint64_t mask)
 {
 TCGv_i64 fpscr = tcg_temp_new_i64();
@@ -739,6 +717,22 @@ static bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 
*a)
 return true;
 }
 
+static bool trans_MFFSL(DisasContext *ctx, arg_X_t *a)
+{
+TCGv_i64 fpscr;
+
+REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+REQUIRE_FPU(ctx);
+
+gen_reset_fpstatus();
+fpscr = place_from_fpscr(a->rt,
+FP_DRN | FP_STATUS | FP_ENABLES | FP_NI | FP_RN);
+
+tcg_temp_free_i64(fpscr);
+
+return true;
+}
+
 /* mtfsb0 */
 static void gen_mtfsb0(DisasContext *ctx)
 {
diff --git a/target/ppc/translate/fp-ops.c.inc 
b/target/ppc/translate/fp-ops.c.inc
index a76943b8bf..f8c35124ae 100644
--- a/target/ppc/translate/fp-ops.c.inc
+++ b/target/ppc/translate/fp-ops.c.inc
@@ -75,8 +75,6 @@ GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x0001, PPC_NONE, 
PPC2_VSX207),
 GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x0001, PPC_NONE, PPC2_VSX207),
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
 GEN_HANDLER_E_2(mffs, 0x3F, 0x07, 0x12, 0x00, 0x, PPC_FLOAT, PPC_NONE),
-GEN_HANDLER_E_2(mffsl, 0x3F, 0x07, 0x12, 0x18, 0x, PPC_FLOAT,
-PPC2_ISA300),
 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x, PPC_FLOAT),
-- 
2.36.1




[PULL 20/34] ppc/spapr: Implement H_WATCHDOG

2022-07-06 Thread Daniel Henrique Barboza
From: Alexey Kardashevskiy 

The new PAPR 2.12 defines a watchdog facility managed via the new
H_WATCHDOG hypercall.

This adds H_WATCHDOG support which a proposed driver for pseries uses:
https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=303120

This was tested by running QEMU with a debug kernel and command line:
-append \
 "pseries-wdt.timeout=60 pseries-wdt.nowayout=1 pseries-wdt.action=2"

and running "echo V > /dev/watchdog0" inside the VM.

Signed-off-by: Alexey Kardashevskiy 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Daniel Henrique Barboza 
Message-Id: <20220622051008.1067464-1-...@ozlabs.ru>
Signed-off-by: Daniel Henrique Barboza 
---
 hw/ppc/spapr.c   |   4 +
 hw/watchdog/meson.build  |   1 +
 hw/watchdog/spapr_watchdog.c | 274 +++
 hw/watchdog/trace-events |   7 +
 include/hw/ppc/spapr.h   |  25 +++-
 5 files changed, 310 insertions(+), 1 deletion(-)
 create mode 100644 hw/watchdog/spapr_watchdog.c

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index fd4942e881..9a5382d527 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -898,6 +898,8 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void 
*fdt)
 add_str(hypertas, "hcall-hpt-resize");
 }
 
+add_str(hypertas, "hcall-watchdog");
+
 _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions",
  hypertas->str, hypertas->len));
 g_string_free(hypertas, TRUE);
@@ -3051,6 +3053,8 @@ static void spapr_machine_init(MachineState *machine)
 spapr->vof->fw_size = fw_size; /* for claim() on itself */
 spapr_register_hypercall(KVMPPC_H_VOF_CLIENT, spapr_h_vof_client);
 }
+
+spapr_watchdog_init(spapr);
 }
 
 #define DEFAULT_KVM_TYPE "auto"
diff --git a/hw/watchdog/meson.build b/hw/watchdog/meson.build
index 054c403dea..8974b5cf4c 100644
--- a/hw/watchdog/meson.build
+++ b/hw/watchdog/meson.build
@@ -6,3 +6,4 @@ softmmu_ss.add(when: 'CONFIG_WDT_DIAG288', if_true: 
files('wdt_diag288.c'))
 softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('wdt_aspeed.c'))
 softmmu_ss.add(when: 'CONFIG_WDT_IMX2', if_true: files('wdt_imx2.c'))
 softmmu_ss.add(when: 'CONFIG_WDT_SBSA', if_true: files('sbsa_gwdt.c'))
+specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_watchdog.c'))
diff --git a/hw/watchdog/spapr_watchdog.c b/hw/watchdog/spapr_watchdog.c
new file mode 100644
index 00..55ff1f03c1
--- /dev/null
+++ b/hw/watchdog/spapr_watchdog.c
@@ -0,0 +1,274 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "target/ppc/cpu.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+#include "hw/ppc/spapr.h"
+
+#define FIELD_BE(reg, field, start, len) \
+FIELD(reg, field, 64 - (start + len), len)
+
+/*
+ * Bits 47: "leaveOtherWatchdogsRunningOnTimeout", specified on
+ * the "Start watchdog" operation,
+ * 0 - stop out-standing watchdogs on timeout,
+ * 1 - leave outstanding watchdogs running on timeout
+ */
+FIELD_BE(PSERIES_WDTF, LEAVE_OTHER, 47, 1)
+
+/*Bits 48-55: "operation" */
+FIELD_BE(PSERIES_WDTF, OP, 48, 8)
+#define PSERIES_WDTF_OP_START   0x1
+#define PSERIES_WDTF_OP_STOP0x2
+#define PSERIES_WDTF_OP_QUERY   0x3
+#define PSERIES_WDTF_OP_QUERY_LPM   0x4
+
+/*Bits 56-63: "timeoutAction" */
+FIELD_BE(PSERIES_WDTF, ACTION, 56, 8)
+#define PSERIES_WDTF_ACTION_HARD_POWER_OFF  0x1
+#define PSERIES_WDTF_ACTION_HARD_RESTART0x2
+#define PSERIES_WDTF_ACTION_DUMP_RESTART0x3
+
+FIELD_BE(PSERIES_WDTF, RESERVED, 0, 47)
+
+/* Special watchdogNumber for the "stop all watchdogs" operation */
+#define PSERIES_WDT_STOP_ALL((uint64_t)~0)
+
+/*
+ * For the "Query watchdog capabilities" operation, a uint64 structure
+ * defined as:
+ * Bits 0-15: The minimum supported timeout in milliseconds
+ * Bits 16-31: The number of watchdogs supported
+ * Bits 32-63: Reserved
+ */
+FIELD_BE(PSERIES_WDTQ, MIN_TIMEOUT, 0, 16)
+FIELD_BE(PSERIES_WDTQ, NUM, 16, 16)
+
+/*
+ * For the "Query watchdog LPM requirement" operation:
+ * 1 = The given "watchdogNumber" must be stopped prior to suspending
+ * 2 = The given "watchdogNumber" does not have to be stopped prior to
+ * suspending
+ */
+#define PSERIES_WDTQL_STOPPED   1
+#define PSERIES_WDTQL_QUERY_NOT_STOPPED 2
+
+#define 

[PULL 04/34] ppc/pnv: make pnv_ics_get() use the chip8->phbs[] array

2022-07-06 Thread Daniel Henrique Barboza
The function is working today by getting all the child objects of the
chip, interacting with each of them to check whether the child is a PHB,
and then doing what needs to be done.

We have all the chip PHBs in the phbs[] array so interacting with all
child objects is unneeded. Open code pnv_ics_get_phb_ics() into
pnv_ics_get() and remove both pnv_ics_get_phb_ics() and the
ForeachPhb3Args struct.

Reviewed-by: Cédric Le Goater 
Reviewed-by: Frederic Barrat 
Signed-off-by: Daniel Henrique Barboza 
Message-Id: <20220621173436.165912-5-danielhb...@gmail.com>
---
 hw/ppc/pnv.c | 38 +++---
 1 file changed, 11 insertions(+), 27 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index c5e63bede7..e6cea789f8 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1950,44 +1950,28 @@ PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t 
pir)
 return NULL;
 }
 
-typedef struct ForeachPhb3Args {
-int irq;
-ICSState *ics;
-} ForeachPhb3Args;
-
-static int pnv_ics_get_child(Object *child, void *opaque)
-{
-ForeachPhb3Args *args = opaque;
-PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
-
-if (phb3) {
-if (ics_valid_irq(>lsis, args->irq)) {
-args->ics = >lsis;
-}
-if (ics_valid_irq(ICS(>msis), args->irq)) {
-args->ics = ICS(>msis);
-}
-}
-return args->ics ? 1 : 0;
-}
-
 static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
 {
 PnvMachineState *pnv = PNV_MACHINE(xi);
-ForeachPhb3Args args = { irq, NULL };
-int i;
+int i, j;
 
 for (i = 0; i < pnv->num_chips; i++) {
-PnvChip *chip = pnv->chips[i];
 Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
 
 if (ics_valid_irq(>psi.ics, irq)) {
 return >psi.ics;
 }
 
-object_child_foreach(OBJECT(chip), pnv_ics_get_child, );
-if (args.ics) {
-return args.ics;
+for (j = 0; j < chip8->num_phbs; j++) {
+PnvPHB3 *phb3 = >phbs[j];
+
+if (ics_valid_irq(>lsis, irq)) {
+return >lsis;
+}
+
+if (ics_valid_irq(ICS(>msis), irq)) {
+return ICS(>msis);
+}
 }
 }
 return NULL;
-- 
2.36.1




[PULL 18/34] target/ppc: use int128.h methods in vsubcuq

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

And also move the insn to decodetree and remove the now unused
avr_qw_not, avr_qw_cmpu, and avr_qw_add methods.

Signed-off-by: Matheus Ferst 
Reviewed-by: Víctor Colombo 
Message-Id: <20220606150037.338931-8-matheus.fe...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/helper.h |  2 +-
 target/ppc/insn32.decode|  1 +
 target/ppc/int_helper.c | 51 +++--
 target/ppc/translate/vmx-impl.c.inc |  5 +--
 target/ppc/translate/vmx-ops.c.inc  |  2 +-
 5 files changed, 9 insertions(+), 52 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 04ced6ef70..84a41d85b0 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -211,7 +211,7 @@ DEF_HELPER_FLAGS_3(VADDCUQ, TCG_CALL_NO_RWG, void, avr, 
avr, avr)
 DEF_HELPER_FLAGS_3(VSUBUQM, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_4(VSUBECUQ, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_4(VSUBEUQM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
-DEF_HELPER_FLAGS_3(vsubcuq, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(VSUBCUQ, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_4(vsldoi, TCG_CALL_NO_RWG, void, avr, avr, avr, i32)
 DEF_HELPER_FLAGS_3(vextractub, TCG_CALL_NO_RWG, void, avr, avr, i32)
 DEF_HELPER_FLAGS_3(vextractuh, TCG_CALL_NO_RWG, void, avr, avr, i32)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 5e6f3b668e..65a6a42f78 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -556,6 +556,7 @@ VADDUQM 000100 . . . 001@VX
 VADDEUQM000100 . . . . 00   @VA
 VADDECUQ000100 . . . . 01   @VA
 
+VSUBCUQ 000100 . . . 1010100@VX
 VSUBUQM 000100 . . . 101@VX
 
 VSUBECUQ000100 . . . . 11   @VA
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index a93398fde4..d905f07d02 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2176,38 +2176,6 @@ VGENERIC_DO(popcntd, u64)
 
 #undef VGENERIC_DO
 
-#ifndef CONFIG_INT128
-
-static inline void avr_qw_not(ppc_avr_t *t, ppc_avr_t a)
-{
-t->u64[0] = ~a.u64[0];
-t->u64[1] = ~a.u64[1];
-}
-
-static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b)
-{
-if (a.VsrD(0) < b.VsrD(0)) {
-return -1;
-} else if (a.VsrD(0) > b.VsrD(0)) {
-return 1;
-} else if (a.VsrD(1) < b.VsrD(1)) {
-return -1;
-} else if (a.VsrD(1) > b.VsrD(1)) {
-return 1;
-} else {
-return 0;
-}
-}
-
-static void avr_qw_add(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b)
-{
-t->VsrD(1) = a.VsrD(1) + b.VsrD(1);
-t->VsrD(0) = a.VsrD(0) + b.VsrD(0) +
- (~a.VsrD(1) < b.VsrD(1));
-}
-
-#endif
-
 void helper_VADDUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
 r->s128 = int128_add(a->s128, b->s128);
@@ -2250,22 +2218,13 @@ void helper_VSUBEUQM(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b, ppc_avr_t *c)
  int128_make64(int128_getlo(c->s128) & 1));
 }
 
-void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
+void helper_VSUBCUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-#ifdef CONFIG_INT128
-r->u128 = (~a->u128 < ~b->u128) ||
- (a->u128 + ~b->u128 == (__uint128_t)-1);
-#else
-int carry = (avr_qw_cmpu(*a, *b) > 0);
-if (!carry) {
-ppc_avr_t tmp;
-avr_qw_not(, *b);
-avr_qw_add(, *a, tmp);
-carry = ((tmp.VsrSD(0) == -1ull) && (tmp.VsrSD(1) == -1ull));
-}
+Int128 tmp = int128_not(b->s128);
+
+r->VsrD(1) = int128_ult(int128_not(a->s128), tmp) ||
+ int128_eq(int128_add(a->s128, tmp), int128_makes64(-1));
 r->VsrD(0) = 0;
-r->VsrD(1) = carry;
-#endif
 }
 
 void helper_VSUBECUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
diff --git a/target/ppc/translate/vmx-impl.c.inc 
b/target/ppc/translate/vmx-impl.c.inc
index 671992f7d1..e644ad3236 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -1234,7 +1234,6 @@ GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
 GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
 GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
 GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
-GEN_VXFORM(vsubcuq, 0, 21);
 GEN_VXFORM_TRANS(vsl, 2, 7);
 GEN_VXFORM_TRANS(vsr, 2, 11);
 GEN_VXFORM_ENV(vpkuhum, 7, 0);
@@ -2856,9 +2855,6 @@ GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \
 bcdus, PPC_NONE, PPC2_ISA300)
 GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
 bcdtrunc, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM_DUAL(vsubcuq, PPC2_ALTIVEC_207, PPC_NONE, \
-bcdutrunc, PPC_NONE, PPC2_ISA300)
-
 
 static void gen_vsbox(DisasContext *ctx)
 {
@@ -3098,6 +3094,7 @@ TRANS_FLAGS2(ALTIVEC_207, VADDUQM, do_vx_helper, 
gen_helper_VADDUQM)
 
 

[PULL 27/34] tests/tcg/ppc64: Add mffsce test

2022-07-06 Thread Daniel Henrique Barboza
From: Víctor Colombo 

Add mffsce test to check both the return value and the new fpscr
stored in the cpu.

Signed-off-by: Víctor Colombo 
Reviewed-by: Matheus Ferst 
Message-Id: <20220629162904.105060-8-victor.colo...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 tests/tcg/ppc64/Makefile.target   |  1 +
 tests/tcg/ppc64le/Makefile.target |  1 +
 tests/tcg/ppc64le/mffsce.c| 37 +++
 3 files changed, 39 insertions(+)
 create mode 100644 tests/tcg/ppc64le/mffsce.c

diff --git a/tests/tcg/ppc64/Makefile.target b/tests/tcg/ppc64/Makefile.target
index babd209573..331fae628e 100644
--- a/tests/tcg/ppc64/Makefile.target
+++ b/tests/tcg/ppc64/Makefile.target
@@ -11,6 +11,7 @@ endif
 $(PPC64_TESTS): CFLAGS += -mpower8-vector
 
 PPC64_TESTS += mtfsf
+PPC64_TESTS += mffsce
 
 ifneq ($(CROSS_CC_HAS_POWER10),)
 PPC64_TESTS += byte_reverse sha512-vector
diff --git a/tests/tcg/ppc64le/Makefile.target 
b/tests/tcg/ppc64le/Makefile.target
index 5b0eb5e870..6ca3003f02 100644
--- a/tests/tcg/ppc64le/Makefile.target
+++ b/tests/tcg/ppc64le/Makefile.target
@@ -24,6 +24,7 @@ run-sha512-vector: QEMU_OPTS+=-cpu POWER10
 run-plugin-sha512-vector-with-%: QEMU_OPTS+=-cpu POWER10
 
 PPC64LE_TESTS += mtfsf
+PPC64LE_TESTS += mffsce
 PPC64LE_TESTS += signal_save_restore_xer
 PPC64LE_TESTS += xxspltw
 
diff --git a/tests/tcg/ppc64le/mffsce.c b/tests/tcg/ppc64le/mffsce.c
new file mode 100644
index 00..20d882cb45
--- /dev/null
+++ b/tests/tcg/ppc64le/mffsce.c
@@ -0,0 +1,37 @@
+#include 
+#include 
+#include 
+
+#define MTFSF(FLM, FRB) asm volatile ("mtfsf %0, %1" :: "i" (FLM), "f" (FRB))
+#define MFFS(FRT) asm("mffs %0" : "=f" (FRT))
+#define MFFSCE(FRT) asm("mffsce %0" : "=f" (FRT))
+
+#define PPC_BIT_NR(nr) (63 - (nr))
+
+#define FP_VE  (1ull << PPC_BIT_NR(56))
+#define FP_UE  (1ull << PPC_BIT_NR(58))
+#define FP_ZE  (1ull << PPC_BIT_NR(59))
+#define FP_XE  (1ull << PPC_BIT_NR(60))
+#define FP_NI  (1ull << PPC_BIT_NR(61))
+#define FP_RN1 (1ull << PPC_BIT_NR(63))
+
+int main(void)
+{
+uint64_t frt, fpscr;
+uint64_t test_value = FP_VE | FP_UE | FP_ZE |
+  FP_XE | FP_NI | FP_RN1;
+MTFSF(0b, test_value); /* set test value to cpu fpscr */
+MFFSCE(frt);
+MFFS(fpscr); /* read the value that mffsce stored to cpu fpscr */
+
+/* the returned value should be as the cpu fpscr was before */
+assert((frt & 0xff) == test_value);
+
+/*
+ * the cpu fpscr last 3 bits should be unchanged
+ * and enable bits should be unset
+ */
+assert((fpscr & 0xff) == (test_value & 0x7));
+
+return 0;
+}
-- 
2.36.1




[PULL 17/34] target/ppc: use int128.h methods in vsubecuq and vsubeuqm

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

And also move the insns to decodetree.

Signed-off-by: Matheus Ferst 
Reviewed-by: Víctor Colombo 
Message-Id: <20220606150037.338931-7-matheus.fe...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/helper.h |  4 +--
 target/ppc/insn32.decode|  3 +++
 target/ppc/int_helper.c | 38 +++--
 target/ppc/translate/vmx-impl.c.inc |  7 +++---
 target/ppc/translate/vmx-ops.c.inc  |  1 -
 5 files changed, 17 insertions(+), 36 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 1c02ad85e5..04ced6ef70 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -209,8 +209,8 @@ DEF_HELPER_FLAGS_4(VADDECUQ, TCG_CALL_NO_RWG, void, avr, 
avr, avr, avr)
 DEF_HELPER_FLAGS_4(VADDEUQM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_3(VADDCUQ, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_3(VSUBUQM, TCG_CALL_NO_RWG, void, avr, avr, avr)
-DEF_HELPER_FLAGS_4(vsubecuq, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
-DEF_HELPER_FLAGS_4(vsubeuqm, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(VSUBECUQ, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(VSUBEUQM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_3(vsubcuq, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_4(vsldoi, TCG_CALL_NO_RWG, void, avr, avr, avr, i32)
 DEF_HELPER_FLAGS_3(vextractub, TCG_CALL_NO_RWG, void, avr, avr, i32)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index a8d3a5a8a1..5e6f3b668e 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -558,6 +558,9 @@ VADDECUQ000100 . . . . 01   @VA
 
 VSUBUQM 000100 . . . 101@VX
 
+VSUBECUQ000100 . . . . 11   @VA
+VSUBEUQM000100 . . . . 10   @VA
+
 VEXTSB2W000100 . 1 . 1100010@VX_tb
 VEXTSH2W000100 . 10001 . 1100010@VX_tb
 VEXTSB2D000100 . 11000 . 1100010@VX_tb
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 159b831d97..a93398fde4 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2244,20 +2244,10 @@ void helper_VSUBUQM(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b)
 r->s128 = int128_sub(a->s128, b->s128);
 }
 
-void helper_vsubeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
+void helper_VSUBEUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 {
-#ifdef CONFIG_INT128
-r->u128 = a->u128 + ~b->u128 + (c->u128 & 1);
-#else
-ppc_avr_t tmp, sum;
-
-avr_qw_not(, *b);
-avr_qw_add(, *a, tmp);
-
-tmp.VsrD(0) = 0;
-tmp.VsrD(1) = c->VsrD(1) & 1;
-avr_qw_add(r, sum, tmp);
-#endif
+r->s128 = int128_add(int128_add(a->s128, int128_not(b->s128)),
+ int128_make64(int128_getlo(c->s128) & 1));
 }
 
 void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
@@ -2278,25 +2268,15 @@ void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b)
 #endif
 }
 
-void helper_vsubecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
+void helper_VSUBECUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 {
-#ifdef CONFIG_INT128
-r->u128 =
-(~a->u128 < ~b->u128) ||
-((c->u128 & 1) && (a->u128 + ~b->u128 == (__uint128_t)-1));
-#else
-int carry_in = c->VsrD(1) & 1;
-int carry_out = (avr_qw_cmpu(*a, *b) > 0);
-if (!carry_out && carry_in) {
-ppc_avr_t tmp;
-avr_qw_not(, *b);
-avr_qw_add(, *a, tmp);
-carry_out = ((tmp.VsrD(0) == -1ull) && (tmp.VsrD(1) == -1ull));
-}
+Int128 tmp = int128_not(b->s128);
+bool carry_out = int128_ult(int128_not(a->s128), tmp),
+ carry_in = int128_getlo(c->s128) & 1;
 
+r->VsrD(1) = carry_out || (carry_in && int128_eq(int128_add(a->s128, tmp),
+ int128_makes64(-1)));
 r->VsrD(0) = 0;
-r->VsrD(1) = carry_out;
-#endif
 }
 
 #define BCD_PLUS_PREF_1 0xC
diff --git a/target/ppc/translate/vmx-impl.c.inc 
b/target/ppc/translate/vmx-impl.c.inc
index 1e665534c3..671992f7d1 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -1235,10 +1235,6 @@ GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
 GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
 GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
 GEN_VXFORM(vsubcuq, 0, 21);
-GEN_VXFORM3(vsubeuqm, 31, 0);
-GEN_VXFORM3(vsubecuq, 31, 0);
-GEN_VXFORM_DUAL(vsubeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
-vsubecuq, PPC_NONE, PPC2_ALTIVEC_207)
 GEN_VXFORM_TRANS(vsl, 2, 7);
 GEN_VXFORM_TRANS(vsr, 2, 11);
 GEN_VXFORM_ENV(vpkuhum, 7, 0);
@@ -2568,6 +2564,9 @@ static bool do_va_helper(DisasContext *ctx, arg_VA *a,
 TRANS_FLAGS2(ALTIVEC_207, VADDECUQ, do_va_helper, gen_helper_VADDECUQ)
 TRANS_FLAGS2(ALTIVEC_207, VADDEUQM, do_va_helper, 

[PULL 07/34] ppc/pnv: remove 'INTERFACE_PCIE_DEVICE' from phb3 root bus

2022-07-06 Thread Daniel Henrique Barboza
It's unneeded. No other PCIE_BUS implements this interface.

Reviewed-by: Frederic Barrat 
Fixes: 9ae1329ee2fe ("ppc/pnv: Add models for POWER8 PHB3 PCIe Host bridge")
Signed-off-by: Daniel Henrique Barboza 
Message-Id: <20220621173436.165912-8-danielhb...@gmail.com>
---
 hw/pci-host/pnv_phb3.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index afe5698167..d58d3c1701 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -1130,10 +1130,6 @@ static const TypeInfo pnv_phb3_root_bus_info = {
 .name = TYPE_PNV_PHB3_ROOT_BUS,
 .parent = TYPE_PCIE_BUS,
 .class_init = pnv_phb3_root_bus_class_init,
-.interfaces = (InterfaceInfo[]) {
-{ INTERFACE_PCIE_DEVICE },
-{ }
-},
 };
 
 static void pnv_phb3_root_port_realize(DeviceState *dev, Error **errp)
-- 
2.36.1




[PULL 05/34] ppc/pnv: make pnv_ics_resend() use chip8->phbs[]

2022-07-06 Thread Daniel Henrique Barboza
pnv_ics_resend() is scrolling through all the child objects of the chip
to search for the PHBs. It's faster and simpler to just use the phbs[]
array.

pnv_ics_resend_child() was folded into pnv_ics_resend() since it's too
simple to justify its own function.

Reviewed-by: Cédric Le Goater 
Reviewed-by: Frederic Barrat 
Signed-off-by: Daniel Henrique Barboza 
Message-Id: <20220621173436.165912-6-danielhb...@gmail.com>
---
 hw/ppc/pnv.c | 22 --
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index e6cea789f8..74a6c88dd2 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1990,28 +1990,22 @@ PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t 
chip_id)
 return NULL;
 }
 
-static int pnv_ics_resend_child(Object *child, void *opaque)
-{
-PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
-
-if (phb3) {
-ics_resend(>lsis);
-ics_resend(ICS(>msis));
-}
-return 0;
-}
-
 static void pnv_ics_resend(XICSFabric *xi)
 {
 PnvMachineState *pnv = PNV_MACHINE(xi);
-int i;
+int i, j;
 
 for (i = 0; i < pnv->num_chips; i++) {
-PnvChip *chip = pnv->chips[i];
 Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
 
 ics_resend(>psi.ics);
-object_child_foreach(OBJECT(chip), pnv_ics_resend_child, NULL);
+
+for (j = 0; j < chip8->num_phbs; j++) {
+PnvPHB3 *phb3 = >phbs[j];
+
+ics_resend(>lsis);
+ics_resend(ICS(>msis));
+}
 }
 }
 
-- 
2.36.1




[PULL 15/34] target/ppc: use int128.h methods in vaddcuq

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

And also move the insn to decodetree.

Signed-off-by: Matheus Ferst 
Reviewed-by: Víctor Colombo 
Message-Id: <20220606150037.338931-5-matheus.fe...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/helper.h |  2 +-
 target/ppc/insn32.decode|  1 +
 target/ppc/int_helper.c | 12 ++--
 target/ppc/translate/vmx-impl.c.inc |  2 +-
 target/ppc/translate/vmx-ops.c.inc  |  1 -
 5 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index f699adbedc..f6b1b2fad2 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -207,7 +207,7 @@ DEF_HELPER_FLAGS_5(vsubuws, TCG_CALL_NO_RWG, void, avr, 
avr, avr, avr, i32)
 DEF_HELPER_FLAGS_3(VADDUQM, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_4(VADDECUQ, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_4(VADDEUQM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
-DEF_HELPER_FLAGS_3(vaddcuq, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(VADDCUQ, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_3(vsubuqm, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_4(vsubecuq, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_4(vsubeuqm, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 139aa3caeb..35252ddd4f 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -550,6 +550,7 @@ VRLQNM  000100 . . . 00101000101@VX
 
 ## Vector Integer Arithmetic Instructions
 
+VADDCUQ 000100 . . . 0010100@VX
 VADDUQM 000100 . . . 001@VX
 
 VADDEUQM000100 . . . . 00   @VA
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index ecfe413ae1..279333a814 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2225,18 +2225,10 @@ void helper_VADDEUQM(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b, ppc_avr_t *c)
  int128_make64(int128_getlo(c->s128) & 1));
 }
 
-void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
+void helper_VADDCUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-#ifdef CONFIG_INT128
-r->u128 = (~a->u128 < b->u128);
-#else
-ppc_avr_t not_a;
-
-avr_qw_not(_a, *a);
-
+r->VsrD(1) = int128_ult(int128_not(a->s128), b->s128);
 r->VsrD(0) = 0;
-r->VsrD(1) = (avr_qw_cmpu(not_a, *b) < 0);
-#endif
 }
 
 void helper_VADDECUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
diff --git a/target/ppc/translate/vmx-impl.c.inc 
b/target/ppc/translate/vmx-impl.c.inc
index 4ec6b841b3..8c0e5bcc03 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -1234,7 +1234,6 @@ GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
 GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
 GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
 GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
-GEN_VXFORM(vaddcuq, 0, 5);
 GEN_VXFORM(vsubuqm, 0, 20);
 GEN_VXFORM(vsubcuq, 0, 21);
 GEN_VXFORM3(vsubeuqm, 31, 0);
@@ -3098,6 +3097,7 @@ static bool do_vx_helper(DisasContext *ctx, arg_VX *a,
 return true;
 }
 
+TRANS_FLAGS2(ALTIVEC_207, VADDCUQ, do_vx_helper, gen_helper_VADDCUQ)
 TRANS_FLAGS2(ALTIVEC_207, VADDUQM, do_vx_helper, gen_helper_VADDUQM)
 
 TRANS_FLAGS2(ALTIVEC_207, VPMSUMD, do_vx_helper, gen_helper_VPMSUMD)
diff --git a/target/ppc/translate/vmx-ops.c.inc 
b/target/ppc/translate/vmx-ops.c.inc
index f8a512f920..33e05929cb 100644
--- a/target/ppc/translate/vmx-ops.c.inc
+++ b/target/ppc/translate/vmx-ops.c.inc
@@ -126,7 +126,6 @@ GEN_VXFORM(vsubuws, 0, 26),
 GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_ALTIVEC, PPC2_ISA300),
 GEN_VXFORM(vsubshs, 0, 29),
 GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_207(vaddcuq, 0, 5),
 GEN_VXFORM_DUAL(vsubuqm, bcdtrunc, 0, 20, PPC2_ALTIVEC_207, PPC2_ISA300),
 GEN_VXFORM_DUAL(vsubcuq, bcdutrunc, 0, 21, PPC2_ALTIVEC_207, PPC2_ISA300),
 GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
-- 
2.36.1




[PULL 14/34] target/ppc: use int128.h methods in vaddecuq and vaddeuqm

2022-07-06 Thread Daniel Henrique Barboza
From: Matheus Ferst 

And also move the insns to decodetree and remove the now unused
avr_qw_addc method.

Signed-off-by: Matheus Ferst 
Reviewed-by: Víctor Colombo 
Message-Id: <20220606150037.338931-4-matheus.fe...@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/helper.h |  4 +--
 target/ppc/insn32.decode|  3 ++
 target/ppc/int_helper.c | 53 +
 target/ppc/translate/vmx-impl.c.inc |  7 ++--
 target/ppc/translate/vmx-ops.c.inc  |  1 -
 5 files changed, 17 insertions(+), 51 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index c6fbe4b6da..f699adbedc 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -205,8 +205,8 @@ DEF_HELPER_FLAGS_5(vsububs, TCG_CALL_NO_RWG, void, avr, 
avr, avr, avr, i32)
 DEF_HELPER_FLAGS_5(vsubuhs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
 DEF_HELPER_FLAGS_5(vsubuws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
 DEF_HELPER_FLAGS_3(VADDUQM, TCG_CALL_NO_RWG, void, avr, avr, avr)
-DEF_HELPER_FLAGS_4(vaddecuq, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
-DEF_HELPER_FLAGS_4(vaddeuqm, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(VADDECUQ, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(VADDEUQM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
 DEF_HELPER_FLAGS_3(vaddcuq, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_3(vsubuqm, TCG_CALL_NO_RWG, void, avr, avr, avr)
 DEF_HELPER_FLAGS_4(vsubecuq, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index d6bfc2c768..139aa3caeb 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -552,6 +552,9 @@ VRLQNM  000100 . . . 00101000101@VX
 
 VADDUQM 000100 . . . 001@VX
 
+VADDEUQM000100 . . . . 00   @VA
+VADDECUQ000100 . . . . 01   @VA
+
 VEXTSB2W000100 . 1 . 1100010@VX_tb
 VEXTSH2W000100 . 10001 . 1100010@VX_tb
 VEXTSB2D000100 . 11000 . 1100010@VX_tb
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 7de69f00b5..ecfe413ae1 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2212,16 +2212,6 @@ static void avr_qw_add(ppc_avr_t *t, ppc_avr_t a, 
ppc_avr_t b)
  (~a.VsrD(1) < b.VsrD(1));
 }
 
-static int avr_qw_addc(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b)
-{
-ppc_avr_t not_a;
-t->VsrD(1) = a.VsrD(1) + b.VsrD(1);
-t->VsrD(0) = a.VsrD(0) + b.VsrD(0) +
- (~a.VsrD(1) < b.VsrD(1));
-avr_qw_not(_a, a);
-return avr_qw_cmpu(not_a, b) < 0;
-}
-
 #endif
 
 void helper_VADDUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
@@ -2229,23 +2219,10 @@ void helper_VADDUQM(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b)
 r->s128 = int128_add(a->s128, b->s128);
 }
 
-void helper_vaddeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
+void helper_VADDEUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 {
-#ifdef CONFIG_INT128
-r->u128 = a->u128 + b->u128 + (c->u128 & 1);
-#else
-
-if (c->VsrD(1) & 1) {
-ppc_avr_t tmp;
-
-tmp.VsrD(0) = 0;
-tmp.VsrD(1) = c->VsrD(1) & 1;
-avr_qw_add(, *a, tmp);
-avr_qw_add(r, tmp, *b);
-} else {
-avr_qw_add(r, *a, *b);
-}
-#endif
+r->s128 = int128_add(int128_add(a->s128, b->s128),
+ int128_make64(int128_getlo(c->s128) & 1));
 }
 
 void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
@@ -2262,30 +2239,18 @@ void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b)
 #endif
 }
 
-void helper_vaddecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
+void helper_VADDECUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 {
-#ifdef CONFIG_INT128
-int carry_out = (~a->u128 < b->u128);
-if (!carry_out && (c->u128 & 1)) {
-carry_out = ((a->u128 + b->u128 + 1) == 0) &&
-((a->u128 != 0) || (b->u128 != 0));
-}
-r->u128 = carry_out;
-#else
-
-int carry_in = c->VsrD(1) & 1;
-int carry_out = 0;
-ppc_avr_t tmp;
-
-carry_out = avr_qw_addc(, *a, *b);
+bool carry_out = int128_ult(int128_not(a->s128), b->s128),
+ carry_in = int128_getlo(c->s128) & 1;
 
 if (!carry_out && carry_in) {
-ppc_avr_t one = QW_ONE;
-carry_out = avr_qw_addc(, tmp, one);
+carry_out = (int128_nz(a->s128) || int128_nz(b->s128)) &&
+int128_eq(int128_add(a->s128, b->s128), 
int128_makes64(-1));
 }
+
 r->VsrD(0) = 0;
 r->VsrD(1) = carry_out;
-#endif
 }
 
 void helper_vsubuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
diff --git a/target/ppc/translate/vmx-impl.c.inc 
b/target/ppc/translate/vmx-impl.c.inc
index 3fb48404d9..4ec6b841b3 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ 

[PULL 03/34] ppc/pnv: assign pnv-phb-root-port chassis/slot earlier

2022-07-06 Thread Daniel Henrique Barboza
It is not advisable to execute an object_dynamic_cast() to poke into
bus->qbus.parent and follow it up with a C cast into the PnvPHB type we
think we got.

In fact this is not needed. There is nothing sophisticated being done
with the PHB object retrieved during root_port_realize() for both PHB3
and PHB4. We're retrieving a PHB reference just to access phb->chip_id
and phb->phb_id and use them to define the chassis/slot of the root
port.

phb->phb_id is already being passed to pnv_phb_attach_root_port() via
the 'index' parameter. Let's also add a 'chip_id' parameter to this
function and assign chassis and slot right there. This will spare us
from the hassle of accessing the PHB object inside realize().

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Frederic Barrat 
Message-Id: <20220621173436.165912-4-danielhb...@gmail.com>
---
 hw/pci-host/pnv_phb3.c | 18 ++
 hw/pci-host/pnv_phb4.c | 18 ++
 hw/ppc/pnv.c   | 15 +--
 include/hw/ppc/pnv.h   |  3 ++-
 4 files changed, 19 insertions(+), 35 deletions(-)

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index 4ba660f8b9..afe5698167 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -1052,7 +1052,8 @@ static void pnv_phb3_realize(DeviceState *dev, Error 
**errp)
 
 pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb);
 
-pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT, phb->phb_id);
+pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT,
+ phb->phb_id, phb->chip_id);
 }
 
 void pnv_phb3_update_regions(PnvPHB3 *phb)
@@ -1139,23 +1140,8 @@ static void pnv_phb3_root_port_realize(DeviceState *dev, 
Error **errp)
 {
 PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
 PCIDevice *pci = PCI_DEVICE(dev);
-PCIBus *bus = pci_get_bus(pci);
-PnvPHB3 *phb = NULL;
 Error *local_err = NULL;
 
-phb = (PnvPHB3 *) object_dynamic_cast(OBJECT(bus->qbus.parent),
-  TYPE_PNV_PHB3);
-
-if (!phb) {
-error_setg(errp,
-"pnv_phb3_root_port devices must be connected to pnv-phb3 buses");
-return;
-}
-
-/* Set unique chassis/slot values for the root port */
-qdev_prop_set_uint8(>qdev, "chassis", phb->chip_id);
-qdev_prop_set_uint16(>qdev, "slot", phb->phb_id);
-
 rpc->parent_realize(dev, _err);
 if (local_err) {
 error_propagate(errp, local_err);
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index ffd9d8a947..725b3d740b 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1585,7 +1585,8 @@ static void pnv_phb4_realize(DeviceState *dev, Error 
**errp)
 pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
 
 /* Add a single Root port if running with defaults */
-pnv_phb_attach_root_port(pci, pecc->rp_model, phb->phb_id);
+pnv_phb_attach_root_port(pci, pecc->rp_model,
+ phb->phb_id, phb->chip_id);
 
 /* Setup XIVE Source */
 if (phb->big_phb) {
@@ -1781,23 +1782,8 @@ static void pnv_phb4_root_port_reset(DeviceState *dev)
 static void pnv_phb4_root_port_realize(DeviceState *dev, Error **errp)
 {
 PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
-PCIDevice *pci = PCI_DEVICE(dev);
-PCIBus *bus = pci_get_bus(pci);
-PnvPHB4 *phb = NULL;
 Error *local_err = NULL;
 
-phb = (PnvPHB4 *) object_dynamic_cast(OBJECT(bus->qbus.parent),
-  TYPE_PNV_PHB4);
-
-if (!phb) {
-error_setg(errp, "%s must be connected to pnv-phb4 buses", dev->id);
-return;
-}
-
-/* Set unique chassis/slot values for the root port */
-qdev_prop_set_uint8(>qdev, "chassis", phb->chip_id);
-qdev_prop_set_uint16(>qdev, "slot", phb->phb_id);
-
 rpc->parent_realize(dev, _err);
 if (local_err) {
 error_propagate(errp, local_err);
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 40e0cbd84d..c5e63bede7 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1189,8 +1189,15 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error 
**errp)
 }
 }
 
-/* Attach a root port device */
-void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, int index)
+/*
+ * Attach a root port device.
+ *
+ * 'index' will be used both as a PCIE slot value and to calculate
+ * QOM id. 'chip_id' is going to be used as PCIE chassis for the
+ * root port.
+ */
+void pnv_phb_attach_root_port(PCIHostState *pci, const char *name,
+  int index, int chip_id)
 {
 PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name);
 g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index);
@@ -1199,6 +1206,10 @@ void pnv_phb_attach_root_port(PCIHostState *pci, const 
char *name, int index)
 object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
   OBJECT(root));
 
+/* Set unique chassis/slot values for the 

[PULL 01/34] ppc/pnv: move root port attach to pnv_phb4_realize()

2022-07-06 Thread Daniel Henrique Barboza
Creating a root port is something related to the PHB, not the PEC. It
also makes the logic more in line with what pnv-phb3 does.

Reviewed-by: Frederic Barrat 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Daniel Henrique Barboza 
Message-Id: <20220621173436.165912-2-danielhb...@gmail.com>
---
 hw/pci-host/pnv_phb4.c | 4 
 hw/pci-host/pnv_phb4_pec.c | 3 ---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 6594016121..23ad8de7ee 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1547,6 +1547,7 @@ static void pnv_phb4_instance_init(Object *obj)
 static void pnv_phb4_realize(DeviceState *dev, Error **errp)
 {
 PnvPHB4 *phb = PNV_PHB4(dev);
+PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec);
 PCIHostState *pci = PCI_HOST_BRIDGE(dev);
 XiveSource *xsrc = >xsrc;
 int nr_irqs;
@@ -1583,6 +1584,9 @@ static void pnv_phb4_realize(DeviceState *dev, Error 
**errp)
 pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb);
 pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
 
+/* Add a single Root port if running with defaults */
+pnv_phb_attach_root_port(pci, pecc->rp_model);
+
 /* Setup XIVE Source */
 if (phb->big_phb) {
 nr_irqs = PNV_PHB4_MAX_INTs;
diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 8b7e823fa5..c9aaf1c28e 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -130,9 +130,6 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState 
*pec,
 if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
 return;
 }
-
-/* Add a single Root port if running with defaults */
-pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), pecc->rp_model);
 }
 
 static void pnv_pec_realize(DeviceState *dev, Error **errp)
-- 
2.36.1




[PULL 09/34] target/ppc: Change FPSCR_* to follow POWER ISA numbering convention

2022-07-06 Thread Daniel Henrique Barboza
From: Víctor Colombo 

FPSCR_* bit values in QEMU are in the 'inverted' order from what Power
ISA defines (e.g. FPSCR.FI is bit 46 but is defined as 17 in cpu.h).
Now that PPC_BIT_NR macro was introduced to fix this situation for the
MSR bits, we can use it for the FPSCR bits too.

Also, adjust the comments to make then fit in 80 columns

Signed-off-by: Víctor Colombo 
Reviewed-by: Fabiano Rosas 
Message-Id: <20220622193203.127698-1-victor.colo...@eldorado.org.br>
[danielhb: fixed 'exceptio' typo in target/ppc/cpu.h]
Signed-off-by: Daniel Henrique Barboza 
---
 target/ppc/cpu.h | 72 
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 6d78078f37..e109b5902b 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -694,42 +694,42 @@ enum {
 
 /*/
 /* Floating point status and control register*/
-#define FPSCR_DRN2   34 /* Decimal Floating-Point rounding control   */
-#define FPSCR_DRN1   33 /* Decimal Floating-Point rounding control   */
-#define FPSCR_DRN0   32 /* Decimal Floating-Point rounding control   */
-#define FPSCR_FX 31 /* Floating-point exception summary  */
-#define FPSCR_FEX30 /* Floating-point enabled exception summary  */
-#define FPSCR_VX 29 /* Floating-point invalid operation exception summ.  */
-#define FPSCR_OX 28 /* Floating-point overflow exception */
-#define FPSCR_UX 27 /* Floating-point underflow exception*/
-#define FPSCR_ZX 26 /* Floating-point zero divide exception  */
-#define FPSCR_XX 25 /* Floating-point inexact exception  */
-#define FPSCR_VXSNAN 24 /* Floating-point invalid operation exception (sNan) */
-#define FPSCR_VXISI  23 /* Floating-point invalid operation exception (inf)  */
-#define FPSCR_VXIDI  22 /* Floating-point invalid operation exception (inf)  */
-#define FPSCR_VXZDZ  21 /* Floating-point invalid operation exception (zero) */
-#define FPSCR_VXIMZ  20 /* Floating-point invalid operation exception (inf)  */
-#define FPSCR_VXVC   19 /* Floating-point invalid operation exception (comp) */
-#define FPSCR_FR 18 /* Floating-point fraction rounded   */
-#define FPSCR_FI 17 /* Floating-point fraction inexact   */
-#define FPSCR_C  16 /* Floating-point result class descriptor*/
-#define FPSCR_FL 15 /* Floating-point less than or negative  */
-#define FPSCR_FG 14 /* Floating-point greater than or negative   */
-#define FPSCR_FE 13 /* Floating-point equal or zero  */
-#define FPSCR_FU 12 /* Floating-point unordered or NaN   */
-#define FPSCR_FPCC   12 /* Floating-point condition code */
-#define FPSCR_FPRF   12 /* Floating-point result flags   */
-#define FPSCR_VXSOFT 10 /* Floating-point invalid operation exception (soft) */
-#define FPSCR_VXSQRT 9  /* Floating-point invalid operation exception (sqrt) */
-#define FPSCR_VXCVI  8  /* Floating-point invalid operation exception (int)  */
-#define FPSCR_VE 7  /* Floating-point invalid operation exception enable */
-#define FPSCR_OE 6  /* Floating-point overflow exception enable  */
-#define FPSCR_UE 5  /* Floating-point underflow exception enable  
*/
-#define FPSCR_ZE 4  /* Floating-point zero divide exception enable   */
-#define FPSCR_XE 3  /* Floating-point inexact exception enable   */
-#define FPSCR_NI 2  /* Floating-point non-IEEE mode  */
-#define FPSCR_RN11
-#define FPSCR_RN00  /* Floating-point rounding control   */
+#define FPSCR_DRN2   PPC_BIT_NR(29) /* Decimal Floating-Point rounding ctrl. */
+#define FPSCR_DRN1   PPC_BIT_NR(30) /* Decimal Floating-Point rounding ctrl. */
+#define FPSCR_DRN0   PPC_BIT_NR(31) /* Decimal Floating-Point rounding ctrl. */
+#define FPSCR_FX PPC_BIT_NR(32) /* Floating-point exception summary  */
+#define FPSCR_FEXPPC_BIT_NR(33) /* Floating-point enabled exception summ.*/
+#define FPSCR_VX PPC_BIT_NR(34) /* Floating-point invalid op. excp. summ.*/
+#define FPSCR_OX PPC_BIT_NR(35) /* Floating-point overflow exception */
+#define FPSCR_UX PPC_BIT_NR(36) /* Floating-point underflow exception*/
+#define FPSCR_ZX PPC_BIT_NR(37) /* Floating-point zero divide exception  */
+#define FPSCR_XX PPC_BIT_NR(38) /* Floating-point inexact exception  */
+#define FPSCR_VXSNAN PPC_BIT_NR(39) /* Floating-point invalid op. excp (sNan)*/
+#define FPSCR_VXISI  PPC_BIT_NR(40) /* Floating-point invalid op. excp (inf) */
+#define FPSCR_VXIDI  PPC_BIT_NR(41) /* Floating-point invalid op. excp (inf) */
+#define FPSCR_VXZDZ  PPC_BIT_NR(42) /* Floating-point invalid op. 

[PULL 06/34] ppc/pnv: make pnv_chip_power8_pic_print_info() use chip8->phbs[]

2022-07-06 Thread Daniel Henrique Barboza
It's inneficient to scroll all child objects when we have all PHBs
available in chip8->phbs[].

pnv_chip_power8_pic_print_info_child() ended up folded into
pic_print_info() for simplicity.

Reviewed-by: Frederic Barrat 
Signed-off-by: Daniel Henrique Barboza 
Message-Id: <20220621173436.165912-7-danielhb...@gmail.com>
---
 hw/ppc/pnv.c | 22 --
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 74a6c88dd2..d3f77c8367 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -652,25 +652,19 @@ static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
 return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
 }
 
-static int pnv_chip_power8_pic_print_info_child(Object *child, void *opaque)
-{
-Monitor *mon = opaque;
-PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
-
-if (phb3) {
-pnv_phb3_msi_pic_print_info(>msis, mon);
-ics_pic_print_info(>lsis, mon);
-}
-return 0;
-}
-
 static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
 {
 Pnv8Chip *chip8 = PNV8_CHIP(chip);
+int i;
 
 ics_pic_print_info(>psi.ics, mon);
-object_child_foreach(OBJECT(chip),
- pnv_chip_power8_pic_print_info_child, mon);
+
+for (i = 0; i < chip8->num_phbs; i++) {
+PnvPHB3 *phb3 = >phbs[i];
+
+pnv_phb3_msi_pic_print_info(>msis, mon);
+ics_pic_print_info(>lsis, mon);
+}
 }
 
 static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
-- 
2.36.1




[PULL 02/34] ppc/pnv: attach phb3/phb4 root ports in QOM tree

2022-07-06 Thread Daniel Henrique Barboza
At this moment we leave the pnv-phb3(4)-root-port unattached in QOM:

  /unattached (container)
(...)
/device[2] (pnv-phb3-root-port)
  /bus master container[0] (memory-region)
  /bus master[0] (memory-region)
  /pci_bridge_io[0] (memory-region)
  /pci_bridge_io[1] (memory-region)
  /pci_bridge_mem[0] (memory-region)
  /pci_bridge_pci[0] (memory-region)
  /pci_bridge_pref_mem[0] (memory-region)
  /pci_bridge_vga_io_hi[0] (memory-region)
  /pci_bridge_vga_io_lo[0] (memory-region)
  /pci_bridge_vga_mem[0] (memory-region)
  /pcie.0 (PCIE)

Let's make changes in pnv_phb_attach_root_port() to attach the created
root ports to its corresponding PHB.

This is the result afterwards:

/pnv-phb3[0] (pnv-phb3)
  /lsi (ics)
  /msi (phb3-msi)
  /msi32[0] (memory-region)
  /msi64[0] (memory-region)
  /pbcq (pnv-pbcq)
(...)
  /phb3_iommu[0] (pnv-phb3-iommu-memory-region)
  /pnv-phb3-root.0 (pnv-phb3-root)
/pnv-phb3-root-port[0] (pnv-phb3-root-port)
  /bus master container[0] (memory-region)
  /bus master[0] (memory-region)
  /pci_bridge_io[0] (memory-region)
  /pci_bridge_io[1] (memory-region)
  /pci_bridge_mem[0] (memory-region)
  /pci_bridge_pci[0] (memory-region)
  /pci_bridge_pref_mem[0] (memory-region)
  /pci_bridge_vga_io_hi[0] (memory-region)
  /pci_bridge_vga_io_lo[0] (memory-region)
  /pci_bridge_vga_mem[0] (memory-region)
  /pcie.0 (PCIE)

Reviewed-by: Frederic Barrat 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Daniel Henrique Barboza 
Message-Id: <20220621173436.165912-3-danielhb...@gmail.com>
---
 hw/pci-host/pnv_phb3.c | 2 +-
 hw/pci-host/pnv_phb4.c | 2 +-
 hw/ppc/pnv.c   | 7 ++-
 include/hw/ppc/pnv.h   | 2 +-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index 26ac9b7123..4ba660f8b9 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -1052,7 +1052,7 @@ static void pnv_phb3_realize(DeviceState *dev, Error 
**errp)
 
 pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb);
 
-pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), TYPE_PNV_PHB3_ROOT_PORT);
+pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT, phb->phb_id);
 }
 
 void pnv_phb3_update_regions(PnvPHB3 *phb)
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 23ad8de7ee..ffd9d8a947 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1585,7 +1585,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error 
**errp)
 pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
 
 /* Add a single Root port if running with defaults */
-pnv_phb_attach_root_port(pci, pecc->rp_model);
+pnv_phb_attach_root_port(pci, pecc->rp_model, phb->phb_id);
 
 /* Setup XIVE Source */
 if (phb->big_phb) {
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 7c08a78d6c..40e0cbd84d 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1190,9 +1190,14 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error 
**errp)
 }
 
 /* Attach a root port device */
-void pnv_phb_attach_root_port(PCIHostState *pci, const char *name)
+void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, int index)
 {
 PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name);
+g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index);
+const char *dev_id = DEVICE(root)->id;
+
+object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
+  OBJECT(root));
 
 pci_realize_and_unref(root, pci->bus, _fatal);
 }
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 86cb7d7f97..033890a23f 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -189,7 +189,7 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10,
  TYPE_PNV_CHIP_POWER10)
 
 PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);
-void pnv_phb_attach_root_port(PCIHostState *pci, const char *name);
+void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, int index);
 
 #define TYPE_PNV_MACHINE   MACHINE_TYPE_NAME("powernv")
 typedef struct PnvMachineClass PnvMachineClass;
-- 
2.36.1




  1   2   3   4   >