Re: [PATCH] hw/riscv: boot: Reduce FDT address alignment constraints

2022-06-27 Thread Atish Patra
On Tue, Jun 7, 2022 at 11:21 PM Alistair Francis
 wrote:
>
> From: Alistair Francis 
>
> We previously stored the device tree at a 16MB alignment from the end of
> memory (or 3GB). This means we need at least 16MB of memory to be able
> to do this. We don't actually need the FDT to be 16MB aligned, so let's
> drop it down to 2MB so that we can support systems with less memory,
> while also allowing FDT size expansion.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/992
> Signed-off-by: Alistair Francis 
> ---
>  hw/riscv/boot.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 57a41df8e9..e476d8f491 100644
> --- a/hw/riscv/boot.c
> +++ b/hw/riscv/boot.c
> @@ -226,11 +226,11 @@ uint64_t riscv_load_fdt(hwaddr dram_base, uint64_t 
> mem_size, void *fdt)
>  /*
>   * We should put fdt as far as possible to avoid kernel/initrd 
> overwriting
>   * its content. But it should be addressable by 32 bit system as well.
> - * Thus, put it at an 16MB aligned address that less than fdt size from 
> the
> + * Thus, put it at an 2MB aligned address that less than fdt size from 
> the
>   * end of dram or 3GB whichever is lesser.
>   */
>  temp = (dram_base < 3072 * MiB) ? MIN(dram_end, 3072 * MiB) : dram_end;
> -fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 16 * MiB);
> +fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB);
>
>  ret = fdt_pack(fdt);
>  /* Should only fail if we've built a corrupted tree */
> --
> 2.36.1
>
>

Reviewed-by: Atish Patra 

-- 
Regards,
Atish



Re: [RFC PATCH v2 0/8] qapi: add generator for Golang interface

2022-06-27 Thread Markus Armbruster
Victor Toso  writes:

> Hi,
>
> This is the second iteration of RFC v1:
>   https://lists.gnu.org/archive/html/qemu-devel/2022-04/msg00226.html
>
>
> # What this is about?
>
> To generate a simple Golang interface that could communicate with QEMU
> over QMP. The Go code that is generated is meant to be used as the bare
> bones to exchange QMP messages.
>
> The goal is to have this as a Go module in QEMU gitlab namespace,
> similar to what have been done to pyhon-qemu-qmp
>   https://gitlab.com/qemu-project/python-qemu-qmp

Aspects of review:

(1) Impact on common code, if any

I care, because any messes made there are likely to affect me down
the road.

(2) The generated Go code

Is it (close to) what we want long term?  If not, is it good enough
short term, and how could we make necessary improvements?

I'd prefer to leave this to folks who actually know their Go.

(3) General Python sanity

We need eyes, but not necessarily mine.  Any takers?

[...]

>  scripts/qapi/golang.py | 765 +
>  scripts/qapi/main.py   |   2 +
>  2 files changed, 767 insertions(+)
>  create mode 100644 scripts/qapi/golang.py

This adds a new generator and calls it from generate(), i.e. review
aspect (1) is empty.  "Empty" is a quick & easy way to get my ACK!

No tests?

No documentation?




[RFC PATCH 01/10] hw/ide/piix: Check for presence of ISABus before using it

2022-06-27 Thread Bernhard Beschow
This is an alternative solution to commit
9405d87be25db6dff4d7b5ab48a81bbf6d083e47 'hw/ide: Fix crash when plugging a
piix3-ide device into the x-remote machine' which allows for cleaning up the
ISA API while keeping PIIX IDE functions user-createable for an arbitrarily
long deprecation period.

Signed-off-by: Bernhard Beschow 
---
 hw/ide/piix.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 9a9b28078e..e8f3abc4b5 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -136,6 +136,17 @@ static int pci_piix_init_ports(PCIIDEState *d)
 };
 int i, ret;
 
+{
+ISABus *isa_bus;
+bool ambiguous;
+
+isa_bus = ISA_BUS(object_resolve_path_type("", TYPE_ISA_BUS,
+   &ambiguous));
+if (!isa_bus || ambiguous) {
+return -ENODEV;
+}
+}
+
 for (i = 0; i < 2; i++) {
 ide_bus_init(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
 ret = ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
-- 
2.36.1




[RFC PATCH 04/10] hw/ide/piix: Avoid the isabus global when wiring ISA interrupts for internal devices

2022-06-27 Thread Bernhard Beschow
isa_get_irq() currently always uses the "isabus" global to get the
desired qemu_irq. In order to resolve this global, we want
isa_get_irq() to determine the ISABus from its *dev parameter using
isa_bus_from_device(). As a preparation, all callers who pass NULL
as *dev need to be resolved which seems to happen in hw/ide/piix only.

This patch roughly implements the solution outlined in https://
lists.nongnu.org/archive/html/qemu-devel/2020-03/msg01707.html.

In oder to address the PIIX IDE functions being user-creatable, (see
https://lists.nongnu.org/archive/html/qemu-devel/2021-04/msg05655.html) a
backwards compatibility quirk is introduced which can be removed after some
deprecation period. The quirk consists of internal devices to opt into new
behavior where the ISA interrupt wiring is performed by the caller rather
than by the device itself. The opt-in can be performed by:

qdev_prop_set_bit(DEVICE(dev), "user-created", false);

RFC: qdev_init_gpio_in() seems to expose interrupts internal to the device.
Can this be fixed?

Signed-off-by: Bernhard Beschow 
---
 hw/i386/pc_piix.c|  3 +++
 hw/ide/piix.c| 41 +++--
 hw/isa/piix4.c   |  3 +++
 include/hw/ide/pci.h |  2 ++
 4 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 2d146b19c0..e24fbab334 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -253,8 +253,11 @@ static void pc_init1(MachineState *machine,
 PCIDevice *dev;
 
 dev = pci_new_multifunction(piix3_devfn + 1, false, "piix3-ide");
+qdev_prop_set_bit(DEVICE(dev), "user-created", false);
 pci_realize_and_unref(dev, pci_bus, &error_fatal);
 pci_ide_create_devs(dev);
+qdev_connect_gpio_out(DEVICE(dev), 0, x86ms->gsi[14]);
+qdev_connect_gpio_out(DEVICE(dev), 1, x86ms->gsi[15]);
 idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
 idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
 pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 21777ecc8b..fbf2756b47 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -103,6 +103,13 @@ static void bmdma_setup_bar(PCIIDEState *d)
 }
 }
 
+static void piix_ide_set_irq(void *opaque, int n, int level)
+{
+PCIIDEState *d = opaque;
+
+qemu_set_irq(d->isa_irqs[n], level);
+}
+
 static void piix_ide_reset(DeviceState *dev)
 {
 PCIIDEState *d = PCI_IDE(dev);
@@ -129,14 +136,14 @@ static int pci_piix_init_ports(PCIIDEState *d)
 static const struct {
 int iobase;
 int iobase2;
-int isairq;
 } port_info[] = {
-{0x1f0, 0x3f6, 14},
-{0x170, 0x376, 15},
+{0x1f0, 0x3f6},
+{0x170, 0x376},
 };
+DeviceState *dev = DEVICE(d);
 int i;
 
-{
+if (d->user_created) {
 ISABus *isa_bus;
 bool ambiguous;
 
@@ -145,13 +152,18 @@ static int pci_piix_init_ports(PCIIDEState *d)
 if (!isa_bus || ambiguous) {
 return -ENODEV;
 }
+
+d->isa_irqs[0] = isa_bus->irqs[14];
+d->isa_irqs[1] = isa_bus->irqs[15];
+} else {
+qdev_init_gpio_out(dev, d->isa_irqs, 2);
 }
 
 for (i = 0; i < 2; i++) {
-ide_bus_init(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
+ide_bus_init(&d->bus[i], sizeof(d->bus[i]), dev, i, 2);
 ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
 port_info[i].iobase2);
-ide_init2(&d->bus[i], isa_get_irq(NULL, port_info[i].isairq));
+ide_init2(&d->bus[i], qdev_get_gpio_in(dev, i));
 
 bmdma_init(&d->bus[i], &d->bmdma[i], d);
 d->bmdma[i].bus = &d->bus[i];
@@ -181,6 +193,14 @@ static void pci_piix_ide_realize(PCIDevice *dev, Error 
**errp)
 }
 }
 
+static void pci_piix_ide_init(Object *obj)
+{
+PCIIDEState *d = PCI_IDE(obj);
+DeviceState *dev = DEVICE(d);
+
+qdev_init_gpio_in(dev, piix_ide_set_irq, 2);
+}
+
 static void pci_piix_ide_exitfn(PCIDevice *dev)
 {
 PCIIDEState *d = PCI_IDE(dev);
@@ -192,6 +212,11 @@ static void pci_piix_ide_exitfn(PCIDevice *dev)
 }
 }
 
+static Property piix_ide_properties[] = {
+DEFINE_PROP_BOOL("user-created", PCIIDEState, user_created, true),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
 static void piix3_ide_class_init(ObjectClass *klass, void *data)
 {
@@ -206,11 +231,13 @@ static void piix3_ide_class_init(ObjectClass *klass, void 
*data)
 k->class_id = PCI_CLASS_STORAGE_IDE;
 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 dc->hotpluggable = false;
+device_class_set_props(dc, piix_ide_properties);
 }
 
 static const TypeInfo piix3_ide_info = {
 .name  = "piix3-ide",
 .parent= TYPE_PCI_IDE,
+.instance_init = pci_piix_ide_init,
 .class_init= piix3_ide_class_init,
 };
 
@@ -228,11 +255,13 @@ static void piix4_ide_class_

[RFC PATCH 06/10] hw/ide/ioport: Rename ide_init_ioport() to isa_ide_init_ioport()

2022-06-27 Thread Bernhard Beschow
ide_init_ioport() takes an ISADevice* parameter which eventually gets passed
to isa_address_space_io(). Unfortunately, there is no ISADevice in hw/ide/
piix, so NULL gets passed instead. This causes isa_address_space_io() to
resort to using the isabus global - which we want to get rid of.

To resolve this, observe that hw/isa/piix* models pass PCI's IO address
space to ISA which can be used instead. The next patch therefore introduces
pci_ide_init_ioport() which takes a PCIDevice* parameter instead and is
available in hw/ide/piix.

Signed-off-by: Bernhard Beschow 
---
 hw/ide/ioport.c   | 2 +-
 hw/ide/isa.c  | 2 +-
 hw/ide/piix.c | 4 ++--
 include/hw/ide/internal.h | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/hw/ide/ioport.c b/hw/ide/ioport.c
index b613ff3bba..ed1f34f573 100644
--- a/hw/ide/ioport.c
+++ b/hw/ide/ioport.c
@@ -50,7 +50,7 @@ static const MemoryRegionPortio ide_portio2_list[] = {
 PORTIO_END_OF_LIST(),
 };
 
-void ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
+void isa_ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
 {
 /* ??? Assume only ISA and PCI configurations, and that the PCI-ISA
bridge has been setup properly to always register with ISA.  */
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 8bedbd13f1..79ed33aefa 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -74,7 +74,7 @@ static void isa_ide_realizefn(DeviceState *dev, Error **errp)
 ISAIDEState *s = ISA_IDE(dev);
 
 ide_bus_init(&s->bus, sizeof(s->bus), dev, 0, 2);
-ide_init_ioport(&s->bus, isadev, s->iobase, s->iobase2);
+isa_ide_init_ioport(&s->bus, isadev, s->iobase, s->iobase2);
 s->irq = isa_get_irq(isadev, s->isairq);
 ide_init2(&s->bus, s->irq);
 vmstate_register(VMSTATE_IF(dev), 0, &vmstate_ide_isa, s);
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index fbf2756b47..312611c61f 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -161,8 +161,8 @@ static int pci_piix_init_ports(PCIIDEState *d)
 
 for (i = 0; i < 2; i++) {
 ide_bus_init(&d->bus[i], sizeof(d->bus[i]), dev, i, 2);
-ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
-port_info[i].iobase2);
+isa_ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
+port_info[i].iobase2);
 ide_init2(&d->bus[i], qdev_get_gpio_in(dev, i));
 
 bmdma_init(&d->bus[i], &d->bmdma[i], d);
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index 348e7f2510..86ecc04ce4 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -624,7 +624,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, 
IDEDriveKind kind,
int chs_trans, Error **errp);
 void ide_init2(IDEBus *bus, qemu_irq irq);
 void ide_exit(IDEState *s);
-void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
+void isa_ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
 void ide_register_restart_cb(IDEBus *bus);
 
 void ide_exec_cmd(IDEBus *bus, uint32_t val);
-- 
2.36.1




[RFC PATCH 00/10] Resolve isabus global

2022-06-27 Thread Bernhard Beschow
This series resolves the global "isabus" variable and is basically a v2 of [1].
Note that the majority of the work consists of fixing ISA API calls in PIIX IDE
which implicitly rely on the usage of the isabus global.

Rather than adding an ISABus pointer in PCIIDEState as in "v1" this series uses
a qemu_irq array which is roughly the approach outlined in [2]. Moreover, this
series considers backwards compatibility for user-created PIIX IDE
"Frankensten" devices by using a temporary hack. This hack can be removed again
once a deprecation period of user-createable PIIX IDE devices is over. This
deprecation wasn't announced yet but now might be a good time.

Testing done:
* `./qemu-system-x86_64 -M x-remote -device piix3-ide` still fails gracefully 
with
`qemu-system-x86_64: -device piix3-ide: Failed to realize piix3-ide: No such 
device`
* `make check-avocado` doesn't report errors
* Booting a live image with `./qemu-system-x86_64 -M pc` works
* Booting a MIPS Malta machine [3] works

[1] https://patchew.org/QEMU/20210518215545.1793947-1-phi...@redhat.com/
[2] https://lists.nongnu.org/archive/html/qemu-devel/2020-03/msg01707.html
[3] https://people.debian.org/~aurel32/qemu/mips/

Bernhard Beschow (10):
  hw/ide/piix: Check for presence of ISABus before using it
  Revert "hw/ide: Fix crash when plugging a piix3-ide device into the
x-remote machine"
  hw/i386/pc_piix: Allow for setting properties on "piix3-ide" before
realizing it
  hw/ide/piix: Avoid the isabus global when wiring ISA interrupts for
internal devices
  hw/isa/isa-bus: assert() if isa_get_irq() gets passed a NULL ISADevice
  hw/ide/ioport: Rename ide_init_ioport() to isa_ide_init_ioport()
  hw/pci/pci: Introduce pci_register_portio_list()
  hw/ide/piix: Use pci_ide_init_ioport() rather than
isa_ide_init_ioport()
  hw/isa: Resolve unneeded usage of isabus global
  hw/isa/isa-bus: Resolve isabus global

 hw/i386/pc_piix.c |  6 +++-
 hw/ide/ioport.c   | 30 +---
 hw/ide/isa.c  |  2 +-
 hw/ide/piix.c | 59 +++
 hw/isa/isa-bus.c  | 46 ++
 hw/isa/piix4.c|  3 ++
 hw/pci/pci.c  | 18 
 include/hw/ide/internal.h |  3 +-
 include/hw/ide/pci.h  |  2 ++
 include/hw/isa/isa.h  | 15 --
 include/hw/pci/pci.h  | 21 ++
 11 files changed, 147 insertions(+), 58 deletions(-)

-- 
2.36.1




[RFC PATCH 02/10] Revert "hw/ide: Fix crash when plugging a piix3-ide device into the x-remote machine"

2022-06-27 Thread Bernhard Beschow
Now that the PIIX IDE device models check for presence of an ISABus before
using it, this fix isn't needed any longer.

This reverts commit 9405d87be25db6dff4d7b5ab48a81bbf6d083e47.

Signed-off-by: Bernhard Beschow 
---
 hw/ide/ioport.c   | 16 ++--
 hw/ide/piix.c |  9 +++--
 hw/isa/isa-bus.c  | 14 --
 include/hw/ide/internal.h |  2 +-
 include/hw/isa/isa.h  | 13 +
 5 files changed, 19 insertions(+), 35 deletions(-)

diff --git a/hw/ide/ioport.c b/hw/ide/ioport.c
index e6caa537fa..b613ff3bba 100644
--- a/hw/ide/ioport.c
+++ b/hw/ide/ioport.c
@@ -50,19 +50,15 @@ static const MemoryRegionPortio ide_portio2_list[] = {
 PORTIO_END_OF_LIST(),
 };
 
-int ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
+void ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
 {
-int ret;
-
 /* ??? Assume only ISA and PCI configurations, and that the PCI-ISA
bridge has been setup properly to always register with ISA.  */
-ret = isa_register_portio_list(dev, &bus->portio_list,
-   iobase, ide_portio_list, bus, "ide");
+isa_register_portio_list(dev, &bus->portio_list,
+ iobase, ide_portio_list, bus, "ide");
 
-if (ret == 0 && iobase2) {
-ret = isa_register_portio_list(dev, &bus->portio2_list,
-   iobase2, ide_portio2_list, bus, "ide");
+if (iobase2) {
+isa_register_portio_list(dev, &bus->portio2_list,
+ iobase2, ide_portio2_list, bus, "ide");
 }
-
-return ret;
 }
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index e8f3abc4b5..21777ecc8b 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -134,7 +134,7 @@ static int pci_piix_init_ports(PCIIDEState *d)
 {0x1f0, 0x3f6, 14},
 {0x170, 0x376, 15},
 };
-int i, ret;
+int i;
 
 {
 ISABus *isa_bus;
@@ -149,11 +149,8 @@ static int pci_piix_init_ports(PCIIDEState *d)
 
 for (i = 0; i < 2; i++) {
 ide_bus_init(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
-ret = ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
-  port_info[i].iobase2);
-if (ret) {
-return ret;
-}
+ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
+port_info[i].iobase2);
 ide_init2(&d->bus[i], isa_get_irq(NULL, port_info[i].isairq));
 
 bmdma_init(&d->bus[i], &d->bmdma[i], d);
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 1bee1a47f1..0537a9f2c1 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -119,17 +119,13 @@ void isa_register_ioport(ISADevice *dev, MemoryRegion 
*io, uint16_t start)
 isa_init_ioport(dev, start);
 }
 
-int isa_register_portio_list(ISADevice *dev,
- PortioList *piolist, uint16_t start,
- const MemoryRegionPortio *pio_start,
- void *opaque, const char *name)
+void isa_register_portio_list(ISADevice *dev,
+  PortioList *piolist, uint16_t start,
+  const MemoryRegionPortio *pio_start,
+  void *opaque, const char *name)
 {
 assert(piolist && !piolist->owner);
 
-if (!isabus) {
-return -ENODEV;
-}
-
 /* START is how we should treat DEV, regardless of the actual
contents of the portio array.  This is how the old code
actually handled e.g. the FDC device.  */
@@ -137,8 +133,6 @@ int isa_register_portio_list(ISADevice *dev,
 
 portio_list_init(piolist, OBJECT(dev), pio_start, opaque, name);
 portio_list_add(piolist, isabus->address_space_io, start);
-
-return 0;
 }
 
 ISADevice *isa_new(const char *name)
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index 97e7e59dc5..348e7f2510 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -624,7 +624,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, 
IDEDriveKind kind,
int chs_trans, Error **errp);
 void ide_init2(IDEBus *bus, qemu_irq irq);
 void ide_exit(IDEState *s);
-int ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
+void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
 void ide_register_restart_cb(IDEBus *bus);
 
 void ide_exec_cmd(IDEBus *bus, uint32_t val);
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index 6c8a8a92cb..8dd2953211 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -114,15 +114,12 @@ void isa_register_ioport(ISADevice *dev, MemoryRegion 
*io, uint16_t start);
  * @portio: the ports, sorted by offset.
  * @opaque: passed into the portio callbacks.
  * @name: passed into memory_region_init_io.
- *
- * Returns: 0 on success, negative error code otherwise (e.g. if the
- *  ISA bus is not available)
  */
-int isa_reg

[RFC PATCH 03/10] hw/i386/pc_piix: Allow for setting properties on "piix3-ide" before realizing it

2022-06-27 Thread Bernhard Beschow
The next patch will introduce a quirk for user-created PIIX IDE devices for
backwards compatibility. In order to opt-in to new behavior for builtin
devices a property will need to be set until a deprecation period is over.

Signed-off-by: Bernhard Beschow 
---
 hw/i386/pc_piix.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 0fc2361ffe..2d146b19c0 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -252,7 +252,8 @@ static void pc_init1(MachineState *machine,
 if (pcmc->pci_enabled) {
 PCIDevice *dev;
 
-dev = pci_create_simple(pci_bus, piix3_devfn + 1, "piix3-ide");
+dev = pci_new_multifunction(piix3_devfn + 1, false, "piix3-ide");
+pci_realize_and_unref(dev, pci_bus, &error_fatal);
 pci_ide_create_devs(dev);
 idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
 idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
-- 
2.36.1




[RFC PATCH 08/10] hw/ide/piix: Use pci_ide_init_ioport() rather than isa_ide_init_ioport()

2022-06-27 Thread Bernhard Beschow
This should fix the last caller causing a NULL ISADev to be passed to
isa_register_portio_list() which now allows for disusing the isabus global
there.

Signed-off-by: Bernhard Beschow 
---
 hw/ide/piix.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 312611c61f..087568ecf1 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -161,7 +161,7 @@ static int pci_piix_init_ports(PCIIDEState *d)
 
 for (i = 0; i < 2; i++) {
 ide_bus_init(&d->bus[i], sizeof(d->bus[i]), dev, i, 2);
-isa_ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
+pci_ide_init_ioport(&d->bus[i], PCI_DEVICE(d), port_info[i].iobase,
 port_info[i].iobase2);
 ide_init2(&d->bus[i], qdev_get_gpio_in(dev, i));
 
-- 
2.36.1




[RFC PATCH 05/10] hw/isa/isa-bus: assert() if isa_get_irq() gets passed a NULL ISADevice

2022-06-27 Thread Bernhard Beschow
Now that all call-sites have been fixed to pass non-NULL ISADevices, we can
assert() on NULL ISADevices to catch regressions.

Signed-off-by: Bernhard Beschow 
---
 hw/isa/isa-bus.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 0537a9f2c1..9e8b5da027 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -81,9 +81,10 @@ void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
  */
 qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq)
 {
-assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus);
+assert(dev);
 assert(isairq < ISA_NUM_IRQS);
-return isabus->irqs[isairq];
+
+return isa_bus_from_device(dev)->irqs[isairq];
 }
 
 void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq)
-- 
2.36.1




Re: QEMU Disassembler

2022-06-27 Thread Richard Henderson

On 6/27/22 12:10, Kenneth Adam Miller wrote:
Actually, I have gotten the QEMU disassembler to run with some short customization. But I 
am having trouble understanding the output. I see lots of lines like this:

|
OBJD-H: 06040102a83507000cd8027620272573004c04cd20c100782244038c


You want --enable-capstone, and to have libcapstone-dev installed.

But for the record, these lines can be decoded by e.g.

./scripts/disas-objdump.pl -h i386:x86-64 

to turn

PROLOGUE: [size=45]

0x7f501000:

OBJD-H: 55534154415541564157488bef4881c478fbffe633c04881c48804c5

OBJD-H: f877415f415e415d415c5b5dc3


into

PROLOGUE: [size=45]

0x7f501000:

7f501000:   55  push   %rbp

7f501001:   53  push   %rbx

7f501002:   41 54   push   %r12

7f501004:   41 55   push   %r13

7f501006:   41 56   push   %r14

7f501008:   41 57   push   %r15

7f50100a:   48 8b efmov%rdi,%rbp

7f50100d:   48 81 c4 78 fb ff ffadd$0xfb78,%rsp

7f501014:   ff e6   jmp*%rsi

7f501016:   33 c0   xor%eax,%eax

7f501018:   48 81 c4 88 04 00 00add$0x488,%rsp

7f50101f:   c5 f8 77vzeroupper

7f501022:   41 5f   pop%r15

7f501024:   41 5e   pop%r14

7f501026:   41 5d   pop%r13

7f501028:   41 5c   pop%r12

7f50102a:   5b  pop%rbx

7f50102b:   5d  pop%rbp

7f50102c:   c3  ret



r~



[RFC PATCH 09/10] hw/isa: Resolve unneeded usage of isabus global

2022-06-27 Thread Bernhard Beschow
Now that all call sites of these functions are fixed to pass non-NULL
ISADevices, the ISABus can be determined from the ISADevice argument.

Patch based on https://lists.nongnu.org/archive/html/qemu-devel/2021-05/
msg05785.html.

Signed-off-by: Bernhard Beschow 
---
 hw/ide/ioport.c  |  4 ++--
 hw/isa/isa-bus.c | 21 +
 include/hw/isa/isa.h |  2 +-
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/hw/ide/ioport.c b/hw/ide/ioport.c
index 69e4fa15d4..112726e415 100644
--- a/hw/ide/ioport.c
+++ b/hw/ide/ioport.c
@@ -53,8 +53,8 @@ static const MemoryRegionPortio ide_portio2_list[] = {
 
 void isa_ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
 {
-/* ??? Assume only ISA and PCI configurations, and that the PCI-ISA
-   bridge has been setup properly to always register with ISA.  */
+assert(dev);
+
 isa_register_portio_list(dev, &bus->portio_list,
  iobase, ide_portio_list, bus, "ide");
 
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 9e8b5da027..5518db93cd 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -116,6 +116,10 @@ static inline void isa_init_ioport(ISADevice *dev, 
uint16_t ioport)
 
 void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start)
 {
+ISABus *isabus;
+
+assert(dev);
+isabus = isa_bus_from_device(dev);
 memory_region_add_subregion(isabus->address_space_io, start, io);
 isa_init_ioport(dev, start);
 }
@@ -125,8 +129,13 @@ void isa_register_portio_list(ISADevice *dev,
   const MemoryRegionPortio *pio_start,
   void *opaque, const char *name)
 {
+ISABus *isabus;
+
+assert(dev);
 assert(piolist && !piolist->owner);
 
+isabus = isa_bus_from_device(dev);
+
 /* START is how we should treat DEV, regardless of the actual
contents of the portio array.  This is how the old code
actually handled e.g. the FDC device.  */
@@ -246,20 +255,16 @@ static char *isabus_get_fw_dev_path(DeviceState *dev)
 
 MemoryRegion *isa_address_space(ISADevice *dev)
 {
-if (dev) {
-return isa_bus_from_device(dev)->address_space;
-}
+assert(dev);
 
-return isabus->address_space;
+return isa_bus_from_device(dev)->address_space;
 }
 
 MemoryRegion *isa_address_space_io(ISADevice *dev)
 {
-if (dev) {
-return isa_bus_from_device(dev)->address_space_io;
-}
+assert(dev);
 
-return isabus->address_space_io;
+return isa_bus_from_device(dev)->address_space_io;
 }
 
 type_init(isabus_register_types)
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index 8dd2953211..486851e7cb 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -108,7 +108,7 @@ void isa_register_ioport(ISADevice *dev, MemoryRegion *io, 
uint16_t start);
  * function makes it easy to create multiple MemoryRegions for a single
  * device and use the legacy portio routines.
  *
- * @dev: the ISADevice against which these are registered; may be NULL.
+ * @dev: the ISADevice against which these are registered
  * @piolist: the PortioList associated with the io ports
  * @start: the base I/O port against which the portio->offset is applied.
  * @portio: the ports, sorted by offset.
-- 
2.36.1




[RFC PATCH 10/10] hw/isa/isa-bus: Resolve isabus global

2022-06-27 Thread Bernhard Beschow
Now that only isa_bus_new() accesses the isabus global it can be removed
assuming that all call sites take care of not passing the same address
spaces twice to different isa_bus_new() invocations.

Signed-off-by: Bernhard Beschow 
---
 hw/isa/isa-bus.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 5518db93cd..783506685d 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -26,8 +26,6 @@
 #include "hw/isa/isa.h"
 #include "hw/acpi/acpi_aml_interface.h"
 
-static ISABus *isabus;
-
 static char *isabus_get_fw_dev_path(DeviceState *dev);
 
 static void isa_bus_class_init(ObjectClass *klass, void *data)
@@ -53,10 +51,8 @@ static const TypeInfo isa_bus_info = {
 ISABus *isa_bus_new(DeviceState *dev, MemoryRegion* address_space,
 MemoryRegion *address_space_io, Error **errp)
 {
-if (isabus) {
-error_setg(errp, "Can't create a second ISA bus");
-return NULL;
-}
+ISABus *isabus;
+
 if (!dev) {
 dev = qdev_new("isabus-bridge");
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
-- 
2.36.1




[PATCH 00/12] Introduce new acpi/smbios qtests using biosbits

2022-06-27 Thread Ani Sinha
Biosbits is a software written by Josh Triplett that can be downloaded by
visiting https://biosbits.org/. The github codebase can be found here:
https://github.com/biosbits/bits/tree/master. It is a software that exercizes
the bios components such as acpi and smbios tables directly through acpica
bios interpreter (a freely available C based library written by Intel,
downloadable from https://acpica.org/ and is included with biosbits) without an
operating system getting involved in between.
There are several advantages to directly testing the bios in a real physical
machine or VM as opposed to indirectly discovering bios issues through the
operating system. For one thing, the OSes tend to hide bios problems from the
end user. The other is that we have more control of what we wanted to test
and how by directly using acpica interpreter on top of the bios on a running
system. More details on the inspiration for developing biosbits and its real
life uses can be found in (a) and (b).
This patchset contains QEMU qtests written in python that exercizes the QEMU
bios components using biosbits and reports test failures.

Details of each of the files added by this patchset are provided in the README
file which is part of Patch 11. Every effort to contact Josh, through various
means including email, twitter, linkedIn etc has failed. Hence, the changes to
build biosbits with the newer compiler, upgrade acpica and other changes are
currently maintained in a forked project in my personal github. We may want to
maintain bits in a separate fork in a stable repository that is accessible by
QEMU developers.

The newly introduced qtest currently only run for x86_64 platform. They pass
both when running make check on a baremetal box as well as from inside a vm.

Thanks to Igor M for pointing me to this work.

(a) 
https://blog.linuxplumbersconf.org/2011/ocw/system/presentations/867/original/bits.pdf
(b) https://www.youtube.com/watch?v=36QIepyUuhg

Ani Sinha (12):
  qtest: meson.build changes required to integrate python based qtests
  acpi/tests/bits: add prebuilt bios bits zip archive
  acpi/tests/bits: add prebuilt bits generated grub modules and scripts
  acpi/tests/bits: initial commit of test scripts that are run by
biosbits
  acpi/tests/bits: disable acpi PSS tests that are failing in biosbits
  acpi/tests/bits: add smilatency test suite from bits in order to
disable it
  acpi/tests/bits: disable smilatency test since it does not pass
everytime
  acpi/tests/bits: add biosbits config file for running bios tests
  acpi/tests/bits: add acpi and smbios python tests that uses biosbits
  acpi/tests/bits: add acpi bits qtest directory in meson for running
tests
  acpi/tests/bits: add README file for bits qtests
  MAINTAINERS: add myself as the maintainer for acpi biosbits qtests

 MAINTAINERS   |5 +
 tests/qtest/acpi-bits/README  |  168 ++
 tests/qtest/acpi-bits/acpi-bits-test-venv.sh  |   59 +
 tests/qtest/acpi-bits/acpi-bits-test.py   |  327 +++
 .../qtest/acpi-bits/bits-config/bits-cfg.txt  |   18 +
 tests/qtest/acpi-bits/bits-config/meson.build |   11 +
 tests/qtest/acpi-bits/bits-tests/meson.build  |   11 +
 tests/qtest/acpi-bits/bits-tests/smbios.py| 2430 +
 .../qtest/acpi-bits/bits-tests/smilatency.py  |  103 +
 tests/qtest/acpi-bits/bits-tests/testacpi.py  |  283 ++
 tests/qtest/acpi-bits/bits-tests/testcpuid.py |   83 +
 tests/qtest/acpi-bits/meson.build |   39 +
 .../acpi-bits/prebuilt/bits-2095-grub.tar.gz  |  Bin 0 -> 41416278 bytes
 tests/qtest/acpi-bits/prebuilt/bits-2095.zip  |  Bin 0 -> 31922898 bytes
 tests/qtest/acpi-bits/prebuilt/meson.build|   11 +
 tests/qtest/acpi-bits/requirements.txt|1 +
 tests/qtest/meson.build   |7 +-
 17 files changed, 3555 insertions(+), 1 deletion(-)
 create mode 100644 tests/qtest/acpi-bits/README
 create mode 100644 tests/qtest/acpi-bits/acpi-bits-test-venv.sh
 create mode 100644 tests/qtest/acpi-bits/acpi-bits-test.py
 create mode 100644 tests/qtest/acpi-bits/bits-config/bits-cfg.txt
 create mode 100644 tests/qtest/acpi-bits/bits-config/meson.build
 create mode 100644 tests/qtest/acpi-bits/bits-tests/meson.build
 create mode 100644 tests/qtest/acpi-bits/bits-tests/smbios.py
 create mode 100644 tests/qtest/acpi-bits/bits-tests/smilatency.py
 create mode 100644 tests/qtest/acpi-bits/bits-tests/testacpi.py
 create mode 100644 tests/qtest/acpi-bits/bits-tests/testcpuid.py
 create mode 100644 tests/qtest/acpi-bits/meson.build
 create mode 100644 tests/qtest/acpi-bits/prebuilt/bits-2095-grub.tar.gz
 create mode 100644 tests/qtest/acpi-bits/prebuilt/bits-2095.zip
 create mode 100644 tests/qtest/acpi-bits/prebuilt/meson.build
 create mode 100644 tests/qtest/acpi-bits/requirements.txt

-- 
2.25.1




Re: [RFC v3 1/5] block: add block layer APIs resembling Linux ZonedBlockDevice ioctls.

2022-06-27 Thread Hannes Reinecke

On 6/27/22 02:19, Sam Li wrote:

By adding zone management operations in BlockDriver, storage
controller emulation can use the new block layer APIs including
zone_report and zone_mgmt(open, close, finish, reset).
---
  block/block-backend.c|  56 
  block/coroutines.h   |   5 +
  block/file-posix.c   | 238 +++
  include/block/block-common.h |  43 +-
  include/block/block_int-common.h |  20 +++
  5 files changed, 361 insertions(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index e0e1aff4b1..786f964d02 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1810,6 +1810,62 @@ int blk_flush(BlockBackend *blk)
  return ret;
  }
  
+/*

+ * Return zone_report from BlockDriver. Offset can be any number within
+ * the zone size. No alignment for offset and len.
+ */
+int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset,
+   int64_t len, int64_t *nr_zones,
+   BlockZoneDescriptor *zones)
+{
+int ret;
+BlockDriverState *bs;
+IO_CODE();
+
+blk_inc_in_flight(blk); /* increase before waiting */
+blk_wait_while_drained(blk);
+bs = blk_bs(blk);
+
+ret = blk_check_byte_request(blk, offset, len);
+if (ret < 0) {
+return ret;
+}
+
+bdrv_inc_in_flight(bs);
+ret = bdrv_co_zone_report(blk->root->bs, offset, len,
+  nr_zones, zones);
+bdrv_dec_in_flight(bs);
+blk_dec_in_flight(blk);
+return ret;
+}
+
+/*
+ * Return zone_mgmt from BlockDriver.
+ * Offset is the start of a zone and len is aligned to zones.
+ */
+int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, enum zone_op op,
+int64_t offset, int64_t len)
+{
+int ret;
+BlockDriverState *bs;
+IO_CODE();
+
+blk_inc_in_flight(blk);
+blk_wait_while_drained(blk);
+bs = blk_bs(blk);
+
+ret = blk_check_byte_request(blk, offset, len);
+if (ret < 0) {
+return ret;
+}
+
+bdrv_inc_in_flight(bs);
+ret = bdrv_co_zone_mgmt(blk->root->bs, op, offset, len);
+bdrv_dec_in_flight(bs);
+blk_dec_in_flight(blk);
+return ret;
+}
+
  void blk_drain(BlockBackend *blk)
  {
  BlockDriverState *bs = blk_bs(blk);
diff --git a/block/coroutines.h b/block/coroutines.h
index 830ecaa733..a114d7bc30 100644
--- a/block/coroutines.h
+++ b/block/coroutines.h
@@ -80,6 +80,11 @@ int coroutine_fn
  blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
  
  int coroutine_fn blk_co_do_flush(BlockBackend *blk);

+int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset,
+int64_t len, int64_t *nr_zones,
+BlockZoneDescriptor *zones);
+int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, enum zone_op op,
+int64_t offset, int64_t len);
  
  
  /*

diff --git a/block/file-posix.c b/block/file-posix.c
index 48cd096624..1b8b0d351f 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -67,6 +67,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -216,6 +217,11 @@ typedef struct RawPosixAIOData {
  PreallocMode prealloc;
  Error **errp;
  } truncate;
+struct {
+int64_t *nr_zones;
+BlockZoneDescriptor *zones;
+} zone_report;
+zone_op op;
  };
  } RawPosixAIOData;
  
@@ -1801,6 +1807,135 @@ static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd,

  }
  #endif
  
+/*

+ * parse_zone - Fill a zone descriptor
+ */
+static inline void parse_zone(struct BlockZoneDescriptor *zone,
+  struct blk_zone *blkz) {
+zone->start = blkz->start;
+zone->length = blkz->len;
+zone->cap = blkz->capacity;
+zone->wp = blkz->wp - blkz->start;
+zone->type = blkz->type;
+zone->cond = blkz->cond;
+}
+
+static int handle_aiocb_zone_report(void *opaque) {
+RawPosixAIOData *aiocb = opaque;
+int fd = aiocb->aio_fildes;
+int64_t *nr_zones = aiocb->zone_report.nr_zones;
+BlockZoneDescriptor *zones = aiocb->zone_report.zones;
+int64_t offset = aiocb->aio_offset;
+int64_t len = aiocb->aio_nbytes;
+
+struct blk_zone *blkz;
+int64_t rep_size, nrz;
+int ret, n = 0, i = 0;
+
+nrz = *nr_zones;
+if (len == -1) {
+return -errno;
+}
+rep_size = sizeof(struct blk_zone_report) + nrz * sizeof(struct blk_zone);
+g_autofree struct blk_zone_report *rep = g_new(struct blk_zone_report, 
nrz);
+offset = offset / 512; /* get the unit of the start sector: sector size is 
512 bytes. */
+printf("start to report zone with offset: 0x%lx\n", offset);
+
+blkz = (struct blk_zone *)(rep + 1);
+while (n < nrz) {
+memset(rep, 0, rep_size);
+rep->sector = offset;
+rep->nr_zones = nrz;
+
+ret = ioctl(fd, BLKREPORTZONE, rep);
+if (ret

[RFC PATCH 07/10] hw/pci/pci: Introduce pci_register_portio_list()

2022-06-27 Thread Bernhard Beschow
pci_ide_init_ioport() and pci_register_portio_list() are introduced which
mirror their ISA counterparts. But rather than asking for an ISADevice, the
functions ask for PCIDevice which can be used in hw/ide/piix which fixes
having to pass a NULL ISADevice which is not avialable there.

Passing NULL as ISADevice to pci_ide_init_ioport() also causes a NULL
ISADevice to be passed to isa_register_ioport(). Currently this function
always uses the isabus global. To fix this, we'll want to determine the
ISABus using isa_bus_from_device(), so no call-site must pass a NULL
ISADevice.

Signed-off-by: Bernhard Beschow 
---
 hw/ide/ioport.c   | 14 ++
 hw/pci/pci.c  | 18 ++
 include/hw/ide/internal.h |  1 +
 include/hw/pci/pci.h  | 21 +
 4 files changed, 54 insertions(+)

diff --git a/hw/ide/ioport.c b/hw/ide/ioport.c
index ed1f34f573..69e4fa15d4 100644
--- a/hw/ide/ioport.c
+++ b/hw/ide/ioport.c
@@ -25,6 +25,7 @@
 
 #include "qemu/osdep.h"
 #include "hw/isa/isa.h"
+#include "hw/pci/pci_bus.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
 #include "sysemu/blockdev.h"
@@ -62,3 +63,16 @@ void isa_ide_init_ioport(IDEBus *bus, ISADevice *dev, int 
iobase, int iobase2)
  iobase2, ide_portio2_list, bus, "ide");
 }
 }
+
+void pci_ide_init_ioport(IDEBus *bus, PCIDevice *dev, int iobase, int iobase2)
+{
+assert(dev);
+
+pci_register_portio_list(dev, &bus->portio_list,
+ iobase, ide_portio_list, bus, "ide");
+
+if (iobase2) {
+pci_register_portio_list(dev, &bus->portio2_list,
+ iobase2, ide_portio2_list, bus, "ide");
+}
+}
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 2f450f6a72..3046dd5477 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1440,6 +1440,24 @@ pcibus_t pci_bar_address(PCIDevice *d,
 return new_addr;
 }
 
+void pci_register_portio_list(PCIDevice *dev,
+  PortioList *piolist, uint16_t start,
+  const MemoryRegionPortio *pio_start,
+  void *opaque, const char *name)
+{
+PCIBus *bus;
+
+assert(dev);
+assert(piolist && !piolist->owner);
+
+bus = pci_get_bus(dev);
+
+assert(bus);
+
+portio_list_init(piolist, OBJECT(dev), pio_start, opaque, name);
+portio_list_add(piolist, bus->address_space_io, start);
+}
+
 static void pci_update_mappings(PCIDevice *d)
 {
 PCIIORegion *r;
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index 86ecc04ce4..4a375d3c09 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -625,6 +625,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, 
IDEDriveKind kind,
 void ide_init2(IDEBus *bus, qemu_irq irq);
 void ide_exit(IDEState *s);
 void isa_ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
+void pci_ide_init_ioport(IDEBus *bus, PCIDevice *isa, int iobase, int iobase2);
 void ide_register_restart_cb(IDEBus *bus);
 
 void ide_exec_cmd(IDEBus *bus, uint32_t val);
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index b54b6ef88f..91b479d542 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -522,6 +522,27 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void 
*opaque);
 pcibus_t pci_bar_address(PCIDevice *d,
  int reg, uint8_t type, pcibus_t size);
 
+/**
+ * pci_register_portio_list: Initialize a set of io ports
+ *
+ * Several ISA devices have many dis-joint I/O ports.  Worse, these I/O
+ * ports can be interleaved with I/O ports from other devices.  This
+ * function makes it easy to create multiple MemoryRegions for a single
+ * device and use the legacy portio routines.
+ *
+ * @dev: the PCIDevice against which these are registered
+ * @piolist: the PortioList associated with the io ports
+ * @start: the base I/O port against which the portio->offset is applied.
+ * @portio: the ports, sorted by offset.
+ * @opaque: passed into the portio callbacks.
+ * @name: passed into memory_region_init_io.
+ */
+void pci_register_portio_list(PCIDevice *dev,
+  PortioList *piolist,
+  uint16_t start,
+  const MemoryRegionPortio *portio,
+  void *opaque, const char *name);
+
 static inline void
 pci_set_byte(uint8_t *config, uint8_t val)
 {
-- 
2.36.1




[PATCH 01/12] qtest: meson.build changes required to integrate python based qtests

2022-06-27 Thread Ani Sinha
These are some basic changes required in meson.build file in order to
incorporate python based qtests later on. No new qtests have been added in this
change.

Signed-off-by: Ani Sinha 
---
 tests/qtest/meson.build | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 31287a9173..ad52f1c81b 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -310,6 +310,8 @@ qtests += {'dbus-display-test': [dbus_display1, gio]}
 endif
 
 qtest_executables = {}
+other_deps = []
+
 foreach dir : target_dirs
   if not dir.endswith('-softmmu')
 continue
@@ -327,6 +329,7 @@ foreach dir : target_dirs
   endif
   qtest_env.set('G_TEST_DBUS_DAEMON', meson.project_source_root() / 
'tests/dbus-vmstate-daemon.sh')
   qtest_env.set('QTEST_QEMU_BINARY', './qemu-system-' + target_base)
+  qtest_env.set('QTEST_SOURCE_ROOT', meson.project_source_root())
   if have_tools and have_vhost_user_blk_server
 qtest_env.set('QTEST_QEMU_STORAGE_DAEMON_BINARY', 
'./storage-daemon/qemu-storage-daemon')
 test_deps += [qsd]
@@ -351,7 +354,7 @@ foreach dir : target_dirs
 endif
 test('qtest-@0@/@1@'.format(target_base, test),
  qtest_executables[test],
- depends: [test_deps, qtest_emulator, emulator_modules],
+ depends: [test_deps, qtest_emulator, emulator_modules, other_deps],
  env: qtest_env,
  args: ['--tap', '-k'],
  protocol: 'tap',
-- 
2.25.1




Re: [RFC v3 2/5] qemu-io: add zoned block device operations.

2022-06-27 Thread Hannes Reinecke

On 6/27/22 02:19, Sam Li wrote:

---


Good coding style would advise to add some text here what the patch does.


  block/io.c   |  21 +++
  include/block/block-io.h |  13 +
  qemu-io-cmds.c   | 121 +++
  3 files changed, 155 insertions(+)

diff --git a/block/io.c b/block/io.c
index 789e6373d5..656a1b7271 100644
--- a/block/io.c
+++ b/block/io.c
@@ -3258,6 +3258,27 @@ out:
  return co.ret;
  }
  
+int bdrv_co_zone_report(BlockDriverState *bs, int64_t offset,

+int64_t len, int64_t *nr_zones,
+BlockZoneDescriptor *zones)
+{
+if (!bs->drv->bdrv_co_zone_report) {
+return -ENOTSUP;


ENOTSUP or EOPNOTSUP?
Kevin?


+}
+
+return bs->drv->bdrv_co_zone_report(bs, offset, len, nr_zones, zones);
+}
+
+int bdrv_co_zone_mgmt(BlockDriverState *bs, enum zone_op op,
+int64_t offset, int64_t len)
+{
+if (!bs->drv->bdrv_co_zone_mgmt) {
+return -ENOTSUP;
+}
+
+return bs->drv->bdrv_co_zone_mgmt(bs, op, offset, len);
+}
+
  void *qemu_blockalign(BlockDriverState *bs, size_t size)
  {
  IO_CODE();
diff --git a/include/block/block-io.h b/include/block/block-io.h
index 62c84f0519..c85c174579 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -80,6 +80,13 @@ int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
  /* Ensure contents are flushed to disk.  */
  int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
  
+/* Report zone information of zone block device. */

+int coroutine_fn bdrv_co_zone_report(BlockDriverState *bs, int64_t offset,
+ int64_t len, int64_t *nr_zones,
+ BlockZoneDescriptor *zones);
+int coroutine_fn bdrv_co_zone_mgmt(BlockDriverState *bs, zone_op op,
+int64_t offset, int64_t len);
+


There's the thing with the intendation ... please make it consistent, 
and ideally follow with whatever the remaining prototypes do.



  int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
  bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
  int bdrv_block_status(BlockDriverState *bs, int64_t offset,
@@ -290,6 +297,12 @@ bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector 
*qiov, int64_t pos);
  int generated_co_wrapper
  bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
  
+int generated_co_wrapper blk_zone_report(BlockBackend *blk, int64_t offset,

+ int64_t len, int64_t *nr_zones,
+ BlockZoneDescriptor *zones);
+int generated_co_wrapper blk_zone_mgmt(BlockBackend *blk, enum zone_op op,
+int64_t offset, int64_t len);
+


Again here.


  /**
   * bdrv_parent_drained_begin_single:
   *
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 2f0d8ac25a..3f2592b9f5 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1706,6 +1706,122 @@ static const cmdinfo_t flush_cmd = {
  .oneline= "flush all in-core file state to disk",
  };
  
+static int zone_report_f(BlockBackend *blk, int argc, char **argv)

+{
+int ret;
+int64_t offset, len, nr_zones;
+int i = 0;
+
+++optind;
+offset = cvtnum(argv[optind]);
+++optind;
+len = cvtnum(argv[optind]);
+++optind;
+nr_zones = cvtnum(argv[optind]);
+

And 'optind' is set where?
Plus do check for 'argv' overflow; before increasing 'optind' and using 
'argv[optind]' you have to validate that 'argv[optind]' is a valid pointer.



+g_autofree BlockZoneDescriptor *zones = g_new(BlockZoneDescriptor, 
nr_zones);
+ret = blk_zone_report(blk, offset, len, &nr_zones, zones);
+while (i < nr_zones) {
+fprintf(stdout, "start: 0x%lx, len 0x%lx, cap 0x%lx, wptr 0x%lx, "
+"zcond:%u, [type: %u]\n",
+zones[i].start, zones[i].length, zones[i].cap, zones[i].wp,
+zones[i].cond, zones[i].type);
+++i;

As 'i' is a simple iterator maybe use a 'for' loop here.
But that really is a matter of preference :-)


+}
+return ret;
+}
+
+static const cmdinfo_t zone_report_cmd = {
+.name = "zone_report",
+.altname = "f",


altname 'f'?
Is that correct?


+.cfunc = zone_report_f,
+.argmin = 3,
+.argmax = 3,
+.args = "offset [offset..] len [len..] number [num..]",
+.oneline = "report a number of zones",
+};
+
+static int zone_open_f(BlockBackend *blk, int argc, char **argv)
+{
+int64_t offset, len;
+++optind;
+offset = cvtnum(argv[optind]);
+++optind;
+len = cvtnum(argv[optind]);


Same here: please check for 'argv' overflow.


+return blk_zone_mgmt(blk, zone_open, offset, len);
+}
+
+static const cmdinfo_t zone_open_cmd = {
+.name = "zone_open",
+.altname = "f",


Same here; shouldn't 'altname' be different for each function?
'zo', maybe?


+.cfunc = zone_open_f,
+.argmin =

[PATCH 08/12] acpi/tests/bits: add biosbits config file for running bios tests

2022-06-27 Thread Ani Sinha
This change adds initial biosbits config file that instructs biosbits to run
bios test suits in batch mode. Additionally acpi and smbios structures are also
dumped.

Signed-off-by: Ani Sinha 
---
 tests/qtest/acpi-bits/bits-config/bits-cfg.txt | 18 ++
 tests/qtest/acpi-bits/bits-config/meson.build  | 11 +++
 2 files changed, 29 insertions(+)
 create mode 100644 tests/qtest/acpi-bits/bits-config/bits-cfg.txt
 create mode 100644 tests/qtest/acpi-bits/bits-config/meson.build

diff --git a/tests/qtest/acpi-bits/bits-config/bits-cfg.txt 
b/tests/qtest/acpi-bits/bits-config/bits-cfg.txt
new file mode 100644
index 00..8010804453
--- /dev/null
+++ b/tests/qtest/acpi-bits/bits-config/bits-cfg.txt
@@ -0,0 +1,18 @@
+# BITS configuration file
+[bits]
+
+# To run BITS in batch mode, set batch to a list of one or more of the
+# following keywords; BITS will then run all of the requested operations, then
+# save the log file to disk.
+#
+# test: Run the full BITS testsuite.
+# acpi: Dump all ACPI structures.
+# smbios: Dump all SMBIOS structures.
+#
+# Leave batch set to an empty string to disable batch mode.
+# batch =
+
+# Uncomment the following to run all available batch operations
+# please take a look at boot/python/init.py in bits zip file
+# to see how these options are parsed and used.
+batch = test acpi smbios
diff --git a/tests/qtest/acpi-bits/bits-config/meson.build 
b/tests/qtest/acpi-bits/bits-config/meson.build
new file mode 100644
index 00..bbd7a940dc
--- /dev/null
+++ b/tests/qtest/acpi-bits/bits-config/meson.build
@@ -0,0 +1,11 @@
+config_files = ['bits-cfg.txt']
+
+copycfgfiles = custom_target('copy cfg files',
+  input : config_files,
+  output :  config_files,
+  command : ['cp', '@INPUT@', '@OUTPUT@'],
+  install : true,
+  install_dir : 'bits-config',
+  build_by_default : true)
+
+other_deps += copycfgfiles
-- 
2.25.1




Re: [PATCH v4 45/53] semihosting: Create qemu_semihosting_console_write

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> Will replace qemu_semihosting_console_{outs,outc},
> but we need more plumbing first.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  include/semihosting/console.h | 12 
>  linux-user/semihost.c |  5 +
>  semihosting/console.c |  9 +
>  3 files changed, 26 insertions(+)
> 
> diff --git a/include/semihosting/console.h b/include/semihosting/console.h
> index 39dbf1b062..6994f23c82 100644
> --- a/include/semihosting/console.h
> +++ b/include/semihosting/console.h
> @@ -54,6 +54,18 @@ void qemu_semihosting_console_outc(CPUArchState *env, 
> target_ulong c);
>   */
>  int qemu_semihosting_console_read(CPUState *cs, void *buf, int len);
>  
> +/**
> + * qemu_semihosting_console_write:
> + * @buf: host buffer
> + * @len: buffer size
> + *
> + * Write len bytes from buf to the debug console.
> + *
> + * Returns: number of bytes written -- this should only ever be short
> + * on some sort of i/o error.
> + */
> +int qemu_semihosting_console_write(void *buf, int len);
> +
>  /**
>   * qemu_semihosting_log_out:
>   * @s: pointer to string
> diff --git a/linux-user/semihost.c b/linux-user/semihost.c
> index 2029fb674c..871edf993a 100644
> --- a/linux-user/semihost.c
> +++ b/linux-user/semihost.c
> @@ -76,3 +76,8 @@ int qemu_semihosting_console_read(CPUState *cs, void *buf, 
> int len)
>  
>  return ret;
>  }
> +
> +int qemu_semihosting_console_write(void *buf, int len)
> +{
> +return fwrite(buf, 1, len, stderr);
> +}
> diff --git a/semihosting/console.c b/semihosting/console.c
> index 4088192842..b6a342744d 100644
> --- a/semihosting/console.c
> +++ b/semihosting/console.c
> @@ -169,6 +169,15 @@ int qemu_semihosting_console_read(CPUState *cs, void 
> *buf, int len)
>  return ret;
>  }
>  
> +int qemu_semihosting_console_write(void *buf, int len)
> +{
> +if (console.chr) {
> +return qemu_chr_write_all(console.chr, (uint8_t *)buf, len);
> +} else {
> +return fwrite(buf, 1, len, stderr);
> +}
> +}
> +
>  void qemu_semihosting_console_init(Chardev *chr)
>  {
>  console.chr = chr;
> -- 
> 2.34.1
> 
> 
> 
> 
> To declare a filtering error, please use the following link : 
> https://www.security-mail.net/reporter.php?mid=17cb8.629fd4d3.e3b54.0&r=lmichel%40kalrayinc.com&s=qemu-devel-bounces%2Blmichel%3Dkalrayinc.com%40nongnu.org&o=%5BPATCH+v4+45%2F53%5D+semihosting%3A+Create+qemu_semihosting_console_write&verdict=C&c=62fc4b596a4980c709b5ba86793f19d99fbc6d6f
> 

-- 







[PATCH 05/12] acpi/tests/bits: disable acpi PSS tests that are failing in biosbits

2022-06-27 Thread Ani Sinha
PSS tests in acpi test suite seems to be failing in biosbits. This is because
the test is unable to find PSS support in QEMU bios. Let us disable
them for now so that make check does not fail. We can fix the tests and
re-enable them later.

Example failure:

 ACPI _PSS (Pstate) table conformance tests 
[assert] _PSS must exist FAIL
  \_SB_.CPUS.C000
  No _PSS exists
Summary: 1 passed, 1 failed
 ACPI _PSS (Pstate) runtime tests 
[assert] _PSS must exist FAIL
  \_SB_.CPUS.C000
  No _PSS exists
Summary: 0 passed, 1 failed

Signed-off-by: Ani Sinha 
---
 tests/qtest/acpi-bits/bits-tests/testacpi.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/acpi-bits/bits-tests/testacpi.py 
b/tests/qtest/acpi-bits/bits-tests/testacpi.py
index 9ec452f330..dbc150076e 100644
--- a/tests/qtest/acpi-bits/bits-tests/testacpi.py
+++ b/tests/qtest/acpi-bits/bits-tests/testacpi.py
@@ -36,8 +36,8 @@
 
 def register_tests():
 testsuite.add_test("ACPI _MAT (Multiple APIC Table Entry) under Processor 
objects", test_mat, submenu="ACPI Tests")
-testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, 
submenu="ACPI Tests")
-testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, 
submenu="ACPI Tests")
+#testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", 
test_pss, submenu="ACPI Tests")
+#testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, 
submenu="ACPI Tests")
 testsuite.add_test("ACPI DSDT (Differentiated System Description Table)", 
test_dsdt, submenu="ACPI Tests")
 testsuite.add_test("ACPI FACP (Fixed ACPI Description Table)", test_facp, 
submenu="ACPI Tests")
 testsuite.add_test("ACPI HPET (High Precision Event Timer Table)", 
test_hpet, submenu="ACPI Tests")
-- 
2.25.1




[PATCH 06/12] acpi/tests/bits: add smilatency test suite from bits in order to disable it

2022-06-27 Thread Ani Sinha
smilatency tests does not reliably pass every time it is run from QEMU. This
change adds the test file unchanged from bits so that the next change can
disable the test.

Signed-off-by: Ani Sinha 
---
 tests/qtest/acpi-bits/bits-tests/meson.build  |   2 +-
 .../qtest/acpi-bits/bits-tests/smilatency.py  | 102 ++
 2 files changed, 103 insertions(+), 1 deletion(-)
 create mode 100644 tests/qtest/acpi-bits/bits-tests/smilatency.py

diff --git a/tests/qtest/acpi-bits/bits-tests/meson.build 
b/tests/qtest/acpi-bits/bits-tests/meson.build
index 3056731a53..06bca75d99 100644
--- a/tests/qtest/acpi-bits/bits-tests/meson.build
+++ b/tests/qtest/acpi-bits/bits-tests/meson.build
@@ -1,4 +1,4 @@
-test_files = ['smbios.py', 'testacpi.py', 'testcpuid.py']
+test_files = ['smbios.py', 'smilatency.py', 'testacpi.py', 'testcpuid.py']
 
 copytestfiles = custom_target('copy test files',
   input : test_files,
diff --git a/tests/qtest/acpi-bits/bits-tests/smilatency.py 
b/tests/qtest/acpi-bits/bits-tests/smilatency.py
new file mode 100644
index 00..fb1b7228e3
--- /dev/null
+++ b/tests/qtest/acpi-bits/bits-tests/smilatency.py
@@ -0,0 +1,102 @@
+# Copyright (c) 2015, Intel Corporation
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright 
notice,
+#   this list of conditions and the following disclaimer in the 
documentation
+#   and/or other materials provided with the distribution.
+# * Neither the name of Intel Corporation nor the names of its contributors
+#   may be used to endorse or promote products derived from this software
+#   without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""SMI latency test."""
+
+import bits
+from collections import namedtuple
+import testsuite
+import time
+import usb
+
+def register_tests():
+testsuite.add_test("SMI latency test", smi_latency);
+testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", 
test_with_usb_disabled, runall=False);
+
+def smi_latency():
+MSR_SMI_COUNT = 0x34
+
+print "Warning: touching the keyboard can affect the results of this test."
+
+tsc_per_sec = bits.tsc_per_sec()
+tsc_per_usec = tsc_per_sec / (1000 * 1000)
+bins = [long(tsc_per_usec * 10**i) for i in range(9)]
+bin_descs = [
+"0 < t <=   1us",
+"1us   < t <=  10us",
+"10us  < t <= 100us",
+"100us < t <=   1ms",
+"1ms   < t <=  10ms",
+"10ms  < t <= 100ms",
+"100ms < t <=   1s ",
+"1s< t <=  10s ",
+"10s   < t <= 100s ",
+"100s  < t ",
+]
+
+print "Starting test. Wait here, I will be back in 15 seconds."
+(max_latency, smi_count_delta, bins) = bits.smi_latency(long(15 * 
tsc_per_sec), bins)
+BinType = namedtuple('BinType', ("max", "total", "count", "times"))
+bins = [BinType(*b) for b in bins]
+
+testsuite.test("SMI latency < 150us to minimize risk of OS timeouts", 
max_latency / tsc_per_usec <= 150)
+if not testsuite.show_detail():
+return
+
+for bin, desc in zip(bins, bin_descs):
+if bin.count == 0:
+continue
+testsuite.print_detail("{}; average = {}; count = {}".format(desc, 
bits.format_tsc(bin.total/bin.count), bin.count))
+deltas = (bits.format_tsc(t2 - t1) for t1,t2 in zip(bin.times, 
bin.times[1:]))
+testsuite.print_detail(" Times between first few observations: 
{}".format(" ".join("{:>6}".format(delta) for delta in deltas)))
+
+if smi_count_delta is not None:
+testsuite.print_detail("{} SMI detected using MSR_SMI_COUNT (MSR 
{:#x})".format(smi_count_delta, MSR_SMI_COUNT))
+
+testsuite.print_detail("Summary of impact: observed maximum latency = 
{}".format(bits.format_tsc(max_latency)))
+
+def test_with_usb_disabled():
+if usb.handoff_to_os():
+smi_latency()
+
+def average_io_smi(port, value, count):

[PATCH 04/12] acpi/tests/bits: initial commit of test scripts that are run by biosbits

2022-06-27 Thread Ani Sinha
This is initial commit of cpuid, acpi and smbios python test scripts for
biosbits to execute. No change has been made to them from the original code
written by the biosbits author Josh Triplett. They are required to be installed
into the bits iso file and then run from within the virtual machine booted off
with biosbits iso.

The original location of these tests are here:
https://github.com/biosbits/bits/blob/master/python/testacpi.py
https://github.com/biosbits/bits/blob/master/python/smbios.py
https://github.com/biosbits/bits/blob/master/python/testcpuid.py

Signed-off-by: Ani Sinha 
---
 tests/qtest/acpi-bits/bits-tests/meson.build  |   11 +
 tests/qtest/acpi-bits/bits-tests/smbios.py| 2430 +
 tests/qtest/acpi-bits/bits-tests/testacpi.py  |  283 ++
 tests/qtest/acpi-bits/bits-tests/testcpuid.py |   83 +
 4 files changed, 2807 insertions(+)
 create mode 100644 tests/qtest/acpi-bits/bits-tests/meson.build
 create mode 100644 tests/qtest/acpi-bits/bits-tests/smbios.py
 create mode 100644 tests/qtest/acpi-bits/bits-tests/testacpi.py
 create mode 100644 tests/qtest/acpi-bits/bits-tests/testcpuid.py

diff --git a/tests/qtest/acpi-bits/bits-tests/meson.build 
b/tests/qtest/acpi-bits/bits-tests/meson.build
new file mode 100644
index 00..3056731a53
--- /dev/null
+++ b/tests/qtest/acpi-bits/bits-tests/meson.build
@@ -0,0 +1,11 @@
+test_files = ['smbios.py', 'testacpi.py', 'testcpuid.py']
+
+copytestfiles = custom_target('copy test files',
+  input : test_files,
+  output :  test_files,
+  command : ['cp', '@INPUT@', '@OUTDIR@'],
+  install : true,
+  install_dir : 'bits-tests',
+  build_by_default : true)
+
+other_deps += copytestfiles
diff --git a/tests/qtest/acpi-bits/bits-tests/smbios.py 
b/tests/qtest/acpi-bits/bits-tests/smbios.py
new file mode 100644
index 00..9667d0542c
--- /dev/null
+++ b/tests/qtest/acpi-bits/bits-tests/smbios.py
@@ -0,0 +1,2430 @@
+# Copyright (c) 2015, Intel Corporation
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright 
notice,
+#   this list of conditions and the following disclaimer in the 
documentation
+#   and/or other materials provided with the distribution.
+# * Neither the name of Intel Corporation nor the names of its contributors
+#   may be used to endorse or promote products derived from this software
+#   without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""SMBIOS/DMI module."""
+
+import bits
+import bitfields
+import ctypes
+import redirect
+import struct
+import uuid
+import unpack
+import ttypager
+import sys
+
+class SMBIOS(unpack.Struct):
+def __new__(cls):
+if sys.platform == "BITS-EFI":
+import efi
+sm_ptr = 
efi.system_table.ConfigurationTableDict.get(efi.SMBIOS_TABLE_GUID)
+else:
+address = 0xF
+mem = bits.memory(0xF, 0x1)
+for offset in range(0, len(mem), 16):
+signature = (ctypes.c_char * 4).from_address(address + 
offset).value
+if signature == "_SM_":
+entry_point_length = ctypes.c_ubyte.from_address(address + 
offset + 5).value
+csum = sum(map(ord, mem[offset:offset + 
entry_point_length])) & 0xff
+if csum == 0:
+sm_ptr = address + offset
+break
+else:
+return None
+
+if not sm_ptr:
+return None
+
+sm = super(SMBIOS, cls).__new__(cls)
+sm._header_memory = bits.memory(sm_ptr, 0x1f)
+return sm
+
+def __init__(self):
+super(SMBIOS, self).__init__()
+u = unpack.Unpackable(self._header_memory)
+self.add_field('header', Header(u))
+self._structure_memory = 
bits.memory(self.header.structure_table_address, 
self.header.structure_table_length)
+u = unpack.

Re: [RFC v3 5/5] qemu-iotests: add zone operation tests.

2022-06-27 Thread Hannes Reinecke

On 6/27/22 02:19, Sam Li wrote:

---
  tests/qemu-iotests/tests/zoned.sh | 49 +++
  1 file changed, 49 insertions(+)
  create mode 100755 tests/qemu-iotests/tests/zoned.sh

diff --git a/tests/qemu-iotests/tests/zoned.sh 
b/tests/qemu-iotests/tests/zoned.sh
new file mode 100755
index 00..262c0b5427
--- /dev/null
+++ b/tests/qemu-iotests/tests/zoned.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+#
+# Test zone management operations.
+#
+
+QEMU_IO="build/qemu-io"
+IMG="--image-opts driver=zoned_host_device,filename=/dev/nullb0"
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
+
+echo "Testing a null_blk device"
+echo "Simple cases: if the operations work"
+sudo modprobe null_blk nr_devices=1 zoned=1
+# hidden issues:
+# 1. memory allocation error of "unaligned tcache chunk detected" when the 
nr_zone=1 in zone report
+# 2. qemu-io: after report 10 zones, the program failed at double free error 
and exited.
+echo "report the first zone"
+sudo $QEMU_IO $IMG -c "zone_report 0 0 1"
+echo "report: the first 10 zones"
+sudo $QEMU_IO $IMG -c "zone_report 0 0 10"
+
+echo "open the first zone"
+sudo $QEMU_IO $IMG -c "zone_open 0 0x8"
+echo "report after:"
+sudo $QEMU_IO $IMG -c "zone_report 0 0 1"
+echo "open the last zone"
+sudo $QEMU_IO $IMG -c "zone_open 0x3e7000 0x8"
+echo "report after:"
+sudo $QEMU_IO $IMG -c "zone_report 0x3e7000 0 2"
+
+echo "close the first zone"
+sudo $QEMU_IO $IMG -c "zone_close 0 0x8"
+echo "report after:"
+sudo $QEMU_IO $IMG -c "zone_report 0 0 1"
+echo "close the last zone"
+sudo $QEMU_IO $IMG -c "zone_close 0x3e7000 0x8"
+echo "report after:"
+sudo $QEMU_IO $IMG -c "zone_report 0x3e7000 0 2"
+
+
+echo "reset the second zone"
+sudo $QEMU_IO $IMG -c "zone_reset 0x8 0x8"
+echo "After resetting a zone:"
+sudo $QEMU_IO $IMG -c "zone_report 0x8 0 5"
+
+# success, all done
+sudo rmmod null_blk
+echo "*** done"
+#rm -f $seq.full
+status=0


Caveat: I'm not that familiar with qemu-iotests.
FWIW:

Reviewed-by: Hannes Reinecke 

Cheers,

Hannes
--
Dr. Hannes ReineckeKernel Storage Architect
h...@suse.de  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer



[PATCH 07/12] acpi/tests/bits: disable smilatency test since it does not pass everytime

2022-06-27 Thread Ani Sinha
smilatency test is latency sensitive and does not pass deterministically when
run in QEMU environment under biosbits. Disable the test suite for now.

Example failure:

 SMI latency test 
Warning: touching the keyboard can affect the results of this test.
Starting test. Wait here, I will be back in 15 seconds.
[assert] SMI latency < 150us to minimize risk of OS timeouts FAIL
  1us   < t <=  10us; average = 1372ns; count = 10912449
   Times between first few observations:  176us 1646ns 1441ns 1450ns 1462ns
  10us  < t <= 100us; average = 16us; count = 1187
   Times between first few observations:   15ms 3148us 5856us   49ms   33ms
  100us < t <=   1ms; average = 259us; count = 8
   Times between first few observations:  111ms 2227ms 1779ms  999ms  219ms
  0 SMI detected using MSR_SMI_COUNT (MSR 0x34)
  Summary of impact: observed maximum latency = 298us
Summary: 0 passed, 1 failed

Signed-off-by: Ani Sinha 
---
 tests/qtest/acpi-bits/bits-tests/smilatency.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/acpi-bits/bits-tests/smilatency.py 
b/tests/qtest/acpi-bits/bits-tests/smilatency.py
index fb1b7228e3..53b5f820a5 100644
--- a/tests/qtest/acpi-bits/bits-tests/smilatency.py
+++ b/tests/qtest/acpi-bits/bits-tests/smilatency.py
@@ -33,8 +33,9 @@
 import usb
 
 def register_tests():
-testsuite.add_test("SMI latency test", smi_latency);
-testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", 
test_with_usb_disabled, runall=False);
+pass
+# testsuite.add_test("SMI latency test", smi_latency);
+# testsuite.add_test("SMI latency test with USB disabled via BIOS 
handoff", test_with_usb_disabled, runall=False);
 
 def smi_latency():
 MSR_SMI_COUNT = 0x34
-- 
2.25.1




[PATCH 09/12] acpi/tests/bits: add acpi and smbios python tests that uses biosbits

2022-06-27 Thread Ani Sinha
This change adds python based qtest framework that can be used to run
qtests from within a virtual environment. A bash script creates the virtual
environment and then runs the python based tests from within that environment.
All dependent python packages are installed in the virtual environment using
pip module. QEMU python test modules are also available in the environment for
spawning the QEMU based VMs.

It also introduces QEMU acpi/smbios biosbits python test script which is run
from within the python virtual environment.

Signed-off-by: Ani Sinha 
---
 tests/qtest/acpi-bits/acpi-bits-test-venv.sh |  59 
 tests/qtest/acpi-bits/acpi-bits-test.py  | 327 +++
 tests/qtest/acpi-bits/meson.build|  39 +++
 tests/qtest/acpi-bits/requirements.txt   |   1 +
 4 files changed, 426 insertions(+)
 create mode 100644 tests/qtest/acpi-bits/acpi-bits-test-venv.sh
 create mode 100644 tests/qtest/acpi-bits/acpi-bits-test.py
 create mode 100644 tests/qtest/acpi-bits/meson.build
 create mode 100644 tests/qtest/acpi-bits/requirements.txt

diff --git a/tests/qtest/acpi-bits/acpi-bits-test-venv.sh 
b/tests/qtest/acpi-bits/acpi-bits-test-venv.sh
new file mode 100644
index 00..124e03ce18
--- /dev/null
+++ b/tests/qtest/acpi-bits/acpi-bits-test-venv.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+# Generates a python virtual environment for the test to run.
+# Then runs python test scripts from within that virtual environment.
+#
+# 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 .
+#
+# Author: Ani Sinha 
+
+set -e
+
+MYPATH=$(realpath ${BASH_SOURCE:-$0})
+MYDIR=$(dirname $MYPATH)
+
+if [ -z "$QTEST_SOURCE_ROOT" ]; then
+echo -n "Please set QTEST_SOURCE_ROOT env pointing"
+echo " to the root of the qemu source tree."
+echo -n "This is required so that the test can find the "
+echo "python modules that it needs for execution."
+exit 1
+fi
+SRCDIR=$QTEST_SOURCE_ROOT
+TESTSCRIPTS=("acpi-bits-test.py")
+PIPCMD="-m pip -q --disable-pip-version-check"
+# we need to save the old value of PWD before we do a change-dir later
+QTEST_PWD=$PWD
+
+TESTS_PYTHON=/usr/bin/python3
+TESTS_VENV_REQ=requirements.txt
+
+# sadly for pip -e and -t options do not work together.
+# please see https://github.com/pypa/pip/issues/562
+cd $MYDIR
+
+$TESTS_PYTHON -m venv .
+$TESTS_PYTHON $PIPCMD install -e $SRCDIR/python/
+[ -f $TESTS_VENV_REQ ] && \
+$TESTS_PYTHON $PIPCMD install -r $TESTS_VENV_REQ
+
+# venv is activated at this point.
+
+# run the test
+for testscript in ${TESTSCRIPTS[@]} ; do
+export QTEST_PWD; python3 $testscript
+done
+
+cd $QTEST_PWD
+
+exit 0
diff --git a/tests/qtest/acpi-bits/acpi-bits-test.py 
b/tests/qtest/acpi-bits/acpi-bits-test.py
new file mode 100644
index 00..673567bf8e
--- /dev/null
+++ b/tests/qtest/acpi-bits/acpi-bits-test.py
@@ -0,0 +1,327 @@
+#!/usr/bin/env python3
+# group: rw quick
+# Exercize QEMU generated ACPI/SMBIOS tables using biosbits,
+# https://biosbits.org/
+#
+# 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 .
+#
+# Some parts are slightly taken from qtest.py and iotests.py
+#
+# Authors:
+#  Ani Sinha 
+
+# pylint: disable=invalid-name
+
+"""
+QEMU bios tests using biosbits available at
+https://biosbits.org/.
+"""
+
+import logging
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tarfile
+import tempfile
+import time
+import unittest
+import zipfile
+from typing import (
+List,
+Optional,
+Sequence,
+)
+from tap import TAPTestRunner
+from qemu.machine import QEMUMachine
+
+QTESTQEMUPROG = os.getenv('QTEST_QEMU_BINARY')
+QTEST_PWD = os.getenv('QTEST_PWD')
+
+def get_arch():
+"""finds the arch from the qemu binary name"""
+match = re.search('.*qemu-system-(.*)', QTESTQEMUPROG)
+if match:
+return match.group(1)

[PATCH 11/12] acpi/tests/bits: add README file for bits qtests

2022-06-27 Thread Ani Sinha
The README file is added describing the directory structure and the purpose
of every file it contains. It also describes how to add new tests, make changes
to existing tests or bits config files or regenerate the bits software.

Signed-off-by: Ani Sinha 
---
 tests/qtest/acpi-bits/README | 168 +++
 1 file changed, 168 insertions(+)
 create mode 100644 tests/qtest/acpi-bits/README

diff --git a/tests/qtest/acpi-bits/README b/tests/qtest/acpi-bits/README
new file mode 100644
index 00..97b15f1665
--- /dev/null
+++ b/tests/qtest/acpi-bits/README
@@ -0,0 +1,168 @@
+=
+ACPI/SMBIOS QTESTS USING BIOSBITS
+=
+
+Biosbits is a software written by Josh Triplett that can be downloaded by
+visiting https://biosbits.org/. The github codebase can be found here:
+https://github.com/biosbits/bits/tree/master. It is a software that exercizes
+the bios components such as acpi and smbios tables directly through acpica
+bios interpreter (a freely available C based library written by Intel,
+downloadable from https://acpica.org/ and is included with biosbits) without an
+operating system getting involved in between.
+There are several advantages to directly testing the bios in a real physical
+machine or VM as opposed to indirectly discovering bios issues through the
+operating system. For one thing, the OSes tend to hide bios problems from the
+end user. The other is that we have more control of what we wanted to test
+and how by directly using acpica interpreter on top of the bios on a running
+system. More details on the inspiration for developing biosbits and its real
+life uses can be found in (a) and (b).
+This directory contains QEMU qtests written in python that exercizes the QEMU
+bios components using biosbits and reports test failures.
+
+These tests use python virtual environment. In debian/ubuntu system, the tests
+would require python3.8-venv and python3-pip packages to be installed.
+
+A brief description of the contents of this directory follows:
+
+├── acpi-bits-test.py
+├── acpi-bits-test-venv.sh
+├── bits-config
+│   ├── bits-cfg.txt
+│   └── meson.build
+├── bits-tests
+│   ├── meson.build
+│   ├── smbios.py
+│   ├── smilatency.py
+│   ├── testacpi.py
+│   └── testcpuid.py
+├── meson.build
+├── prebuilt
+│   ├── bits-2095-grub.tar.gz
+│   ├── bits-2095.zip
+│   └── meson.build
+├── README
+└── requirements.txt
+
+acpi-bits:
+ - acpi-bits-test-venv.sh: This is a shell script that sets up the virtual
+   environment necessary for the actual python test script to run. Amongst
+   other things, it makes sure that QEMU python library is available within
+   that venv so that QEMU machines can be forked. QEMU python library can be
+   found within python/ directory in QEMU source.
+   After setting up the virtual environment, it runs the python test script
+   from within that environment.
+   If you want to enable verbose mode only for bits test and run make check,
+   one trick is to add V=1 before the call to execute the python script in
+   this file.
+ - acpi-bits-test.py: This is the main python test script that generates a
+   biosbits iso. It then spawns a QEMU VM with it, collects the logs and 
reports
+   test failures. This is the script one would be interested in if they wanted
+   to add or change some component of the log parsing, add a new commandline to
+   how QEMU is spawned etc. Test writers typically would not need to modify
+   this script unless they wanted to enhance or change the log parsing for
+   their tests.
+ - requirements.txt: This text file contains the dependent python libraries
+   needed for the tests to run. If a new dependent library is needed, it would
+   be added here as a new entry and then acpi-bits-test-venv.sh would install
+   it when setting up the python virtual environment using pip.
+ - README: This text file.
+
+acpi-bits/bits-config:
+   This location contains biosbits config files that determine how the software
+   runs the tests.
+ - bits-config.txt: this is the biosbits config file that determines what tests
+   or actions are performed by bits. The description of the config options are
+   provided in the file itself.
+
+acpi-bits/prebuilt:
+   This location contains prebuilt biosbits binaries that are used to generate
+   the bits iso file for testing.
+ - bits-2095.zip: The contents from this zip archive are the main contents of
+the iso file that are used for testing. This binary zip archive also
+contains the full source of the bits software including the full text of
+the license agreement listed here:
+https://github.com/biosbits/bits/blob/master/COPYING
+The source tarball can be found in this location in the zip file:
+boot/src/bits-2095.tar.gz
+The additional changes beyond those that are present in the official
+biosbits github re

[PATCH 12/12] MAINTAINERS: add myself as the maintainer for acpi biosbits qtests

2022-06-27 Thread Ani Sinha
I wrote the biosbits test framework, the qtest for testing QEMU with biosbits
and all the related changes. Making myself as the maintainer for biosbits
related files and test scripts.

Signed-off-by: Ani Sinha 
---
 MAINTAINERS | 5 +
 1 file changed, 5 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index aaa649a50d..f5358a1f96 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1860,6 +1860,11 @@ S: Supported
 F: hw/acpi/viot.c
 F: hw/acpi/viot.h
 
+ACPI/QTEST/BIOSBITS
+M: Ani Sinha 
+S: Supported
+F: tests/qtest/acpi-bits/*
+
 ACPI/HEST/GHES
 R: Dongjiu Geng 
 L: qemu-...@nongnu.org
-- 
2.25.1




Re: [RFC v3 4/5] file-posix: introduce get_sysfs_str_val for device zoned model.

2022-06-27 Thread Hannes Reinecke

On 6/27/22 02:19, Sam Li wrote:

---
  block/file-posix.c   | 60 
  include/block/block-common.h |  4 +--
  2 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/block/file-posix.c b/block/file-posix.c
index 73c2cdfbca..74c0245e0f 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1277,6 +1277,66 @@ out:
  #endif
  }
  
+/*

+ * Convert the zoned attribute file in sysfs to internal value.
+ */
+static zone_model get_sysfs_str_val(int fd, struct stat *st) {
+#ifdef CONFIG_LINUX
+char buf[32];
+char *sysfspath = NULL;
+int ret;
+int sysfd = -1;
+
+if (S_ISCHR(st->st_mode)) {
+if (ioctl(fd, SG_GET_SG_TABLESIZE, &ret) == 0) {
+return ret;
+}
+return -ENOTSUP;
+}
+
+if (!S_ISBLK(st->st_mode)) {
+return -ENOTSUP;
+}
+
+sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/zoned",
+major(st->st_rdev), minor(st->st_rdev));
+sysfd = open(sysfspath, O_RDONLY);
+if (sysfd == -1) {
+ret = -errno;
+goto out;
+}
+do {
+ret = read(sysfd, buf, sizeof(buf) - 1);
+} while (ret == -1 && errno == EINTR);


This is wrong.
read() might return a value smaller than the 'len' argument (sizeof(buf) 
-1 in your case). But in that case it's a short read, and one need to 
call 'read()' again to fetch the remaining bytes.


So the correct code would be something like:

offset = 0;
do {
ret = read(sysfd, buf + offset, sizeof(buf) - 1 + offset);
if (ret > 0)
offset += ret;
} while (ret > 0);

Not that you'd actually need it; reads from sysfs are basically never 
interrupted, so you should be able to read from an attribute in one go.

IE alternatively you can drop the 'while' loop and just call read().


+if (ret < 0) {
+ret = -errno;
+goto out;
+} else if (ret == 0) {
+ret = -EIO;
+goto out;
+}
+buf[ret] = 0;
+
+/* The file is ended with '\n' */


I'd rather check if the string ends with an '\n', and overwrite
it with a '\0'. That way you'd be insulated against any changes
to sysfs.


+if (strcmp(buf, "host-managed\n") == 0) {
+return BLK_Z_HM;
+} else if (strcmp(buf, "host-aware\n") == 0) {
+return BLK_Z_HA;
+} else {
+return -ENOTSUP;
+}
+
+out:
+if (sysfd != -1) {
+close(sysfd);
+}
+g_free(sysfspath);
+return ret;
+#else
+return -ENOTSUP;
+#endif
+}
+
  static int hdev_get_max_segments(int fd, struct stat *st) {
  int ret;
  ret = get_sysfs_long_val(fd, st, "max_segments");


And as you already set a precedent in your previous patch, I'd recommend 
split this in two patches, one introducing a generic function 
'get_sysfs_str_val()' which returns a string and another function
(eg hdev_get_zone_model()) which calls this function to fetch the device 
zoned model.



diff --git a/include/block/block-common.h b/include/block/block-common.h
index 78cddeeda5..35e00afe8e 100644
--- a/include/block/block-common.h
+++ b/include/block/block-common.h
@@ -56,8 +56,8 @@ typedef enum zone_op {
  } zone_op;
  
  typedef enum zone_model {

-BLK_Z_HM,
-BLK_Z_HA,
+BLK_Z_HM = 0x1,
+BLK_Z_HA = 0x2,
  } zone_model;
  
  typedef enum BlkZoneCondition {


Cheers,

Hannes
--
Dr. Hannes ReineckeKernel Storage Architect
h...@suse.de  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer



[PATCH 10/12] acpi/tests/bits: add acpi bits qtest directory in meson for running tests

2022-06-27 Thread Ani Sinha
added acpi-bits subdirectory in meson.build so that the tests in that
subdirectory can be run as a part of make check.

Signed-off-by: Ani Sinha 
---
 tests/qtest/acpi-bits/acpi-bits-test.py | 4 ++--
 tests/qtest/meson.build | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/acpi-bits/acpi-bits-test.py 
b/tests/qtest/acpi-bits/acpi-bits-test.py
index 673567bf8e..ef4ace8028 100644
--- a/tests/qtest/acpi-bits/acpi-bits-test.py
+++ b/tests/qtest/acpi-bits/acpi-bits-test.py
@@ -244,9 +244,9 @@ def parse_log(self):
 
 if os.getenv('V'):
 print('\nlogs from biosbits follows:')
-print('==\n\n')
+print('==\n')
 print(log)
-print('\n==\n')
+print('==\n')
 
 matchiter = re.finditer(r'(.*Summary: )(\d+ passed), (\d+ failed).*',
 log)
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index ad52f1c81b..2c72c42933 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -312,6 +312,8 @@ endif
 qtest_executables = {}
 other_deps = []
 
+subdir('acpi-bits')
+
 foreach dir : target_dirs
   if not dir.endswith('-softmmu')
 continue
-- 
2.25.1




Re: [PATCH v2 00/11] vfio/migration: Implement VFIO migration protocol v2

2022-06-27 Thread Avihai Horon



On 6/18/2022 12:51 AM, Alex Williamson wrote:

External email: Use caution opening links or attachments


On Mon, 13 Jun 2022 14:21:26 +0300
Avihai Horon  wrote:


On 6/8/2022 12:32 AM, Alex Williamson wrote:

External email: Use caution opening links or attachments


On Tue, 7 Jun 2022 20:44:23 +0300
Avihai Horon  wrote:


On 5/30/2022 8:07 PM, Avihai Horon wrote:

Hello,

Following VFIO migration protocol v2 acceptance in kernel, this series
implements VFIO migration according to the new v2 protocol and replaces
the now deprecated v1 implementation.

The main differences between v1 and v2 migration protocols are:
1. VFIO device state is represented as a finite state machine instead of
  a bitmap.

2. The migration interface with kernel is done using VFIO_DEVICE_FEATURE
  ioctl and normal read() and write() instead of the migration region
  used in v1.

3. Migration protocol v2 currently doesn't support the pre-copy phase of
  migration.

Full description of the v2 protocol and the differences from v1 can be
found here [1].

Patches 1-3 are prep patches fixing bugs and adding QEMUFile function
that will be used later.

Patches 4-6 refactor v1 protocol code to make it easier to add v2
protocol.

Patches 7-11 implement v2 protocol and remove v1 protocol.

Thanks.

[1]
https://lore.kernel.org/all/20220224142024.147653-10-yish...@nvidia.com/

Changes from v1: 
https://lore.kernel.org/all/20220512154320.19697-1-avih...@nvidia.com/
- Split the big patch that replaced v1 with v2 into several patches as
 suggested by Joao, to make review easier.
- Change warn_report to warn_report_once when container doesn't support
 dirty tracking.
- Add Reviewed-by tag.

Avihai Horon (11):
 vfio/migration: Fix NULL pointer dereference bug
 vfio/migration: Skip pre-copy if dirty page tracking is not supported
 migration/qemu-file: Add qemu_file_get_to_fd()
 vfio/common: Change vfio_devices_all_running_and_saving() logic to
   equivalent one
 vfio/migration: Move migration v1 logic to vfio_migration_init()
 vfio/migration: Rename functions/structs related to v1 protocol
 vfio/migration: Implement VFIO migration protocol v2
 vfio/migration: Remove VFIO migration protocol v1
 vfio/migration: Reset device if setting recover state fails
 vfio: Alphabetize migration section of VFIO trace-events file
 docs/devel: Align vfio-migration docs to VFIO migration v2

docs/devel/vfio-migration.rst |  77 ++--
hw/vfio/common.c  |  21 +-
hw/vfio/migration.c   | 640 --
hw/vfio/trace-events  |  25 +-
include/hw/vfio/vfio-common.h |   8 +-
migration/migration.c |   5 +
migration/migration.h |   3 +
migration/qemu-file.c |  34 ++
migration/qemu-file.h |   1 +
9 files changed, 252 insertions(+), 562 deletions(-)


Ping.

Based on the changelog, this seems like a mostly cosmetic spin and I
don't see that all of the discussion threads from v1 were resolved to
everyone's satisfaction.  I'm certainly still uncomfortable with the
pre-copy behavior and I thought there were still some action items to
figure out whether an SLA is present and vet the solution with
management tools.  Thanks,

Yes.
OK, so let's clear things up and reach an agreement before I prepare the
v3 series.

There are three topics that came up in previous discussion:

  1. [PATCH v2 01/11] vfio/migration: Fix NULL pointer dereference bug.
 Juan gave his Reviewed-by but he wasn't sure about qemu_file_* usage
 outside migration thread.
 This code existed before and I fixed a NULL pointer dereference that
 I encountered.
 I suggested that later we can refactor VMChangeStateHandler to
 return error.
 I prefer not to do this refactor right now because I am not sure
 it's as straightforward change as it might seem - if some notifier
 fails and we abort do_vm_stop/vm_prepare_start in the middle, can
 this leave the VM in some unstable state?
 We plan to leave it as is and not do the refactor as part of this
 series.
 Are you ok with this?

I'll defer to Juan here, it's not 100% clear to me from the last reply
if he's looking for that sooner than later.  Juan?



  3. [PATCH v2 03/11] migration/qemu-file: Add qemu_file_get_to_fd().
 Juan expressed his concern about the amount of data that will go
 through main migration thread.

This is already the case in v1 protocol - VFIO devices send all their
data in the main migration thread. Note that like in v1 protocol, here
as well the data is sent in small sized chunks, each with a header.
This patch just aims to eliminate an extra copy.

We plan to leave it as is. Is this ok?

I don't think we should lean too heavily on this being a bump from v1 to
v2 protocol as v1 was only ever experimental and hasn't been widely
used in practice AFAIK.  Again, I'll defer to the migration folks for
this,

Re: [RFC v3 3/5] file-posix: introduce get_sysfs_long_val for zoned device information.

2022-06-27 Thread Hannes Reinecke

On 6/27/22 02:19, Sam Li wrote:

Use sysfs attribute files to get the zoned device information in case
that ioctl() commands of zone management interface won't work. It can
return long type of value like chunk_sectors, zoned_append_max_bytes,
max_open_zones, max_active_zones.
---
  block/file-posix.c | 37 +
  1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/block/file-posix.c b/block/file-posix.c
index 1b8b0d351f..73c2cdfbca 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1216,15 +1216,19 @@ static int hdev_get_max_hw_transfer(int fd, struct stat 
*st)
  #endif
  }
  
-static int hdev_get_max_segments(int fd, struct stat *st)

-{
+/*
+ * Get zoned device information (chunk_sectors, zoned_append_max_bytes,
+ * max_open_zones, max_active_zones) through sysfs attribute files.
+ */
+static long get_sysfs_long_val(int fd, struct stat *st,
+   const char *attribute) {
  #ifdef CONFIG_LINUX
  char buf[32];
  const char *end;
  char *sysfspath = NULL;
  int ret;
  int sysfd = -1;
-long max_segments;
+long val;
  
  if (S_ISCHR(st->st_mode)) {

  if (ioctl(fd, SG_GET_SG_TABLESIZE, &ret) == 0) {
@@ -1237,8 +1241,9 @@ static int hdev_get_max_segments(int fd, struct stat *st)
  return -ENOTSUP;
  }
  
-sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments",

-major(st->st_rdev), minor(st->st_rdev));
+sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/%s",
+major(st->st_rdev), minor(st->st_rdev),
+attribute);
  sysfd = open(sysfspath, O_RDONLY);
  if (sysfd == -1) {
  ret = -errno;
@@ -1256,9 +1261,9 @@ static int hdev_get_max_segments(int fd, struct stat *st)
  }
  buf[ret] = 0;
  /* The file is ended with '\n', pass 'end' to accept that. */
-ret = qemu_strtol(buf, &end, 10, &max_segments);
+ret = qemu_strtol(buf, &end, 10, &val);
  if (ret == 0 && end && *end == '\n') {
-ret = max_segments;
+ret = val;
  }
  
  out:

@@ -1272,6 +1277,15 @@ out:
  #endif
  }
  
+static int hdev_get_max_segments(int fd, struct stat *st) {

+int ret;
+ret = get_sysfs_long_val(fd, st, "max_segments");
+if (ret < 0) {
+return -1;
+}
+return ret;
+}
+
  static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
  {
  BDRVRawState *s = bs->opaque;
@@ -1872,6 +1886,7 @@ static int handle_aiocb_zone_report(void *opaque) {
  
  static int handle_aiocb_zone_mgmt(void *opaque) {

  RawPosixAIOData *aiocb = opaque;
+BlockDriverState *s = aiocb->bs;
  int fd = aiocb->aio_fildes;
  int64_t offset = aiocb->aio_offset;
  int64_t len = aiocb->aio_nbytes;
@@ -1884,11 +1899,9 @@ static int handle_aiocb_zone_mgmt(void *opaque) {
  int64_t zone_size_mask;
  int ret;
  
-ret = ioctl(fd, BLKGETZONESZ, &zone_size);

-if (ret) {
-return -1;
-}
-
+g_autofree struct stat *file = g_new(struct stat, 1);
+stat(s->filename, file);
+zone_size = get_sysfs_long_val(fd, file, "chunk_sectors");
  zone_size_mask = zone_size - 1;
  if (offset & zone_size_mask) {
  error_report("offset is not the start of a zone");


Round of applause.

Reviewed-by: Hannes Reinecke 

Cheers,

Hannes
--
Dr. Hannes ReineckeKernel Storage Architect
h...@suse.de  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer



Re: [PATCH 00/12] Introduce new acpi/smbios qtests using biosbits

2022-06-27 Thread Ani Sinha
On Mon, Jun 27, 2022 at 12:25 PM Ani Sinha  wrote:
>
> On Mon, Jun 27, 2022 at 12:22 PM Ani Sinha  wrote:
> >
> > On Mon, Jun 27, 2022 at 12:14 PM Ani Sinha  wrote:
> > >
> > > Biosbits is a software written by Josh Triplett that can be downloaded by
> > > visiting https://biosbits.org/. The github codebase can be found here:
> > > https://github.com/biosbits/bits/tree/master. It is a software that 
> > > exercizes
> > > the bios components such as acpi and smbios tables directly through acpica
> > > bios interpreter (a freely available C based library written by Intel,
> > > downloadable from https://acpica.org/ and is included with biosbits) 
> > > without an
> > > operating system getting involved in between.
> > > There are several advantages to directly testing the bios in a real 
> > > physical
> > > machine or VM as opposed to indirectly discovering bios issues through the
> > > operating system. For one thing, the OSes tend to hide bios problems from 
> > > the
> > > end user. The other is that we have more control of what we wanted to test
> > > and how by directly using acpica interpreter on top of the bios on a 
> > > running
> > > system. More details on the inspiration for developing biosbits and its 
> > > real
> > > life uses can be found in (a) and (b).
> > > This patchset contains QEMU qtests written in python that exercizes the 
> > > QEMU
> > > bios components using biosbits and reports test failures.
> > >
> > > Details of each of the files added by this patchset are provided in the 
> > > README
> > > file which is part of Patch 11. Every effort to contact Josh, through 
> > > various
> > > means including email, twitter, linkedIn etc has failed. Hence, the 
> > > changes to
> > > build biosbits with the newer compiler, upgrade acpica and other changes 
> > > are
> > > currently maintained in a forked project in my personal github. We may 
> > > want to
> > > maintain bits in a separate fork in a stable repository that is 
> > > accessible by
> > > QEMU developers.
> > >
> > > The newly introduced qtest currently only run for x86_64 platform. They 
> > > pass
> > > both when running make check on a baremetal box as well as from inside a 
> > > vm.
> > >
> > > Thanks to Igor M for pointing me to this work.
> > >
> > > (a) 
> > > https://blog.linuxplumbersconf.org/2011/ocw/system/presentations/867/original/bits.pdf
> > > (b) https://www.youtube.com/watch?v=36QIepyUuhg
> >
> > Doh, sending the patch series failed since google won't allow file
> > sizes larger than 25 MB. The bits prebuilt binaries have sizes 30 MB
> > and 40 MB in two separate patches :(
>
> I have pushed the patchset here:
> https://gitlab.com/anisinha/qemu/-/commits/acpi-bits .

I have re-sent all the patches except patches 2 and 3 that contain
pre-built biosbits archives. For those two patches, please see the
gitlab repo above.

>
> >
> > >
> > > Ani Sinha (12):
> > >   qtest: meson.build changes required to integrate python based qtests
> > >   acpi/tests/bits: add prebuilt bios bits zip archive
> > >   acpi/tests/bits: add prebuilt bits generated grub modules and scripts
> > >   acpi/tests/bits: initial commit of test scripts that are run by
> > > biosbits
> > >   acpi/tests/bits: disable acpi PSS tests that are failing in biosbits
> > >   acpi/tests/bits: add smilatency test suite from bits in order to
> > > disable it
> > >   acpi/tests/bits: disable smilatency test since it does not pass
> > > everytime
> > >   acpi/tests/bits: add biosbits config file for running bios tests
> > >   acpi/tests/bits: add acpi and smbios python tests that uses biosbits
> > >   acpi/tests/bits: add acpi bits qtest directory in meson for running
> > > tests
> > >   acpi/tests/bits: add README file for bits qtests
> > >   MAINTAINERS: add myself as the maintainer for acpi biosbits qtests
> > >
> > >  MAINTAINERS   |5 +
> > >  tests/qtest/acpi-bits/README  |  168 ++
> > >  tests/qtest/acpi-bits/acpi-bits-test-venv.sh  |   59 +
> > >  tests/qtest/acpi-bits/acpi-bits-test.py   |  327 +++
> > >  .../qtest/acpi-bits/bits-config/bits-cfg.txt  |   18 +
> > >  tests/qtest/acpi-bits/bits-config/meson.build |   11 +
> > >  tests/qtest/acpi-bits/bits-tests/meson.build  |   11 +
> > >  tests/qtest/acpi-bits/bits-tests/smbios.py| 2430 +
> > >  .../qtest/acpi-bits/bits-tests/smilatency.py  |  103 +
> > >  tests/qtest/acpi-bits/bits-tests/testacpi.py  |  283 ++
> > >  tests/qtest/acpi-bits/bits-tests/testcpuid.py |   83 +
> > >  tests/qtest/acpi-bits/meson.build |   39 +
> > >  .../acpi-bits/prebuilt/bits-2095-grub.tar.gz  |  Bin 0 -> 41416278 bytes
> > >  tests/qtest/acpi-bits/prebuilt/bits-2095.zip  |  Bin 0 -> 31922898 bytes
> > >  tests/qtest/acpi-bits/prebuilt/meson.build|   11 +
> > >  tests/qtest/acpi-bits/requirements.txt|1 +
> > >  tests/qtest/meson.build   |7 +-
> > >  17 files changed, 3555 inserti

Re: [RFC v3 1/5] block: add block layer APIs resembling Linux ZonedBlockDevice ioctls.

2022-06-27 Thread Sam Li
Hi Hannes,

Hannes Reinecke  于2022年6月27日周一 15:21写道:

>
> On 6/27/22 02:19, Sam Li wrote:
> > By adding zone management operations in BlockDriver, storage
> > controller emulation can use the new block layer APIs including
> > zone_report and zone_mgmt(open, close, finish, reset).
> > ---
> >   block/block-backend.c|  56 
> >   block/coroutines.h   |   5 +
> >   block/file-posix.c   | 238 +++
> >   include/block/block-common.h |  43 +-
> >   include/block/block_int-common.h |  20 +++
> >   5 files changed, 361 insertions(+), 1 deletion(-)
> >
> > diff --git a/block/block-backend.c b/block/block-backend.c
> > index e0e1aff4b1..786f964d02 100644
> > --- a/block/block-backend.c
> > +++ b/block/block-backend.c
> > @@ -1810,6 +1810,62 @@ int blk_flush(BlockBackend *blk)
> >   return ret;
> >   }
> >
> > +/*
> > + * Return zone_report from BlockDriver. Offset can be any number within
> > + * the zone size. No alignment for offset and len.
> > + */
> > +int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset,
> > +   int64_t len, int64_t *nr_zones,
> > +   BlockZoneDescriptor *zones)
> > +{
> > +int ret;
> > +BlockDriverState *bs;
> > +IO_CODE();
> > +
> > +blk_inc_in_flight(blk); /* increase before waiting */
> > +blk_wait_while_drained(blk);
> > +bs = blk_bs(blk);
> > +
> > +ret = blk_check_byte_request(blk, offset, len);
> > +if (ret < 0) {
> > +return ret;
> > +}
> > +
> > +bdrv_inc_in_flight(bs);
> > +ret = bdrv_co_zone_report(blk->root->bs, offset, len,
> > +  nr_zones, zones);
> > +bdrv_dec_in_flight(bs);
> > +blk_dec_in_flight(blk);
> > +return ret;
> > +}
> > +
> > +/*
> > + * Return zone_mgmt from BlockDriver.
> > + * Offset is the start of a zone and len is aligned to zones.
> > + */
> > +int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, enum zone_op op,
> > +int64_t offset, int64_t len)
> > +{
> > +int ret;
> > +BlockDriverState *bs;
> > +IO_CODE();
> > +
> > +blk_inc_in_flight(blk);
> > +blk_wait_while_drained(blk);
> > +bs = blk_bs(blk);
> > +
> > +ret = blk_check_byte_request(blk, offset, len);
> > +if (ret < 0) {
> > +return ret;
> > +}
> > +
> > +bdrv_inc_in_flight(bs);
> > +ret = bdrv_co_zone_mgmt(blk->root->bs, op, offset, len);
> > +bdrv_dec_in_flight(bs);
> > +blk_dec_in_flight(blk);
> > +return ret;
> > +}
> > +
> >   void blk_drain(BlockBackend *blk)
> >   {
> >   BlockDriverState *bs = blk_bs(blk);
> > diff --git a/block/coroutines.h b/block/coroutines.h
> > index 830ecaa733..a114d7bc30 100644
> > --- a/block/coroutines.h
> > +++ b/block/coroutines.h
> > @@ -80,6 +80,11 @@ int coroutine_fn
> >   blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
> >
> >   int coroutine_fn blk_co_do_flush(BlockBackend *blk);
> > +int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset,
> > +int64_t len, int64_t *nr_zones,
> > +BlockZoneDescriptor *zones);
> > +int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, enum zone_op op,
> > +int64_t offset, int64_t len);
> >
> >
> >   /*
> > diff --git a/block/file-posix.c b/block/file-posix.c
> > index 48cd096624..1b8b0d351f 100644
> > --- a/block/file-posix.c
> > +++ b/block/file-posix.c
> > @@ -67,6 +67,7 @@
> >   #include 
> >   #include 
> >   #include 
> > +#include 
> >   #include 
> >   #include 
> >   #include 
> > @@ -216,6 +217,11 @@ typedef struct RawPosixAIOData {
> >   PreallocMode prealloc;
> >   Error **errp;
> >   } truncate;
> > +struct {
> > +int64_t *nr_zones;
> > +BlockZoneDescriptor *zones;
> > +} zone_report;
> > +zone_op op;
> >   };
> >   } RawPosixAIOData;
> >
> > @@ -1801,6 +1807,135 @@ static off_t copy_file_range(int in_fd, off_t 
> > *in_off, int out_fd,
> >   }
> >   #endif
> >
> > +/*
> > + * parse_zone - Fill a zone descriptor
> > + */
> > +static inline void parse_zone(struct BlockZoneDescriptor *zone,
> > +  struct blk_zone *blkz) {
> > +zone->start = blkz->start;
> > +zone->length = blkz->len;
> > +zone->cap = blkz->capacity;
> > +zone->wp = blkz->wp - blkz->start;
> > +zone->type = blkz->type;
> > +zone->cond = blkz->cond;
> > +}
> > +
> > +static int handle_aiocb_zone_report(void *opaque) {
> > +RawPosixAIOData *aiocb = opaque;
> > +int fd = aiocb->aio_fildes;
> > +int64_t *nr_zones = aiocb->zone_report.nr_zones;
> > +BlockZoneDescriptor *zones = aiocb->zone_report.zones;
> > +int64_t offset = aiocb->aio_offset;
> > +int64_t len = aiocb->aio_nbytes;
> > +
> > +struct blk_zone *blkz;
> > +int64_t rep_size, nrz;
> > +int ret, n = 0, i = 0;
> > +
> 

Re: [RFC PATCH v3] RISC-V: Add Zawrs ISA extension support

2022-06-27 Thread Christoph Müllner
On Mon, Jun 27, 2022 at 7:20 AM Alistair Francis 
wrote:

> On Fri, Jun 24, 2022 at 1:31 AM Christoph Muellner
>  wrote:
> >
> > This patch adds support for the Zawrs ISA extension.
> > Given the current (incomplete) implementation of reservation sets
> > there seems to be no way to provide a full emulation of the WRS
> > instruction (wake on reservation set invalidation or timeout or
> > interrupt). Therefore, we just pretend that an interrupt occured,
> > exit the execution loop and finally continue execution.
> >
> > The specification can be found here:
> > https://github.com/riscv/riscv-zawrs/blob/main/zawrs.adoc
> >
> > Note, that the Zawrs extension is not frozen or ratified yet.
> > Therefore this patch is an RFC and not intended to get merged.
> >
> > Changes since v2:
> > * Adjustments according to a specification change
> > * Inline REQUIRE_ZAWRS() since it has only one user
> >
> > Changes since v1:
> > * Adding zawrs to the ISA string that is passed to the kernel
> >
> > Signed-off-by: Christoph Müllner 
> > ---
> >  target/riscv/cpu.c  |  2 +
> >  target/riscv/cpu.h  |  1 +
> >  target/riscv/insn32.decode  |  4 ++
> >  target/riscv/insn_trans/trans_rvzawrs.c.inc | 54 +
> >  target/riscv/translate.c|  1 +
> >  5 files changed, 62 insertions(+)
> >  create mode 100644 target/riscv/insn_trans/trans_rvzawrs.c.inc
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 05e6521351..6cb00fadff 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -882,6 +882,7 @@ static Property riscv_cpu_extensions[] = {
> >  DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
> >  DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
> >  DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
> > +DEFINE_PROP_BOOL("zawrs", RISCVCPU, cfg.ext_zawrs, true),
>
> Would this be enabled by default?
>

The "true" was a personal preference (I prefer to keep the argument list
for QEMU short)
and I did not see any conflicts with existing behavior (no code should
break).
If you prefer otherwise or if I missed a policy I will change it.


>
> >  DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
> >  DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false),
> >  DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false),
> > @@ -1075,6 +1076,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu,
> char **isa_str, int max_str_len)
> >  ISA_EDATA_ENTRY(zicsr, ext_icsr),
> >  ISA_EDATA_ENTRY(zifencei, ext_ifencei),
> >  ISA_EDATA_ENTRY(zmmul, ext_zmmul),
> > +ISA_EDATA_ENTRY(zawrs, ext_zawrs),
> >  ISA_EDATA_ENTRY(zfh, ext_zfh),
> >  ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
> >  ISA_EDATA_ENTRY(zfinx, ext_zfinx),
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index 7d6397acdf..a22bc0fa09 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -380,6 +380,7 @@ struct RISCVCPUConfig {
> >  bool ext_h;
> >  bool ext_j;
> >  bool ext_v;
> > +bool ext_zawrs;
> >  bool ext_zba;
> >  bool ext_zbb;
> >  bool ext_zbc;
> > diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> > index 4033565393..513ea227fe 100644
> > --- a/target/riscv/insn32.decode
> > +++ b/target/riscv/insn32.decode
> > @@ -711,6 +711,10 @@ vsetvli 0 ... . 111 .
> 1010111  @r2_zimm11
> >  vsetivli11 .. . 111 . 1010111  @r2_zimm10
> >  vsetvl  100 . . 111 . 1010111  @r
> >
> > +# *** Zawrs Standard Extension ***
> > +wrs_nto1101 0 000 0 1110011
> > +wrs_sto00011101 0 000 0 1110011
> > +
> >  # *** RV32 Zba Standard Extension ***
> >  sh1add 001 .. 010 . 0110011 @r
> >  sh2add 001 .. 100 . 0110011 @r
> > diff --git a/target/riscv/insn_trans/trans_rvzawrs.c.inc
> b/target/riscv/insn_trans/trans_rvzawrs.c.inc
> > new file mode 100644
> > index 00..d0df56378e
> > --- /dev/null
> > +++ b/target/riscv/insn_trans/trans_rvzawrs.c.inc
> > @@ -0,0 +1,54 @@
> > +/*
> > + * RISC-V translation routines for the RISC-V Zawrs Extension.
> > + *
> > + * Copyright (c) 2022 Christoph Muellner, christoph.muell...@vrull.io
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> it
> > + * under the terms and conditions of the GNU General Public License,
> > + * version 2 or later, as published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope 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
> > + *

Re: [RFC v3 3/5] file-posix: introduce get_sysfs_long_val for zoned device information.

2022-06-27 Thread Sam Li
Hannes Reinecke  于2022年6月27日周一 15:31写道:
>
> On 6/27/22 02:19, Sam Li wrote:
> > Use sysfs attribute files to get the zoned device information in case
> > that ioctl() commands of zone management interface won't work. It can
> > return long type of value like chunk_sectors, zoned_append_max_bytes,
> > max_open_zones, max_active_zones.
> > ---
> >   block/file-posix.c | 37 +
> >   1 file changed, 25 insertions(+), 12 deletions(-)
> >
> > diff --git a/block/file-posix.c b/block/file-posix.c
> > index 1b8b0d351f..73c2cdfbca 100644
> > --- a/block/file-posix.c
> > +++ b/block/file-posix.c
> > @@ -1216,15 +1216,19 @@ static int hdev_get_max_hw_transfer(int fd, struct 
> > stat *st)
> >   #endif
> >   }
> >
> > -static int hdev_get_max_segments(int fd, struct stat *st)
> > -{
> > +/*
> > + * Get zoned device information (chunk_sectors, zoned_append_max_bytes,
> > + * max_open_zones, max_active_zones) through sysfs attribute files.
> > + */
> > +static long get_sysfs_long_val(int fd, struct stat *st,
> > +   const char *attribute) {
> >   #ifdef CONFIG_LINUX
> >   char buf[32];
> >   const char *end;
> >   char *sysfspath = NULL;
> >   int ret;
> >   int sysfd = -1;
> > -long max_segments;
> > +long val;
> >
> >   if (S_ISCHR(st->st_mode)) {
> >   if (ioctl(fd, SG_GET_SG_TABLESIZE, &ret) == 0) {
> > @@ -1237,8 +1241,9 @@ static int hdev_get_max_segments(int fd, struct stat 
> > *st)
> >   return -ENOTSUP;
> >   }
> >
> > -sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments",
> > -major(st->st_rdev), minor(st->st_rdev));
> > +sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/%s",
> > +major(st->st_rdev), minor(st->st_rdev),
> > +attribute);
> >   sysfd = open(sysfspath, O_RDONLY);
> >   if (sysfd == -1) {
> >   ret = -errno;
> > @@ -1256,9 +1261,9 @@ static int hdev_get_max_segments(int fd, struct stat 
> > *st)
> >   }
> >   buf[ret] = 0;
> >   /* The file is ended with '\n', pass 'end' to accept that. */
> > -ret = qemu_strtol(buf, &end, 10, &max_segments);
> > +ret = qemu_strtol(buf, &end, 10, &val);
> >   if (ret == 0 && end && *end == '\n') {
> > -ret = max_segments;
> > +ret = val;
> >   }
> >
> >   out:
> > @@ -1272,6 +1277,15 @@ out:
> >   #endif
> >   }
> >
> > +static int hdev_get_max_segments(int fd, struct stat *st) {
> > +int ret;
> > +ret = get_sysfs_long_val(fd, st, "max_segments");
> > +if (ret < 0) {
> > +return -1;
> > +}
> > +return ret;
> > +}
> > +
> >   static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
> >   {
> >   BDRVRawState *s = bs->opaque;
> > @@ -1872,6 +1886,7 @@ static int handle_aiocb_zone_report(void *opaque) {
> >
> >   static int handle_aiocb_zone_mgmt(void *opaque) {
> >   RawPosixAIOData *aiocb = opaque;
> > +BlockDriverState *s = aiocb->bs;
> >   int fd = aiocb->aio_fildes;
> >   int64_t offset = aiocb->aio_offset;
> >   int64_t len = aiocb->aio_nbytes;
> > @@ -1884,11 +1899,9 @@ static int handle_aiocb_zone_mgmt(void *opaque) {
> >   int64_t zone_size_mask;
> >   int ret;
> >
> > -ret = ioctl(fd, BLKGETZONESZ, &zone_size);
> > -if (ret) {
> > -return -1;
> > -}
> > -
> > +g_autofree struct stat *file = g_new(struct stat, 1);
> > +stat(s->filename, file);
> > +zone_size = get_sysfs_long_val(fd, file, "chunk_sectors");
> >   zone_size_mask = zone_size - 1;
> >   if (offset & zone_size_mask) {
> >   error_report("offset is not the start of a zone");
>
> Round of applause.
>
Thanks! It was based on Damien's suggestion.

> Reviewed-by: Hannes Reinecke 
>
> Cheers,
>
> Hannes
> --
> Dr. Hannes ReineckeKernel Storage Architect
> h...@suse.de  +49 911 74053 688
> SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
> HRB 36809 (AG Nürnberg), GF: Felix Imendörffer



Re: [RFC v3 2/5] qemu-io: add zoned block device operations.

2022-06-27 Thread Sam Li
Hannes Reinecke  于2022年6月27日周一 15:30写道:
>
> On 6/27/22 02:19, Sam Li wrote:
> > ---
>
> Good coding style would advise to add some text here what the patch does.
>
> >   block/io.c   |  21 +++
> >   include/block/block-io.h |  13 +
> >   qemu-io-cmds.c   | 121 +++
> >   3 files changed, 155 insertions(+)
> >
> > diff --git a/block/io.c b/block/io.c
> > index 789e6373d5..656a1b7271 100644
> > --- a/block/io.c
> > +++ b/block/io.c
> > @@ -3258,6 +3258,27 @@ out:
> >   return co.ret;
> >   }
> >
> > +int bdrv_co_zone_report(BlockDriverState *bs, int64_t offset,
> > +int64_t len, int64_t *nr_zones,
> > +BlockZoneDescriptor *zones)
> > +{
> > +if (!bs->drv->bdrv_co_zone_report) {
> > +return -ENOTSUP;
>
> ENOTSUP or EOPNOTSUP?
> Kevin?
>
> > +}
> > +
> > +return bs->drv->bdrv_co_zone_report(bs, offset, len, nr_zones, zones);
> > +}
> > +
> > +int bdrv_co_zone_mgmt(BlockDriverState *bs, enum zone_op op,
> > +int64_t offset, int64_t len)
> > +{
> > +if (!bs->drv->bdrv_co_zone_mgmt) {
> > +return -ENOTSUP;
> > +}
> > +
> > +return bs->drv->bdrv_co_zone_mgmt(bs, op, offset, len);
> > +}
> > +
> >   void *qemu_blockalign(BlockDriverState *bs, size_t size)
> >   {
> >   IO_CODE();
> > diff --git a/include/block/block-io.h b/include/block/block-io.h
> > index 62c84f0519..c85c174579 100644
> > --- a/include/block/block-io.h
> > +++ b/include/block/block-io.h
> > @@ -80,6 +80,13 @@ int bdrv_co_ioctl(BlockDriverState *bs, int req, void 
> > *buf);
> >   /* Ensure contents are flushed to disk.  */
> >   int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
> >
> > +/* Report zone information of zone block device. */
> > +int coroutine_fn bdrv_co_zone_report(BlockDriverState *bs, int64_t offset,
> > + int64_t len, int64_t *nr_zones,
> > + BlockZoneDescriptor *zones);
> > +int coroutine_fn bdrv_co_zone_mgmt(BlockDriverState *bs, zone_op op,
> > +int64_t offset, int64_t len);
> > +
>
> There's the thing with the intendation ... please make it consistent,
> and ideally follow with whatever the remaining prototypes do.
>
> >   int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
> >   bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
> >   int bdrv_block_status(BlockDriverState *bs, int64_t offset,
> > @@ -290,6 +297,12 @@ bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector 
> > *qiov, int64_t pos);
> >   int generated_co_wrapper
> >   bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t 
> > pos);
> >
> > +int generated_co_wrapper blk_zone_report(BlockBackend *blk, int64_t offset,
> > + int64_t len, int64_t *nr_zones,
> > + BlockZoneDescriptor *zones);
> > +int generated_co_wrapper blk_zone_mgmt(BlockBackend *blk, enum zone_op op,
> > +int64_t offset, int64_t len);
> > +
>
> Again here.
>
> >   /**
> >* bdrv_parent_drained_begin_single:
> >*
> > diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
> > index 2f0d8ac25a..3f2592b9f5 100644
> > --- a/qemu-io-cmds.c
> > +++ b/qemu-io-cmds.c
> > @@ -1706,6 +1706,122 @@ static const cmdinfo_t flush_cmd = {
> >   .oneline= "flush all in-core file state to disk",
> >   };
> >
> > +static int zone_report_f(BlockBackend *blk, int argc, char **argv)
> > +{
> > +int ret;
> > +int64_t offset, len, nr_zones;
> > +int i = 0;
> > +
> > +++optind;
> > +offset = cvtnum(argv[optind]);
> > +++optind;
> > +len = cvtnum(argv[optind]);
> > +++optind;
> > +nr_zones = cvtnum(argv[optind]);
> > +
> And 'optind' is set where?

optind is declared in getopt_core.h.

> Plus do check for 'argv' overflow; before increasing 'optind' and using
> 'argv[optind]' you have to validate that 'argv[optind]' is a valid pointer.
>

Maybe we can check if argc is bigger than what we want?


> > +g_autofree BlockZoneDescriptor *zones = g_new(BlockZoneDescriptor, 
> > nr_zones);
> > +ret = blk_zone_report(blk, offset, len, &nr_zones, zones);
> > +while (i < nr_zones) {
> > +fprintf(stdout, "start: 0x%lx, len 0x%lx, cap 0x%lx, wptr 0x%lx, "
> > +"zcond:%u, [type: %u]\n",
> > +zones[i].start, zones[i].length, zones[i].cap, zones[i].wp,
> > +zones[i].cond, zones[i].type);
> > +++i;
> As 'i' is a simple iterator maybe use a 'for' loop here.
> But that really is a matter of preference :-)
>
Ok!

> > +}
> > +return ret;
> > +}
> > +
> > +static const cmdinfo_t zone_report_cmd = {
> > +.name = "zone_report",
> > +.altname = "f",
>
> altname 'f'?
> Is that correct?
>
No, it's not. I misunderstood altname's meaning. Changed it now.

> > +.cfunc = zone_report_f,
> > +.argmin = 3,
> > +  

Re: [PULL v2 10/20] libvduse: Add VDUSE (vDPA Device in Userspace) library

2022-06-27 Thread Yongji Xie
On Mon, Jun 27, 2022 at 12:45 PM Markus Armbruster  wrote:
>
> Kevin Wolf  writes:
>
> > From: Xie Yongji 
> >
> > VDUSE [1] is a linux framework that makes it possible to implement
> > software-emulated vDPA devices in userspace. This adds a library
> > as a subproject to help implementing VDUSE backends in QEMU.
> >
> > [1] https://www.kernel.org/doc/html/latest/userspace-api/vduse.html
> >
> > Signed-off-by: Xie Yongji 
> > Message-Id: <20220523084611.91-6-xieyon...@bytedance.com>
> > Reviewed-by: Stefan Hajnoczi 
> > Signed-off-by: Kevin Wolf 
> > ---
> >  meson_options.txt   |2 +
> >  subprojects/libvduse/include/atomic.h   |1 +
> >  subprojects/libvduse/include/compiler.h |1 +
> >  subprojects/libvduse/libvduse.h |  235 
> >  subprojects/libvduse/libvduse.c | 1150 +++
> >  MAINTAINERS |5 +
> >  meson.build |   15 +
> >  scripts/meson-buildoptions.sh   |3 +
> >  subprojects/libvduse/linux-headers/linux|1 +
> >  subprojects/libvduse/meson.build|   10 +
> >  subprojects/libvduse/standard-headers/linux |1 +
> >  11 files changed, 1424 insertions(+)
> >  create mode 12 subprojects/libvduse/include/atomic.h
> >  create mode 12 subprojects/libvduse/include/compiler.h
> >  create mode 100644 subprojects/libvduse/libvduse.h
> >  create mode 100644 subprojects/libvduse/libvduse.c
> >  create mode 12 subprojects/libvduse/linux-headers/linux
> >  create mode 100644 subprojects/libvduse/meson.build
> >  create mode 12 subprojects/libvduse/standard-headers/linux
> >
> > diff --git a/meson_options.txt b/meson_options.txt
> > index f3e2f22c1e..23a9f440f7 100644
> > --- a/meson_options.txt
> > +++ b/meson_options.txt
> > @@ -257,6 +257,8 @@ option('virtfs', type: 'feature', value: 'auto',
> > description: 'virtio-9p support')
> >  option('virtiofsd', type: 'feature', value: 'auto',
> > description: 'build virtiofs daemon (virtiofsd)')
> > +option('libvduse', type: 'feature', value: 'auto',
> > +   description: 'build VDUSE Library')
> >
> >  option('capstone', type: 'feature', value: 'auto',
> > description: 'Whether and how to find the capstone library')
> > diff --git a/subprojects/libvduse/include/atomic.h 
> > b/subprojects/libvduse/include/atomic.h
> > new file mode 12
> > index 00..8c2be64f7b
> > --- /dev/null
> > +++ b/subprojects/libvduse/include/atomic.h
> > @@ -0,0 +1 @@
> > +../../../include/qemu/atomic.h
> > \ No newline at end of file
> > diff --git a/subprojects/libvduse/include/compiler.h 
> > b/subprojects/libvduse/include/compiler.h
> > new file mode 12
> > index 00..de7b70697c
> > --- /dev/null
> > +++ b/subprojects/libvduse/include/compiler.h
> > @@ -0,0 +1 @@
> > +../../../include/qemu/compiler.h
> > \ No newline at end of file
> > diff --git a/subprojects/libvduse/libvduse.h 
> > b/subprojects/libvduse/libvduse.h
> > new file mode 100644
> > index 00..6c2fe98213
> > --- /dev/null
> > +++ b/subprojects/libvduse/libvduse.h
> > @@ -0,0 +1,235 @@
> > +/*
> > + * VDUSE (vDPA Device in Userspace) library
> > + *
> > + * Copyright (C) 2022 Bytedance Inc. and/or its affiliates. All rights 
> > reserved.
> > + *
> > + * Author:
> > + *   Xie Yongji 
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2 or
> > + * later.  See the COPYING file in the top-level directory.
> > + */
> > +
> > +#ifndef LIBVDUSE_H
> > +#define LIBVDUSE_H
> > +
> > +#include 
> > +#include 
> > +
> > +#define VIRTQUEUE_MAX_SIZE 1024
> > +
> > +/* VDUSE device structure */
> > +typedef struct VduseDev VduseDev;
> > +
> > +/* Virtqueue structure */
> > +typedef struct VduseVirtq VduseVirtq;
> > +
> > +/* Some operation of VDUSE backend */
> > +typedef struct VduseOps {
> > +/* Called when virtqueue can be processed */
> > +void (*enable_queue)(VduseDev *dev, VduseVirtq *vq);
> > +/* Called when virtqueue processing should be stopped */
> > +void (*disable_queue)(VduseDev *dev, VduseVirtq *vq);
> > +} VduseOps;
> > +
> > +/* Describing elements of the I/O buffer */
> > +typedef struct VduseVirtqElement {
> > +/* Descriptor table index */
> > +unsigned int index;
> > +/* Number of physically-contiguous device-readable descriptors */
> > +unsigned int out_num;
> > +/* Number of physically-contiguous device-writable descriptors */
> > +unsigned int in_num;
> > +/* Array to store physically-contiguous device-writable descriptors */
> > +struct iovec *in_sg;
> > +/* Array to store physically-contiguous device-readable descriptors */
> > +struct iovec *out_sg;
> > +} VduseVirtqElement;
> > +
> > +
> > +/**
> > + * vduse_get_virtio_features:
> > + *
> > + * Get supported virtio features
> > + *
> > + * Returns: supported feature bits
> > + */
> > +uint64_t vduse_get_virtio_features(void);
> >

Re: [PATCH v4 46/53] semihosting: Add GuestFDConsole

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> Add a GuestFDType for connecting to the semihosting console.
> Hook up to read, write, isatty, and fstat syscalls.
> 
> Note that the arm-specific syscall flen cannot be applied
> to the console, because the console is not a descriptor
> exposed to the guest.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  include/semihosting/guestfd.h |  7 ++--
>  semihosting/syscalls.c| 68 +++
>  2 files changed, 72 insertions(+), 3 deletions(-)
> 
> diff --git a/include/semihosting/guestfd.h b/include/semihosting/guestfd.h
> index ef268abe85..a7ea1041ea 100644
> --- a/include/semihosting/guestfd.h
> +++ b/include/semihosting/guestfd.h
> @@ -13,9 +13,10 @@
>  
>  typedef enum GuestFDType {
>  GuestFDUnused = 0,
> -GuestFDHost = 1,
> -GuestFDGDB = 2,
> -GuestFDStatic = 3,
> +GuestFDHost,
> +GuestFDGDB,
> +GuestFDStatic,
> +GuestFDConsole,
>  } GuestFDType;
>  
>  /*
> diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c
> index 13a9bdeda6..9e499b1751 100644
> --- a/semihosting/syscalls.c
> +++ b/semihosting/syscalls.c
> @@ -10,6 +10,7 @@
>  #include "exec/gdbstub.h"
>  #include "semihosting/guestfd.h"
>  #include "semihosting/syscalls.h"
> +#include "semihosting/console.h"
>  #ifdef CONFIG_USER_ONLY
>  #include "qemu.h"
>  #else
> @@ -577,6 +578,56 @@ static void staticfile_flen(CPUState *cs, 
> gdb_syscall_complete_cb complete,
>  complete(cs, gf->staticfile.len, 0);
>  }
>  
> +/*
> + * Console semihosting syscall implementations.
> + */
> +
> +static void console_read(CPUState *cs, gdb_syscall_complete_cb complete,
> + GuestFD *gf, target_ulong buf, target_ulong len)
> +{
> +CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
> +char *ptr;
> +int ret;
> +
> +ptr = lock_user(VERIFY_WRITE, buf, len, 0);
> +if (!ptr) {
> +complete(cs, -1, EFAULT);
> +return;
> +}
> +ret = qemu_semihosting_console_read(cs, ptr, len);
> +complete(cs, ret, 0);
> +unlock_user(ptr, buf, ret);
> +}
> +
> +static void console_write(CPUState *cs, gdb_syscall_complete_cb complete,
> +  GuestFD *gf, target_ulong buf, target_ulong len)
> +{
> +CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
> +char *ptr = lock_user(VERIFY_READ, buf, len, 1);
> +int ret;
> +
> +if (!ptr) {
> +complete(cs, -1, EFAULT);
> +return;
> +}
> +ret = qemu_semihosting_console_write(ptr, len);
> +complete(cs, ret ? ret : -1, ret ? 0 : EIO);
> +unlock_user(ptr, buf, ret);
> +}
> +
> +static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
> +  GuestFD *gf, target_ulong addr)
> +{
> +static const struct stat tty_buf = {
> +.st_mode = 020666,  /* S_IFCHR, ugo+rw */
> +.st_rdev = 5,   /* makedev(5, 0) -- linux /dev/tty */
> +};
> +int ret;
> +
> +ret = copy_stat_to_user(cs, addr, &tty_buf);
> +complete(cs, ret ? -1 : 0, ret ? -ret : 0);
> +}
> +
>  /*
>   * Syscall entry points.
>   */
> @@ -608,6 +659,7 @@ void semihost_sys_close(CPUState *cs, 
> gdb_syscall_complete_cb complete, int fd)
>  host_close(cs, complete, gf);
>  break;
>  case GuestFDStatic:
> +case GuestFDConsole:
>  complete(cs, 0, 0);
>  break;
>  default:
> @@ -637,6 +689,9 @@ void semihost_sys_read_gf(CPUState *cs, 
> gdb_syscall_complete_cb complete,
>  case GuestFDStatic:
>  staticfile_read(cs, complete, gf, buf, len);
>  break;
> +case GuestFDConsole:
> +console_read(cs, complete, gf, buf, len);
> +break;
>  default:
>  g_assert_not_reached();
>  }
> @@ -672,6 +727,9 @@ void semihost_sys_write_gf(CPUState *cs, 
> gdb_syscall_complete_cb complete,
>  case GuestFDHost:
>  host_write(cs, complete, gf, buf, len);
>  break;
> +case GuestFDConsole:
> +console_write(cs, complete, gf, buf, len);
> +break;
>  case GuestFDStatic:
>  /* Static files are never open for writing: EBADF. */
>  complete(cs, -1, EBADF);
> @@ -712,6 +770,9 @@ void semihost_sys_lseek(CPUState *cs, 
> gdb_syscall_complete_cb complete,
>  case GuestFDStatic:
>  staticfile_lseek(cs, complete, gf, off, gdb_whence);
>  break;
> +case GuestFDConsole:
> +complete(cs, -1, ESPIPE);
> +break;
>  default:
>  g_assert_not_reached();
>  }
> @@ -735,6 +796,9 @@ void semihost_sys_isatty(CPUState *cs, 
> gdb_syscall_complete_cb complete, int fd)
>  case GuestFDStatic:
>  complete(cs, 0, ENOTTY);
>  break;
> +case GuestFDConsole:
> +complete(cs, 1, 0);
> +break;
>  default:
>  g_assert_not_reached();
>  }
> @@ -760,6 +824,7 @@ void semihost_sys_flen(CPUState *cs, 
> gdb_syscall_complete_cb fstat_cb,
>  case Gues

Re: [PATCH v4 47/53] semihosting: Create qemu_semihosting_guestfd_init

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> For arm-compat, initialize console_{in,out}_gf;
> otherwise, initialize stdio file descriptors.
> 
> This will go some way to cleaning up arm-compat, and
> will allow other semihosting to use normal stdio.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  include/semihosting/guestfd.h  |  7 +
>  include/semihosting/semihost.h |  1 +
>  linux-user/main.c  |  9 ++
>  semihosting/console.c  |  2 ++
>  semihosting/guestfd.c  | 52 +++---
>  5 files changed, 61 insertions(+), 10 deletions(-)
> 
> diff --git a/include/semihosting/guestfd.h b/include/semihosting/guestfd.h
> index a7ea1041ea..3d426fedab 100644
> --- a/include/semihosting/guestfd.h
> +++ b/include/semihosting/guestfd.h
> @@ -35,6 +35,13 @@ typedef struct GuestFD {
>  };
>  } GuestFD;
>  
> +/*
> + * For ARM semihosting, we have a separate structure for routing
> + * data for the console which is outside the guest fd address space.
> + */
> +extern GuestFD console_in_gf;
> +extern GuestFD console_out_gf;
> +
>  /**
>   * alloc_guestfd:
>   *
> diff --git a/include/semihosting/semihost.h b/include/semihosting/semihost.h
> index 5b36a76f08..93a3c21b44 100644
> --- a/include/semihosting/semihost.h
> +++ b/include/semihosting/semihost.h
> @@ -64,5 +64,6 @@ int qemu_semihosting_config_options(const char *opt);
>  void qemu_semihosting_chardev_init(void);
>  void qemu_semihosting_console_init(Chardev *);
>  #endif /* CONFIG_USER_ONLY */
> +void qemu_semihosting_guestfd_init(void);
>  
>  #endif /* SEMIHOST_H */
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 651e32f5f2..e44bdb17b8 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -54,6 +54,10 @@
>  #include "loader.h"
>  #include "user-mmap.h"
>  
> +#ifdef CONFIG_SEMIHOSTING
> +#include "semihosting/semihost.h"
> +#endif
> +
>  #ifndef AT_FLAGS_PRESERVE_ARGV0
>  #define AT_FLAGS_PRESERVE_ARGV0_BIT 0
>  #define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
> @@ -906,6 +910,11 @@ int main(int argc, char **argv, char **envp)
>  }
>  gdb_handlesig(cpu, 0);
>  }
> +
> +#ifdef CONFIG_SEMIHOSTING
> +qemu_semihosting_guestfd_init();
> +#endif
> +
>  cpu_loop(env);
>  /* never exits */
>  return 0;
> diff --git a/semihosting/console.c b/semihosting/console.c
> index b6a342744d..677ec2b176 100644
> --- a/semihosting/console.c
> +++ b/semihosting/console.c
> @@ -190,4 +190,6 @@ void qemu_semihosting_console_init(Chardev *chr)
>   NULL, NULL, &console,
>   NULL, true);
>  }
> +
> +qemu_semihosting_guestfd_init();
>  }
> diff --git a/semihosting/guestfd.c b/semihosting/guestfd.c
> index e3122ebba9..b05c52f26f 100644
> --- a/semihosting/guestfd.c
> +++ b/semihosting/guestfd.c
> @@ -10,15 +10,56 @@
>  
>  #include "qemu/osdep.h"
>  #include "exec/gdbstub.h"
> +#include "semihosting/semihost.h"
>  #include "semihosting/guestfd.h"
>  #ifdef CONFIG_USER_ONLY
>  #include "qemu.h"
>  #else
>  #include "semihosting/softmmu-uaccess.h"
> +#include CONFIG_DEVICES
>  #endif
>  
>  static GArray *guestfd_array;
>  
> +#ifdef CONFIG_ARM_COMPATIBLE_SEMIHOSTING
> +GuestFD console_in_gf;
> +GuestFD console_out_gf;
> +#endif
> +
> +void qemu_semihosting_guestfd_init(void)
> +{
> +/* New entries zero-initialized, i.e. type GuestFDUnused */
> +guestfd_array = g_array_new(FALSE, TRUE, sizeof(GuestFD));
> +
> +#ifdef CONFIG_ARM_COMPATIBLE_SEMIHOSTING
> +/* For ARM-compat, the console is in a separate namespace. */
> +if (use_gdb_syscalls()) {
> +console_in_gf.type = GuestFDGDB;
> +console_in_gf.hostfd = 0;
> +console_out_gf.type = GuestFDGDB;
> +console_out_gf.hostfd = 2;
> +} else {
> +console_in_gf.type = GuestFDConsole;
> +console_out_gf.type = GuestFDConsole;
> +}
> +#else
> +/* Otherwise, the stdio file descriptors apply. */
> +guestfd_array = g_array_set_size(guestfd_array, 3);
> +#ifndef CONFIG_USER_ONLY
> +if (!use_gdb_syscalls()) {
> +GuestFD *gf = &g_array_index(guestfd_array, GuestFD, 0);
> +gf[0].type = GuestFDConsole;
> +gf[1].type = GuestFDConsole;
> +gf[2].type = GuestFDConsole;
> +return;
> +}
> +#endif
> +associate_guestfd(0, 0);
> +associate_guestfd(1, 1);
> +associate_guestfd(2, 2);
> +#endif
> +}
> +
>  /*
>   * Allocate a new guest file descriptor and return it; if we
>   * couldn't allocate a new fd then return -1.
> @@ -30,11 +71,6 @@ int alloc_guestfd(void)
>  {
>  guint i;
>  
> -if (!guestfd_array) {
> -/* New entries zero-initialized, i.e. type GuestFDUnused */
> -guestfd_array = g_array_new(FALSE, TRUE, sizeof(GuestFD));
> -}
> -
>  /* SYS_OPEN should return nonzero handle on success. Start guestfd from 
> 1 */
>  for (i = 1; i < guestfd_array->len; i

Re: [PATCH v4 48/53] semihosting: Use console_in_gf for SYS_READC

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  semihosting/arm-compat-semi.c | 27 ++-
>  1 file changed, 18 insertions(+), 9 deletions(-)
> 
> diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
> index 20e99cdcc0..4c8932ad54 100644
> --- a/semihosting/arm-compat-semi.c
> +++ b/semihosting/arm-compat-semi.c
> @@ -302,6 +302,22 @@ common_semi_flen_fstat_cb(CPUState *cs, uint64_t ret, 
> int err)
>  common_semi_cb(cs, ret, err);
>  }
>  
> +static void
> +common_semi_readc_cb(CPUState *cs, uint64_t ret, int err)
> +{
> +if (!err) {
> +CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;
> +uint8_t ch;
> +
> +if (get_user_u8(ch, common_semi_stack_bottom(cs) - 1)) {
> +ret = -1, err = EFAULT;
> +} else {
> +ret = ch;
> +}
> +}
> +common_semi_cb(cs, ret, err);
> +}
> +
>  #define SHFB_MAGIC_0 0x53
>  #define SHFB_MAGIC_1 0x48
>  #define SHFB_MAGIC_2 0x46
> @@ -427,15 +443,8 @@ void do_common_semihosting(CPUState *cs)
>  break;
>  
>  case TARGET_SYS_READC:
> -{
> -uint8_t ch;
> -int ret = qemu_semihosting_console_read(cs, &ch, 1);
> -if (ret == 1) {
> -common_semi_cb(cs, ch, 0);
> -} else {
> -common_semi_cb(cs, -1, EIO);
> -}
> -}
> +semihost_sys_read_gf(cs, common_semi_readc_cb, &console_in_gf,
> + common_semi_stack_bottom(cs) - 1, 1);
>  break;
>  
>  case TARGET_SYS_ISERROR:
> -- 
> 2.34.1
> 
> 
> 
> 
> To declare a filtering error, please use the following link : 
> https://www.security-mail.net/reporter.php?mid=1799d.629fd6b1.98b43.0&r=lmichel%40kalrayinc.com&s=qemu-devel-bounces%2Blmichel%3Dkalrayinc.com%40nongnu.org&o=%5BPATCH+v4+48%2F53%5D+semihosting%3A+Use+console_in_gf+for+SYS_READC&verdict=C&c=b9cfba5cbbf5d995e5235734d7ab1a5181b14825
> 

-- 







Re: [PATCH v4 49/53] semihosting: Use console_out_gf for SYS_WRITEC

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  semihosting/arm-compat-semi.c | 20 
>  1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
> index 4c8932ad54..dea5b2de8d 100644
> --- a/semihosting/arm-compat-semi.c
> +++ b/semihosting/arm-compat-semi.c
> @@ -228,6 +228,15 @@ static void common_semi_cb(CPUState *cs, uint64_t ret, 
> int err)
>  common_semi_set_ret(cs, ret);
>  }
>  
> +/*
> + * Use 0xdeadbeef as the return value when there isn't a defined
> + * return value for the call.
> + */
> +static void common_semi_dead_cb(CPUState *cs, uint64_t ret, int err)
> +{
> +common_semi_set_ret(cs, 0xdeadbeef);
> +}
> +
>  /*
>   * SYS_READ and SYS_WRITE always return the number of bytes not read/written.
>   * There is no error condition, other than returning the original length.
> @@ -341,8 +350,7 @@ static const uint8_t featurefile_data[] = {
>   * The specification always says that the "return register" either
>   * returns a specific value or is corrupted, so we don't need to
>   * report to our caller whether we are returning a value or trying to
> - * leave the register unchanged. We use 0xdeadbeef as the return value
> - * when there isn't a defined return value for the call.
> + * leave the register unchanged.
>   */
>  void do_common_semihosting(CPUState *cs)
>  {
> @@ -419,8 +427,12 @@ void do_common_semihosting(CPUState *cs)
>  break;
>  
>  case TARGET_SYS_WRITEC:
> -qemu_semihosting_console_outc(env, args);
> -common_semi_set_ret(cs, 0xdeadbeef);
> +/*
> + * FIXME: the byte to be written is in a target_ulong slot,
> + * which means this is wrong for a big-endian guest.
> + */
> +semihost_sys_write_gf(cs, common_semi_dead_cb,
> +  &console_out_gf, args, 1);
>  break;
>  
>  case TARGET_SYS_WRITE0:
> -- 
> 2.34.1
> 
> 
> 
> 
> To declare a filtering error, please use the following link : 
> https://www.security-mail.net/reporter.php?mid=1578f.629fd28e.3eb4d.0&r=lmichel%40kalrayinc.com&s=qemu-devel-bounces%2Blmichel%3Dkalrayinc.com%40nongnu.org&o=%5BPATCH+v4+49%2F53%5D+semihosting%3A+Use+console_out_gf+for+SYS_WRITEC&verdict=C&c=9f59ee0c491343fa50053073959ee288e2920868
> 

-- 







Re: [PATCH v4 50/53] semihosting: Remove qemu_semihosting_console_outc

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> This function has been replaced by *_write.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  include/semihosting/console.h | 13 -
>  linux-user/semihost.c | 16 
>  semihosting/console.c | 18 --
>  3 files changed, 47 deletions(-)
> 
> diff --git a/include/semihosting/console.h b/include/semihosting/console.h
> index 6994f23c82..d6c1cc58ab 100644
> --- a/include/semihosting/console.h
> +++ b/include/semihosting/console.h
> @@ -24,19 +24,6 @@
>   */
>  int qemu_semihosting_console_outs(CPUArchState *env, target_ulong s);
>  
> -/**
> - * qemu_semihosting_console_outc:
> - * @env: CPUArchState
> - * @s: host address of null terminated guest string
> - *
> - * Send single character from guest memory to the debug console. This
> - * may be the remote gdb session if a softmmu guest is currently being
> - * debugged.
> - *
> - * Returns: nothing
> - */
> -void qemu_semihosting_console_outc(CPUArchState *env, target_ulong c);
> -
>  /**
>   * qemu_semihosting_console_read:
>   * @cs: CPUState
> diff --git a/linux-user/semihost.c b/linux-user/semihost.c
> index 871edf993a..f8bc8889f3 100644
> --- a/linux-user/semihost.c
> +++ b/linux-user/semihost.c
> @@ -33,22 +33,6 @@ int qemu_semihosting_console_outs(CPUArchState *env, 
> target_ulong addr)
>  return len;
>  }
>  
> -void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr)
> -{
> -char c;
> -
> -if (get_user_u8(c, addr)) {
> -qemu_log_mask(LOG_GUEST_ERROR,
> -  "%s: passed inaccessible address " TARGET_FMT_lx,
> -  __func__, addr);
> -} else {
> -if (write(STDERR_FILENO, &c, 1) != 1) {
> -qemu_log_mask(LOG_UNIMP, "%s: unexpected write to stdout 
> failure",
> -  __func__);
> -}
> -}
> -}
> -
>  /*
>   * For linux-user we can safely block. However as we want to return as
>   * soon as a character is read we need to tweak the termio to disable
> diff --git a/semihosting/console.c b/semihosting/console.c
> index 677ec2b176..f6fab5933a 100644
> --- a/semihosting/console.c
> +++ b/semihosting/console.c
> @@ -96,24 +96,6 @@ int qemu_semihosting_console_outs(CPUArchState *env, 
> target_ulong addr)
>  return out;
>  }
>  
> -void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr)
> -{
> -CPUState *cpu = env_cpu(env);
> -uint8_t c;
> -
> -if (cpu_memory_rw_debug(cpu, addr, &c, 1, 0) == 0) {
> -if (use_gdb_syscalls()) {
> -gdb_do_syscall(semihosting_cb, "write,2,%x,%x", addr, 1);
> -} else {
> -qemu_semihosting_log_out((const char *) &c, 1);
> -}
> -} else {
> -qemu_log_mask(LOG_GUEST_ERROR,
> -  "%s: passed inaccessible address " TARGET_FMT_lx,
> -  __func__, addr);
> -}
> -}
> -
>  #define FIFO_SIZE   1024
>  
>  static int console_can_read(void *opaque)
> -- 
> 2.34.1
> 
> 
> 
> 
> To declare a filtering error, please use the following link : 
> https://www.security-mail.net/reporter.php?mid=17199.629fd830.873a5.0&r=lmichel%40kalrayinc.com&s=qemu-devel-bounces%2Blmichel%3Dkalrayinc.com%40nongnu.org&o=%5BPATCH+v4+50%2F53%5D+semihosting%3A+Remove+qemu_semihosting_console_outc&verdict=C&c=17fd1d8aafc59b73861d5d8e80dfec815f24e02d
> 

-- 







Re: [RFC v3 4/5] file-posix: introduce get_sysfs_str_val for device zoned model.

2022-06-27 Thread Sam Li
Hannes Reinecke  于2022年6月27日周一 15:41写道:
>
> On 6/27/22 02:19, Sam Li wrote:
> > ---
> >   block/file-posix.c   | 60 
> >   include/block/block-common.h |  4 +--
> >   2 files changed, 62 insertions(+), 2 deletions(-)
> >
> > diff --git a/block/file-posix.c b/block/file-posix.c
> > index 73c2cdfbca..74c0245e0f 100644
> > --- a/block/file-posix.c
> > +++ b/block/file-posix.c
> > @@ -1277,6 +1277,66 @@ out:
> >   #endif
> >   }
> >
> > +/*
> > + * Convert the zoned attribute file in sysfs to internal value.
> > + */
> > +static zone_model get_sysfs_str_val(int fd, struct stat *st) {
> > +#ifdef CONFIG_LINUX
> > +char buf[32];
> > +char *sysfspath = NULL;
> > +int ret;
> > +int sysfd = -1;
> > +
> > +if (S_ISCHR(st->st_mode)) {
> > +if (ioctl(fd, SG_GET_SG_TABLESIZE, &ret) == 0) {
> > +return ret;
> > +}
> > +return -ENOTSUP;
> > +}
> > +
> > +if (!S_ISBLK(st->st_mode)) {
> > +return -ENOTSUP;
> > +}
> > +
> > +sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/zoned",
> > +major(st->st_rdev), minor(st->st_rdev));
> > +sysfd = open(sysfspath, O_RDONLY);
> > +if (sysfd == -1) {
> > +ret = -errno;
> > +goto out;
> > +}
> > +do {
> > +ret = read(sysfd, buf, sizeof(buf) - 1);
> > +} while (ret == -1 && errno == EINTR);
>
> This is wrong.
> read() might return a value smaller than the 'len' argument (sizeof(buf)
> -1 in your case). But in that case it's a short read, and one need to
> call 'read()' again to fetch the remaining bytes.
>
> So the correct code would be something like:
>
> offset = 0;
> do {
>  ret = read(sysfd, buf + offset, sizeof(buf) - 1 + offset);
>  if (ret > 0)
>  offset += ret;
> } while (ret > 0);
>
> Not that you'd actually need it; reads from sysfs are basically never
> interrupted, so you should be able to read from an attribute in one go.
> IE alternatively you can drop the 'while' loop and just call read().
>
Yes, I didn't think it through.

> > +if (ret < 0) {
> > +ret = -errno;
> > +goto out;
> > +} else if (ret == 0) {
> > +ret = -EIO;
> > +goto out;
> > +}
> > +buf[ret] = 0;
> > +
> > +/* The file is ended with '\n' */
>
> I'd rather check if the string ends with an '\n', and overwrite
> it with a '\0'. That way you'd be insulated against any changes
> to sysfs.
>
Right! I was thinking about it but got hasty to hardcode everything.

> > +if (strcmp(buf, "host-managed\n") == 0) {
> > +return BLK_Z_HM;
> > +} else if (strcmp(buf, "host-aware\n") == 0) {
> > +return BLK_Z_HA;
> > +} else {
> > +return -ENOTSUP;
> > +}
> > +
> > +out:
> > +if (sysfd != -1) {
> > +close(sysfd);
> > +}
> > +g_free(sysfspath);
> > +return ret;
> > +#else
> > +return -ENOTSUP;
> > +#endif
> > +}
> > +
> >   static int hdev_get_max_segments(int fd, struct stat *st) {
> >   int ret;
> >   ret = get_sysfs_long_val(fd, st, "max_segments");
>
> And as you already set a precedent in your previous patch, I'd recommend
> split this in two patches, one introducing a generic function
> 'get_sysfs_str_val()' which returns a string and another function
> (eg hdev_get_zone_model()) which calls this function to fetch the device
> zoned model.
>
Maybe we can just return a str in get_sysfs_str_val and ignore
returning a zone_model for now? I was using zone_model for testing
purpose. Right now, this function is not used by others in
file-posix.c that causes compilation error in QEMU.

Thanks for reviewing!
Sam
> > diff --git a/include/block/block-common.h b/include/block/block-common.h
> > index 78cddeeda5..35e00afe8e 100644
> > --- a/include/block/block-common.h
> > +++ b/include/block/block-common.h
> > @@ -56,8 +56,8 @@ typedef enum zone_op {
> >   } zone_op;
> >
> >   typedef enum zone_model {
> > -BLK_Z_HM,
> > -BLK_Z_HA,
> > +BLK_Z_HM = 0x1,
> > +BLK_Z_HA = 0x2,
> >   } zone_model;
> >
> >   typedef enum BlkZoneCondition {
>
> Cheers,
>
> Hannes
> --
> Dr. Hannes ReineckeKernel Storage Architect
> h...@suse.de  +49 911 74053 688
> SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
> HRB 36809 (AG Nürnberg), GF: Felix Imendörffer



Re: [PATCH v4 52/53] semihosting: Remove qemu_semihosting_console_outs

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> This function has been replaced by *_write.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  include/semihosting/console.h | 13 --
>  linux-user/semihost.c | 17 
>  semihosting/console.c | 49 ---
>  3 files changed, 79 deletions(-)
> 
> diff --git a/include/semihosting/console.h b/include/semihosting/console.h
> index d6c1cc58ab..20c31d89d4 100644
> --- a/include/semihosting/console.h
> +++ b/include/semihosting/console.h
> @@ -11,19 +11,6 @@
>  
>  #include "cpu.h"
>  
> -/**
> - * qemu_semihosting_console_outs:
> - * @env: CPUArchState
> - * @s: host address of null terminated guest string
> - *
> - * Send a null terminated guest string to the debug console. This may
> - * be the remote gdb session if a softmmu guest is currently being
> - * debugged.
> - *
> - * Returns: number of bytes written.
> - */
> -int qemu_semihosting_console_outs(CPUArchState *env, target_ulong s);
> -
>  /**
>   * qemu_semihosting_console_read:
>   * @cs: CPUState
> diff --git a/linux-user/semihost.c b/linux-user/semihost.c
> index f8bc8889f3..cee62a365c 100644
> --- a/linux-user/semihost.c
> +++ b/linux-user/semihost.c
> @@ -16,23 +16,6 @@
>  #include "user-internals.h"
>  #include 
>  
> -int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr)
> -{
> -int len = target_strlen(addr);
> -void *s;
> -if (len < 0){
> -   qemu_log_mask(LOG_GUEST_ERROR,
> - "%s: passed inaccessible address " TARGET_FMT_lx,
> - __func__, addr);
> -   return 0;
> -}
> -s = lock_user(VERIFY_READ, addr, (long)(len + 1), 1);
> -g_assert(s);  /* target_strlen has already verified this will work */
> -len = write(STDERR_FILENO, s, len);
> -unlock_user(s, addr, 0);
> -return len;
> -}
> -
>  /*
>   * For linux-user we can safely block. However as we want to return as
>   * soon as a character is read we need to tweak the termio to disable
> diff --git a/semihosting/console.c b/semihosting/console.c
> index f6fab5933a..c84ab97ab6 100644
> --- a/semihosting/console.c
> +++ b/semihosting/console.c
> @@ -47,55 +47,6 @@ int qemu_semihosting_log_out(const char *s, int len)
>  }
>  }
>  
> -/*
> - * A re-implementation of lock_user_string that we can use locally
> - * instead of relying on softmmu-semi. Hopefully we can deprecate that
> - * in time. Copy string until we find a 0 or address error.
> - */
> -static GString *copy_user_string(CPUArchState *env, target_ulong addr)
> -{
> -CPUState *cpu = env_cpu(env);
> -GString *s = g_string_sized_new(128);
> -uint8_t c;
> -
> -do {
> -if (cpu_memory_rw_debug(cpu, addr++, &c, 1, 0) == 0) {
> -if (c) {
> -s = g_string_append_c(s, c);
> -}
> -} else {
> -qemu_log_mask(LOG_GUEST_ERROR,
> -  "%s: passed inaccessible address " TARGET_FMT_lx,
> -  __func__, addr);
> -break;
> -}
> -} while (c!=0);
> -
> -return s;
> -}
> -
> -static void semihosting_cb(CPUState *cs, uint64_t ret, int err)
> -{
> -if (err) {
> -qemu_log("%s: gdb console output failed (%d)", __func__, err);
> -}
> -}
> -
> -int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr)
> -{
> -GString *s = copy_user_string(env, addr);
> -int out = s->len;
> -
> -if (use_gdb_syscalls()) {
> -gdb_do_syscall(semihosting_cb, "write,2,%x,%x", addr, s->len);
> -} else {
> -out = qemu_semihosting_log_out(s->str, s->len);
> -}
> -
> -g_string_free(s, true);
> -return out;
> -}
> -
>  #define FIFO_SIZE   1024
>  
>  static int console_can_read(void *opaque)
> -- 
> 2.34.1
> 
> 
> 
> 
> To declare a filtering error, please use the following link : 
> https://www.security-mail.net/reporter.php?mid=29a4.629fd909.2884b.0&r=lmichel%40kalrayinc.com&s=qemu-devel-bounces%2Blmichel%3Dkalrayinc.com%40nongnu.org&o=%5BPATCH+v4+52%2F53%5D+semihosting%3A+Remove+qemu_semihosting_console_outs&verdict=C&c=8ee0b8982c8025f3b6af275d795772fa0673b149
> 

-- 







Re: [PATCH v4 51/53] semihosting: Use console_out_gf for SYS_WRITE0

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  semihosting/arm-compat-semi.c | 11 +--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
> index dea5b2de8d..21b6bc3a0f 100644
> --- a/semihosting/arm-compat-semi.c
> +++ b/semihosting/arm-compat-semi.c
> @@ -436,8 +436,15 @@ void do_common_semihosting(CPUState *cs)
>  break;
>  
>  case TARGET_SYS_WRITE0:
> -ret = qemu_semihosting_console_outs(env, args);
> -common_semi_set_ret(cs, ret);
> +{
> +ssize_t len = target_strlen(args);
> +if (len < 0) {
> +common_semi_dead_cb(cs, -1, EFAULT);
> +} else {
> +semihost_sys_write_gf(cs, common_semi_dead_cb,
> +  &console_out_gf, args, len);
> +}
> +}
>  break;
>  
>  case TARGET_SYS_WRITE:
> -- 
> 2.34.1
> 
> 
> 
> 
> To declare a filtering error, please use the following link : 
> https://www.security-mail.net/reporter.php?mid=c4ea.629fd73d.b3ca0.0&r=lmichel%40kalrayinc.com&s=qemu-devel-bounces%2Blmichel%3Dkalrayinc.com%40nongnu.org&o=%5BPATCH+v4+51%2F53%5D+semihosting%3A+Use+console_out_gf+for+SYS_WRITE0&verdict=C&c=a15d92901bee73eeb1fb2b2232be37c9cb5356be
> 

-- 







Re: [PATCH v4 26/53] semihosting: Move GET_ARG/SET_ARG earlier in the file

2022-06-27 Thread Alex Bennée


Richard Henderson  writes:

> Moving this to be useful for another function
> besides do_common_semihosting.
>
> Reviewed-by: Peter Maydell 
> Signed-off-by: Richard Henderson 

Reviewed-by: Alex Bennée 

-- 
Alex Bennée



Re: [PATCH 1/2] hw/i386/xen/xen-hvm: Allow for stubbing xen_set_pci_link_route()

2022-06-27 Thread Durrant, Paul

On 26/06/2022 10:46, Bernhard Beschow wrote:

The only user of xen_set_pci_link_route() is
xen_piix_pci_write_config_client() which implements PIIX-specific logic in
the xen namespace. This makes xen-hvm depend on PIIX which could be
avoided if xen_piix_pci_write_config_client() was implemented in PIIX. In
order to do this, xen_set_pci_link_route() needs to be stubbable which
this patch addresses.

Signed-off-by: Bernhard Beschow 


Reviewed-by: Paul Durrant 



Re: [PATCH v4 24/53] semihosting: Split out common-semi-target.h

2022-06-27 Thread Alex Bennée


Richard Henderson  writes:

> Move the ARM and RISCV specific helpers into
> their own header file.
>
> Signed-off-by: Richard Henderson 

Reviewed-by: Alex Bennée 

> ---
>  target/arm/common-semi-target.h   | 62 
>  target/riscv/common-semi-target.h | 50 
>  semihosting/arm-compat-semi.c | 94 +--
>  3 files changed, 113 insertions(+), 93 deletions(-)
>  create mode 100644 target/arm/common-semi-target.h
>  create mode 100644 target/riscv/common-semi-target.h
>
> diff --git a/target/arm/common-semi-target.h b/target/arm/common-semi-target.h
> new file mode 100644
> index 00..629d75ca5a
> --- /dev/null
> +++ b/target/arm/common-semi-target.h
> @@ -0,0 +1,62 @@
> +/*
> + * Target-specific parts of semihosting/arm-compat-semi.c.
> + *
> + * Copyright (c) 2005, 2007 CodeSourcery.
> + * Copyright (c) 2019, 2022 Linaro
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef TARGET_ARM_COMMON_SEMI_TARGET_H
> +#define TARGET_ARM_COMMON_SEMI_TARGET_H
> +
> +#ifndef CONFIG_USER_ONLY
> +#include "hw/arm/boot.h"
> +#endif
> +
> +static inline target_ulong common_semi_arg(CPUState *cs, int argno)
> +{
> +ARMCPU *cpu = ARM_CPU(cs);
> +CPUARMState *env = &cpu->env;
> +if (is_a64(env)) {
> +return env->xregs[argno];
> +} else {
> +return env->regs[argno];
> +}
> +}
> +
> +static inline void common_semi_set_ret(CPUState *cs, target_ulong ret)
> +{
> +ARMCPU *cpu = ARM_CPU(cs);
> +CPUARMState *env = &cpu->env;
> +if (is_a64(env)) {
> +env->xregs[0] = ret;
> +} else {
> +env->regs[0] = ret;
> +}
> +}
> +
> +static inline bool common_semi_sys_exit_extended(CPUState *cs, int nr)
> +{
> +return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
> +}
> +
> +static inline bool is_64bit_semihosting(CPUArchState *env)
> +{
> +return is_a64(env);
> +}
> +
> +static inline target_ulong common_semi_stack_bottom(CPUState *cs)
> +{
> +ARMCPU *cpu = ARM_CPU(cs);
> +CPUARMState *env = &cpu->env;
> +return is_a64(env) ? env->xregs[31] : env->regs[13];
> +}
> +
> +static inline bool common_semi_has_synccache(CPUArchState *env)
> +{
> +/* Ok for A64, invalid for A32/T32 */
> +return is_a64(env);
> +}
> +
> +#endif
> diff --git a/target/riscv/common-semi-target.h 
> b/target/riscv/common-semi-target.h
> new file mode 100644
> index 00..7c8a59e0cc
> --- /dev/null
> +++ b/target/riscv/common-semi-target.h
> @@ -0,0 +1,50 @@
> +/*
> + * Target-specific parts of semihosting/arm-compat-semi.c.
> + *
> + * Copyright (c) 2005, 2007 CodeSourcery.
> + * Copyright (c) 2019, 2022 Linaro
> + * Copyright © 2020 by Keith Packard 
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef TARGET_RISCV_COMMON_SEMI_TARGET_H
> +#define TARGET_RISCV_COMMON_SEMI_TARGET_H
> +
> +static inline target_ulong common_semi_arg(CPUState *cs, int argno)
> +{
> +RISCVCPU *cpu = RISCV_CPU(cs);
> +CPURISCVState *env = &cpu->env;
> +return env->gpr[xA0 + argno];
> +}
> +
> +static inline void common_semi_set_ret(CPUState *cs, target_ulong ret)
> +{
> +RISCVCPU *cpu = RISCV_CPU(cs);
> +CPURISCVState *env = &cpu->env;
> +env->gpr[xA0] = ret;
> +}
> +
> +static inline bool common_semi_sys_exit_extended(CPUState *cs, int nr)
> +{
> +return (nr == TARGET_SYS_EXIT_EXTENDED || sizeof(target_ulong) == 8);
> +}
> +
> +static inline bool is_64bit_semihosting(CPUArchState *env)
> +{
> +return riscv_cpu_mxl(env) != MXL_RV32;
> +}
> +
> +static inline target_ulong common_semi_stack_bottom(CPUState *cs)
> +{
> +RISCVCPU *cpu = RISCV_CPU(cs);
> +CPURISCVState *env = &cpu->env;
> +return env->gpr[xSP];
> +}
> +
> +static inline bool common_semi_has_synccache(CPUArchState *env)
> +{
> +return true;
> +}
> +
> +#endif
> diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
> index 50f40a2a1a..5e442e549d 100644
> --- a/semihosting/arm-compat-semi.c
> +++ b/semihosting/arm-compat-semi.c
> @@ -46,9 +46,6 @@
>  #else
>  #include "qemu/cutils.h"
>  #include "hw/loader.h"
> -#ifdef TARGET_ARM
> -#include "hw/arm/boot.h"
> -#endif
>  #include "hw/boards.h"
>  #endif
>  
> @@ -182,96 +179,7 @@ static LayoutInfo common_semi_find_bases(CPUState *cs)
>  
>  #endif
>  
> -#ifdef TARGET_ARM
> -static inline target_ulong
> -common_semi_arg(CPUState *cs, int argno)
> -{
> -ARMCPU *cpu = ARM_CPU(cs);
> -CPUARMState *env = &cpu->env;
> -if (is_a64(env)) {
> -return env->xregs[argno];
> -} else {
> -return env->regs[argno];
> -}
> -}
> -
> -static inline void
> -common_semi_set_ret(CPUState *cs, target_ulong ret)
> -{
> -ARMCPU *cpu = ARM_CPU(cs);
> -CPUARMState *env = &cpu->env;
> -if (is_a64(env)) {
> -env->xregs[0] = ret;
> -} else {
> -env->regs[0] = ret;
> -}
> -}
> -
> -static inline bool
> -common_semi_sys_exit_extended(CPUState *cs, int n

Re: [PATCH 2/2] hw/i386/xen/xen-hvm: Inline xen_piix_pci_write_config_client() and remove it

2022-06-27 Thread Durrant, Paul

On 26/06/2022 10:46, Bernhard Beschow wrote:

xen_piix_pci_write_config_client() is implemented in the xen sub tree and
uses PIIX constants internally, thus creating a direct dependency on
PIIX. Now that xen_set_pci_link_route() is stubbable, the logic of
xen_piix_pci_write_config_client() can be moved to PIIX which resolves
the dependency.

Signed-off-by: Bernhard Beschow 


Reviewed-by: Paul Durrant 



Re: [PATCH v4 47/53] semihosting: Create qemu_semihosting_guestfd_init

2022-06-27 Thread Alex Bennée


Richard Henderson  writes:

> For arm-compat, initialize console_{in,out}_gf;
> otherwise, initialize stdio file descriptors.
>
> This will go some way to cleaning up arm-compat, and
> will allow other semihosting to use normal stdio.
>
> Signed-off-by: Richard Henderson 

Reviewed-by: Alex Bennée 

-- 
Alex Bennée



Re: [PATCH v4 53/53] semihosting: Create semihost_sys_poll_one

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> This will be used for implementing the xtensa select_one
> system call.  Choose "poll" over "select" so that we can
> reuse Glib's g_poll constants and to avoid struct timeval.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  include/semihosting/console.h  | 16 
>  include/semihosting/syscalls.h |  3 ++
>  semihosting/console.c  | 19 -
>  semihosting/syscalls.c | 70 ++
>  4 files changed, 106 insertions(+), 2 deletions(-)
> 
> diff --git a/include/semihosting/console.h b/include/semihosting/console.h
> index 20c31d89d4..61b0cb3a94 100644
> --- a/include/semihosting/console.h
> +++ b/include/semihosting/console.h
> @@ -53,4 +53,20 @@ int qemu_semihosting_console_write(void *buf, int len);
>   */
>  int qemu_semihosting_log_out(const char *s, int len);
>  
> +/*
> + * qemu_semihosting_console_block_until_ready:
> + * @cs: CPUState
> + *
> + * If no data is available we suspend the CPU and will re-execute the
> + * instruction when data is available.
> + */
> +void qemu_semihosting_console_block_until_ready(CPUState *cs);
> +
> +/**
> + * qemu_semihosting_console_ready:
> + *
> + * Return true if characters are available for read; does not block.
> + */
> +bool qemu_semihosting_console_ready(void);
> +
>  #endif /* SEMIHOST_CONSOLE_H */
> diff --git a/include/semihosting/syscalls.h b/include/semihosting/syscalls.h
> index 347200cb9f..3a5ec229eb 100644
> --- a/include/semihosting/syscalls.h
> +++ b/include/semihosting/syscalls.h
> @@ -69,4 +69,7 @@ void semihost_sys_system(CPUState *cs, 
> gdb_syscall_complete_cb complete,
>  void semihost_sys_gettimeofday(CPUState *cs, gdb_syscall_complete_cb 
> complete,
> target_ulong tv_addr, target_ulong tz_addr);
>  
> +void semihost_sys_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
> +   int fd, GIOCondition cond, int timeout);
> +
>  #endif /* SEMIHOSTING_SYSCALLS_H */
> diff --git a/semihosting/console.c b/semihosting/console.c
> index c84ab97ab6..cda7cf1905 100644
> --- a/semihosting/console.c
> +++ b/semihosting/console.c
> @@ -77,10 +77,17 @@ static void console_read(void *opaque, const uint8_t 
> *buf, int size)
>  c->sleeping_cpus = NULL;
>  }
>  
> -int qemu_semihosting_console_read(CPUState *cs, void *buf, int len)
> +bool qemu_semihosting_console_ready(void)
> +{
> +SemihostingConsole *c = &console;
> +
> +g_assert(qemu_mutex_iothread_locked());
> +return !fifo8_is_empty(&c->fifo);
> +}
> +
> +void qemu_semihosting_console_block_until_ready(CPUState *cs)
>  {
>  SemihostingConsole *c = &console;
> -int ret = 0;
>  
>  g_assert(qemu_mutex_iothread_locked());
>  
> @@ -92,6 +99,14 @@ int qemu_semihosting_console_read(CPUState *cs, void *buf, 
> int len)
>  cpu_loop_exit(cs);
>  /* never returns */
>  }
> +}
> +
> +int qemu_semihosting_console_read(CPUState *cs, void *buf, int len)
> +{
> +SemihostingConsole *c = &console;
> +int ret = 0;
> +
> +qemu_semihosting_console_block_until_ready(cs);
>  
>  /* Read until buffer full or fifo exhausted. */
>  do {
> diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c
> index 9e499b1751..4847f66c02 100644
> --- a/semihosting/syscalls.c
> +++ b/semihosting/syscalls.c
> @@ -520,6 +520,21 @@ static void host_gettimeofday(CPUState *cs, 
> gdb_syscall_complete_cb complete,
>  unlock_user(p, tv_addr, sizeof(struct gdb_timeval));
>  }
>  
> +#ifndef CONFIG_USER_ONLY
> +static void host_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
> +  GuestFD *gf, GIOCondition cond, int timeout)
> +{
> +/*
> + * Since this is only used by xtensa in system mode, and stdio is
> + * handled through GuestFDConsole, and there are no semihosting
> + * system calls for sockets and the like, that means this descriptor
> + * must be a normal file.  Normal files never block and are thus
> + * always ready.
> + */
> +complete(cs, cond & (G_IO_IN | G_IO_OUT), 0);
> +}
> +#endif
> +
>  /*
>   * Static file semihosting syscall implementations.
>   */
> @@ -628,6 +643,34 @@ static void console_fstat(CPUState *cs, 
> gdb_syscall_complete_cb complete,
>  complete(cs, ret ? -1 : 0, ret ? -ret : 0);
>  }
>  
> +#ifndef CONFIG_USER_ONLY
> +static void console_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
> + GuestFD *gf, GIOCondition cond, int timeout)
> +{
> +/* The semihosting console does not support urgent data or errors. */
> +cond &= G_IO_IN | G_IO_OUT;
> +
> +/*
> + * Since qemu_semihosting_console_write never blocks, we can
> + * consider output always ready -- leave G_IO_OUT alone.
> + * All that remains is to conditionally signal input ready.
> + * Since output ready causes an immediate return, only block
> + * for G_IO_IN alone.
>

[PATCH 1/4] libvduse: Fix the incorrect function name

2022-06-27 Thread Xie Yongji
In vduse_name_is_valid(), we actually check whether
the name is invalid or not. So let's change the
function name to vduse_name_is_invalid() to match
the behavior.

Signed-off-by: Xie Yongji 
---
 subprojects/libvduse/libvduse.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c
index 9a2bcec282..6374933881 100644
--- a/subprojects/libvduse/libvduse.c
+++ b/subprojects/libvduse/libvduse.c
@@ -1193,7 +1193,7 @@ static int vduse_dev_init(VduseDev *dev, const char *name,
 return 0;
 }
 
-static inline bool vduse_name_is_valid(const char *name)
+static inline bool vduse_name_is_invalid(const char *name)
 {
 return strlen(name) >= VDUSE_NAME_MAX || strstr(name, "..");
 }
@@ -1242,7 +1242,7 @@ VduseDev *vduse_dev_create_by_name(const char *name, 
uint16_t num_queues,
 VduseDev *dev;
 int ret;
 
-if (!name || vduse_name_is_valid(name) || !ops ||
+if (!name || vduse_name_is_invalid(name) || !ops ||
 !ops->enable_queue || !ops->disable_queue) {
 fprintf(stderr, "Invalid parameter for vduse\n");
 return NULL;
@@ -1276,7 +1276,7 @@ VduseDev *vduse_dev_create(const char *name, uint32_t 
device_id,
 struct vduse_dev_config *dev_config;
 size_t size = offsetof(struct vduse_dev_config, config);
 
-if (!name || vduse_name_is_valid(name) ||
+if (!name || vduse_name_is_invalid(name) ||
 !has_feature(features,  VIRTIO_F_VERSION_1) || !config ||
 !config_size || !ops || !ops->enable_queue || !ops->disable_queue) {
 fprintf(stderr, "Invalid parameter for vduse\n");
-- 
2.20.1




Re: [PATCH v4 46/53] semihosting: Add GuestFDConsole

2022-06-27 Thread Alex Bennée


Richard Henderson  writes:

> Add a GuestFDType for connecting to the semihosting console.
> Hook up to read, write, isatty, and fstat syscalls.
>
> Note that the arm-specific syscall flen cannot be applied
> to the console, because the console is not a descriptor
> exposed to the guest.
>
> Signed-off-by: Richard Henderson 

Reviewed-by: Alex Bennée 

-- 
Alex Bennée



[PATCH 0/4] Fix some coverity issues on VDUSE

2022-06-27 Thread Xie Yongji
This series fixes some issues reported by coverity.

Patch 1 fixes an incorrect function name.

Patch 2 fixes Coverity CID 1490224.

Patch 3 fixes Coverity CID 1490226, 1490223.

Patch 4 fixes Coverity CID 1490222, 1490227.

Xie Yongji (4):
  libvduse: Fix the incorrect function name
  libvduse: Replace strcpy() with strncpy()
  libvduse: Pass positive value to strerror()
  libvduse: Check the return value of some ioctls

 subprojects/libvduse/libvduse.c | 23 +++
 1 file changed, 15 insertions(+), 8 deletions(-)

-- 
2.20.1




[PATCH 2/4] libvduse: Replace strcpy() with strncpy()

2022-06-27 Thread Xie Yongji
Coverity reported a string overflow issue since we copied
"name" to "dev_config->name" without checking the length.
This should be a false positive since we already checked
the length of "name" in vduse_name_is_invalid(). But anyway,
let's replace strcpy() with strncpy() to fix the coverity
complaint.

Fixes: Coverity CID 1490224
Signed-off-by: Xie Yongji 
---
 subprojects/libvduse/libvduse.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c
index 6374933881..1e36227388 100644
--- a/subprojects/libvduse/libvduse.c
+++ b/subprojects/libvduse/libvduse.c
@@ -1309,7 +1309,8 @@ VduseDev *vduse_dev_create(const char *name, uint32_t 
device_id,
 goto err_dev;
 }
 
-strcpy(dev_config->name, name);
+strncpy(dev_config->name, name, VDUSE_NAME_MAX);
+dev_config->name[VDUSE_NAME_MAX - 1] = '\0';
 dev_config->device_id = device_id;
 dev_config->vendor_id = vendor_id;
 dev_config->features = features;
-- 
2.20.1




[PATCH 4/4] libvduse: Check the return value of some ioctls

2022-06-27 Thread Xie Yongji
Coverity pointed out (CID 1490222, 1490227) that we called
ioctl somewhere without checking the return value. This
patch fixes these issues.

Fixes: Coverity CID 1490222, 1490227
Signed-off-by: Xie Yongji 
---
 subprojects/libvduse/libvduse.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c
index 1a5981445c..bf7302c60a 100644
--- a/subprojects/libvduse/libvduse.c
+++ b/subprojects/libvduse/libvduse.c
@@ -947,7 +947,10 @@ static void vduse_queue_disable(VduseVirtq *vq)
 
 eventfd.index = vq->index;
 eventfd.fd = VDUSE_EVENTFD_DEASSIGN;
-ioctl(dev->fd, VDUSE_VQ_SETUP_KICKFD, &eventfd);
+if (ioctl(dev->fd, VDUSE_VQ_SETUP_KICKFD, &eventfd)) {
+fprintf(stderr, "Failed to disable eventfd for vq[%d]: %s\n",
+vq->index, strerror(errno));
+}
 close(vq->fd);
 
 assert(vq->inuse == 0);
@@ -1337,7 +1340,10 @@ VduseDev *vduse_dev_create(const char *name, uint32_t 
device_id,
 
 return dev;
 err:
-ioctl(ctrl_fd, VDUSE_DESTROY_DEV, name);
+if (ioctl(ctrl_fd, VDUSE_DESTROY_DEV, name)) {
+fprintf(stderr, "Failed to destroy vduse device %s: %s\n",
+name, strerror(errno));
+}
 err_dev:
 close(ctrl_fd);
 err_ctrl:
-- 
2.20.1




[PATCH 3/4] libvduse: Pass positive value to strerror()

2022-06-27 Thread Xie Yongji
The value passed to strerror() should be positive.
So let's fix it.

Fixes: Coverity CID 1490226, 1490223
Signed-off-by: Xie Yongji 
---
 subprojects/libvduse/libvduse.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c
index 1e36227388..1a5981445c 100644
--- a/subprojects/libvduse/libvduse.c
+++ b/subprojects/libvduse/libvduse.c
@@ -1257,7 +1257,7 @@ VduseDev *vduse_dev_create_by_name(const char *name, 
uint16_t num_queues,
 ret = vduse_dev_init(dev, name, num_queues, ops, priv);
 if (ret < 0) {
 fprintf(stderr, "Failed to init vduse device %s: %s\n",
-name, strerror(ret));
+name, strerror(-ret));
 free(dev);
 return NULL;
 }
@@ -1331,7 +1331,7 @@ VduseDev *vduse_dev_create(const char *name, uint32_t 
device_id,
 ret = vduse_dev_init(dev, name, num_queues, ops, priv);
 if (ret < 0) {
 fprintf(stderr, "Failed to init vduse device %s: %s\n",
-name, strerror(ret));
+name, strerror(-ret));
 goto err;
 }
 
-- 
2.20.1




Re: [PATCH v4 24/53] semihosting: Split out common-semi-target.h

2022-06-27 Thread Luc Michel
On 13:45 Tue 07 Jun , Richard Henderson wrote:
> Move the ARM and RISCV specific helpers into
> their own header file.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Luc Michel 

> ---
>  target/arm/common-semi-target.h   | 62 
>  target/riscv/common-semi-target.h | 50 
>  semihosting/arm-compat-semi.c | 94 +--
>  3 files changed, 113 insertions(+), 93 deletions(-)
>  create mode 100644 target/arm/common-semi-target.h
>  create mode 100644 target/riscv/common-semi-target.h
> 
> diff --git a/target/arm/common-semi-target.h b/target/arm/common-semi-target.h
> new file mode 100644
> index 00..629d75ca5a
> --- /dev/null
> +++ b/target/arm/common-semi-target.h
> @@ -0,0 +1,62 @@
> +/*
> + * Target-specific parts of semihosting/arm-compat-semi.c.
> + *
> + * Copyright (c) 2005, 2007 CodeSourcery.
> + * Copyright (c) 2019, 2022 Linaro
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef TARGET_ARM_COMMON_SEMI_TARGET_H
> +#define TARGET_ARM_COMMON_SEMI_TARGET_H
> +
> +#ifndef CONFIG_USER_ONLY
> +#include "hw/arm/boot.h"
> +#endif
> +
> +static inline target_ulong common_semi_arg(CPUState *cs, int argno)
> +{
> +ARMCPU *cpu = ARM_CPU(cs);
> +CPUARMState *env = &cpu->env;
> +if (is_a64(env)) {
> +return env->xregs[argno];
> +} else {
> +return env->regs[argno];
> +}
> +}
> +
> +static inline void common_semi_set_ret(CPUState *cs, target_ulong ret)
> +{
> +ARMCPU *cpu = ARM_CPU(cs);
> +CPUARMState *env = &cpu->env;
> +if (is_a64(env)) {
> +env->xregs[0] = ret;
> +} else {
> +env->regs[0] = ret;
> +}
> +}
> +
> +static inline bool common_semi_sys_exit_extended(CPUState *cs, int nr)
> +{
> +return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
> +}
> +
> +static inline bool is_64bit_semihosting(CPUArchState *env)
> +{
> +return is_a64(env);
> +}
> +
> +static inline target_ulong common_semi_stack_bottom(CPUState *cs)
> +{
> +ARMCPU *cpu = ARM_CPU(cs);
> +CPUARMState *env = &cpu->env;
> +return is_a64(env) ? env->xregs[31] : env->regs[13];
> +}
> +
> +static inline bool common_semi_has_synccache(CPUArchState *env)
> +{
> +/* Ok for A64, invalid for A32/T32 */
> +return is_a64(env);
> +}
> +
> +#endif
> diff --git a/target/riscv/common-semi-target.h 
> b/target/riscv/common-semi-target.h
> new file mode 100644
> index 00..7c8a59e0cc
> --- /dev/null
> +++ b/target/riscv/common-semi-target.h
> @@ -0,0 +1,50 @@
> +/*
> + * Target-specific parts of semihosting/arm-compat-semi.c.
> + *
> + * Copyright (c) 2005, 2007 CodeSourcery.
> + * Copyright (c) 2019, 2022 Linaro
> + * Copyright © 2020 by Keith Packard 
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef TARGET_RISCV_COMMON_SEMI_TARGET_H
> +#define TARGET_RISCV_COMMON_SEMI_TARGET_H
> +
> +static inline target_ulong common_semi_arg(CPUState *cs, int argno)
> +{
> +RISCVCPU *cpu = RISCV_CPU(cs);
> +CPURISCVState *env = &cpu->env;
> +return env->gpr[xA0 + argno];
> +}
> +
> +static inline void common_semi_set_ret(CPUState *cs, target_ulong ret)
> +{
> +RISCVCPU *cpu = RISCV_CPU(cs);
> +CPURISCVState *env = &cpu->env;
> +env->gpr[xA0] = ret;
> +}
> +
> +static inline bool common_semi_sys_exit_extended(CPUState *cs, int nr)
> +{
> +return (nr == TARGET_SYS_EXIT_EXTENDED || sizeof(target_ulong) == 8);
> +}
> +
> +static inline bool is_64bit_semihosting(CPUArchState *env)
> +{
> +return riscv_cpu_mxl(env) != MXL_RV32;
> +}
> +
> +static inline target_ulong common_semi_stack_bottom(CPUState *cs)
> +{
> +RISCVCPU *cpu = RISCV_CPU(cs);
> +CPURISCVState *env = &cpu->env;
> +return env->gpr[xSP];
> +}
> +
> +static inline bool common_semi_has_synccache(CPUArchState *env)
> +{
> +return true;
> +}
> +
> +#endif
> diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
> index 50f40a2a1a..5e442e549d 100644
> --- a/semihosting/arm-compat-semi.c
> +++ b/semihosting/arm-compat-semi.c
> @@ -46,9 +46,6 @@
>  #else
>  #include "qemu/cutils.h"
>  #include "hw/loader.h"
> -#ifdef TARGET_ARM
> -#include "hw/arm/boot.h"
> -#endif
>  #include "hw/boards.h"
>  #endif
>  
> @@ -182,96 +179,7 @@ static LayoutInfo common_semi_find_bases(CPUState *cs)
>  
>  #endif
>  
> -#ifdef TARGET_ARM
> -static inline target_ulong
> -common_semi_arg(CPUState *cs, int argno)
> -{
> -ARMCPU *cpu = ARM_CPU(cs);
> -CPUARMState *env = &cpu->env;
> -if (is_a64(env)) {
> -return env->xregs[argno];
> -} else {
> -return env->regs[argno];
> -}
> -}
> -
> -static inline void
> -common_semi_set_ret(CPUState *cs, target_ulong ret)
> -{
> -ARMCPU *cpu = ARM_CPU(cs);
> -CPUARMState *env = &cpu->env;
> -if (is_a64(env)) {
> -env->xregs[0] = ret;
> -} else {
> -env->regs[0] = ret;
> -}
> -}
> -
> -static inline bool
> -common_semi_sys_exit_extend

Re: [PATCH v4 48/53] semihosting: Use console_in_gf for SYS_READC

2022-06-27 Thread Alex Bennée


Richard Henderson  writes:

> Signed-off-by: Richard Henderson 
> ---
>  semihosting/arm-compat-semi.c | 27 ++-
>  1 file changed, 18 insertions(+), 9 deletions(-)
>
> diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
> index 20e99cdcc0..4c8932ad54 100644
> --- a/semihosting/arm-compat-semi.c
> +++ b/semihosting/arm-compat-semi.c
> @@ -302,6 +302,22 @@ common_semi_flen_fstat_cb(CPUState *cs, uint64_t ret, 
> int err)
>  common_semi_cb(cs, ret, err);
>  }
>  
> +static void
> +common_semi_readc_cb(CPUState *cs, uint64_t ret, int err)
> +{
> +if (!err) {
> +CPUArchState *env G_GNUC_UNUSED = cs->env_ptr;

Why do you even both extracting env here if it's not being used?

> +uint8_t ch;
> +
> +if (get_user_u8(ch, common_semi_stack_bottom(cs) - 1)) {
> +ret = -1, err = EFAULT;
> +} else {
> +ret = ch;
> +}
> +}
> +common_semi_cb(cs, ret, err);
> +}
> +
>  #define SHFB_MAGIC_0 0x53
>  #define SHFB_MAGIC_1 0x48
>  #define SHFB_MAGIC_2 0x46
> @@ -427,15 +443,8 @@ void do_common_semihosting(CPUState *cs)
>  break;
>  
>  case TARGET_SYS_READC:
> -{
> -uint8_t ch;
> -int ret = qemu_semihosting_console_read(cs, &ch, 1);
> -if (ret == 1) {
> -common_semi_cb(cs, ch, 0);
> -} else {
> -common_semi_cb(cs, -1, EIO);
> -}
> -}
> +semihost_sys_read_gf(cs, common_semi_readc_cb, &console_in_gf,
> + common_semi_stack_bottom(cs) - 1, 1);
>  break;
>  
>  case TARGET_SYS_ISERROR:


-- 
Alex Bennée



Re: [PATCH v4 52/53] semihosting: Remove qemu_semihosting_console_outs

2022-06-27 Thread Alex Bennée


Richard Henderson  writes:

> This function has been replaced by *_write.
>
> Signed-off-by: Richard Henderson 

Reviewed-by: Alex Bennée 

-- 
Alex Bennée



Re: [PATCH v4 27/53] semihosting: Split out semihost_sys_open

2022-06-27 Thread Luc Michel
On 08:05 Wed 22 Jun , Richard Henderson wrote:
> On 6/22/22 02:35, Luc Michel wrote:
> > On 13:45 Tue 07 Jun , Richard Henderson wrote:
> > > Split out the non-ARM specific portions of SYS_OPEN to a
> > > reusable function.  This handles gdb and host file i/o.
> > > 
> > > Add helpers to validate the length of the filename string.
> > > Prepare for usage by other semihosting by allowing the
> > > filename length parameter to be 0, and calling strlen.
> > > 
> > > Signed-off-by: Richard Henderson 
> > > ---
> > >   include/semihosting/syscalls.h |  25 ++
> > >   semihosting/arm-compat-semi.c  |  52 ++-
> > >   semihosting/guestfd.c  |   5 ++
> > >   semihosting/syscalls.c | 156 +
> > >   semihosting/meson.build|   1 +
> > >   5 files changed, 193 insertions(+), 46 deletions(-)
> > >   create mode 100644 include/semihosting/syscalls.h
> > >   create mode 100644 semihosting/syscalls.c
> > > 
> > 
> > [...]
> > 
> > >   } else {
> > > -hostfd = open(s, open_modeflags[arg1], 0644);
> > > -if (hostfd < 0) {
> > > -ret = -1;
> > > -err = errno;
> > > -} else {
> > > -ret = alloc_guestfd();
> > > -associate_guestfd(ret, hostfd);
> > > -}
> > > +semihost_sys_open(cs, common_semi_cb, arg0, arg2 + 1,
> > > +  gdb_open_modeflags[arg1], 0644);
> > 
> > You're missing a unlock_user(s, arg0, 0); here
> 
> Good catch.  Fixed.

With this fixed:

Reviewed-by: Luc Michel 


> 
> 
> r~
> 
> 
> To declare a filtering error, please use the following link : 
> https://www.security-mail.net/reporter.php?mid=3812.62b32fac.79d6c.0&r=lmichel%40kalray.eu&s=richard.henderson%40linaro.org&o=Re%3A+%5BPATCH+v4+27%2F53%5D+semihosting%3A+Split+out+semihost_sys_open&verdict=C&c=588dc0ed7d12e87bd5846dca36ad4d902888f28e
> 

-- 







[PATCH] target/riscv: fix user-mode build issue because mhartid

2022-06-27 Thread Rahul Pathak
mhartid csr is not available in user-mode code path and
user-mode build fails because of its reference in
riscv_cpu_realize function

Signed-off-by: Rahul Pathak 
---
 target/riscv/cpu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0a794ef622..03f23d4b6d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -643,9 +643,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 if (isa_ext_is_enabled(cpu, &isa_edata_arr[i]) &&
 (env->priv_ver < isa_edata_arr[i].min_version)) {
 isa_ext_update_enabled(cpu, &isa_edata_arr[i], false);
+#ifndef CONFIG_USER_ONLY
 warn_report("disabling %s extension for hart 0x%lx because "
 "privilege spec version does not match",
 isa_edata_arr[i].name, (unsigned long)env->mhartid);
+#else
+warn_report("disabling %s extension for hart 0x%lx because "
+"privilege spec version does not match",
+isa_edata_arr[i].name);
+#endif
 }
 }
 
-- 
2.34.1




Re: [PATCH v4] hw: m25p80: add tests for write protect (WP# and SRWD bit)

2022-06-27 Thread Cédric Le Goater

On 6/24/22 20:30, Iris Chen wrote:

Signed-off-by: Iris Chen 


Reviewed-by: Cédric Le Goater 

Thanks,

C.


---
Adding Signed Off By tag -- sorry I missed that !

  tests/qtest/aspeed_smc-test.c | 62 +++
  1 file changed, 62 insertions(+)

diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c
index ec233315e6..7786addfb8 100644
--- a/tests/qtest/aspeed_smc-test.c
+++ b/tests/qtest/aspeed_smc-test.c
@@ -56,7 +56,9 @@ enum {
  BULK_ERASE = 0xc7,
  READ = 0x03,
  PP = 0x02,
+WRSR = 0x1,
  WREN = 0x6,
+SRWD = 0x80,
  RESET_ENABLE = 0x66,
  RESET_MEMORY = 0x99,
  EN_4BYTE_ADDR = 0xB7,
@@ -390,6 +392,64 @@ static void test_read_status_reg(void)
  flash_reset();
  }
  
+static void test_status_reg_write_protection(void)

+{
+uint8_t r;
+
+spi_conf(CONF_ENABLE_W0);
+
+/* default case: WP# is high and SRWD is low -> status register writable */
+spi_ctrl_start_user();
+writeb(ASPEED_FLASH_BASE, WREN);
+/* test ability to write SRWD */
+writeb(ASPEED_FLASH_BASE, WRSR);
+writeb(ASPEED_FLASH_BASE, SRWD);
+writeb(ASPEED_FLASH_BASE, RDSR);
+r = readb(ASPEED_FLASH_BASE);
+spi_ctrl_stop_user();
+g_assert_cmphex(r & SRWD, ==, SRWD);
+
+/* WP# high and SRWD high -> status register writable */
+spi_ctrl_start_user();
+writeb(ASPEED_FLASH_BASE, WREN);
+/* test ability to write SRWD */
+writeb(ASPEED_FLASH_BASE, WRSR);
+writeb(ASPEED_FLASH_BASE, 0);
+writeb(ASPEED_FLASH_BASE, RDSR);
+r = readb(ASPEED_FLASH_BASE);
+spi_ctrl_stop_user();
+g_assert_cmphex(r & SRWD, ==, 0);
+
+/* WP# low and SRWD low -> status register writable */
+qtest_set_irq_in(global_qtest,
+ "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 0);
+spi_ctrl_start_user();
+writeb(ASPEED_FLASH_BASE, WREN);
+/* test ability to write SRWD */
+writeb(ASPEED_FLASH_BASE, WRSR);
+writeb(ASPEED_FLASH_BASE, SRWD);
+writeb(ASPEED_FLASH_BASE, RDSR);
+r = readb(ASPEED_FLASH_BASE);
+spi_ctrl_stop_user();
+g_assert_cmphex(r & SRWD, ==, SRWD);
+
+/* WP# low and SRWD high -> status register NOT writable */
+spi_ctrl_start_user();
+writeb(ASPEED_FLASH_BASE, WREN);
+/* test ability to write SRWD */
+writeb(ASPEED_FLASH_BASE, WRSR);
+writeb(ASPEED_FLASH_BASE, 0);
+writeb(ASPEED_FLASH_BASE, RDSR);
+r = readb(ASPEED_FLASH_BASE);
+spi_ctrl_stop_user();
+/* write is not successful */
+g_assert_cmphex(r & SRWD, ==, SRWD);
+
+qtest_set_irq_in(global_qtest,
+ "/machine/soc/fmc/ssi.0/child[0]", "WP#", 0, 1);
+flash_reset();
+}
+
  static char tmp_path[] = "/tmp/qtest.m25p80.XX";
  
  int main(int argc, char **argv)

@@ -416,6 +476,8 @@ int main(int argc, char **argv)
  qtest_add_func("/ast2400/smc/read_page_mem", test_read_page_mem);
  qtest_add_func("/ast2400/smc/write_page_mem", test_write_page_mem);
  qtest_add_func("/ast2400/smc/read_status_reg", test_read_status_reg);
+qtest_add_func("/ast2400/smc/status_reg_write_protection",
+   test_status_reg_write_protection);
  
  ret = g_test_run();
  





Re: [PATCH 1/2] pc-bios/s390-ccw/virtio-blkdev: Simplify/fix virtio_ipl_disk_is_valid()

2022-06-27 Thread Thomas Huth

On 24/06/2022 10.50, Thomas Huth wrote:

The s390-ccw bios fails to boot if the boot disk is a virtio-blk
disk with a sector size of 4096. For example:

  dasdfmt -b 4096 -d cdl -y -p -M quick /dev/dasdX
  fdasd -a /dev/dasdX
  install a guest onto /dev/dasdX1 using virtio-blk
  qemu-system-s390x -nographic -hda /dev/dasdX1

The bios then bails out with:

  ! Cannot read block 0 !

Looking at virtio_ipl_disk_is_valid() and especially the function
virtio_disk_is_scsi(), it does not really make sense that we expect
only such a limited disk geometry (like a block size of 512) for
out boot disks. Let's relax the check and allow everything that
remotely looks like a sane disk.

Signed-off-by: Thomas Huth 
---
  pc-bios/s390-ccw/virtio.h|  2 --
  pc-bios/s390-ccw/virtio-blkdev.c | 41 ++--
  2 files changed, 7 insertions(+), 36 deletions(-)


I just noticed that this breaks booting ISO images via the "-cdrom" option 
... looks like this needs some additional fixes on top.


 Thomas




[PATCH] aspeed/hace: Accumulative mode supported

2022-06-27 Thread Joel Stanley
While the HMAC mode is not modelled, the accumulative mode is.

Accumulative mode is enabled by setting one of the bits in the HMAC
engine command mode part of the register, so fix the unimplemented check
to only look at the upper of the two bits.

Fixes: 5cd7d8564a8b ("aspeed/hace: Support AST2600 HACE")
Signed-off-by: Joel Stanley 
---
 hw/misc/aspeed_hace.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c
index 731234b78c4c..ac21be306c69 100644
--- a/hw/misc/aspeed_hace.c
+++ b/hw/misc/aspeed_hace.c
@@ -338,10 +338,10 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, 
uint64_t data,
 int algo;
 data &= ahc->hash_mask;
 
-if ((data & HASH_HMAC_MASK)) {
+if ((data & HASH_DIGEST_HMAC)) {
 qemu_log_mask(LOG_UNIMP,
-  "%s: HMAC engine command mode %"PRIx64" not 
implemented\n",
-  __func__, (data & HASH_HMAC_MASK) >> 8);
+  "%s: HMAC mode not implemented\n",
+  __func__);
 }
 if (data & BIT(1)) {
 qemu_log_mask(LOG_UNIMP,
-- 
2.35.1




[PULL 00/25] target-arm queue

2022-06-27 Thread Peter Maydell
target-arm queue, mostly SME preliminaries.

In the unlikely event we don't land the rest of SME before freeze
for 7.1 we can revert the docs/property changes included here.

-- PMM

The following changes since commit 097ccbbbaf2681df1e65542e5b7d2b2d0c66e2bc:

  Merge tag 'qemu-sparc-20220626' of https://github.com/mcayland/qemu into 
staging (2022-06-27 05:21:05 +0530)

are available in the Git repository at:

  https://git.linaro.org/people/pmaydell/qemu-arm.git 
tags/pull-target-arm-20220627

for you to fetch changes up to 59e1b8a22ea9f947d038ccac784de1020f266e14:

  target/arm: Check V7VE as well as LPAE in arm_pamax (2022-06-27 11:18:17 
+0100)


target-arm queue:
 * sphinx: change default language to 'en'
 * Diagnose attempts to emulate EL3 in hvf as well as kvm
 * More SME groundwork patches
 * virt: Fix calculation of physical address space size
   for v7VE CPUs (eg cortex-a15)


Alexander Graf (2):
  accel: Introduce current_accel_name()
  target/arm: Catch invalid kvm state also for hvf

Martin Liška (1):
  sphinx: change default language to 'en'

Richard Henderson (22):
  target/arm: Implement TPIDR2_EL0
  target/arm: Add SMEEXC_EL to TB flags
  target/arm: Add syn_smetrap
  target/arm: Add ARM_CP_SME
  target/arm: Add SVCR
  target/arm: Add SMCR_ELx
  target/arm: Add SMIDR_EL1, SMPRI_EL1, SMPRIMAP_EL2
  target/arm: Add PSTATE.{SM,ZA} to TB flags
  target/arm: Add the SME ZA storage to CPUARMState
  target/arm: Implement SMSTART, SMSTOP
  target/arm: Move error for sve%d property to arm_cpu_sve_finalize
  target/arm: Create ARMVQMap
  target/arm: Generalize cpu_arm_{get,set}_vq
  target/arm: Generalize cpu_arm_{get, set}_default_vec_len
  target/arm: Move arm_cpu_*_finalize to internals.h
  target/arm: Unexport aarch64_add_*_properties
  target/arm: Add cpu properties for SME
  target/arm: Introduce sve_vqm1_for_el_sm
  target/arm: Add SVL to TB flags
  target/arm: Move pred_{full, gvec}_reg_{offset, size} to translate-a64.h
  target/arm: Extend arm_pamax to more than aarch64
  target/arm: Check V7VE as well as LPAE in arm_pamax

 docs/conf.py |   2 +-
 docs/system/arm/cpu-features.rst |  56 ++
 include/qemu/accel.h |   1 +
 target/arm/cpregs.h  |   5 +
 target/arm/cpu.h | 103 ++-
 target/arm/helper-sme.h  |  21 
 target/arm/helper.h  |   1 +
 target/arm/internals.h   |   4 +
 target/arm/syndrome.h|  14 +++
 target/arm/translate-a64.h   |  38 +++
 target/arm/translate.h   |   6 ++
 accel/accel-common.c |   8 ++
 hw/arm/virt.c|  10 +-
 softmmu/vl.c |   3 +-
 target/arm/cpu.c |  32 --
 target/arm/cpu64.c   | 205 -
 target/arm/helper.c  | 213 +--
 target/arm/kvm64.c   |   2 +-
 target/arm/machine.c |  34 +++
 target/arm/ptw.c |  26 +++--
 target/arm/sme_helper.c  |  61 +++
 target/arm/translate-a64.c   |  46 +
 target/arm/translate-sve.c   |  36 ---
 target/arm/meson.build   |   1 +
 24 files changed, 782 insertions(+), 146 deletions(-)
 create mode 100644 target/arm/helper-sme.h
 create mode 100644 target/arm/sme_helper.c



[PULL 04/25] target/arm: Implement TPIDR2_EL0

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

This register is part of SME, but isn't closely related to the
rest of the extension.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-2-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h|  1 +
 target/arm/helper.c | 32 
 2 files changed, 33 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index df677b2d5d2..05d1e2e8dd1 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -474,6 +474,7 @@ typedef struct CPUArchState {
 };
 uint64_t tpidr_el[4];
 };
+uint64_t tpidr2_el0;
 /* The secure banks of these registers don't map anywhere */
 uint64_t tpidrurw_s;
 uint64_t tpidrprw_s;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 6457e6301cd..d21ba7ab836 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6279,6 +6279,35 @@ static const ARMCPRegInfo zcr_reginfo[] = {
   .writefn = zcr_write, .raw_writefn = raw_write },
 };
 
+#ifdef TARGET_AARCH64
+static CPAccessResult access_tpidr2(CPUARMState *env, const ARMCPRegInfo *ri,
+bool isread)
+{
+int el = arm_current_el(env);
+
+if (el == 0) {
+uint64_t sctlr = arm_sctlr(env, el);
+if (!(sctlr & SCTLR_EnTP2)) {
+return CP_ACCESS_TRAP;
+}
+}
+/* TODO: FEAT_FGT */
+if (el < 3
+&& arm_feature(env, ARM_FEATURE_EL3)
+&& !(env->cp15.scr_el3 & SCR_ENTP2)) {
+return CP_ACCESS_TRAP_EL3;
+}
+return CP_ACCESS_OK;
+}
+
+static const ARMCPRegInfo sme_reginfo[] = {
+{ .name = "TPIDR2_EL0", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 3, .crn = 13, .crm = 0, .opc2 = 5,
+  .access = PL0_RW, .accessfn = access_tpidr2,
+  .fieldoffset = offsetof(CPUARMState, cp15.tpidr2_el0) },
+};
+#endif /* TARGET_AARCH64 */
+
 void hw_watchpoint_update(ARMCPU *cpu, int n)
 {
 CPUARMState *env = &cpu->env;
@@ -8440,6 +8469,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 }
 
 #ifdef TARGET_AARCH64
+if (cpu_isar_feature(aa64_sme, cpu)) {
+define_arm_cp_regs(cpu, sme_reginfo);
+}
 if (cpu_isar_feature(aa64_pauth, cpu)) {
 define_arm_cp_regs(cpu, pauth_reginfo);
 }
-- 
2.25.1




[PULL 02/25] accel: Introduce current_accel_name()

2022-06-27 Thread Peter Maydell
From: Alexander Graf 

We need to fetch the name of the current accelerator in flexible error
messages more going forward. Let's create a helper that gives it to us
without casting in the target code.

Signed-off-by: Alexander Graf 
Reviewed-by: Richard Henderson 
Message-id: 20220620192242.70573-1-ag...@csgraf.de
Signed-off-by: Peter Maydell 
---
 include/qemu/accel.h | 1 +
 accel/accel-common.c | 8 
 softmmu/vl.c | 3 +--
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/qemu/accel.h b/include/qemu/accel.h
index 4f4c283f6fc..be56da1b999 100644
--- a/include/qemu/accel.h
+++ b/include/qemu/accel.h
@@ -68,6 +68,7 @@ typedef struct AccelClass {
 
 AccelClass *accel_find(const char *opt_name);
 AccelState *current_accel(void);
+const char *current_accel_name(void);
 
 void accel_init_interfaces(AccelClass *ac);
 
diff --git a/accel/accel-common.c b/accel/accel-common.c
index 7b8ec7e0f72..50035bda55d 100644
--- a/accel/accel-common.c
+++ b/accel/accel-common.c
@@ -49,6 +49,14 @@ AccelClass *accel_find(const char *opt_name)
 return ac;
 }
 
+/* Return the name of the current accelerator */
+const char *current_accel_name(void)
+{
+AccelClass *ac = ACCEL_GET_CLASS(current_accel());
+
+return ac->name;
+}
+
 static void accel_init_cpu_int_aux(ObjectClass *klass, void *opaque)
 {
 CPUClass *cc = CPU_CLASS(klass);
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 54e920ada1a..3dca5936c76 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2271,8 +2271,7 @@ static void configure_accelerators(const char *progname)
 }
 
 if (init_failed && !qtest_chrdev) {
-AccelClass *ac = ACCEL_GET_CLASS(current_accel());
-error_report("falling back to %s", ac->name);
+error_report("falling back to %s", current_accel_name());
 }
 
 if (icount_enabled() && !tcg_enabled()) {
-- 
2.25.1




[PULL 01/25] sphinx: change default language to 'en'

2022-06-27 Thread Peter Maydell
From: Martin Liška 

Fixes the following Sphinx warning (treated as error) starting
with 5.0 release:

Warning, treated as error:
Invalid configuration value found: 'language = None'. Update your configuration 
to a valid langauge code. Falling back to 'en' (English).

Signed-off-by: Martin Liska 
Message-id: e91e51ee-48ac-437e-6467-98b56ee40...@suse.cz
Reviewed-by: Peter Maydell 
Signed-off-by: Peter Maydell 
---
 docs/conf.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/conf.py b/docs/conf.py
index 49dab44cca5..e33cf3d3812 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -126,7 +126,7 @@
 #
 # This is also used if you do content translation via gettext catalogs.
 # Usually you set "language" from the command line for these cases.
-language = None
+language = 'en'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-- 
2.25.1




[PULL 05/25] target/arm: Add SMEEXC_EL to TB flags

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

This is CheckSMEAccess, which is the basis for a set of
related tests for various SME cpregs and instructions.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-3-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h   |  2 ++
 target/arm/translate.h |  1 +
 target/arm/helper.c| 52 ++
 target/arm/translate-a64.c |  1 +
 4 files changed, 56 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 05d1e2e8dd1..e99de180978 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1134,6 +1134,7 @@ void aarch64_sync_64_to_32(CPUARMState *env);
 
 int fp_exception_el(CPUARMState *env, int cur_el);
 int sve_exception_el(CPUARMState *env, int cur_el);
+int sme_exception_el(CPUARMState *env, int cur_el);
 
 /**
  * sve_vqm1_for_el:
@@ -3148,6 +3149,7 @@ FIELD(TBFLAG_A64, ATA, 15, 1)
 FIELD(TBFLAG_A64, TCMA, 16, 2)
 FIELD(TBFLAG_A64, MTE_ACTIVE, 18, 1)
 FIELD(TBFLAG_A64, MTE0_ACTIVE, 19, 1)
+FIELD(TBFLAG_A64, SMEEXC_EL, 20, 2)
 
 /*
  * Helpers for using the above.
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 88dc18a034b..c88c9533253 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -42,6 +42,7 @@ typedef struct DisasContext {
 bool ns;/* Use non-secure CPREG bank on access */
 int fp_excp_el; /* FP exception EL or 0 if enabled */
 int sve_excp_el; /* SVE exception EL or 0 if enabled */
+int sme_excp_el; /* SME exception EL or 0 if enabled */
 int vl;  /* current vector length in bytes */
 bool vfp_enabled; /* FP enabled via FPSCR.EN */
 int vec_len;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index d21ba7ab836..2c080c6cac0 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6218,6 +6218,55 @@ int sve_exception_el(CPUARMState *env, int el)
 return 0;
 }
 
+/*
+ * Return the exception level to which exceptions should be taken for SME.
+ * C.f. the ARM pseudocode function CheckSMEAccess.
+ */
+int sme_exception_el(CPUARMState *env, int el)
+{
+#ifndef CONFIG_USER_ONLY
+if (el <= 1 && !el_is_in_host(env, el)) {
+switch (FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, SMEN)) {
+case 1:
+if (el != 0) {
+break;
+}
+/* fall through */
+case 0:
+case 2:
+return 1;
+}
+}
+
+if (el <= 2 && arm_is_el2_enabled(env)) {
+/* CPTR_EL2 changes format with HCR_EL2.E2H (regardless of TGE). */
+if (env->cp15.hcr_el2 & HCR_E2H) {
+switch (FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, SMEN)) {
+case 1:
+if (el != 0 || !(env->cp15.hcr_el2 & HCR_TGE)) {
+break;
+}
+/* fall through */
+case 0:
+case 2:
+return 2;
+}
+} else {
+if (FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, TSM)) {
+return 2;
+}
+}
+}
+
+/* CPTR_EL3.  Since ESM is negative we must check for EL3.  */
+if (arm_feature(env, ARM_FEATURE_EL3)
+&& !FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, ESM)) {
+return 3;
+}
+#endif
+return 0;
+}
+
 /*
  * Given that SVE is enabled, return the vector length for EL.
  */
@@ -11197,6 +11246,9 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState 
*env, int el, int fp_el,
 }
 DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el);
 }
+if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
+DP_TBFLAG_A64(flags, SMEEXC_EL, sme_exception_el(env, el));
+}
 
 sctlr = regime_sctlr(env, stage1);
 
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 4c64546090c..9a285dd1774 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -14603,6 +14603,7 @@ static void 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
 dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
 dc->sve_excp_el = EX_TBFLAG_A64(tb_flags, SVEEXC_EL);
+dc->sme_excp_el = EX_TBFLAG_A64(tb_flags, SMEEXC_EL);
 dc->vl = (EX_TBFLAG_A64(tb_flags, VL) + 1) * 16;
 dc->pauth_active = EX_TBFLAG_A64(tb_flags, PAUTH_ACTIVE);
 dc->bt = EX_TBFLAG_A64(tb_flags, BT);
-- 
2.25.1




[PULL 10/25] target/arm: Add SMIDR_EL1, SMPRI_EL1, SMPRIMAP_EL2

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

Implement the streaming mode identification register, and the
two streaming priority registers.  For QEMU, they are all RES0.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-8-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/helper.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2072f2a550e..bbd04fbd67b 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6351,6 +6351,18 @@ static CPAccessResult access_tpidr2(CPUARMState *env, 
const ARMCPRegInfo *ri,
 return CP_ACCESS_OK;
 }
 
+static CPAccessResult access_esm(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+/* TODO: FEAT_FGT for SMPRI_EL1 but not SMPRIMAP_EL2 */
+if (arm_current_el(env) < 3
+&& arm_feature(env, ARM_FEATURE_EL3)
+&& !FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, ESM)) {
+return CP_ACCESS_TRAP_EL3;
+}
+return CP_ACCESS_OK;
+}
+
 static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
 {
@@ -6408,6 +6420,27 @@ static const ARMCPRegInfo sme_reginfo[] = {
   .access = PL3_RW, .type = ARM_CP_SME,
   .fieldoffset = offsetof(CPUARMState, vfp.smcr_el[3]),
   .writefn = smcr_write, .raw_writefn = raw_write },
+{ .name = "SMIDR_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 6,
+  .access = PL1_R, .accessfn = access_aa64_tid1,
+  /*
+   * IMPLEMENTOR = 0 (software)
+   * REVISION= 0 (implementation defined)
+   * SMPS= 0 (no streaming execution priority in QEMU)
+   * AFFINITY= 0 (streaming sve mode not shared with other PEs)
+   */
+  .type = ARM_CP_CONST, .resetvalue = 0, },
+/*
+ * Because SMIDR_EL1.SMPS is 0, SMPRI_EL1 and SMPRIMAP_EL2 are RES 0.
+ */
+{ .name = "SMPRI_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 4,
+  .access = PL1_RW, .accessfn = access_esm,
+  .type = ARM_CP_CONST, .resetvalue = 0 },
+{ .name = "SMPRIMAP_EL2", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 5,
+  .access = PL2_RW, .accessfn = access_esm,
+  .type = ARM_CP_CONST, .resetvalue = 0 },
 };
 #endif /* TARGET_AARCH64 */
 
-- 
2.25.1




[PULL 07/25] target/arm: Add ARM_CP_SME

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

This will be used for controlling access to SME cpregs.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-5-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpregs.h|  5 +
 target/arm/translate-a64.c | 18 ++
 2 files changed, 23 insertions(+)

diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index d9b678c2f17..d30758ee713 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -113,6 +113,11 @@ enum {
 ARM_CP_EL3_NO_EL2_UNDEF  = 1 << 16,
 ARM_CP_EL3_NO_EL2_KEEP   = 1 << 17,
 ARM_CP_EL3_NO_EL2_C_NZ   = 1 << 18,
+/*
+ * Flag: Access check for this sysreg is constrained by the
+ * ARM pseudocode function CheckSMEAccess().
+ */
+ARM_CP_SME   = 1 << 19,
 };
 
 /*
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 9a285dd1774..8f609f46b6a 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1187,6 +1187,22 @@ bool sve_access_check(DisasContext *s)
 return fp_access_check(s);
 }
 
+/*
+ * Check that SME access is enabled, raise an exception if not.
+ * Note that this function corresponds to CheckSMEAccess and is
+ * only used directly for cpregs.
+ */
+static bool sme_access_check(DisasContext *s)
+{
+if (s->sme_excp_el) {
+gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
+  syn_smetrap(SME_ET_AccessTrap, false),
+  s->sme_excp_el);
+return false;
+}
+return true;
+}
+
 /*
  * This utility function is for doing register extension with an
  * optional shift. You will likely want to pass a temporary for the
@@ -1958,6 +1974,8 @@ static void handle_sys(DisasContext *s, uint32_t insn, 
bool isread,
 return;
 } else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
 return;
+} else if ((ri->type & ARM_CP_SME) && !sme_access_check(s)) {
+return;
 }
 
 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
-- 
2.25.1




[PULL 03/25] target/arm: Catch invalid kvm state also for hvf

2022-06-27 Thread Peter Maydell
From: Alexander Graf 

Some features such as running in EL3 or running M profile code are
incompatible with virtualization as QEMU implements it today. To prevent
users from picking invalid configurations on other virt solutions like
Hvf, let's run the same checks there too.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1073
Signed-off-by: Alexander Graf 
Reviewed-by: Richard Henderson 
Message-id: 20220620192242.70573-2-ag...@csgraf.de
[PMM: Allow qtest accelerator too; tweak comment]
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 1b5d5357880..d9c4a9f56d2 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -39,6 +39,7 @@
 #include "hw/boards.h"
 #endif
 #include "sysemu/tcg.h"
+#include "sysemu/qtest.h"
 #include "sysemu/hw_accel.h"
 #include "kvm_arm.h"
 #include "disas/capstone.h"
@@ -1490,25 +1491,32 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 }
 }
 
-if (kvm_enabled()) {
+if (!tcg_enabled() && !qtest_enabled()) {
 /*
+ * We assume that no accelerator except TCG (and the "not really an
+ * accelerator" qtest) can handle these features, because Arm hardware
+ * virtualization can't virtualize them.
+ *
  * Catch all the cases which might cause us to create more than one
  * address space for the CPU (otherwise we will assert() later in
  * cpu_address_space_init()).
  */
 if (arm_feature(env, ARM_FEATURE_M)) {
 error_setg(errp,
-   "Cannot enable KVM when using an M-profile guest CPU");
+   "Cannot enable %s when using an M-profile guest CPU",
+   current_accel_name());
 return;
 }
 if (cpu->has_el3) {
 error_setg(errp,
-   "Cannot enable KVM when guest CPU has EL3 enabled");
+   "Cannot enable %s when guest CPU has EL3 enabled",
+   current_accel_name());
 return;
 }
 if (cpu->tag_memory) {
 error_setg(errp,
-   "Cannot enable KVM when guest CPUs has MTE enabled");
+   "Cannot enable %s when guest CPUs has MTE enabled",
+   current_accel_name());
 return;
 }
 }
-- 
2.25.1




[PULL 08/25] target/arm: Add SVCR

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

This cpreg is used to access two new bits of PSTATE
that are not visible via any other mechanism.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-6-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h|  6 ++
 target/arm/helper.c | 13 +
 2 files changed, 19 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index e99de180978..bb8cb959d12 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -258,6 +258,7 @@ typedef struct CPUArchState {
  *  nRW (also known as M[4]) is kept, inverted, in env->aarch64
  *  DAIF (exception masks) are kept in env->daif
  *  BTYPE is kept in env->btype
+ *  SM and ZA are kept in env->svcr
  *  all other bits are stored in their correct places in env->pstate
  */
 uint32_t pstate;
@@ -292,6 +293,7 @@ typedef struct CPUArchState {
 uint32_t condexec_bits; /* IT bits.  cpsr[15:10,26:25].  */
 uint32_t btype;  /* BTI branch type.  spsr[11:10].  */
 uint64_t daif; /* exception masks, in the bits they are in PSTATE */
+uint64_t svcr; /* PSTATE.{SM,ZA} in the bits they are in SVCR */
 
 uint64_t elr_el[4]; /* AArch64 exception link regs  */
 uint64_t sp_el[4]; /* AArch64 banked stack pointers */
@@ -1428,6 +1430,10 @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
 #define PSTATE_MODE_EL1t 4
 #define PSTATE_MODE_EL0t 0
 
+/* PSTATE bits that are accessed via SVCR and not stored in SPSR_ELx. */
+FIELD(SVCR, SM, 0, 1)
+FIELD(SVCR, ZA, 1, 1)
+
 /* Write a new value to v7m.exception, thus transitioning into or out
  * of Handler mode; this may result in a change of active stack pointer.
  */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2c080c6cac0..3acc1dc378a 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6349,11 +6349,24 @@ static CPAccessResult access_tpidr2(CPUARMState *env, 
const ARMCPRegInfo *ri,
 return CP_ACCESS_OK;
 }
 
+static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+   uint64_t value)
+{
+value &= R_SVCR_SM_MASK | R_SVCR_ZA_MASK;
+/* TODO: Side effects. */
+env->svcr = value;
+}
+
 static const ARMCPRegInfo sme_reginfo[] = {
 { .name = "TPIDR2_EL0", .state = ARM_CP_STATE_AA64,
   .opc0 = 3, .opc1 = 3, .crn = 13, .crm = 0, .opc2 = 5,
   .access = PL0_RW, .accessfn = access_tpidr2,
   .fieldoffset = offsetof(CPUARMState, cp15.tpidr2_el0) },
+{ .name = "SVCR", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 2,
+  .access = PL0_RW, .type = ARM_CP_SME,
+  .fieldoffset = offsetof(CPUARMState, svcr),
+  .writefn = svcr_write, .raw_writefn = raw_write },
 };
 #endif /* TARGET_AARCH64 */
 
-- 
2.25.1




[PULL 11/25] target/arm: Add PSTATE.{SM,ZA} to TB flags

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

These are required to determine if various insns
are allowed to issue.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-9-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h   | 2 ++
 target/arm/translate.h | 4 
 target/arm/helper.c| 4 
 target/arm/translate-a64.c | 2 ++
 4 files changed, 12 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index dec52c6c3b9..05d369e690a 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3160,6 +3160,8 @@ FIELD(TBFLAG_A64, TCMA, 16, 2)
 FIELD(TBFLAG_A64, MTE_ACTIVE, 18, 1)
 FIELD(TBFLAG_A64, MTE0_ACTIVE, 19, 1)
 FIELD(TBFLAG_A64, SMEEXC_EL, 20, 2)
+FIELD(TBFLAG_A64, PSTATE_SM, 22, 1)
+FIELD(TBFLAG_A64, PSTATE_ZA, 23, 1)
 
 /*
  * Helpers for using the above.
diff --git a/target/arm/translate.h b/target/arm/translate.h
index c88c9533253..93766649f7f 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -97,6 +97,10 @@ typedef struct DisasContext {
 bool align_mem;
 /* True if PSTATE.IL is set */
 bool pstate_il;
+/* True if PSTATE.SM is set. */
+bool pstate_sm;
+/* True if PSTATE.ZA is set. */
+bool pstate_za;
 /* True if MVE insns are definitely not predicated by VPR or LTPSIZE */
 bool mve_no_pred;
 /*
diff --git a/target/arm/helper.c b/target/arm/helper.c
index bbd04fbd67b..e06c054c3d7 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11335,6 +11335,10 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState 
*env, int el, int fp_el,
 }
 if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
 DP_TBFLAG_A64(flags, SMEEXC_EL, sme_exception_el(env, el));
+if (FIELD_EX64(env->svcr, SVCR, SM)) {
+DP_TBFLAG_A64(flags, PSTATE_SM, 1);
+}
+DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA));
 }
 
 sctlr = regime_sctlr(env, stage1);
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 8f609f46b6a..5cf4a283bac 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -14630,6 +14630,8 @@ static void 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 dc->ata = EX_TBFLAG_A64(tb_flags, ATA);
 dc->mte_active[0] = EX_TBFLAG_A64(tb_flags, MTE_ACTIVE);
 dc->mte_active[1] = EX_TBFLAG_A64(tb_flags, MTE0_ACTIVE);
+dc->pstate_sm = EX_TBFLAG_A64(tb_flags, PSTATE_SM);
+dc->pstate_za = EX_TBFLAG_A64(tb_flags, PSTATE_ZA);
 dc->vec_len = 0;
 dc->vec_stride = 0;
 dc->cp_regs = arm_cpu->cp_regs;
-- 
2.25.1




[PULL 18/25] target/arm: Move arm_cpu_*_finalize to internals.h

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

Drop the aa32-only inline fallbacks,
and just use a couple of ifdefs.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-16-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h   | 6 --
 target/arm/internals.h | 3 +++
 target/arm/cpu.c   | 2 ++
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 2ce47f8d29f..675c49f93e0 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -205,14 +205,8 @@ typedef struct {
 
 #ifdef TARGET_AARCH64
 # define ARM_MAX_VQ16
-void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
-void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
-void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
 #else
 # define ARM_MAX_VQ1
-static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
-static inline void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) { }
-static inline void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) { }
 #endif
 
 typedef struct ARMVectorReg {
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 6f94f3019db..aef568adf75 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1288,6 +1288,9 @@ int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, 
int reg);
 int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg);
 int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg);
 int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg);
+void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
+void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
+void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
 #endif
 
 #ifdef CONFIG_USER_ONLY
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index d9c4a9f56d2..660fd8b8b90 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1422,6 +1422,7 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
 {
 Error *local_err = NULL;
 
+#ifdef TARGET_AARCH64
 if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
 arm_cpu_sve_finalize(cpu, &local_err);
 if (local_err != NULL) {
@@ -1441,6 +1442,7 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
 return;
 }
 }
+#endif
 
 if (kvm_enabled()) {
 kvm_arm_steal_time_finalize(cpu, &local_err);
-- 
2.25.1




[PULL 17/25] target/arm: Generalize cpu_arm_{get, set}_default_vec_len

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

Rename from cpu_arm_{get,set}_sve_default_vec_len,
and take the pointer to default_vq from opaque.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-15-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu64.c | 27 ++-
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 1a3cb953bf0..b15a0d398ad 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -638,11 +638,11 @@ static void cpu_arm_set_sve(Object *obj, bool value, 
Error **errp)
 
 #ifdef CONFIG_USER_ONLY
 /* Mirror linux /proc/sys/abi/sve_default_vector_length. */
-static void cpu_arm_set_sve_default_vec_len(Object *obj, Visitor *v,
-const char *name, void *opaque,
-Error **errp)
+static void cpu_arm_set_default_vec_len(Object *obj, Visitor *v,
+const char *name, void *opaque,
+Error **errp)
 {
-ARMCPU *cpu = ARM_CPU(obj);
+uint32_t *ptr_default_vq = opaque;
 int32_t default_len, default_vq, remainder;
 
 if (!visit_type_int32(v, name, &default_len, errp)) {
@@ -651,7 +651,7 @@ static void cpu_arm_set_sve_default_vec_len(Object *obj, 
Visitor *v,
 
 /* Undocumented, but the kernel allows -1 to indicate "maximum". */
 if (default_len == -1) {
-cpu->sve_default_vq = ARM_MAX_VQ;
+*ptr_default_vq = ARM_MAX_VQ;
 return;
 }
 
@@ -675,15 +675,15 @@ static void cpu_arm_set_sve_default_vec_len(Object *obj, 
Visitor *v,
 return;
 }
 
-cpu->sve_default_vq = default_vq;
+*ptr_default_vq = default_vq;
 }
 
-static void cpu_arm_get_sve_default_vec_len(Object *obj, Visitor *v,
-const char *name, void *opaque,
-Error **errp)
+static void cpu_arm_get_default_vec_len(Object *obj, Visitor *v,
+const char *name, void *opaque,
+Error **errp)
 {
-ARMCPU *cpu = ARM_CPU(obj);
-int32_t value = cpu->sve_default_vq * 16;
+uint32_t *ptr_default_vq = opaque;
+int32_t value = *ptr_default_vq * 16;
 
 visit_type_int32(v, name, &value, errp);
 }
@@ -706,8 +706,9 @@ void aarch64_add_sve_properties(Object *obj)
 #ifdef CONFIG_USER_ONLY
 /* Mirror linux /proc/sys/abi/sve_default_vector_length. */
 object_property_add(obj, "sve-default-vector-length", "int32",
-cpu_arm_get_sve_default_vec_len,
-cpu_arm_set_sve_default_vec_len, NULL, NULL);
+cpu_arm_get_default_vec_len,
+cpu_arm_set_default_vec_len, NULL,
+&cpu->sve_default_vq);
 #endif
 }
 
-- 
2.25.1




[PULL 06/25] target/arm: Add syn_smetrap

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

This will be used for raising various traps for SME.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-4-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/syndrome.h | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
index c105f9e6ba5..73df5e37938 100644
--- a/target/arm/syndrome.h
+++ b/target/arm/syndrome.h
@@ -48,6 +48,7 @@ enum arm_exception_class {
 EC_AA64_SMC   = 0x17,
 EC_SYSTEMREGISTERTRAP = 0x18,
 EC_SVEACCESSTRAP  = 0x19,
+EC_SMETRAP= 0x1d,
 EC_INSNABORT  = 0x20,
 EC_INSNABORT_SAME_EL  = 0x21,
 EC_PCALIGNMENT= 0x22,
@@ -68,6 +69,13 @@ enum arm_exception_class {
 EC_AA64_BKPT  = 0x3c,
 };
 
+typedef enum {
+SME_ET_AccessTrap,
+SME_ET_Streaming,
+SME_ET_NotStreaming,
+SME_ET_InactiveZA,
+} SMEExceptionType;
+
 #define ARM_EL_EC_SHIFT 26
 #define ARM_EL_IL_SHIFT 25
 #define ARM_EL_ISV_SHIFT 24
@@ -207,6 +215,12 @@ static inline uint32_t syn_sve_access_trap(void)
 return EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT;
 }
 
+static inline uint32_t syn_smetrap(SMEExceptionType etype, bool is_16bit)
+{
+return (EC_SMETRAP << ARM_EL_EC_SHIFT)
+| (is_16bit ? 0 : ARM_EL_IL) | etype;
+}
+
 static inline uint32_t syn_pactrap(void)
 {
 return EC_PACTRAP << ARM_EL_EC_SHIFT;
-- 
2.25.1




[PULL 09/25] target/arm: Add SMCR_ELx

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

These cpregs control the streaming vector length and whether the
full a64 instruction set is allowed while in streaming mode.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-7-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h|  8 ++--
 target/arm/helper.c | 41 +
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index bb8cb959d12..dec52c6c3b9 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -669,8 +669,8 @@ typedef struct CPUArchState {
 float_status standard_fp_status;
 float_status standard_fp_status_f16;
 
-/* ZCR_EL[1-3] */
-uint64_t zcr_el[4];
+uint64_t zcr_el[4];   /* ZCR_EL[1-3] */
+uint64_t smcr_el[4];  /* SMCR_EL[1-3] */
 } vfp;
 uint64_t exclusive_addr;
 uint64_t exclusive_val;
@@ -1434,6 +1434,10 @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
 FIELD(SVCR, SM, 0, 1)
 FIELD(SVCR, ZA, 1, 1)
 
+/* Fields for SMCR_ELx. */
+FIELD(SMCR, LEN, 0, 4)
+FIELD(SMCR, FA64, 31, 1)
+
 /* Write a new value to v7m.exception, thus transitioning into or out
  * of Handler mode; this may result in a change of active stack pointer.
  */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 3acc1dc378a..2072f2a550e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5879,6 +5879,8 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU 
*cpu)
  */
 { K(3, 0,  1, 2, 0), K(3, 4,  1, 2, 0), K(3, 5, 1, 2, 0),
   "ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve },
+{ K(3, 0,  1, 2, 6), K(3, 4,  1, 2, 6), K(3, 5, 1, 2, 6),
+  "SMCR_EL1", "SMCR_EL2", "SMCR_EL12", isar_feature_aa64_sme },
 
 { K(3, 0,  5, 6, 0), K(3, 4,  5, 6, 0), K(3, 5, 5, 6, 0),
   "TFSR_EL1", "TFSR_EL2", "TFSR_EL12", isar_feature_aa64_mte },
@@ -6357,6 +6359,30 @@ static void svcr_write(CPUARMState *env, const 
ARMCPRegInfo *ri,
 env->svcr = value;
 }
 
+static void smcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+   uint64_t value)
+{
+int cur_el = arm_current_el(env);
+int old_len = sve_vqm1_for_el(env, cur_el);
+int new_len;
+
+QEMU_BUILD_BUG_ON(ARM_MAX_VQ > R_SMCR_LEN_MASK + 1);
+value &= R_SMCR_LEN_MASK | R_SMCR_FA64_MASK;
+raw_write(env, ri, value);
+
+/*
+ * Note that it is CONSTRAINED UNPREDICTABLE what happens to ZA storage
+ * when SVL is widened (old values kept, or zeros).  Choose to keep the
+ * current values for simplicity.  But for QEMU internals, we must still
+ * apply the narrower SVL to the Zregs and Pregs -- see the comment
+ * above aarch64_sve_narrow_vq.
+ */
+new_len = sve_vqm1_for_el(env, cur_el);
+if (new_len < old_len) {
+aarch64_sve_narrow_vq(env, new_len + 1);
+}
+}
+
 static const ARMCPRegInfo sme_reginfo[] = {
 { .name = "TPIDR2_EL0", .state = ARM_CP_STATE_AA64,
   .opc0 = 3, .opc1 = 3, .crn = 13, .crm = 0, .opc2 = 5,
@@ -6367,6 +6393,21 @@ static const ARMCPRegInfo sme_reginfo[] = {
   .access = PL0_RW, .type = ARM_CP_SME,
   .fieldoffset = offsetof(CPUARMState, svcr),
   .writefn = svcr_write, .raw_writefn = raw_write },
+{ .name = "SMCR_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 6,
+  .access = PL1_RW, .type = ARM_CP_SME,
+  .fieldoffset = offsetof(CPUARMState, vfp.smcr_el[1]),
+  .writefn = smcr_write, .raw_writefn = raw_write },
+{ .name = "SMCR_EL2", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 6,
+  .access = PL2_RW, .type = ARM_CP_SME,
+  .fieldoffset = offsetof(CPUARMState, vfp.smcr_el[2]),
+  .writefn = smcr_write, .raw_writefn = raw_write },
+{ .name = "SMCR_EL3", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 6,
+  .access = PL3_RW, .type = ARM_CP_SME,
+  .fieldoffset = offsetof(CPUARMState, vfp.smcr_el[3]),
+  .writefn = smcr_write, .raw_writefn = raw_write },
 };
 #endif /* TARGET_AARCH64 */
 
-- 
2.25.1




[PULL 22/25] target/arm: Add SVL to TB flags

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

We need SVL separate from VL for RDSVL et al, as well as
ZA storage loads and stores, which do not require PSTATE.SM.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-20-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h   | 12 
 target/arm/translate.h |  1 +
 target/arm/helper.c|  8 +++-
 target/arm/translate-a64.c |  1 +
 4 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0295e854838..4a4342f2622 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3182,6 +3182,7 @@ FIELD(TBFLAG_A64, MTE0_ACTIVE, 19, 1)
 FIELD(TBFLAG_A64, SMEEXC_EL, 20, 2)
 FIELD(TBFLAG_A64, PSTATE_SM, 22, 1)
 FIELD(TBFLAG_A64, PSTATE_ZA, 23, 1)
+FIELD(TBFLAG_A64, SVL, 24, 4)
 
 /*
  * Helpers for using the above.
@@ -3227,6 +3228,17 @@ static inline int sve_vq(CPUARMState *env)
 return EX_TBFLAG_A64(env->hflags, VL) + 1;
 }
 
+/**
+ * sme_vq
+ * @env: the cpu context
+ *
+ * Return the SVL cached within env->hflags, in units of quadwords.
+ */
+static inline int sme_vq(CPUARMState *env)
+{
+return EX_TBFLAG_A64(env->hflags, SVL) + 1;
+}
+
 static inline bool bswap_code(bool sctlr_b)
 {
 #ifdef CONFIG_USER_ONLY
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 93766649f7f..22fd882368b 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -44,6 +44,7 @@ typedef struct DisasContext {
 int sve_excp_el; /* SVE exception EL or 0 if enabled */
 int sme_excp_el; /* SME exception EL or 0 if enabled */
 int vl;  /* current vector length in bytes */
+int svl; /* current streaming vector length in bytes */
 bool vfp_enabled; /* FP enabled via FPSCR.EN */
 int vec_len;
 int vec_stride;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2e4e739969a..d2886a123a6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11352,7 +11352,13 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState 
*env, int el, int fp_el,
 DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el);
 }
 if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
-DP_TBFLAG_A64(flags, SMEEXC_EL, sme_exception_el(env, el));
+int sme_el = sme_exception_el(env, el);
+
+DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el);
+if (sme_el == 0) {
+/* Similarly, do not compute SVL if SME is disabled. */
+DP_TBFLAG_A64(flags, SVL, sve_vqm1_for_el_sm(env, el, true));
+}
 if (FIELD_EX64(env->svcr, SVCR, SM)) {
 DP_TBFLAG_A64(flags, PSTATE_SM, 1);
 }
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index c050ebe0053..c86b97b1d49 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -14647,6 +14647,7 @@ static void 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 dc->sve_excp_el = EX_TBFLAG_A64(tb_flags, SVEEXC_EL);
 dc->sme_excp_el = EX_TBFLAG_A64(tb_flags, SMEEXC_EL);
 dc->vl = (EX_TBFLAG_A64(tb_flags, VL) + 1) * 16;
+dc->svl = (EX_TBFLAG_A64(tb_flags, SVL) + 1) * 16;
 dc->pauth_active = EX_TBFLAG_A64(tb_flags, PAUTH_ACTIVE);
 dc->bt = EX_TBFLAG_A64(tb_flags, BT);
 dc->btype = EX_TBFLAG_A64(tb_flags, BTYPE);
-- 
2.25.1




[PULL 21/25] target/arm: Introduce sve_vqm1_for_el_sm

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

When Streaming SVE mode is enabled, the size is taken from
SMCR_ELx instead of ZCR_ELx.  The format is shared, but the
set of vector lengths is not.  Further, Streaming SVE does
not require any particular length to be supported.

Adjust sve_vqm1_for_el to pass the current value of PSTATE.SM
to the new function.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-19-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h|  9 +++--
 target/arm/helper.c | 32 +---
 2 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c018f97b77b..0295e854838 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1154,13 +1154,18 @@ int sve_exception_el(CPUARMState *env, int cur_el);
 int sme_exception_el(CPUARMState *env, int cur_el);
 
 /**
- * sve_vqm1_for_el:
+ * sve_vqm1_for_el_sm:
  * @env: CPUARMState
  * @el: exception level
+ * @sm: streaming mode
  *
- * Compute the current SVE vector length for @el, in units of
+ * Compute the current vector length for @el & @sm, in units of
  * Quadwords Minus 1 -- the same scale used for ZCR_ELx.LEN.
+ * If @sm, compute for SVL, otherwise NVL.
  */
+uint32_t sve_vqm1_for_el_sm(CPUARMState *env, int el, bool sm);
+
+/* Likewise, but using @sm = PSTATE.SM. */
 uint32_t sve_vqm1_for_el(CPUARMState *env, int el);
 
 static inline bool is_a64(CPUARMState *env)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a80ca461e53..2e4e739969a 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6272,23 +6272,41 @@ int sme_exception_el(CPUARMState *env, int el)
 /*
  * Given that SVE is enabled, return the vector length for EL.
  */
-uint32_t sve_vqm1_for_el(CPUARMState *env, int el)
+uint32_t sve_vqm1_for_el_sm(CPUARMState *env, int el, bool sm)
 {
 ARMCPU *cpu = env_archcpu(env);
-uint32_t len = cpu->sve_max_vq - 1;
+uint64_t *cr = env->vfp.zcr_el;
+uint32_t map = cpu->sve_vq.map;
+uint32_t len = ARM_MAX_VQ - 1;
+
+if (sm) {
+cr = env->vfp.smcr_el;
+map = cpu->sme_vq.map;
+}
 
 if (el <= 1 && !el_is_in_host(env, el)) {
-len = MIN(len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
+len = MIN(len, 0xf & (uint32_t)cr[1]);
 }
 if (el <= 2 && arm_feature(env, ARM_FEATURE_EL2)) {
-len = MIN(len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
+len = MIN(len, 0xf & (uint32_t)cr[2]);
 }
 if (arm_feature(env, ARM_FEATURE_EL3)) {
-len = MIN(len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
+len = MIN(len, 0xf & (uint32_t)cr[3]);
 }
 
-len = 31 - clz32(cpu->sve_vq.map & MAKE_64BIT_MASK(0, len + 1));
-return len;
+map &= MAKE_64BIT_MASK(0, len + 1);
+if (map != 0) {
+return 31 - clz32(map);
+}
+
+/* Bit 0 is always set for Normal SVE -- not so for Streaming SVE. */
+assert(sm);
+return ctz32(cpu->sme_vq.map);
+}
+
+uint32_t sve_vqm1_for_el(CPUARMState *env, int el)
+{
+return sve_vqm1_for_el_sm(env, el, FIELD_EX64(env->svcr, SVCR, SM));
 }
 
 static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
-- 
2.25.1




[PULL 24/25] target/arm: Extend arm_pamax to more than aarch64

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

Move the code from hw/arm/virt.c that is supposed
to handle v7 into the one function.

Signed-off-by: Richard Henderson 
Reported-by: He Zhe 
Message-id: 20220619001541.131672-2-richard.hender...@linaro.org
Reviewed-by: Peter Maydell 
Signed-off-by: Peter Maydell 
---
 hw/arm/virt.c| 10 +-
 target/arm/ptw.c | 24 
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 097238faa7a..5502aa60c83 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2010,15 +2010,7 @@ static void machvirt_init(MachineState *machine)
 cpuobj = object_new(possible_cpus->cpus[0].type);
 armcpu = ARM_CPU(cpuobj);
 
-if (object_property_get_bool(cpuobj, "aarch64", NULL)) {
-pa_bits = arm_pamax(armcpu);
-} else if (arm_feature(&armcpu->env, ARM_FEATURE_LPAE)) {
-/* v7 with LPAE */
-pa_bits = 40;
-} else {
-/* Anything else */
-pa_bits = 32;
-}
+pa_bits = arm_pamax(armcpu);
 
 object_unref(cpuobj);
 
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 4d97a248084..07f7a218611 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -36,15 +36,23 @@ static const uint8_t pamax_map[] = {
 /* The cpu-specific constant value of PAMax; also used by hw/arm/virt. */
 unsigned int arm_pamax(ARMCPU *cpu)
 {
-unsigned int parange =
-FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
+if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+unsigned int parange =
+FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
 
-/*
- * id_aa64mmfr0 is a read-only register so values outside of the
- * supported mappings can be considered an implementation error.
- */
-assert(parange < ARRAY_SIZE(pamax_map));
-return pamax_map[parange];
+/*
+ * id_aa64mmfr0 is a read-only register so values outside of the
+ * supported mappings can be considered an implementation error.
+ */
+assert(parange < ARRAY_SIZE(pamax_map));
+return pamax_map[parange];
+}
+if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
+/* v7 with LPAE */
+return 40;
+}
+/* Anything else */
+return 32;
 }
 
 /*
-- 
2.25.1




[PULL 12/25] target/arm: Add the SME ZA storage to CPUARMState

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

Place this late in the resettable section of the structure,
to keep the most common element offsets from being > 64k.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-10-richard.hender...@linaro.org
[PMM: expanded comment on zarray[] format]
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h | 22 ++
 target/arm/machine.c | 34 ++
 2 files changed, 56 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 05d369e690a..52ab6f9bb99 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -694,6 +694,28 @@ typedef struct CPUArchState {
 } keys;
 
 uint64_t scxtnum_el[4];
+
+/*
+ * SME ZA storage -- 256 x 256 byte array, with bytes in host word order,
+ * as we do with vfp.zregs[].  This corresponds to the architectural ZA
+ * array, where ZA[N] is in the least-significant bytes of env->zarray[N].
+ * When SVL is less than the architectural maximum, the accessible
+ * storage is restricted, such that if the SVL is X bytes the guest can
+ * see only the bottom X elements of zarray[], and only the least
+ * significant X bytes of each element of the array. (In other words,
+ * the observable part is always square.)
+ *
+ * The ZA storage can also be considered as a set of square tiles of
+ * elements of different sizes. The mapping from tiles to the ZA array
+ * is architecturally defined, such that for tiles of elements of esz
+ * bytes, the Nth row (or "horizontal slice") of tile T is in
+ * ZA[T + N * esz]. Note that this means that each tile is not contiguous
+ * in the ZA storage, because its rows are striped through the ZA array.
+ *
+ * Because this is so large, keep this toward the end of the reset area,
+ * to keep the offsets into the rest of the structure smaller.
+ */
+ARMVectorReg zarray[ARM_MAX_VQ * 16];
 #endif
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 285e387d2c3..54c5c62433d 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -167,6 +167,39 @@ static const VMStateDescription vmstate_sve = {
 VMSTATE_END_OF_LIST()
 }
 };
+
+static const VMStateDescription vmstate_vreg = {
+.name = "vreg",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64_ARRAY(d, ARMVectorReg, ARM_MAX_VQ * 2),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static bool za_needed(void *opaque)
+{
+ARMCPU *cpu = opaque;
+
+/*
+ * When ZA storage is disabled, its contents are discarded.
+ * It will be zeroed when ZA storage is re-enabled.
+ */
+return FIELD_EX64(cpu->env.svcr, SVCR, ZA);
+}
+
+static const VMStateDescription vmstate_za = {
+.name = "cpu/sme",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = za_needed,
+.fields = (VMStateField[]) {
+VMSTATE_STRUCT_ARRAY(env.zarray, ARMCPU, ARM_MAX_VQ * 16, 0,
+ vmstate_vreg, ARMVectorReg),
+VMSTATE_END_OF_LIST()
+}
+};
 #endif /* AARCH64 */
 
 static bool serror_needed(void *opaque)
@@ -884,6 +917,7 @@ const VMStateDescription vmstate_arm_cpu = {
 &vmstate_m_security,
 #ifdef TARGET_AARCH64
 &vmstate_sve,
+&vmstate_za,
 #endif
 &vmstate_serror,
 &vmstate_irq_line_state,
-- 
2.25.1




[PULL 13/25] target/arm: Implement SMSTART, SMSTOP

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

These two instructions are aliases of MSR (immediate).
Use the two helpers to properly implement svcr_write.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-11-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h   |  1 +
 target/arm/helper-sme.h| 21 +
 target/arm/helper.h|  1 +
 target/arm/helper.c|  6 ++--
 target/arm/sme_helper.c| 61 ++
 target/arm/translate-a64.c | 24 +++
 target/arm/meson.build |  1 +
 7 files changed, 112 insertions(+), 3 deletions(-)
 create mode 100644 target/arm/helper-sme.h
 create mode 100644 target/arm/sme_helper.c

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 52ab6f9bb99..5877d76c9f3 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1120,6 +1120,7 @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
int new_el, bool el0_a64);
 void aarch64_add_sve_properties(Object *obj);
 void aarch64_add_pauth_properties(Object *obj);
+void arm_reset_sve_state(CPUARMState *env);
 
 /*
  * SVE registers are encoded in KVM's memory in an endianness-invariant format.
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
new file mode 100644
index 000..3bd48c235f0
--- /dev/null
+++ b/target/arm/helper-sme.h
@@ -0,0 +1,21 @@
+/*
+ *  AArch64 SME specific helper definitions
+ *
+ *  Copyright (c) 2022 Linaro, Ltd
+ *
+ * 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 .
+ */
+
+DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
+DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
diff --git a/target/arm/helper.h b/target/arm/helper.h
index 07d45faf495..3a8ce42ab01 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -1022,6 +1022,7 @@ DEF_HELPER_FLAGS_6(gvec_bfmlal_idx, TCG_CALL_NO_RWG,
 #ifdef TARGET_AARCH64
 #include "helper-a64.h"
 #include "helper-sve.h"
+#include "helper-sme.h"
 #endif
 
 #include "helper-mve.h"
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e06c054c3d7..88d96f7991f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6366,9 +6366,9 @@ static CPAccessResult access_esm(CPUARMState *env, const 
ARMCPRegInfo *ri,
 static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
 {
-value &= R_SVCR_SM_MASK | R_SVCR_ZA_MASK;
-/* TODO: Side effects. */
-env->svcr = value;
+helper_set_pstate_sm(env, FIELD_EX64(value, SVCR, SM));
+helper_set_pstate_za(env, FIELD_EX64(value, SVCR, ZA));
+arm_rebuild_hflags(env);
 }
 
 static void smcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
new file mode 100644
index 000..b2157255943
--- /dev/null
+++ b/target/arm/sme_helper.c
@@ -0,0 +1,61 @@
+/*
+ * ARM SME Operations
+ *
+ * Copyright (c) 2022 Linaro, Ltd.
+ *
+ * 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 "cpu.h"
+#include "internals.h"
+#include "exec/helper-proto.h"
+
+/* ResetSVEState */
+void arm_reset_sve_state(CPUARMState *env)
+{
+memset(env->vfp.zregs, 0, sizeof(env->vfp.zregs));
+/* Recall that FFR is stored as pregs[16]. */
+memset(env->vfp.pregs, 0, sizeof(env->vfp.pregs));
+vfp_set_fpcr(env, 0x089f);
+}
+
+void helper_set_pstate_sm(CPUARMState *env, uint32_t i)
+{
+if (i == FIELD_EX64(env->svcr, SVCR, SM)) {
+return;
+}
+env->svcr ^= R_SVCR_SM_MASK;
+arm_reset_sve_state(env);
+}
+
+void helper_set_pstate_za(CPUARMState *env, uint32_t i)
+{
+if (i == FIELD_EX64(env->svcr, SVCR, ZA)) {
+retur

[PULL 20/25] target/arm: Add cpu properties for SME

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

Mirror the properties for SVE.  The main difference is
that any arbitrary set of powers of 2 may be supported,
and not the stricter constraints that apply to SVE.

Include a property to control FEAT_SME_FA64, as failing
to restrict the runtime to the proper subset of insns
could be a major point for bugs.

Signed-off-by: Richard Henderson 
Reviewed-by: Peter Maydell 
Message-id: 20220620175235.60881-18-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 docs/system/arm/cpu-features.rst |  56 +++
 target/arm/cpu.h |   2 +
 target/arm/internals.h   |   1 +
 target/arm/cpu.c |  14 +++-
 target/arm/cpu64.c   | 114 +--
 5 files changed, 180 insertions(+), 7 deletions(-)

diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
index 3e626c4b68a..3fd76fa0b4f 100644
--- a/docs/system/arm/cpu-features.rst
+++ b/docs/system/arm/cpu-features.rst
@@ -372,6 +372,31 @@ verbose command lines.  However, the recommended way to 
select vector
 lengths is to explicitly enable each desired length.  Therefore only
 example's (1), (4), and (6) exhibit recommended uses of the properties.
 
+SME CPU Property Examples
+-
+
+  1) Disable SME::
+
+ $ qemu-system-aarch64 -M virt -cpu max,sme=off
+
+  2) Implicitly enable all vector lengths for the ``max`` CPU type::
+
+ $ qemu-system-aarch64 -M virt -cpu max
+
+  3) Only enable the 256-bit vector length::
+
+ $ qemu-system-aarch64 -M virt -cpu max,sme256=on
+
+  3) Enable the 256-bit and 1024-bit vector lengths::
+
+ $ qemu-system-aarch64 -M virt -cpu max,sme256=on,sme1024=on
+
+  4) Disable the 512-bit vector length.  This results in all the other
+ lengths supported by ``max`` defaulting to enabled
+ (128, 256, 1024 and 2048)::
+
+ $ qemu-system-aarch64 -M virt -cpu max,sve512=off
+
 SVE User-mode Default Vector Length Property
 
 
@@ -387,3 +412,34 @@ length supported by QEMU is 256.
 
 If this property is set to ``-1`` then the default vector length
 is set to the maximum possible length.
+
+SME CPU Properties
+==
+
+The SME CPU properties are much like the SVE properties: ``sme`` is
+used to enable or disable the entire SME feature, and ``sme`` is
+used to enable or disable specific vector lengths.  Finally,
+``sme_fa64`` is used to enable or disable ``FEAT_SME_FA64``, which
+allows execution of the "full a64" instruction set while Streaming
+SVE mode is enabled.
+
+SME is not supported by KVM at this time.
+
+At least one vector length must be enabled when ``sme`` is enabled,
+and all vector lengths must be powers of 2.  The maximum vector
+length supported by qemu is 2048 bits.  Otherwise, there are no
+additional constraints on the set of vector lengths supported by SME.
+
+SME User-mode Default Vector Length Property
+
+
+For qemu-aarch64, the cpu propery ``sme-default-vector-length=N`` is
+defined to mirror the Linux kernel parameter file
+``/proc/sys/abi/sme_default_vector_length``.  The default length, ``N``,
+is in units of bytes and must be between 16 and 8192.
+If not specified, the default vector length is 32.
+
+As with ``sve-default-vector-length``, if the default length is larger
+than the maximum vector length enabled, the actual vector length will
+be reduced.  If this property is set to ``-1`` then the default vector
+length is set to the maximum possible length.
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index d2b005f76c8..c018f97b77b 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1060,9 +1060,11 @@ struct ArchCPU {
 #ifdef CONFIG_USER_ONLY
 /* Used to set the default vector length at process start. */
 uint32_t sve_default_vq;
+uint32_t sme_default_vq;
 #endif
 
 ARMVQMap sve_vq;
+ARMVQMap sme_vq;
 
 /* Generic timer counter frequency, in Hz */
 uint64_t gt_cntfrq_hz;
diff --git a/target/arm/internals.h b/target/arm/internals.h
index aef568adf75..c66f74a0db1 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1289,6 +1289,7 @@ int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, 
int reg);
 int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg);
 int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg);
 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
+void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
 #endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 660fd8b8b90..bb44ad45aa1 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1123,11 +1123,13 @@ static void arm_cpu_initfn(Object *obj)
 #ifdef CONFIG_USER_ONLY
 # ifdef TARGET_AARCH64
 /*
- * The linux kernel defaults to 512-bit vectors, when sve is supported.
- * Se

[PULL 23/25] target/arm: Move pred_{full, gvec}_reg_{offset, size} to translate-a64.h

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

We will need these functions in translate-sme.c.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-21-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/translate-a64.h | 38 ++
 target/arm/translate-sve.c | 36 
 2 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
index dbc917ee65b..f0970c6b8cf 100644
--- a/target/arm/translate-a64.h
+++ b/target/arm/translate-a64.h
@@ -107,6 +107,44 @@ static inline int vec_full_reg_size(DisasContext *s)
 return s->vl;
 }
 
+/*
+ * Return the offset info CPUARMState of the predicate vector register Pn.
+ * Note for this purpose, FFR is P16.
+ */
+static inline int pred_full_reg_offset(DisasContext *s, int regno)
+{
+return offsetof(CPUARMState, vfp.pregs[regno]);
+}
+
+/* Return the byte size of the whole predicate register, VL / 64.  */
+static inline int pred_full_reg_size(DisasContext *s)
+{
+return s->vl >> 3;
+}
+
+/*
+ * Round up the size of a register to a size allowed by
+ * the tcg vector infrastructure.  Any operation which uses this
+ * size may assume that the bits above pred_full_reg_size are zero,
+ * and must leave them the same way.
+ *
+ * Note that this is not needed for the vector registers as they
+ * are always properly sized for tcg vectors.
+ */
+static inline int size_for_gvec(int size)
+{
+if (size <= 8) {
+return 8;
+} else {
+return QEMU_ALIGN_UP(size, 16);
+}
+}
+
+static inline int pred_gvec_reg_size(DisasContext *s)
+{
+return size_for_gvec(pred_full_reg_size(s));
+}
+
 bool disas_sve(DisasContext *, uint32_t);
 
 void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index 67761bf2cc5..62b5f3040c7 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -100,42 +100,6 @@ static inline int msz_dtype(DisasContext *s, int msz)
  * Implement all of the translator functions referenced by the decoder.
  */
 
-/* Return the offset info CPUARMState of the predicate vector register Pn.
- * Note for this purpose, FFR is P16.
- */
-static inline int pred_full_reg_offset(DisasContext *s, int regno)
-{
-return offsetof(CPUARMState, vfp.pregs[regno]);
-}
-
-/* Return the byte size of the whole predicate register, VL / 64.  */
-static inline int pred_full_reg_size(DisasContext *s)
-{
-return s->vl >> 3;
-}
-
-/* Round up the size of a register to a size allowed by
- * the tcg vector infrastructure.  Any operation which uses this
- * size may assume that the bits above pred_full_reg_size are zero,
- * and must leave them the same way.
- *
- * Note that this is not needed for the vector registers as they
- * are always properly sized for tcg vectors.
- */
-static int size_for_gvec(int size)
-{
-if (size <= 8) {
-return 8;
-} else {
-return QEMU_ALIGN_UP(size, 16);
-}
-}
-
-static int pred_gvec_reg_size(DisasContext *s)
-{
-return size_for_gvec(pred_full_reg_size(s));
-}
-
 /* Invoke an out-of-line helper on 2 Zregs. */
 static bool gen_gvec_ool_zz(DisasContext *s, gen_helper_gvec_2 *fn,
 int rd, int rn, int data)
-- 
2.25.1




Re: virgl avocado hang

2022-06-27 Thread Marc-André Lureau
Hi

On Mon, Jun 27, 2022 at 7:14 AM Richard Henderson <
richard.hender...@linaro.org> wrote:

> Hi Mark,
>
> > +def test_virtio_vga_virgl(self):
>
> > +"""
>
> > +:avocado: tags=arch:x86_64
>
> > +:avocado: tags=device:virtio-vga
>
> > +"""
>
> > +kernel_command_line = (
>
> > +self.KERNEL_COMMON_COMMAND_LINE + "console=ttyS0
> rdinit=/bin/bash"
>
> > +)
>
> > +# FIXME: should check presence of virtio, virgl etc
>
>
> This little nugget really must be fixed.
>
> The observed behaviour is an indefinite hang in avocado, waiting for qemu,
> which is in
> zombie state.  A manual kill -INT to the parent wakes it up like so:
>
>   (159/184)
> tests/avocado/virtio-gpu.py:VirtioGPUx86.test_virtio_vga_virgl: CANCEL:
> VirGL
> not enabled? (1264.25 s)
>
>
Could you describe how to reproduce? I naively --disable-virglrenderer and
I get:

$ tests/venv/bin/avocado run tests/avocado/virtio-gpu.py
Fetching asset from
tests/avocado/virtio-gpu.py:VirtioGPUx86.test_virtio_vga_virgl
Fetching asset from
tests/avocado/virtio-gpu.py:VirtioGPUx86.test_virtio_vga_virgl
Fetching asset from
tests/avocado/virtio-gpu.py:VirtioGPUx86.test_vhost_user_vga_virgl
Fetching asset from
tests/avocado/virtio-gpu.py:VirtioGPUx86.test_vhost_user_vga_virgl
JOB ID : d9c5b6577564d1d926fdfb58deaf0e967d15
JOB LOG:
/home/elmarco/avocado/job-results/job-2022-06-27T12.56-d9c5b65/job.log
 (1/2) tests/avocado/virtio-gpu.py:VirtioGPUx86.test_virtio_vga_virgl:
CANCEL: VirGL not enabled? (0.08 s)
 (2/2) tests/avocado/virtio-gpu.py:VirtioGPUx86.test_vhost_user_vga_virgl:
CANCEL: Could not find vhost-user-gpu (0.02 s)
RESULTS: PASS 0 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 |
CANCEL 2
JOB TIME   : 0.56 s


-- 
Marc-André Lureau


[PULL 14/25] target/arm: Move error for sve%d property to arm_cpu_sve_finalize

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

Keep all of the error messages together.  This does mean that
when setting many sve length properties we'll only generate
one error, but we only really need one.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-12-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu64.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 15665c962b2..a46e40f4f2f 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -487,8 +487,13 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
   "using only sve properties.\n");
 } else {
 error_setg(errp, "cannot enable sve%d", vq * 128);
-error_append_hint(errp, "This CPU does not support "
-  "the vector length %d-bits.\n", vq * 128);
+if (vq_supported) {
+error_append_hint(errp, "This CPU does not support "
+  "the vector length %d-bits.\n", vq * 
128);
+} else {
+error_append_hint(errp, "SVE not supported by KVM "
+  "on this host\n");
+}
 }
 return;
 } else {
@@ -606,12 +611,6 @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, 
const char *name,
 return;
 }
 
-if (value && kvm_enabled() && !kvm_arm_sve_supported()) {
-error_setg(errp, "cannot enable %s", name);
-error_append_hint(errp, "SVE not supported by KVM on this host\n");
-return;
-}
-
 cpu->sve_vq_map = deposit32(cpu->sve_vq_map, vq - 1, 1, value);
 cpu->sve_vq_init |= 1 << (vq - 1);
 }
-- 
2.25.1




[PULL 25/25] target/arm: Check V7VE as well as LPAE in arm_pamax

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

In machvirt_init we create a cpu but do not fully initialize it.
Thus the propagation of V7VE to LPAE has not been done, and we
compute the wrong value for some v7 cpus, e.g. cortex-a15.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1078
Signed-off-by: Richard Henderson 
Reported-by: He Zhe 
Message-id: 20220619001541.131672-3-richard.hender...@linaro.org
Reviewed-by: Peter Maydell 
Signed-off-by: Peter Maydell 
---
 target/arm/ptw.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 07f7a218611..da478104f05 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -47,7 +47,13 @@ unsigned int arm_pamax(ARMCPU *cpu)
 assert(parange < ARRAY_SIZE(pamax_map));
 return pamax_map[parange];
 }
-if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
+
+/*
+ * In machvirt_init, we call arm_pamax on a cpu that is not fully
+ * initialized, so we can't rely on the propagation done in realize.
+ */
+if (arm_feature(&cpu->env, ARM_FEATURE_LPAE) ||
+arm_feature(&cpu->env, ARM_FEATURE_V7VE)) {
 /* v7 with LPAE */
 return 40;
 }
-- 
2.25.1




[PULL 16/25] target/arm: Generalize cpu_arm_{get,set}_vq

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

Rename from cpu_arm_{get,set}_sve_vq, and take the
ARMVQMap as the opaque parameter.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-14-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu64.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index cadc401c7e0..1a3cb953bf0 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -579,15 +579,15 @@ static void cpu_max_set_sve_max_vq(Object *obj, Visitor 
*v, const char *name,
 }
 
 /*
- * Note that cpu_arm_get/set_sve_vq cannot use the simpler
- * object_property_add_bool interface because they make use
- * of the contents of "name" to determine which bit on which
- * to operate.
+ * Note that cpu_arm_{get,set}_vq cannot use the simpler
+ * object_property_add_bool interface because they make use of the
+ * contents of "name" to determine which bit on which to operate.
  */
-static void cpu_arm_get_sve_vq(Object *obj, Visitor *v, const char *name,
-   void *opaque, Error **errp)
+static void cpu_arm_get_vq(Object *obj, Visitor *v, const char *name,
+   void *opaque, Error **errp)
 {
 ARMCPU *cpu = ARM_CPU(obj);
+ARMVQMap *vq_map = opaque;
 uint32_t vq = atoi(&name[3]) / 128;
 bool value;
 
@@ -595,15 +595,15 @@ static void cpu_arm_get_sve_vq(Object *obj, Visitor *v, 
const char *name,
 if (!cpu_isar_feature(aa64_sve, cpu)) {
 value = false;
 } else {
-value = extract32(cpu->sve_vq.map, vq - 1, 1);
+value = extract32(vq_map->map, vq - 1, 1);
 }
 visit_type_bool(v, name, &value, errp);
 }
 
-static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, const char *name,
-   void *opaque, Error **errp)
+static void cpu_arm_set_vq(Object *obj, Visitor *v, const char *name,
+   void *opaque, Error **errp)
 {
-ARMCPU *cpu = ARM_CPU(obj);
+ARMVQMap *vq_map = opaque;
 uint32_t vq = atoi(&name[3]) / 128;
 bool value;
 
@@ -611,8 +611,8 @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, 
const char *name,
 return;
 }
 
-cpu->sve_vq.map = deposit32(cpu->sve_vq.map, vq - 1, 1, value);
-cpu->sve_vq.init |= 1 << (vq - 1);
+vq_map->map = deposit32(vq_map->map, vq - 1, 1, value);
+vq_map->init |= 1 << (vq - 1);
 }
 
 static bool cpu_arm_get_sve(Object *obj, Error **errp)
@@ -691,6 +691,7 @@ static void cpu_arm_get_sve_default_vec_len(Object *obj, 
Visitor *v,
 
 void aarch64_add_sve_properties(Object *obj)
 {
+ARMCPU *cpu = ARM_CPU(obj);
 uint32_t vq;
 
 object_property_add_bool(obj, "sve", cpu_arm_get_sve, cpu_arm_set_sve);
@@ -698,8 +699,8 @@ void aarch64_add_sve_properties(Object *obj)
 for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
 char name[8];
 sprintf(name, "sve%d", vq * 128);
-object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
-cpu_arm_set_sve_vq, NULL, NULL);
+object_property_add(obj, name, "bool", cpu_arm_get_vq,
+cpu_arm_set_vq, NULL, &cpu->sve_vq);
 }
 
 #ifdef CONFIG_USER_ONLY
-- 
2.25.1




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

2022-06-27 Thread Jinhao Fan
Add property "ioeventfd" which is enabled by default. When this is
enabled, updates on the doorbell registers will cause KVM to signal
an event to the QEMU main loop to handle the doorbell updates.
Therefore, instead of letting the vcpu thread run both guest VM and
IO emulation, we now use the main loop thread to do IO emulation and
thus the vcpu thread has more cycles for the guest VM.

Since ioeventfd does not tell us the exact value that is written, it is
only useful when shadow doorbell buffer is enabled, where we check
for the value in the shadow doorbell buffer when we get the doorbell
update event.

IOPS comparison on Linux 5.19-rc2: (Unit: KIOPS)

qd   1   4  16  64
qemu35 121 176 153
ioeventfd   41 133 258 313

Signed-off-by: Jinhao Fan 
---
 hw/nvme/ctrl.c | 97 +-
 hw/nvme/nvme.h |  5 +++
 2 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index c952c34f94..787b89f7d3 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -1374,7 +1374,14 @@ static void nvme_enqueue_req_completion(NvmeCQueue *cq, 
NvmeRequest *req)
 
 QTAILQ_REMOVE(&req->sq->out_req_list, req, entry);
 QTAILQ_INSERT_TAIL(&cq->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);
+}
 }
 
 static void nvme_process_aers(void *opaque)
@@ -4195,10 +4202,74 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest 
*req)
 return NVME_INVALID_OPCODE | NVME_DNR;
 }
 
+static void nvme_cq_notifier(EventNotifier *e)
+{
+NvmeCQueue *cq = container_of(e, NvmeCQueue, notifier);
+NvmeCtrl *n = cq->ctrl;
+
+event_notifier_test_and_clear(&cq->notifier);
+
+nvme_update_cq_head(cq);
+
+if (cq->tail == cq->head) {
+if (cq->irq_enabled) {
+n->cq_pending--;
+}
+
+nvme_irq_deassert(n, cq);
+}
+
+nvme_post_cqes(cq);
+}
+
+static int nvme_init_cq_ioeventfd(NvmeCQueue *cq)
+{
+NvmeCtrl *n = cq->ctrl;
+uint16_t offset = (cq->cqid << 3) + (1 << 2);
+int ret;
+
+if ((ret = event_notifier_init(&cq->notifier, 0))) {
+return ret;
+}
+
+event_notifier_set_handler(&cq->notifier, nvme_cq_notifier);
+memory_region_add_eventfd(&n->iomem,
+  0x1000 + offset, 4, false, 0, &cq->notifier);
+
+return 0;
+}
+
+static void nvme_sq_notifier(EventNotifier *e)
+{
+NvmeSQueue *sq = container_of(e, NvmeSQueue, notifier);
+
+event_notifier_test_and_clear(&sq->notifier);
+
+nvme_process_sq(sq);
+}
+
+static int nvme_init_sq_ioeventfd(NvmeSQueue *sq)
+{
+NvmeCtrl *n = sq->ctrl;
+uint16_t offset = sq->sqid << 3;
+int ret;
+
+if ((ret = event_notifier_init(&sq->notifier, 0))) {
+return ret;
+}
+
+event_notifier_set_handler(&sq->notifier, nvme_sq_notifier);
+memory_region_add_eventfd(&n->iomem,
+  0x1000 + offset, 4, false, 0, &sq->notifier);
+
+return 0;
+}
+
 static void nvme_free_sq(NvmeSQueue *sq, NvmeCtrl *n)
 {
 n->sq[sq->sqid] = NULL;
 timer_free(sq->timer);
+event_notifier_cleanup(&sq->notifier);
 g_free(sq->io_req);
 if (sq->sqid) {
 g_free(sq);
@@ -4250,6 +4321,7 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, 
uint64_t dma_addr,
  uint16_t sqid, uint16_t cqid, uint16_t size)
 {
 int i;
+int ret;
 NvmeCQueue *cq;
 
 sq->ctrl = n;
@@ -4271,6 +4343,11 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, 
uint64_t dma_addr,
 if (n->dbbuf_enabled) {
 sq->db_addr = n->dbbuf_dbs + (sqid << 3);
 sq->ei_addr = n->dbbuf_eis + (sqid << 3);
+
+if (n->params.ioeventfd && sq->sqid != 0) {
+ret = nvme_init_sq_ioeventfd(sq);
+sq->ioeventfd_enabled = ret == 0;
+}
 }
 
 assert(n->cq[cqid]);
@@ -4577,6 +4654,7 @@ static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n)
 {
 n->cq[cq->cqid] = NULL;
 timer_free(cq->timer);
+event_notifier_cleanup(&cq->notifier);
 if (msix_enabled(&n->parent_obj)) {
 msix_vector_unuse(&n->parent_obj, cq->vector);
 }
@@ -4635,6 +4713,11 @@ static void nvme_init_cq(NvmeCQueue *cq, NvmeCtrl *n, 
uint64_t dma_addr,
 if (n->dbbuf_enabled) {
 cq->db_addr = n->dbbuf_dbs + (cqid << 3) + (1 << 2);
 cq->ei_addr = n->dbbuf_eis + (cqid << 3) + (1 << 2);
+
+if (n->params.ioeventfd && cqid != 0) {
+ret = nvme_init_cq_ioeventfd(cq);
+cq->ioeventfd_enabled = ret == 0;
+}
 }
 n->cq[cqid] = cq;
 cq->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, nvme_post_cqes, 

[PULL 15/25] target/arm: Create ARMVQMap

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

Pull the three sve_vq_* values into a structure.
This will be reused for SME.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-13-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h| 29 ++---
 target/arm/cpu64.c  | 22 +++---
 target/arm/helper.c |  2 +-
 target/arm/kvm64.c  |  2 +-
 4 files changed, 27 insertions(+), 28 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 5877d76c9f3..2ce47f8d29f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -807,6 +807,19 @@ typedef enum ARMPSCIState {
 
 typedef struct ARMISARegisters ARMISARegisters;
 
+/*
+ * In map, each set bit is a supported vector length of (bit-number + 1) * 16
+ * bytes, i.e. each bit number + 1 is the vector length in quadwords.
+ *
+ * While processing properties during initialization, corresponding init bits
+ * are set for bits in sve_vq_map that have been set by properties.
+ *
+ * Bits set in supported represent valid vector lengths for the CPU type.
+ */
+typedef struct {
+uint32_t map, init, supported;
+} ARMVQMap;
+
 /**
  * ARMCPU:
  * @env: #CPUARMState
@@ -1055,21 +1068,7 @@ struct ArchCPU {
 uint32_t sve_default_vq;
 #endif
 
-/*
- * In sve_vq_map each set bit is a supported vector length of
- * (bit-number + 1) * 16 bytes, i.e. each bit number + 1 is the vector
- * length in quadwords.
- *
- * While processing properties during initialization, corresponding
- * sve_vq_init bits are set for bits in sve_vq_map that have been
- * set by properties.
- *
- * Bits set in sve_vq_supported represent valid vector lengths for
- * the CPU type.
- */
-uint32_t sve_vq_map;
-uint32_t sve_vq_init;
-uint32_t sve_vq_supported;
+ARMVQMap sve_vq;
 
 /* Generic timer counter frequency, in Hz */
 uint64_t gt_cntfrq_hz;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index a46e40f4f2f..cadc401c7e0 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -355,8 +355,8 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
  * any of the above.  Finally, if SVE is not disabled, then at least one
  * vector length must be enabled.
  */
-uint32_t vq_map = cpu->sve_vq_map;
-uint32_t vq_init = cpu->sve_vq_init;
+uint32_t vq_map = cpu->sve_vq.map;
+uint32_t vq_init = cpu->sve_vq.init;
 uint32_t vq_supported;
 uint32_t vq_mask = 0;
 uint32_t tmp, vq, max_vq = 0;
@@ -369,14 +369,14 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
  */
 if (kvm_enabled()) {
 if (kvm_arm_sve_supported()) {
-cpu->sve_vq_supported = kvm_arm_sve_get_vls(CPU(cpu));
-vq_supported = cpu->sve_vq_supported;
+cpu->sve_vq.supported = kvm_arm_sve_get_vls(CPU(cpu));
+vq_supported = cpu->sve_vq.supported;
 } else {
 assert(!cpu_isar_feature(aa64_sve, cpu));
 vq_supported = 0;
 }
 } else {
-vq_supported = cpu->sve_vq_supported;
+vq_supported = cpu->sve_vq.supported;
 }
 
 /*
@@ -534,7 +534,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
 
 /* From now on sve_max_vq is the actual maximum supported length. */
 cpu->sve_max_vq = max_vq;
-cpu->sve_vq_map = vq_map;
+cpu->sve_vq.map = vq_map;
 }
 
 static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name,
@@ -595,7 +595,7 @@ static void cpu_arm_get_sve_vq(Object *obj, Visitor *v, 
const char *name,
 if (!cpu_isar_feature(aa64_sve, cpu)) {
 value = false;
 } else {
-value = extract32(cpu->sve_vq_map, vq - 1, 1);
+value = extract32(cpu->sve_vq.map, vq - 1, 1);
 }
 visit_type_bool(v, name, &value, errp);
 }
@@ -611,8 +611,8 @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, 
const char *name,
 return;
 }
 
-cpu->sve_vq_map = deposit32(cpu->sve_vq_map, vq - 1, 1, value);
-cpu->sve_vq_init |= 1 << (vq - 1);
+cpu->sve_vq.map = deposit32(cpu->sve_vq.map, vq - 1, 1, value);
+cpu->sve_vq.init |= 1 << (vq - 1);
 }
 
 static bool cpu_arm_get_sve(Object *obj, Error **errp)
@@ -974,7 +974,7 @@ static void aarch64_max_initfn(Object *obj)
 cpu->dcz_blocksize = 7; /*  512 bytes */
 #endif
 
-cpu->sve_vq_supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ);
+cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ);
 
 aarch64_add_pauth_properties(obj);
 aarch64_add_sve_properties(obj);
@@ -1023,7 +1023,7 @@ static void aarch64_a64fx_initfn(Object *obj)
 
 /* The A64FX supports only 128, 256 and 512 bit vector lengths */
 aarch64_add_sve_properties(obj);
-cpu->sve_vq_supported = (1 << 0)  /* 128bit */
+cpu->sve_vq.supported = (1 << 0)  /* 128bit */
   | (1 << 1)  /* 256bit */
   | (1 << 3); /* 512bit */
 
diff --git a/target/arm/helper.c b/target/

[PULL 19/25] target/arm: Unexport aarch64_add_*_properties

2022-06-27 Thread Peter Maydell
From: Richard Henderson 

These functions are not used outside cpu64.c,
so make them static.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20220620175235.60881-17-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h   | 3 ---
 target/arm/cpu64.c | 4 ++--
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 675c49f93e0..d2b005f76c8 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -,8 +,6 @@ int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t 
*buf, int reg);
 void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
 void aarch64_sve_change_el(CPUARMState *env, int old_el,
int new_el, bool el0_a64);
-void aarch64_add_sve_properties(Object *obj);
-void aarch64_add_pauth_properties(Object *obj);
 void arm_reset_sve_state(CPUARMState *env);
 
 /*
@@ -1144,7 +1142,6 @@ static inline void aarch64_sve_narrow_vq(CPUARMState 
*env, unsigned vq) { }
 static inline void aarch64_sve_change_el(CPUARMState *env, int o,
  int n, bool a)
 { }
-static inline void aarch64_add_sve_properties(Object *obj) { }
 #endif
 
 void aarch64_sync_32_to_64(CPUARMState *env);
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index b15a0d398ad..6f6ee57a914 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -689,7 +689,7 @@ static void cpu_arm_get_default_vec_len(Object *obj, 
Visitor *v,
 }
 #endif
 
-void aarch64_add_sve_properties(Object *obj)
+static void aarch64_add_sve_properties(Object *obj)
 {
 ARMCPU *cpu = ARM_CPU(obj);
 uint32_t vq;
@@ -752,7 +752,7 @@ static Property arm_cpu_pauth_property =
 static Property arm_cpu_pauth_impdef_property =
 DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false);
 
-void aarch64_add_pauth_properties(Object *obj)
+static void aarch64_add_pauth_properties(Object *obj)
 {
 ARMCPU *cpu = ARM_CPU(obj);
 
-- 
2.25.1




[PATCH v2 0/4] hw/nvme: add support for TP4084

2022-06-27 Thread Niklas Cassel via
Hello there,

considering that Linux v5.19 will include support for NVMe TP4084:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/nvme/host/core.c?id=354201c53e61e493017b15327294b0c8ab522d69

I thought that it might be nice to have QEMU support for the same.

TP4084 adds a new mode, CC.CRIME, that can be used to mark a namespace
as ready independently from the controller.

When CC.CRIME is 0 (default), things behave as before, all namespaces
are ready when CSTS.RDY gets set to 1.

Add a new "ready_delay" namespace device parameter, in order to emulate
different ready latencies for namespaces when CC.CRIME is 1.

The patch series also adds a "crwmt" controller parameter, in order to
be able to expose the worst case timeout that the host should wait for
all namespaces to become ready.


Example qemu cmd line for the new options:

# delay in s (20s)
NS1_DELAY_S=20
# convert to units of 500ms
NS1_DELAY=$((NS1_DELAY_S*2))

# delay in s (60s)
NS2_DELAY_S=60
# convert to units of 500ms
NS2_DELAY=$((NS2_DELAY_S*2))

# timeout in s (120s)
CRWMT_S=120
# convert to units of 500ms
CRWMT=$((CRWMT_S*2))

 -device nvme,serial=deadbeef,crwmt=$CRWMT \
 -drive file=$NS1_DATA,id=nvm-1,format=raw,if=none \
 -device nvme-ns,drive=nvm-1,ready_delay=$NS1_DELAY \
 -drive file=$NS2_DATA,id=nvm-2,format=raw,if=none \
 -device nvme-ns,drive=nvm-2,ready_delay=$NS2_DELAY \


Changes since v1:
-Rebased on nvme-next
-Set id_indep_ns->nmic if ns->params.shared in patch 3/4.


Niklas Cassel (4):
  hw/nvme: claim NVMe 2.0 compliance
  hw/nvme: store a pointer to the NvmeSubsystem in the NvmeNamespace
  hw/nvme: add support for ratified TP4084
  hw/nvme: add new never_ready parameter to test the DNR bit

 hw/nvme/ctrl.c   | 151 +--
 hw/nvme/ns.c |  20 ++
 hw/nvme/nvme.h   |   9 +++
 hw/nvme/trace-events |   1 +
 include/block/nvme.h |  60 -
 5 files changed, 236 insertions(+), 5 deletions(-)

-- 
2.36.1




[PATCH v2 1/4] hw/nvme: claim NVMe 2.0 compliance

2022-06-27 Thread Niklas Cassel via
CRMS.CRWMS bit shall be set to 1 on controllers compliant with versions
later than NVMe 1.4.

The first version later than NVMe 1.4 is NVMe 2.0

Let's claim compliance with NVMe 2.0 such that a follow up patch can
set the CRMS.CRWMS bit.

This is needed since CC.CRIME is only writable when both CRMS.CRIMS
and CRMS.CRWMS is set.

Signed-off-by: Niklas Cassel 
---
 hw/nvme/ctrl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index f8ec4a7be3..8ca824ea14 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -204,7 +204,7 @@
 
 #define NVME_MAX_IOQPAIRS 0x
 #define NVME_DB_SIZE  4
-#define NVME_SPEC_VER 0x00010400
+#define NVME_SPEC_VER 0x0002
 #define NVME_CMB_BIR 2
 #define NVME_PMR_BIR 4
 #define NVME_TEMPERATURE 0x143
-- 
2.36.1




[PATCH v2 2/4] hw/nvme: store a pointer to the NvmeSubsystem in the NvmeNamespace

2022-06-27 Thread Niklas Cassel via
Each NvmeNamespace can be used by serveral controllers,
but a NvmeNamespace can at most belong to a single NvmeSubsystem.
Store a pointer to the NvmeSubsystem, if the namespace was realized
with a NvmeSubsystem.

This will be used by a follow up patch.

Signed-off-by: Niklas Cassel 
---
 hw/nvme/ns.c   | 1 +
 hw/nvme/nvme.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
index 870c3ca1a2..8bee3e8b3b 100644
--- a/hw/nvme/ns.c
+++ b/hw/nvme/ns.c
@@ -559,6 +559,7 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
 if (!qdev_set_parent_bus(dev, &subsys->bus.parent_bus, errp)) {
 return;
 }
+ns->subsys = subsys;
 }
 
 if (nvme_ns_setup(ns, errp)) {
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index 0711b9748c..5487e2db40 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -167,6 +167,7 @@ typedef struct NvmeNamespace {
 int32_t nr_active_zones;
 
 NvmeNamespaceParams params;
+NvmeSubsystem *subsys;
 
 struct {
 uint32_t err_rec;
-- 
2.36.1




[PATCH v2 4/4] hw/nvme: add new never_ready parameter to test the DNR bit

2022-06-27 Thread Niklas Cassel via
Since we verify that "ready_delay" parameter has to be smaller than CRWMT,
we know that the namespace will always become ready.
Therefore the "Namespace Not Ready" status code will never have the DNR
bit set.

Add a new parameter "never_ready" that can be used to emulate a namespace
that never gets ready, such that the DNR bit gets set after CRWMT amount
of time.

Signed-off-by: Niklas Cassel 
---
 hw/nvme/ctrl.c | 28 +++-
 hw/nvme/ns.c   |  1 +
 hw/nvme/nvme.h |  2 ++
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 5404f67480..5f98d4778d 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -168,6 +168,12 @@
  *   before being marked ready. Only applicable if CC.CRIME is set by the user.
  *   The value is in units of 500 milliseconds (to be consistent with `crwmt`).
  *
+ * - `never_ready`
+ *   This parameter specifies that a namespace should never be marked as ready.
+ *   When `crwmt` amount of time has passed after enabling the controller,
+ *   status code "Namespace Not Ready" will have the DNR bit set. If specified
+ *   together with `ready_delay`, `never_ready` will take precedence.
+ *
  * Setting `zoned` to true selects Zoned Command Set at the namespace.
  * In this case, the following namespace properties are available to configure
  * zoned operation:
@@ -4156,6 +4162,14 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, 
NvmeRequest *req)
 return status;
 }
 
+static bool nvme_ready_has_passed_timeout(NvmeCtrl *n)
+{
+int64_t current_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
+int64_t elapsed_time = current_time - n->cc_enable_timestamp;
+
+return elapsed_time > n->params.crwmt * 500;
+}
+
 static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req)
 {
 NvmeNamespace *ns;
@@ -4202,7 +4216,11 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest 
*req)
 }
 
 if (!(ns->id_indep_ns.nstat & NVME_NSTAT_NRDY)) {
-return NVME_NS_NOT_READY;
+uint16_t ret = NVME_NS_NOT_READY;
+if (ns->params.never_ready && nvme_ready_has_passed_timeout(n)) {
+ret |= NVME_DNR;
+}
+return ret;
 }
 
 if (ns->status) {
@@ -5616,6 +5634,10 @@ static void nvme_set_ready_or_start_timer(NvmeCtrl *n, 
NvmeNamespace *ns)
 {
 int64_t expire_time;
 
+if (ns->params.never_ready) {
+return;
+}
+
 if (!NVME_CC_CRIME(ldl_le_p(&n->bar.cc)) || ns->params.ready_delay == 0) {
 ns->id_indep_ns.nstat |= NVME_NSTAT_NRDY;
 return;
@@ -6346,6 +6368,7 @@ static void nvme_ctrl_reset(NvmeCtrl *n, NvmeResetType 
rst)
 }
 }
 
+n->cc_enable_timestamp = 0;
 n->aer_queued = 0;
 n->aer_mask = 0;
 n->outstanding_aers = 0;
@@ -6389,6 +6412,8 @@ static void nvme_ctrl_shutdown(NvmeCtrl *n)
 
 nvme_ns_shutdown(ns);
 }
+
+n->cc_enable_timestamp = 0;
 }
 
 static void nvme_ctrl_per_ns_action_on_start(NvmeCtrl *n)
@@ -6506,6 +6531,7 @@ static int nvme_start_ctrl(NvmeCtrl *n)
 NVME_CAP_SET_TO(cap, new_cap_timeout);
 stq_le_p(&n->bar.cap, cap);
 
+n->cc_enable_timestamp = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
 n->page_bits = page_bits;
 n->page_size = page_size;
 n->max_prp_ents = n->page_size / sizeof(uint64_t);
diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
index c1d70183c4..fc12b4e0d3 100644
--- a/hw/nvme/ns.c
+++ b/hw/nvme/ns.c
@@ -661,6 +661,7 @@ static Property nvme_ns_props[] = {
 DEFINE_PROP_BOOL("eui64-default", NvmeNamespace, params.eui64_default,
  false),
 DEFINE_PROP_UINT16("ready_delay", NvmeNamespace, params.ready_delay, 0),
+DEFINE_PROP_BOOL("never_ready", NvmeNamespace, params.never_ready, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index 9d2f13dfdb..292b1acf15 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -127,6 +127,7 @@ typedef struct NvmeNamespaceParams {
 uint64_t zrwafg;
 
 uint16_t ready_delay;
+bool never_ready;
 } NvmeNamespaceParams;
 
 typedef struct NvmeNamespace {
@@ -451,6 +452,7 @@ typedef struct NvmeCtrl {
 int cq_pending;
 uint64_thost_timestamp; /* Timestamp sent by the host 
*/
 uint64_ttimestamp_set_qemu_clock_ms;/* QEMU clock time */
+uint64_tcc_enable_timestamp;/* QEMU clock time */
 uint64_tstarttime_ms;
 uint16_ttemperature;
 uint8_t smart_critical_warning;
-- 
2.36.1




[PATCH v2 3/4] hw/nvme: add support for ratified TP4084

2022-06-27 Thread Niklas Cassel via
TP4084 adds a new mode, CC.CRIME, that can be used to mark a namespace
as ready independently from the controller.

When CC.CRIME is 0 (default), things behave as before, all namespaces
are ready when CSTS.RDY gets set to 1.

When CC.CRIME is 1, the controller will become ready when CSTS.RDY gets
set to 1, but commands accessing a namespace are allowed to return
"Namespace Not Ready" or "Admin Command Media Not Ready".
After CRTO.CRWMT amount of time, if the namespace has not yet been
marked ready, the status codes also need to have the DNR bit set.

Add a new "ready_delay" namespace device parameter, in order to emulate
different ready latencies for namespaces.

Once a namespace is ready, it will set the NRDY bit in the I/O Command
Set Independent Identify Namespace Data Structure, and then send out a
Namespace Attribute Changed event.

This new "ready_delay" is supported on controllers not part of a NVMe
subsystem. The reasons are many. One problem is that multiple controllers
can have different CC.CRIME modes running. Another problem is the extra
locking needed. The third problem is when to actually clear NRDY. If we
assume that a namespace clears NRDY when it no longer has any controller
online for that namespace. The problem then is that Linux will reset the
controllers one by one during probe time. The reset goes so fast so that
there is no time when all controllers are in reset at the same time, so
NRDY will never get cleared. (The controllers are enabled by SeaBIOS by
default.) We could introduce a reset_time param, but this would only
increase the chances that all controllers are in reset at the same time.

Signed-off-by: Niklas Cassel 
---
 hw/nvme/ctrl.c   | 123 +--
 hw/nvme/ns.c |  18 +++
 hw/nvme/nvme.h   |   6 +++
 hw/nvme/trace-events |   1 +
 include/block/nvme.h |  60 -
 5 files changed, 204 insertions(+), 4 deletions(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 8ca824ea14..5404f67480 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -88,6 +88,12 @@
  *   completion when there are no outstanding AERs. When the maximum number of
  *   enqueued events are reached, subsequent events will be dropped.
  *
+ * - `crwmt`
+ *   This is the Controller Ready With Media Timeout (CRWMT) field that is
+ *   defined in the CRTO register. This specifies the worst-case time that host
+ *   software should wait for the controller and all attached namespaces to
+ *   become ready. The value is in units of 500 milliseconds.
+ *
  * - `mdts`
  *   Indicates the maximum data transfer size for a command that transfers data
  *   between host-accessible memory and the controller. The value is specified
@@ -157,6 +163,11 @@
  *   namespace will be available in the subsystem but not attached to any
  *   controllers.
  *
+ * - `ready_delay`
+ *   This parameter specifies the amount of time that the namespace should wait
+ *   before being marked ready. Only applicable if CC.CRIME is set by the user.
+ *   The value is in units of 500 milliseconds (to be consistent with `crwmt`).
+ *
  * Setting `zoned` to true selects Zoned Command Set at the namespace.
  * In this case, the following namespace properties are available to configure
  * zoned operation:
@@ -216,6 +227,8 @@
 #define NVME_VF_RES_GRANULARITY 1
 #define NVME_VF_OFFSET 0x1
 #define NVME_VF_STRIDE 1
+#define NVME_DEFAULT_CRIMT 0xa
+#define NVME_DEFAULT_CRWMT 0xf
 
 #define NVME_GUEST_ERR(trace, fmt, ...) \
 do { \
@@ -4188,6 +4201,10 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest 
*req)
 return NVME_INVALID_OPCODE | NVME_DNR;
 }
 
+if (!(ns->id_indep_ns.nstat & NVME_NSTAT_NRDY)) {
+return NVME_NS_NOT_READY;
+}
+
 if (ns->status) {
 return ns->status;
 }
@@ -4791,6 +4808,27 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, 
NvmeRequest *req, bool active)
 return NVME_INVALID_CMD_SET | NVME_DNR;
 }
 
+static uint16_t nvme_identify_cs_indep_ns(NvmeCtrl *n, NvmeRequest *req)
+{
+NvmeNamespace *ns;
+NvmeIdentify *c = (NvmeIdentify *)&req->cmd;
+uint32_t nsid = le32_to_cpu(c->nsid);
+
+trace_pci_nvme_identify_cs_indep_ns(nsid);
+
+if (!nvme_nsid_valid(n, nsid) || nsid == NVME_NSID_BROADCAST) {
+return NVME_INVALID_NSID | NVME_DNR;
+}
+
+ns = nvme_ns(n, nsid);
+if (unlikely(!ns)) {
+return nvme_rpt_empty_id_struct(n, req);
+}
+
+return nvme_c2h(n, (uint8_t *)&ns->id_indep_ns, sizeof(NvmeIdNsCsIndep),
+req);
+}
+
 static uint16_t nvme_identify_ctrl_list(NvmeCtrl *n, NvmeRequest *req,
 bool attached)
 {
@@ -5081,6 +5119,8 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest 
*req)
 return nvme_identify_ns(n, req, true);
 case NVME_ID_CNS_NS_PRESENT:
 return nvme_identify_ns(n, req, false);
+case NVME_ID_CNS_CS_INDEPENDENT_NS:
+return nvme_identify_cs_indep_ns(

Re: [PATCH v2 18/21] migration: remove the QEMUFileOps 'get_buffer' callback

2022-06-27 Thread Dr. David Alan Gilbert
* Daniel P. Berrangé (berra...@redhat.com) wrote:
> This directly implements the get_buffer logic using QIOChannel APIs.
> 
> Reviewed-by: Dr. David Alan Gilbert 
> Signed-off-by: Daniel P. Berrangé 

Coverity is pointing out a fun deadcode path from this:

> diff --git a/migration/qemu-file.c b/migration/qemu-file.c
> index 5eb8cf0e28..df438724cd 100644
> --- a/migration/qemu-file.c
> +++ b/migration/qemu-file.c
> @@ -377,8 +377,22 @@ static ssize_t qemu_fill_buffer(QEMUFile *f)
>  return 0;
>  }
>  
> -len = f->ops->get_buffer(f->ioc, f->buf + pending, f->total_transferred,
> - IO_BUF_SIZE - pending, &local_error);
> +do {
> +len = qio_channel_read(f->ioc,
> +   (char *)f->buf + pending,
> +   IO_BUF_SIZE - pending,
> +   &local_error);
> +if (len == QIO_CHANNEL_ERR_BLOCK) {
> +if (qemu_in_coroutine()) {
> +qio_channel_yield(f->ioc, G_IO_IN);
> +} else {
> +qio_channel_wait(f->ioc, G_IO_IN);
> +}
> +} else if (len < 0) {
> +len = EIO;
> +}
> +} while (len == QIO_CHANNEL_ERR_BLOCK);
> +

the next code is:
if (len > 0) {
f->buf_size += len;
f->total_transferred += len;  
} else if (len == 0) {
qemu_file_set_error_obj(f, -EIO, local_error);
} else if (len != -EAGAIN) {  
qemu_file_set_error_obj(f, len, local_error);
} else {
error_free(local_error);  
}

because of the while loop, we should never actually see
len = QIO_CHANNEL_ERR_BLOCK out of the bottom; so the only
error value we should have is -EIO;  so that error_free is 
not hittable.

Dave

>  if (len > 0) {
>  f->buf_size += len;
>  f->total_transferred += len;
> diff --git a/migration/qemu-file.h b/migration/qemu-file.h
> index 4a3beedb5b..f7ed568894 100644
> --- a/migration/qemu-file.h
> +++ b/migration/qemu-file.h
> @@ -29,14 +29,6 @@
>  #include "exec/cpu-common.h"
>  #include "io/channel.h"
>  
> -/* Read a chunk of data from a file at the given position.  The pos argument
> - * can be ignored if the file is only be used for streaming.  The number of
> - * bytes actually read should be returned.
> - */
> -typedef ssize_t (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf,
> -int64_t pos, size_t size,
> -Error **errp);
> -
>  /*
>   * This function writes an iovec to file. The handler must write all
>   * of the data or return a negative errno value.
> @@ -77,7 +69,6 @@ typedef size_t (QEMURamSaveFunc)(QEMUFile *f,
>  typedef QEMUFile *(QEMURetPathFunc)(void *opaque);
>  
>  typedef struct QEMUFileOps {
> -QEMUFileGetBufferFunc *get_buffer;
>  QEMUFileWritevBufferFunc *writev_buffer;
>  QEMURetPathFunc *get_return_path;
>  } QEMUFileOps;
> -- 
> 2.36.1
> 
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




  1   2   3   4   >