Re: [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device

2023-08-31 Thread Erik Schilling
On Thu Aug 31, 2023 at 5:47 PM CEST, Alex Bennée wrote:
>
> Albert Esteve  writes:
>
> > Sorry to bring up this post, it's been a while since you posted.
> > But I have been testing the patch the last couple of days.
> >
> > On Mon, Jul 10, 2023 at 9:58 PM Michael S. Tsirkin  wrote:
> >
> >  On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
> >  > To use the generic device the user will need to provide the config
> >  > region size via the command line. We also add a notifier so the guest
> >  > can be pinged if the remote daemon updates the config.
> >  > 
> >  > With these changes:
> >  > 
> >  >   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
> >  > 
> >  > is equivalent to:
> >  > 
> >  >   -device vhost-user-gpio-pci
> >  > 
> >  > Signed-off-by: Alex Bennée 
> >
> >  This one I think it's best to defer until we get a better
> >  handle on how we want the configuration to look.
> >
> >  > ---
> >  >  include/hw/virtio/vhost-user-device.h |  1 +
> >  >  hw/virtio/vhost-user-device.c | 58 ++-
> >  >  2 files changed, 58 insertions(+), 1 deletion(-)
> >  > 
> >  > diff --git a/include/hw/virtio/vhost-user-device.h 
> > b/include/hw/virtio/vhost-user-device.h
> >  > index 9105011e25..3ddf88a146 100644
> >  > --- a/include/hw/virtio/vhost-user-device.h
> >  > +++ b/include/hw/virtio/vhost-user-device.h
> >  > @@ -22,6 +22,7 @@ struct VHostUserBase {
> >  >  CharBackend chardev;
> >  >  uint16_t virtio_id;
> >  >  uint32_t num_vqs;
> >  > +uint32_t config_size;
> >  >  /* State tracking */
> >  >  VhostUserState vhost_user;
> >  >  struct vhost_virtqueue *vhost_vq;
> >  > diff --git a/hw/virtio/vhost-user-device.c 
> > b/hw/virtio/vhost-user-device.c
> >  > index b0239fa033..2b028cae08 100644
> >  > --- a/hw/virtio/vhost-user-device.c
> >  > +++ b/hw/virtio/vhost-user-device.c
> >  > @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
> >  >  return vub->vhost_dev.features & ~(1ULL << 
> > VHOST_USER_F_PROTOCOL_FEATURES);
> >  >  }
> >  >  
> >  > +/*
> >  > + * To handle VirtIO config we need to know the size of the config
> >  > + * space. We don't cache the config but re-fetch it from the guest
> >  > + * every time in case something has changed.
> >  > + */
> >  > +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
> >  > +{
> >  > +VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +Error *local_err = NULL;
> >  > +
> >  > +/*
> >  > + * There will have been a warning during vhost_dev_init, but lets
> >  > + * assert here as nothing will go right now.
> >  > + */
> >  > +g_assert(vub->config_size && vub->vhost_user.supports_config == 
> > true);
> >  > +
> >  > +if (vhost_dev_get_config(>vhost_dev, config,
> >  > + vub->config_size, _err)) {
> >  > +error_report_err(local_err);
> >  > +}
> >  > +}
> >  > +
> >  > +/*
> >  > + * When the daemon signals an update to the config we just need to
> >  > + * signal the guest as we re-read the config on demand above.
> >  > + */
> >  > +static int vub_config_notifier(struct vhost_dev *dev)
> >  > +{
> >  > +virtio_notify_config(dev->vdev);
> >  > +return 0;
> >  > +}
> >  > +
> >  > +const VhostDevConfigOps vub_config_ops = {
> >  > +.vhost_dev_config_notifier = vub_config_notifier,
> >  > +};
> >  > +
> >  >  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> >  >  {
> >  >  /*
> >  > @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
> >  >  {
> >  >  VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> >  >  VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +struct vhost_dev *vhost_dev = >vhost_dev;
> >  >  
> >  >  if (vub->connected) {
> >  >  return 0;
> >  >  }
> >  >  vub->connected = true;
> >  >  
> >  > +/*
> >  > + * If we support VHOST_USER_GET_CONFIG we must enable the notifier
> >  > + * so we can ping the guest when it updates.
> >  > + */
> >  > +if (vub->vhost_user.supports_config) {
> >  > +vhost_dev_set_config_notifier(vhost_dev, _config_ops);
> >  > +}
> >  > +
> >  >  /* restore vhost state */
> >  >  if (virtio_device_started(vdev, vdev->status)) {
> >  >  vub_start(vdev);
> >  > @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev, 
> > Error **errp)
> >  >  vub->num_vqs = 1; /* reasonable default? */
> >  >  }
> >  >  
> >  > +/*
> >  > + * We can't handle config requests unless we know the size of the
> >  > + * config region, specialisations of the vhost-user-device will be
> >  > + * able to set this.
> >  > + */
> >  > +if (vub->config_size) {
> >  > +vub->vhost_user.supports_config = true;
> >  > +}
> >
> > Shouldn't the `supports_config = true' be set before we call 
> > vhost_dev_init() a few lines above?
> > Otherwise, we end up checking the 

Re: [PATCH 07/11] hw/arm/aspeed: Clean up local variable shadowing

2023-08-31 Thread Cédric Le Goater

On 9/1/23 00:56, Philippe Mathieu-Daudé wrote:

Fix:

   hw/arm/aspeed_ast2600.c:391:18: error: declaration shadows a local variable 
[-Werror,-Wshadow]
 qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i);
  ^
   hw/arm/aspeed_ast2600.c:283:14: note: previous declaration is here
 qemu_irq irq;
  ^
   hw/arm/aspeed_ast2600.c:416:18: error: declaration shadows a local variable 
[-Werror,-Wshadow]
 qemu_irq irq = qdev_get_gpio_in(DEVICE(>a7mpcore),
  ^
   hw/arm/aspeed_ast2600.c:283:14: note: previous declaration is here
 qemu_irq irq;
  ^

Signed-off-by: Philippe Mathieu-Daudé 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  hw/arm/aspeed_ast2600.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index a8b3a8065a..f54063445d 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -280,7 +280,6 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
  AspeedSoCState *s = ASPEED_SOC(dev);
  AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
  Error *err = NULL;
-qemu_irq irq;
  g_autofree char *sram_name = NULL;
  
  /* Default boot region (SPI memory or ROMs) */

@@ -339,6 +338,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
  for (i = 0; i < sc->num_cpus; i++) {
  SysBusDevice *sbd = SYS_BUS_DEVICE(>a7mpcore);
  DeviceState  *d   = DEVICE(>cpu[i]);
+qemu_irq irq;
  
  irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);

  sysbus_connect_irq(sbd, i, irq);





Re: [PATCH v2 09/12] hw/vmapple/cfg: Introduce vmapple cfg region

2023-08-31 Thread Mark Cave-Ayland

On 30/08/2023 17:14, Alexander Graf wrote:

Hi Alex,


Instead of device tree or other more standardized means, VMApple passes
platform configuration to the first stage boot loader in a binary encoded
format that resides at a dedicated RAM region in physical address space.

This patch models this configuration space as a qdev device which we can
then map at the fixed location in the address space. That way, we can
influence and annotate all configuration fields easily.

Signed-off-by: Alexander Graf 

---

v1 -> v2:

   - Adapt to system_ss meson.build target
---
  include/hw/vmapple/cfg.h |  68 +
  hw/vmapple/cfg.c | 105 +++
  hw/vmapple/Kconfig   |   3 ++
  hw/vmapple/meson.build   |   1 +
  4 files changed, 177 insertions(+)
  create mode 100644 include/hw/vmapple/cfg.h
  create mode 100644 hw/vmapple/cfg.c

diff --git a/include/hw/vmapple/cfg.h b/include/hw/vmapple/cfg.h
new file mode 100644
index 00..3337064e44
--- /dev/null
+++ b/include/hw/vmapple/cfg.h
@@ -0,0 +1,68 @@
+/*
+ * VMApple Configuration Region
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_VMAPPLE_CFG_H
+#define HW_VMAPPLE_CFG_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#include "net/net.h"
+
+typedef struct VMAppleCfg {
+uint32_t version; /* 0x000 */
+uint32_t nr_cpus; /* 0x004 */
+uint32_t unk1;/* 0x008 */
+uint32_t unk2;/* 0x00c */
+uint32_t unk3;/* 0x010 */
+uint32_t unk4;/* 0x014 */
+uint64_t ecid;/* 0x018 */
+uint64_t ram_size;/* 0x020 */
+uint32_t run_installer1;  /* 0x028 */
+uint32_t unk5;/* 0x02c */
+uint32_t unk6;/* 0x030 */
+uint32_t run_installer2;  /* 0x034 */
+uint32_t rnd; /* 0x038 */
+uint32_t unk7;/* 0x03c */
+MACAddr mac_en0;  /* 0x040 */
+uint8_t pad1[2];
+MACAddr mac_en1;  /* 0x048 */
+uint8_t pad2[2];
+MACAddr mac_wifi0;/* 0x050 */
+uint8_t pad3[2];
+MACAddr mac_bt0;  /* 0x058 */
+uint8_t pad4[2];
+uint8_t reserved[0xa0];   /* 0x060 */
+uint32_t cpu_ids[0x80];   /* 0x100 */
+uint8_t scratch[0x200];   /* 0x180 */
+char serial[32];  /* 0x380 */
+char unk8[32];/* 0x3a0 */
+char model[32];   /* 0x3c0 */
+uint8_t unk9[32]; /* 0x3e0 */
+uint32_t unk10;   /* 0x400 */
+char soc_name[32];/* 0x404 */
+} VMAppleCfg;
+
+#define TYPE_VMAPPLE_CFG "vmapple-cfg"
+OBJECT_DECLARE_SIMPLE_TYPE(VMAppleCfgState, VMAPPLE_CFG)
+
+struct VMAppleCfgState {
+/*  */
+SysBusDevice parent_obj;


Missing newline after parent_obj here (we do this so that it's obvious looking 
through a file that if you see the first member of parent_obj followed by a newline 
then you know that struct belongs to a QOM type).



+VMAppleCfg cfg;
+
+/*  */
+MemoryRegion mem;
+char *serial;
+char *model;
+char *soc_name;
+};


And again please drop the private/public comments.


+#define VMAPPLE_CFG_SIZE 0x0001
+
+#endif /* HW_VMAPPLE_CFG_H */
diff --git a/hw/vmapple/cfg.c b/hw/vmapple/cfg.c
new file mode 100644
index 00..d48e3c3afa
--- /dev/null
+++ b/hw/vmapple/cfg.c
@@ -0,0 +1,105 @@
+/*
+ * VMApple Configuration Region
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/vmapple/cfg.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qapi/error.h"
+
+static void vmapple_cfg_reset(DeviceState *dev)
+{
+VMAppleCfgState *s = VMAPPLE_CFG(dev);
+VMAppleCfg *cfg;
+
+cfg = memory_region_get_ram_ptr(>mem);
+memset((void *)cfg, 0, VMAPPLE_CFG_SIZE);
+*cfg = s->cfg;


Is this last line needed?


+}


And again for SysBusDevice you can use the Resettable interface instead of the legacy 
DeviceClass::reset.



+static void vmapple_cfg_realize(DeviceState *dev, Error **errp)
+{
+VMAppleCfgState *s = VMAPPLE_CFG(dev);
+uint32_t i;
+
+strncpy(s->cfg.serial, s->serial, sizeof(s->cfg.serial));
+strncpy(s->cfg.model, s->model, sizeof(s->cfg.model));
+strncpy(s->cfg.soc_name, s->soc_name, sizeof(s->cfg.soc_name));
+strncpy(s->cfg.unk8, "D/A", sizeof(s->cfg.soc_name));
+s->cfg.ecid = cpu_to_be64(s->cfg.ecid);
+s->cfg.version = 2;
+s->cfg.unk1 = 1;
+s->cfg.unk2 = 1;
+s->cfg.unk3 = 0x20;
+s->cfg.unk4 = 0;
+s->cfg.unk5 = 1;
+s->cfg.unk6 = 1;
+s->cfg.unk7 = 0;
+s->cfg.unk10 = 1;
+
+g_assert(s->cfg.nr_cpus < 

Re: [PATCH v2 08/12] hw/vmapple/bdif: Introduce vmapple backdoor interface

2023-08-31 Thread Mark Cave-Ayland

On 30/08/2023 17:14, Alexander Graf wrote:

Hi Alex,


The VMApple machine exposes AUX and ROOT block devices (as well as USB OTG
emulation) via virtio-pci as well as a special, simple backdoor platform
device.

This patch implements this backdoor platform device to the best of my
understanding. I left out any USB OTG parts; they're only needed for
guest recovery and I don't understand the protocol yet.

Signed-off-by: Alexander Graf 

---

v1 -> v2:

   - Adapt to system_ss meson.build target
---
  include/hw/vmapple/bdif.h |  31 +
  hw/vmapple/bdif.c | 245 ++
  hw/vmapple/Kconfig|   2 +
  hw/vmapple/meson.build|   1 +
  hw/vmapple/trace-events   |   5 +
  5 files changed, 284 insertions(+)
  create mode 100644 include/hw/vmapple/bdif.h
  create mode 100644 hw/vmapple/bdif.c

diff --git a/include/hw/vmapple/bdif.h b/include/hw/vmapple/bdif.h
new file mode 100644
index 00..65ee43457b
--- /dev/null
+++ b/include/hw/vmapple/bdif.h
@@ -0,0 +1,31 @@
+/*
+ * VMApple Backdoor Interface
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_VMAPPLE_BDIF_H
+#define HW_VMAPPLE_BDIF_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_VMAPPLE_BDIF "vmapple-bdif"
+OBJECT_DECLARE_SIMPLE_TYPE(VMAppleBdifState, VMAPPLE_BDIF)
+
+struct VMAppleBdifState {
+/*  */
+SysBusDevice parent_obj;
+
+/*  */
+BlockBackend *aux;
+BlockBackend *root;
+MemoryRegion mmio;
+};


This looks better :). You can drop the private/public comments though.


+
+#define VMAPPLE_BDIF_SIZE 0x0020
+
+#endif /* HW_VMAPPLE_BDIF_H */
diff --git a/hw/vmapple/bdif.c b/hw/vmapple/bdif.c
new file mode 100644
index 00..36b5915ff3
--- /dev/null
+++ b/hw/vmapple/bdif.c
@@ -0,0 +1,245 @@
+/*
+ * VMApple Backdoor Interface
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/vmapple/bdif.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qapi/error.h"
+#include "trace.h"
+#include "hw/block/block.h"
+#include "sysemu/block-backend.h"
+
+#define REG_DEVID_MASK  0x
+#define DEVID_ROOT  0x
+#define DEVID_AUX   0x0001
+#define DEVID_USB   0x0010
+
+#define REG_STATUS  0x0
+#define REG_STATUS_ACTIVE BIT(0)
+#define REG_CFG 0x4
+#define REG_CFG_ACTIVEBIT(1)
+#define REG_UNK10x8
+#define REG_BUSY0x10
+#define REG_BUSY_READYBIT(0)
+#define REG_UNK20x400
+#define REG_CMD 0x408
+#define REG_NEXT_DEVICE 0x420
+#define REG_UNK30x434
+
+typedef struct vblk_sector {
+uint32_t pad;
+uint32_t pad2;
+uint32_t sector;
+uint32_t pad3;
+} VblkSector;
+
+typedef struct vblk_req_cmd {
+uint64_t addr;
+uint32_t len;
+uint32_t flags;
+} VblkReqCmd;
+
+typedef struct vblk_req {
+VblkReqCmd sector;
+VblkReqCmd data;
+VblkReqCmd retval;
+} VblkReq;
+
+#define VBLK_DATA_FLAGS_READ  0x00030001
+#define VBLK_DATA_FLAGS_WRITE 0x00010001
+
+#define VBLK_RET_SUCCESS  0
+#define VBLK_RET_FAILED   1
+
+static uint64_t bdif_read(void *opaque, hwaddr offset, unsigned size)
+{
+uint64_t ret = -1;
+uint64_t devid = (offset & REG_DEVID_MASK);
+
+switch (offset & ~REG_DEVID_MASK) {
+case REG_STATUS:
+ret = REG_STATUS_ACTIVE;
+break;
+case REG_CFG:
+ret = REG_CFG_ACTIVE;
+break;
+case REG_UNK1:
+ret = 0x420;
+break;
+case REG_BUSY:
+ret = REG_BUSY_READY;
+break;
+case REG_UNK2:
+ret = 0x1;
+break;
+case REG_UNK3:
+ret = 0x0;
+break;
+case REG_NEXT_DEVICE:
+switch (devid) {
+case DEVID_ROOT:
+ret = 0x800;
+break;
+case DEVID_AUX:
+ret = 0x1;
+break;
+}
+break;
+}
+
+trace_bdif_read(offset, size, ret);
+return ret;
+}
+
+static void le2cpu_sector(VblkSector *sector)
+{
+sector->sector = le32_to_cpu(sector->sector);
+}
+
+static void le2cpu_reqcmd(VblkReqCmd *cmd)
+{
+cmd->addr = le64_to_cpu(cmd->addr);
+cmd->len = le32_to_cpu(cmd->len);
+cmd->flags = le32_to_cpu(cmd->flags);
+}
+
+static void le2cpu_req(VblkReq *req)
+{
+le2cpu_reqcmd(>sector);
+le2cpu_reqcmd(>data);
+le2cpu_reqcmd(>retval);
+}
+
+static void vblk_cmd(uint64_t devid, BlockBackend *blk, uint64_t value,
+ uint64_t static_off)
+{
+VblkReq req;
+VblkSector sector;
+uint64_t off = 0;
+char *buf = NULL;
+uint8_t ret = 

Re: [PATCH v2 07/12] hw/vmapple/aes: Introduce aes engine

2023-08-31 Thread Mark Cave-Ayland

On 30/08/2023 17:14, Alexander Graf wrote:

Hi Alex,


VMApple contains an "aes" engine device that it uses to encrypt and
decrypt its nvram. It has trivial hard coded keys it uses for that
purpose.

Add device emulation for this device model.

Signed-off-by: Alexander Graf 
---
  hw/vmapple/aes.c| 583 
  hw/vmapple/Kconfig  |   2 +
  hw/vmapple/meson.build  |   1 +
  hw/vmapple/trace-events |  18 ++
  4 files changed, 604 insertions(+)
  create mode 100644 hw/vmapple/aes.c

diff --git a/hw/vmapple/aes.c b/hw/vmapple/aes.c
new file mode 100644
index 00..eaf1e26abe
--- /dev/null
+++ b/hw/vmapple/aes.c
@@ -0,0 +1,583 @@
+/*
+ * QEMU Apple AES device emulation
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+#include "hw/sysbus.h"
+#include "crypto/hash.h"
+#include "crypto/aes.h"
+#include "crypto/cipher.h"
+
+#define TYPE_AES  "apple-aes"
+#define MAX_FIFO_SIZE 9
+
+#define CMD_KEY   0x1
+#define CMD_KEY_CONTEXT_SHIFT27
+#define CMD_KEY_CONTEXT_MASK (0x1 << CMD_KEY_CONTEXT_SHIFT)
+#define CMD_KEY_SELECT_SHIFT 24
+#define CMD_KEY_SELECT_MASK  (0x7 << CMD_KEY_SELECT_SHIFT)
+#define CMD_KEY_KEY_LEN_SHIFT22
+#define CMD_KEY_KEY_LEN_MASK (0x3 << CMD_KEY_KEY_LEN_SHIFT)
+#define CMD_KEY_ENCRYPT_SHIFT20
+#define CMD_KEY_ENCRYPT_MASK (0x1 << CMD_KEY_ENCRYPT_SHIFT)
+#define CMD_KEY_BLOCK_MODE_SHIFT 16
+#define CMD_KEY_BLOCK_MODE_MASK  (0x3 << CMD_KEY_BLOCK_MODE_SHIFT)
+#define CMD_IV0x2
+#define CMD_IV_CONTEXT_SHIFT 26
+#define CMD_IV_CONTEXT_MASK  (0x3 << CMD_KEY_CONTEXT_SHIFT)
+#define CMD_DSB   0x3
+#define CMD_SKG   0x4
+#define CMD_DATA  0x5
+#define CMD_DATA_KEY_CTX_SHIFT   27
+#define CMD_DATA_KEY_CTX_MASK(0x1 << CMD_DATA_KEY_CTX_SHIFT)
+#define CMD_DATA_IV_CTX_SHIFT25
+#define CMD_DATA_IV_CTX_MASK (0x3 << CMD_DATA_IV_CTX_SHIFT)
+#define CMD_DATA_LEN_MASK0xff
+#define CMD_STORE_IV  0x6
+#define CMD_STORE_IV_ADDR_MASK   0xff
+#define CMD_WRITE_REG 0x7
+#define CMD_FLAG  0x8
+#define CMD_FLAG_STOP_MASK   BIT(26)
+#define CMD_FLAG_RAISE_IRQ_MASK  BIT(27)
+#define CMD_FLAG_INFO_MASK   0xff
+#define CMD_MAX   0x10
+
+#define CMD_SHIFT 28
+
+#define REG_STATUS0xc
+#define REG_STATUS_DMA_READ_RUNNING BIT(0)
+#define REG_STATUS_DMA_READ_PENDING BIT(1)
+#define REG_STATUS_DMA_WRITE_RUNNINGBIT(2)
+#define REG_STATUS_DMA_WRITE_PENDINGBIT(3)
+#define REG_STATUS_BUSY BIT(4)
+#define REG_STATUS_EXECUTINGBIT(5)
+#define REG_STATUS_READYBIT(6)
+#define REG_STATUS_TEXT_DPA_SEEDED  BIT(7)
+#define REG_STATUS_UNWRAP_DPA_SEEDEDBIT(8)
+
+#define REG_IRQ_STATUS0x18
+#define REG_IRQ_STATUS_INVALID_CMD  BIT(2)
+#define REG_IRQ_STATUS_FLAG BIT(5)
+#define REG_IRQ_ENABLE0x1c
+#define REG_WATERMARK 0x20
+#define REG_Q_STATUS  0x24
+#define REG_FLAG_INFO 0x30
+#define REG_FIFO  0x200
+
+static const uint32_t key_lens[4] = {
+[0] = 16,
+[1] = 24,
+[2] = 32,
+[3] = 64,
+};
+
+struct key {
+uint32_t key_len;
+uint32_t key[8];
+};
+
+struct iv {
+uint32_t iv[4];
+};
+
+struct context {
+struct key key;
+struct iv iv;
+};
+
+static struct key builtin_keys[7] = {
+[1] = {
+.key_len = 32,
+.key = { 0x1 },
+},
+[2] = {
+.key_len = 32,
+.key = { 0x2 },
+},
+[3] = {
+.key_len = 32,
+.key = { 0x3 },
+}
+};


For the QOM type below:


+typedef struct AESState {
+/* Private */
+SysBusDevice parent_obj;
+
+/* Public */
+qemu_irq irq;
+MemoryRegion iomem1;
+MemoryRegion iomem2;
+
+uint32_t status;
+uint32_t q_status;
+uint32_t irq_status;
+uint32_t irq_enable;
+uint32_t watermark;
+uint32_t flag_info;
+uint32_t fifo[MAX_FIFO_SIZE];
+uint32_t fifo_idx;
+struct key key[2];
+struct iv iv[4];
+bool is_encrypt;
+QCryptoCipherMode block_mode;
+} AESState;
+
+OBJECT_DECLARE_SIMPLE_TYPE(AESState, AES)


... down to here, this should live in a separate .h file so that users of the device 
can include the header and reference TYPE_AES instead of hardcoding the type string. 
Possibly you may also want to rename the type since this AES implementation appears 
to be very Apple specific :)


Note that you can also drop the typedef as this is handled by the OBJECT_*_TYPE() 
macros for you. Also we don't use separate "/* Private */" and "/* Public */" 
comments anymore so they can also be removed: we assume 

Re: [PATCH v2 02/12] hw/misc/pvpanic: Add MMIO interface

2023-08-31 Thread Mark Cave-Ayland

On 30/08/2023 17:14, Alexander Graf wrote:

Hi Alex,


In addition to the ISA and PCI variants of pvpanic, let's add an MMIO
platform device that we can use in embedded arm environments.

Signed-off-by: Alexander Graf 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 

---

v1 -> v2:

   - Use SPDX header
   - Remove useless includes
   - Adapt to new meson.build target (system_ss)
---
  include/hw/misc/pvpanic.h |  1 +
  hw/misc/pvpanic-mmio.c| 61 +++
  hw/misc/Kconfig   |  4 +++
  hw/misc/meson.build   |  1 +
  4 files changed, 67 insertions(+)
  create mode 100644 hw/misc/pvpanic-mmio.c

diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
index fab94165d0..f9e7c1ea17 100644
--- a/include/hw/misc/pvpanic.h
+++ b/include/hw/misc/pvpanic.h
@@ -20,6 +20,7 @@
  
  #define TYPE_PVPANIC_ISA_DEVICE "pvpanic"

  #define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci"
+#define TYPE_PVPANIC_MMIO_DEVICE "pvpanic-mmio"
  
  #define PVPANIC_IOPORT_PROP "ioport"
  
diff --git a/hw/misc/pvpanic-mmio.c b/hw/misc/pvpanic-mmio.c

new file mode 100644
index 00..99a24f104c
--- /dev/null
+++ b/hw/misc/pvpanic-mmio.c
@@ -0,0 +1,61 @@
+/*
+ * QEMU simulated pvpanic device (MMIO frontend)
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/qdev-properties.h"
+#include "hw/misc/pvpanic.h"
+#include "hw/sysbus.h"
+#include "standard-headers/linux/pvpanic.h"
+
+OBJECT_DECLARE_SIMPLE_TYPE(PVPanicMMIOState, PVPANIC_MMIO_DEVICE)
+
+#define PVPANIC_MMIO_SIZE 0x2
+
+struct PVPanicMMIOState {
+SysBusDevice parent_obj;
+
+PVPanicState pvpanic;
+};
+
+static void pvpanic_mmio_initfn(Object *obj)
+{
+PVPanicMMIOState *s = PVPANIC_MMIO_DEVICE(obj);
+
+pvpanic_setup_io(>pvpanic, DEVICE(s), PVPANIC_MMIO_SIZE);
+sysbus_init_mmio(SYS_BUS_DEVICE(obj), >pvpanic.mr);
+}
+
+static Property pvpanic_mmio_properties[] = {
+DEFINE_PROP_UINT8("events", PVPanicMMIOState, pvpanic.events,
+  PVPANIC_PANICKED | PVPANIC_CRASH_LOADED),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pvpanic_mmio_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+device_class_set_props(dc, pvpanic_mmio_properties);
+set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo pvpanic_mmio_info = {
+.name  = TYPE_PVPANIC_MMIO_DEVICE,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(PVPanicMMIOState),
+.instance_init = pvpanic_mmio_initfn,
+.class_init= pvpanic_mmio_class_init,
+};
+
+static void pvpanic_register_types(void)
+{
+type_register_static(_mmio_info);
+}
+
+type_init(pvpanic_register_types)


Instead of using the above boilerplate, the current recommended way to register QOM 
types is with the DEFINE_TYPES() macro.



diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 6996d265e4..b69746a60a 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -125,6 +125,10 @@ config PVPANIC_ISA
  depends on ISA_BUS
  select PVPANIC_COMMON
  
+config PVPANIC_MMIO

+bool
+select PVPANIC_COMMON
+
  config AUX
  bool
  select I2C
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 892f8b91c5..63821d6040 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -116,6 +116,7 @@ system_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: 
files('armsse-mhu.c'))
  
  system_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))

  system_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c'))
+system_ss.add(when: 'CONFIG_PVPANIC_MMIO', if_true: files('pvpanic-mmio.c'))
  system_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
  system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
'aspeed_hace.c',



ATB,

Mark.




RE: [PATCH 1/3] hw/misc: Introduce AMD/Xilix Versal TRNG device

2023-08-31 Thread Ho, Tong
Hi Richard,

Thanks for your input.

I have questions regarding using qemu/guest-random.h for QEMU device models.

Using qemu/guest-random.h, how can this TRNG model ensure its independence from
other uses of the same qemu_guest_getrandom() and qemu_guest_random_seed_*()?

By "other uses", I mean components and/or devices using qemu/guest-random.h but 
unrelated to this Xilinx Versal TRNG device.

By "independent", I mean the Xilinx Versal TRNG device is:

1. Not impacted by other uses that may or may not need to set the '-seed' 
option, and

2. Not impacting other uses just because a Xilinx Versal machine user decides 
to use deterministic mode *only" for this TRNG device.

Also, I am at a loss in how unrelated QEMU devices can remain independent when:

3. qemu/guest-random.h uses '__thread' variable for GRand context, but

4. QEMU devices run mostly as co-routines and not as separate threads.

I suppose the Versal TRNG implementation could use g_rand_*() directly,
having a GRand object in the device state and seeding through 
g_rand_set_seed_array().

Best regards,
Tong Ho

-Original Message-
From: Richard Henderson  
Sent: Thursday, August 31, 2023 4:45 PM
To: Ho, Tong ; qemu-...@nongnu.org
Cc: qemu-devel@nongnu.org; alist...@alistair23.me; edgar.igles...@gmail.com; 
peter.mayd...@linaro.org
Subject: Re: [PATCH 1/3] hw/misc: Introduce AMD/Xilix Versal TRNG device

On 8/31/23 10:18, Tong Ho wrote:
> This adds a non-cryptographic grade implementation of the model for 
> the True Random Number Generator (TRNG) component in AMD/Xilinx Versal 
> device family.
> 
> This model is only intended for non-real world testing of guest 
> software, where cryptographically strong TRNG is not needed.
> 
> This model supports versions 1 & 2 of the Versal TRNG, with default to 
> be version 2; the 'hw-version' uint32 property can be set to 0x0100 to 
> override the default.
> 
> Other implemented properties:
> - 'forced-prng', uint64
>When set to non-zero, "true random reseed" is replaced by
>deterministic reseed based on the given value and other
>deterministic parameters, even when guest software has
>configured the TRNG as "true random reseed".  This option
>allows guest software to reproduce data-dependent defects.
> 
> - 'fips-fault-events', uint32, bit-mask
>bit 3: Triggers the SP800-90B entropy health test fault irq
>bit 1: Triggers the FIPS 140-2 continuous test fault irq
> 
> Signed-off-by: Tong Ho
> ---
>   hw/misc/Kconfig|   3 +
>   hw/misc/meson.build|   3 +
>   hw/misc/xlnx-versal-trng.c | 725 +
>   include/hw/misc/xlnx-versal-trng.h |  58 +++
>   4 files changed, 789 insertions(+)
>   create mode 100644 hw/misc/xlnx-versal-trng.c
>   create mode 100644 include/hw/misc/xlnx-versal-trng.h

I don't think you should be inventing another PRNG, or related properties.

We already have qemu/guest-random.h, and the -seed command-line parameter to 
force the use of a deterministic PRNG with a given seed value.


r~


Re: [PATCH v2] target/riscv: Allocate itrigger timers only once

2023-08-31 Thread Alistair Francis
On Fri, Aug 18, 2023 at 1:42 PM Akihiko Odaki  wrote:
>
> riscv_trigger_init() had been called on reset events that can happen
> several times for a CPU and it allocated timers for itrigger. If old
> timers were present, they were simply overwritten by the new timers,
> resulting in a memory leak.
>
> Divide riscv_trigger_init() into two functions, namely
> riscv_trigger_realize() and riscv_trigger_reset() and call them in
> appropriate timing. The timer allocation will happen only once for a
> CPU in riscv_trigger_realize().
>
> Fixes: 5a4ae64cac ("target/riscv: Add itrigger support when icount is 
> enabled")
> Signed-off-by: Akihiko Odaki 
> Reviewed-by: Philippe Mathieu-Daudé 
> Reviewed-by: LIU Zhiwei 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/debug.h |  3 ++-
>  target/riscv/cpu.c   |  8 +++-
>  target/riscv/debug.c | 15 ---
>  3 files changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/debug.h b/target/riscv/debug.h
> index c471748d5a..5794aa6ee5 100644
> --- a/target/riscv/debug.h
> +++ b/target/riscv/debug.h
> @@ -143,7 +143,8 @@ void riscv_cpu_debug_excp_handler(CPUState *cs);
>  bool riscv_cpu_debug_check_breakpoint(CPUState *cs);
>  bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
>
> -void riscv_trigger_init(CPURISCVState *env);
> +void riscv_trigger_realize(CPURISCVState *env);
> +void riscv_trigger_reset_hold(CPURISCVState *env);
>
>  bool riscv_itrigger_enabled(CPURISCVState *env);
>  void riscv_itrigger_update_priv(CPURISCVState *env);
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index e12b6ef7f6..7e0512dd5f 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -904,7 +904,7 @@ static void riscv_cpu_reset_hold(Object *obj)
>
>  #ifndef CONFIG_USER_ONLY
>  if (cpu->cfg.debug) {
> -riscv_trigger_init(env);
> +riscv_trigger_reset_hold(env);
>  }
>
>  if (kvm_enabled()) {
> @@ -1475,6 +1475,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> **errp)
>
>  riscv_cpu_register_gdb_regs_for_features(cs);
>
> +#ifndef CONFIG_USER_ONLY
> +if (cpu->cfg.debug) {
> +riscv_trigger_realize(>env);
> +}
> +#endif
> +
>  qemu_init_vcpu(cs);
>  cpu_reset(cs);
>
> diff --git a/target/riscv/debug.c b/target/riscv/debug.c
> index 75ee1c4971..ddd46b2d3e 100644
> --- a/target/riscv/debug.c
> +++ b/target/riscv/debug.c
> @@ -903,7 +903,17 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
> CPUWatchpoint *wp)
>  return false;
>  }
>
> -void riscv_trigger_init(CPURISCVState *env)
> +void riscv_trigger_realize(CPURISCVState *env)
> +{
> +int i;
> +
> +for (i = 0; i < RV_MAX_TRIGGERS; i++) {
> +env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
> +  riscv_itrigger_timer_cb, env);
> +}
> +}
> +
> +void riscv_trigger_reset_hold(CPURISCVState *env)
>  {
>  target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0);
>  int i;
> @@ -928,7 +938,6 @@ void riscv_trigger_init(CPURISCVState *env)
>  env->tdata3[i] = 0;
>  env->cpu_breakpoint[i] = NULL;
>  env->cpu_watchpoint[i] = NULL;
> -env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
> -  riscv_itrigger_timer_cb, env);
> +timer_del(env->itrigger_timer[i]);
>  }
>  }
> --
> 2.41.0
>
>



Re: [PATCH] target/riscv: Allocate itrigger timers only once

2023-08-31 Thread Alistair Francis
On Thu, Aug 17, 2023 at 2:28 AM Akihiko Odaki  wrote:
>
> riscv_trigger_init() had been called on reset events that can happen
> several times for a CPU and it allocated timers for itrigger. If old
> timers were present, they were simply overwritten by the new timers,
> resulting in a memory leak.
>
> Divide riscv_trigger_init() into two functions, namely
> riscv_trigger_realize() and riscv_trigger_reset() and call them in
> appropriate timing. The timer allocation will happen only once for a
> CPU in riscv_trigger_realize().
>
> Fixes: 5a4ae64cac ("target/riscv: Add itrigger support when icount is 
> enabled")
> Signed-off-by: Akihiko Odaki 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/debug.h |  3 ++-
>  target/riscv/cpu.c   |  8 +++-
>  target/riscv/debug.c | 15 ---
>  3 files changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/debug.h b/target/riscv/debug.h
> index c471748d5a..7edc31e7cc 100644
> --- a/target/riscv/debug.h
> +++ b/target/riscv/debug.h
> @@ -143,7 +143,8 @@ void riscv_cpu_debug_excp_handler(CPUState *cs);
>  bool riscv_cpu_debug_check_breakpoint(CPUState *cs);
>  bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
>
> -void riscv_trigger_init(CPURISCVState *env);
> +void riscv_trigger_realize(CPURISCVState *env);
> +void riscv_trigger_reset(CPURISCVState *env);
>
>  bool riscv_itrigger_enabled(CPURISCVState *env);
>  void riscv_itrigger_update_priv(CPURISCVState *env);
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index e12b6ef7f6..3bc3f96a58 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -904,7 +904,7 @@ static void riscv_cpu_reset_hold(Object *obj)
>
>  #ifndef CONFIG_USER_ONLY
>  if (cpu->cfg.debug) {
> -riscv_trigger_init(env);
> +riscv_trigger_reset(env);
>  }
>
>  if (kvm_enabled()) {
> @@ -1475,6 +1475,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> **errp)
>
>  riscv_cpu_register_gdb_regs_for_features(cs);
>
> +#ifndef CONFIG_USER_ONLY
> +if (cpu->cfg.debug) {
> +riscv_trigger_realize(>env);
> +}
> +#endif
> +
>  qemu_init_vcpu(cs);
>  cpu_reset(cs);
>
> diff --git a/target/riscv/debug.c b/target/riscv/debug.c
> index 75ee1c4971..1c44403205 100644
> --- a/target/riscv/debug.c
> +++ b/target/riscv/debug.c
> @@ -903,7 +903,17 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
> CPUWatchpoint *wp)
>  return false;
>  }
>
> -void riscv_trigger_init(CPURISCVState *env)
> +void riscv_trigger_realize(CPURISCVState *env)
> +{
> +int i;
> +
> +for (i = 0; i < RV_MAX_TRIGGERS; i++) {
> +env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
> +  riscv_itrigger_timer_cb, env);
> +}
> +}
> +
> +void riscv_trigger_reset(CPURISCVState *env)
>  {
>  target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0);
>  int i;
> @@ -928,7 +938,6 @@ void riscv_trigger_init(CPURISCVState *env)
>  env->tdata3[i] = 0;
>  env->cpu_breakpoint[i] = NULL;
>  env->cpu_watchpoint[i] = NULL;
> -env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
> -  riscv_itrigger_timer_cb, env);
> +timer_del(env->itrigger_timer[i]);
>  }
>  }
> --
> 2.41.0
>
>



Re: [PATCH 00/13] linux-user patch queue

2023-08-31 Thread Richard Henderson

Ping.

On 8/23/23 18:02, Richard Henderson wrote:

Combine a bunch of smaller linux-user patches:

Supercedes: 20230801230842.414421-1-del...@gmx.de
("[PATCH v2 0/3] linux-user: /proc/cpuinfo fix and content emulation for arm")
Supercedes: 20230807122206.655701-1-...@linux.ibm.com
("[PATCH v2] linux-user: Emulate the Anonymous: keyword in /proc/self/smaps")
Supercedes: 20230816181437.572997-1-richard.hender...@linaro.org
("[PATCH 0/6] linux-user: Rewrite open_self_maps")
Supercedes: 20230820204408.327348-1-richard.hender...@linaro.org
("[PATCH 0/4] linux-user: shmat/shmdt improvements")

with some additions.  Patches needing review:

   01-linux-user-Split-out-cpu-target_proc.h.patch
   11-linux-user-Use-WITH_MMAP_LOCK_GUARD-in-target_-shmat.patch
   12-linux-user-Fix-shmdt.patch
   13-linux-user-Track-shm-regions-with-an-interval-tree.patch


r~


Helge Deller (2):
   linux-user: Emulate /proc/cpuinfo on aarch64 and arm
   linux-user: Emulate /proc/cpuinfo for Alpha

Ilya Leoshkevich (1):
   linux-user: Emulate the Anonymous: keyword in /proc/self/smaps

Richard Henderson (10):
   linux-user: Split out cpu/target_proc.h
   util/selfmap: Use dev_t and ino_t in MapInfo
   linux-user: Use walk_memory_regions for open_self_maps
   linux-user: Adjust brk for load_bias
   linux-user: Show heap address in /proc/pid/maps
   linux-user: Remove ELF_START_MMAP and image_info.start_mmap
   linux-user: Move shmat and shmdt implementations to mmap.c
   linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat,shmdt}
   linux-user: Fix shmdt
   linux-user: Track shm regions with an interval tree

  include/qemu/selfmap.h   |   4 +-
  linux-user/aarch64/target_proc.h |   1 +
  linux-user/alpha/target_proc.h   |  67 
  linux-user/arm/target_proc.h | 101 ++
  linux-user/cris/target_proc.h|   1 +
  linux-user/hexagon/target_proc.h |   1 +
  linux-user/hppa/target_proc.h|  26 ++
  linux-user/i386/target_proc.h|   1 +
  linux-user/loader.h  |   6 +-
  linux-user/loongarch64/target_proc.h |   1 +
  linux-user/m68k/target_proc.h|  16 +
  linux-user/microblaze/target_proc.h  |   1 +
  linux-user/mips/target_proc.h|   1 +
  linux-user/mips64/target_proc.h  |   1 +
  linux-user/nios2/target_proc.h   |   1 +
  linux-user/openrisc/target_proc.h|   1 +
  linux-user/ppc/target_proc.h |   1 +
  linux-user/qemu.h|   1 -
  linux-user/riscv/target_proc.h   |  37 ++
  linux-user/s390x/target_proc.h   | 109 ++
  linux-user/sh4/target_proc.h |   1 +
  linux-user/sparc/target_proc.h   |  16 +
  linux-user/user-mmap.h   |   4 +
  linux-user/x86_64/target_proc.h  |   1 +
  linux-user/xtensa/target_proc.h  |   1 +
  linux-user/elfload.c | 170 ++---
  linux-user/mmap.c| 168 +
  linux-user/syscall.c | 514 +++
  util/selfmap.c   |  12 +-
  29 files changed, 828 insertions(+), 437 deletions(-)
  create mode 100644 linux-user/aarch64/target_proc.h
  create mode 100644 linux-user/alpha/target_proc.h
  create mode 100644 linux-user/arm/target_proc.h
  create mode 100644 linux-user/cris/target_proc.h
  create mode 100644 linux-user/hexagon/target_proc.h
  create mode 100644 linux-user/hppa/target_proc.h
  create mode 100644 linux-user/i386/target_proc.h
  create mode 100644 linux-user/loongarch64/target_proc.h
  create mode 100644 linux-user/m68k/target_proc.h
  create mode 100644 linux-user/microblaze/target_proc.h
  create mode 100644 linux-user/mips/target_proc.h
  create mode 100644 linux-user/mips64/target_proc.h
  create mode 100644 linux-user/nios2/target_proc.h
  create mode 100644 linux-user/openrisc/target_proc.h
  create mode 100644 linux-user/ppc/target_proc.h
  create mode 100644 linux-user/riscv/target_proc.h
  create mode 100644 linux-user/s390x/target_proc.h
  create mode 100644 linux-user/sh4/target_proc.h
  create mode 100644 linux-user/sparc/target_proc.h
  create mode 100644 linux-user/x86_64/target_proc.h
  create mode 100644 linux-user/xtensa/target_proc.h






Re: [PATCH v2 27/33] cpu: Remove page_size_init

2023-08-31 Thread Warner Losh
On Thu, Aug 31, 2023 at 8:23 PM Richard Henderson <
richard.hender...@linaro.org> wrote:

> Move qemu_host_page_{size,mask} and HOST_PAGE_ALIGN into bsd-user.
> It should be removed from bsd-user as well, but defer that cleanup.
>
> Cc: Warner Losh 
> Reviewed-by: Philippe Mathieu-Daudé 
> Signed-off-by: Richard Henderson 
> ---
>  bsd-user/qemu.h   |  7 +++
>  include/exec/cpu-common.h |  7 ---
>  include/hw/core/cpu.h |  2 --
>  accel/tcg/translate-all.c |  1 -
>  bsd-user/main.c   | 12 
>  cpu.c | 13 -
>  softmmu/vl.c  |  1 -
>  7 files changed, 19 insertions(+), 24 deletions(-)
>

ACK on the todo... My student is close to submitting the mmap series of his
patches, so I appreciate the 'quick fix' to not disrupt that effort.

Reviewed-by: Warner Losh 


Re: [PATCH v2] target/riscv: Use accelerated helper for AES64KS1I

2023-08-31 Thread Alistair Francis
On Fri, Sep 1, 2023 at 3:12 AM Ard Biesheuvel  wrote:
>
> Use the accelerated SubBytes/ShiftRows/AddRoundKey AES helper to
> implement the first half of the key schedule derivation. This does not
> actually involve shifting rows, so clone the same value into all four
> columns of the AES vector to counter that operation.
>
> Cc: Richard Henderson 
> Cc: Philippe Mathieu-Daudé 
> Cc: Palmer Dabbelt 
> Cc: Alistair Francis 
> Signed-off-by: Ard Biesheuvel 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
> v2: assign round constant to elements 0 and 1 only
>
>  target/riscv/crypto_helper.c | 17 +
>  1 file changed, 5 insertions(+), 12 deletions(-)
>
> diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
> index 4d65945429c6dcc4..bb084e00efe52d1b 100644
> --- a/target/riscv/crypto_helper.c
> +++ b/target/riscv/crypto_helper.c
> @@ -148,24 +148,17 @@ target_ulong HELPER(aes64ks1i)(target_ulong rs1, 
> target_ulong rnum)
>
>  uint8_t enc_rnum = rnum;
>  uint32_t temp = (RS1 >> 32) & 0x;
> -uint8_t rcon_ = 0;
> -target_ulong result;
> +AESState t, rc = {};
>
>  if (enc_rnum != 0xA) {
>  temp = ror32(temp, 8); /* Rotate right by 8 */
> -rcon_ = round_consts[enc_rnum];
> +rc.w[0] = rc.w[1] = round_consts[enc_rnum];
>  }
>
> -temp = ((uint32_t)AES_sbox[(temp >> 24) & 0xFF] << 24) |
> -   ((uint32_t)AES_sbox[(temp >> 16) & 0xFF] << 16) |
> -   ((uint32_t)AES_sbox[(temp >> 8) & 0xFF] << 8) |
> -   ((uint32_t)AES_sbox[(temp >> 0) & 0xFF] << 0);
> +t.w[0] = t.w[1] = t.w[2] = t.w[3] = temp;
> +aesenc_SB_SR_AK(, , , false);
>
> -temp ^= rcon_;
> -
> -result = ((uint64_t)temp << 32) | temp;
> -
> -return result;
> +return t.d[0];
>  }
>
>  target_ulong HELPER(aes64im)(target_ulong rs1)
> --
> 2.39.2
>
>



Re: [PATCH] linux-user/riscv: Add new extensions to hwprobe

2023-08-31 Thread Alistair Francis
On Tue, Aug 29, 2023 at 12:58 AM Robbin Ehn  wrote:
>
> This patch adds the new extensions in
> linux 6.5 to the hwprobe syscall.
>
> And fixes RVC check to OR with correct value.
> The previous variable contains 0 therefore it
> did work.
>
> Signed-off-by: Robbin Ehn 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  linux-user/syscall.c | 14 +-
>  1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 9353268cc1..c46a0b1493 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -9049,6 +9049,10 @@ static int do_getdents64(abi_long dirfd, abi_long 
> arg2, abi_long count)
>  #define RISCV_HWPROBE_KEY_IMA_EXT_0 4
>  #define RISCV_HWPROBE_IMA_FD   (1 << 0)
>  #define RISCV_HWPROBE_IMA_C(1 << 1)
> +#define RISCV_HWPROBE_IMA_V(1 << 2)
> +#define RISCV_HWPROBE_EXT_ZBA  (1 << 3)
> +#define RISCV_HWPROBE_EXT_ZBB  (1 << 4)
> +#define RISCV_HWPROBE_EXT_ZBS  (1 << 5)
>
>  #define RISCV_HWPROBE_KEY_CPUPERF_0 5
>  #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
> @@ -9096,7 +9100,15 @@ static void risc_hwprobe_fill_pairs(CPURISCVState *env,
>  riscv_has_ext(env, RVD) ?
>  RISCV_HWPROBE_IMA_FD : 0;
>  value |= riscv_has_ext(env, RVC) ?
> - RISCV_HWPROBE_IMA_C : pair->value;
> + RISCV_HWPROBE_IMA_C : 0;
> +value |= riscv_has_ext(env, RVV) ?
> + RISCV_HWPROBE_IMA_V : 0;
> +value |= cfg->ext_zba ?
> + RISCV_HWPROBE_EXT_ZBA : 0;
> +value |= cfg->ext_zbb ?
> + RISCV_HWPROBE_EXT_ZBB : 0;
> +value |= cfg->ext_zbs ?
> + RISCV_HWPROBE_EXT_ZBS : 0;
>  __put_user(value, >value);
>  break;
>  case RISCV_HWPROBE_KEY_CPUPERF_0:
> --
> 2.39.2
>
>



[PATCH v2 02/33] linux-user: Adjust SVr4 NULL page mapping

2023-08-31 Thread Richard Henderson
Use TARGET_PAGE_SIZE and MAP_FIXED_NOREPLACE.

We really should be attending to this earlier during
probe_guest_base, as well as better detection and
emulation of various Linux personalities.

Signed-off-by: Richard Henderson 
---
 linux-user/elfload.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 19503d8469..803281a53a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3730,8 +3730,9 @@ int load_elf_binary(struct linux_binprm *bprm, struct 
image_info *info)
and some applications "depend" upon this behavior.  Since
we do not have the power to recompile these, we emulate
the SVr4 behavior.  Sigh.  */
-target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
-MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+target_mmap(0, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC,
+MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_ANONYMOUS,
+-1, 0);
 }
 #ifdef TARGET_MIPS
 info->interp_fp_abi = interp_info.fp_abi;
-- 
2.34.1




[PATCH v2 14/33] softmmu/physmem: Remove HOST_PAGE_ALIGN

2023-08-31 Thread Richard Henderson
Align allocation sizes to the maximum of host and target page sizes.

Signed-off-by: Richard Henderson 
---
 softmmu/physmem.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 6f963ea127..04d8423b68 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -1662,7 +1662,8 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, 
Error **errp)
 
 assert(block);
 
-newsize = HOST_PAGE_ALIGN(newsize);
+newsize = TARGET_PAGE_ALIGN(newsize);
+newsize = REAL_HOST_PAGE_ALIGN(newsize);
 
 if (block->used_length == newsize) {
 /*
@@ -1897,7 +1898,9 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, 
MemoryRegion *mr,
 return NULL;
 }
 
-size = HOST_PAGE_ALIGN(size);
+size = TARGET_PAGE_ALIGN(size);
+size = REAL_HOST_PAGE_ALIGN(size);
+
 file_size = get_file_size(fd);
 if (file_size > offset && file_size < (offset + size)) {
 error_setg(errp, "backing store size 0x%" PRIx64
@@ -1975,13 +1978,17 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, 
ram_addr_t max_size,
 {
 RAMBlock *new_block;
 Error *local_err = NULL;
+int align;
 
 assert((ram_flags & ~(RAM_SHARED | RAM_RESIZEABLE | RAM_PREALLOC |
   RAM_NORESERVE)) == 0);
 assert(!host ^ (ram_flags & RAM_PREALLOC));
 
-size = HOST_PAGE_ALIGN(size);
-max_size = HOST_PAGE_ALIGN(max_size);
+align = qemu_real_host_page_size();
+align = MAX(align, TARGET_PAGE_SIZE);
+size = ROUND_UP(size, align);
+max_size = ROUND_UP(max_size, align);
+
 new_block = g_malloc0(sizeof(*new_block));
 new_block->mr = mr;
 new_block->resized = resized;
-- 
2.34.1




[PATCH v2 13/33] softmmu/physmem: Remove qemu_host_page_size

2023-08-31 Thread Richard Henderson
Use qemu_real_host_page_size() instead.

Signed-off-by: Richard Henderson 
---
 softmmu/physmem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 18277ddd67..6f963ea127 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -3472,7 +3472,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, 
size_t length)
  *fallocate works on hugepages and shmem
  *shared anonymous memory requires madvise REMOVE
  */
-need_madvise = (rb->page_size == qemu_host_page_size);
+need_madvise = (rb->page_size == qemu_real_host_page_size());
 need_fallocate = rb->fd != -1;
 if (need_fallocate) {
 /* For a file, this causes the area of the file to be zero'd
-- 
2.34.1




Re: [PATCH] linux-user/riscv: Add new extensions to hwprobe

2023-08-31 Thread Alistair Francis
On Tue, Aug 29, 2023 at 12:58 AM Robbin Ehn  wrote:
>
> This patch adds the new extensions in
> linux 6.5 to the hwprobe syscall.
>
> And fixes RVC check to OR with correct value.
> The previous variable contains 0 therefore it
> did work.
>
> Signed-off-by: Robbin Ehn 

Acked-by: Alistair Francis 

Alistair

> ---
>  linux-user/syscall.c | 14 +-
>  1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 9353268cc1..c46a0b1493 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -9049,6 +9049,10 @@ static int do_getdents64(abi_long dirfd, abi_long 
> arg2, abi_long count)
>  #define RISCV_HWPROBE_KEY_IMA_EXT_0 4
>  #define RISCV_HWPROBE_IMA_FD   (1 << 0)
>  #define RISCV_HWPROBE_IMA_C(1 << 1)
> +#define RISCV_HWPROBE_IMA_V(1 << 2)
> +#define RISCV_HWPROBE_EXT_ZBA  (1 << 3)
> +#define RISCV_HWPROBE_EXT_ZBB  (1 << 4)
> +#define RISCV_HWPROBE_EXT_ZBS  (1 << 5)
>
>  #define RISCV_HWPROBE_KEY_CPUPERF_0 5
>  #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
> @@ -9096,7 +9100,15 @@ static void risc_hwprobe_fill_pairs(CPURISCVState *env,
>  riscv_has_ext(env, RVD) ?
>  RISCV_HWPROBE_IMA_FD : 0;
>  value |= riscv_has_ext(env, RVC) ?
> - RISCV_HWPROBE_IMA_C : pair->value;
> + RISCV_HWPROBE_IMA_C : 0;
> +value |= riscv_has_ext(env, RVV) ?
> + RISCV_HWPROBE_IMA_V : 0;
> +value |= cfg->ext_zba ?
> + RISCV_HWPROBE_EXT_ZBA : 0;
> +value |= cfg->ext_zbb ?
> + RISCV_HWPROBE_EXT_ZBB : 0;
> +value |= cfg->ext_zbs ?
> + RISCV_HWPROBE_EXT_ZBS : 0;
>  __put_user(value, >value);
>  break;
>  case RISCV_HWPROBE_KEY_CPUPERF_0:
> --
> 2.39.2
>
>



[PATCH] softmmu/dirtylimit: Fix usleep early return on signal

2023-08-31 Thread alloc . young
From: alloc 

Timeout functions like usleep can return early on signal, which reduces
more dirty pages than expected. In dirtylimit case, dirtyrate meter
thread needs to kick all vcpus out to sync. The callchain:

vcpu_calculate_dirtyrate
global_dirty_log_sync
memory_global_dirty_log_sync
kvm_log_sync_global
kvm_dirty_ring_flush
kvm_cpu_synchronize_kick_all < send vcpu signal

For long time sleep, use qemu_cond_timedwait_iothread to handle cpu stop
event.

Signed-off-by: alloc 
---
 softmmu/dirtylimit.c | 19 +--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c
index fa959d7743..ee938c636d 100644
--- a/softmmu/dirtylimit.c
+++ b/softmmu/dirtylimit.c
@@ -411,13 +411,28 @@ void dirtylimit_set_all(uint64_t quota,
 
 void dirtylimit_vcpu_execute(CPUState *cpu)
 {
+int64_t sleep_us, endtime_us;
+
+dirtylimit_state_lock();
 if (dirtylimit_in_service() &&
 dirtylimit_vcpu_get_state(cpu->cpu_index)->enabled &&
 cpu->throttle_us_per_full) {
 trace_dirtylimit_vcpu_execute(cpu->cpu_index,
 cpu->throttle_us_per_full);
-usleep(cpu->throttle_us_per_full);
-}
+sleep_us = cpu->throttle_us_per_full;
+dirtylimit_state_unlock();
+endtime_us = qemu_clock_get_us(QEMU_CLOCK_REALTIME) + sleep_us;
+while (sleep_us > 0 && !cpu->stop) {
+if (sleep_us > SCALE_US) {
+qemu_mutex_lock_iothread();
+qemu_cond_timedwait_iothread(cpu->halt_cond, sleep_us / 
SCALE_US);
+qemu_mutex_unlock_iothread();
+} else
+g_usleep(sleep_us);
+sleep_us = endtime_us - qemu_clock_get_us(QEMU_CLOCK_REALTIME);
+}
+} else
+dirtylimit_state_unlock();
 }
 
 static void dirtylimit_init(void)
-- 
2.39.3




[PATCH v2 26/33] *-user: Deprecate and disable -p pagesize

2023-08-31 Thread Richard Henderson
This option controls the host page size.  From the mis-usage in
our own testsuite, this is easily confused with guest page size.

The only thing that occurs when changing the host page size is
that stuff breaks, because one cannot actually change the host
page size.  Therefore reject all but the no-op setting as part
of the deprecation process.

Cc: Warner Losh 
Signed-off-by: Richard Henderson 
---
 docs/about/deprecated.rst |  7 +++
 docs/user/main.rst|  3 ---
 bsd-user/main.c   |  9 +
 linux-user/main.c | 11 ++-
 4 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 92a2bafd2b..25f8220449 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -131,6 +131,13 @@ Use ``-accel tcg,one-insn-per-tb=on`` instead.
 User-mode emulator command line arguments
 -
 
+``-p`` (since 8.2)
+''
+
+The ``-p`` option pretends to control the host page size.  However,
+it is not possible to change the host page size, and using the
+option only causes failures.
+
 ``-singlestep`` (since 8.1)
 '''
 
diff --git a/docs/user/main.rst b/docs/user/main.rst
index f478635396..3a07be1278 100644
--- a/docs/user/main.rst
+++ b/docs/user/main.rst
@@ -87,9 +87,6 @@ Debug options:
Activate logging of the specified items (use '-d help' for a list of
log items)
 
-``-p pagesize``
-   Act as if the host page size was 'pagesize' bytes
-
 ``-g port``
Wait gdb connection to port
 
diff --git a/bsd-user/main.c b/bsd-user/main.c
index f913cb55a7..f227d87834 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -365,10 +365,11 @@ int main(int argc, char **argv)
 } else if (!strcmp(r, "L")) {
 interp_prefix = argv[optind++];
 } else if (!strcmp(r, "p")) {
-qemu_host_page_size = atoi(argv[optind++]);
-if (qemu_host_page_size == 0 ||
-(qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
-fprintf(stderr, "page size must be a power of two\n");
+unsigned size, want = qemu_real_host_page_size();
+
+if (qemu_strtoui(arg, NULL, 10, ) || size != want) {
+error_report("Deprecated page size option cannot "
+ "change host page size (%u)", want);
 exit(1);
 }
 } else if (!strcmp(r, "g")) {
diff --git a/linux-user/main.c b/linux-user/main.c
index c1058abc3c..3dd3310331 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -332,10 +332,11 @@ static void handle_arg_ld_prefix(const char *arg)
 
 static void handle_arg_pagesize(const char *arg)
 {
-qemu_host_page_size = atoi(arg);
-if (qemu_host_page_size == 0 ||
-(qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
-fprintf(stderr, "page size must be a power of two\n");
+unsigned size, want = qemu_real_host_page_size();
+
+if (qemu_strtoui(arg, NULL, 10, ) || size != want) {
+error_report("Deprecated page size option cannot "
+ "change host page size (%u)", want);
 exit(EXIT_FAILURE);
 }
 }
@@ -496,7 +497,7 @@ static const struct qemu_argument arg_table[] = {
 {"D",  "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
  "logfile", "write logs to 'logfile' (default stderr)"},
 {"p",  "QEMU_PAGESIZE",true,  handle_arg_pagesize,
- "pagesize",   "set the host page size to 'pagesize'"},
+ "pagesize",   "deprecated change to host page size"},
 {"one-insn-per-tb",
"QEMU_ONE_INSN_PER_TB",  false, handle_arg_one_insn_per_tb,
  "",   "run with one guest instruction per emulated TB"},
-- 
2.34.1




[PATCH v2 09/33] linux-user: Remove REAL_HOST_PAGE_ALIGN from mmap.c

2023-08-31 Thread Richard Henderson
We already have qemu_real_host_page_size() in a local variable.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index fc23192a32..48a6ef0af9 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -541,7 +541,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
  * the hosts real pagesize. Additional anonymous maps
  * will be created beyond EOF.
  */
-len = REAL_HOST_PAGE_ALIGN(sb.st_size - offset);
+len = ROUND_UP(sb.st_size - offset, host_page_size);
 }
 }
 
-- 
2.34.1




Re: [PATCH v2 0/2] riscv: fix --enable-debug in riscv-to-apply.next

2023-08-31 Thread Alistair Francis
On Wed, Aug 30, 2023 at 11:36 PM Daniel Henrique Barboza
 wrote:
>
> Hi,
>
> This is the second version of the --enable-debug build fix for the
> riscv-to-apply.next branch:
>
> https://github.com/alistair23/qemu/tree/riscv-to-apply.next
>
> This implements suggestions from Richard Henderson made in v1. Most
> notable difference is that riscv_kvm_aplic_request() was moved to
> kvm.c and it's now being declared in kvm_riscv.h.

Thanks!

Applied to riscv-to-apply.next

Alistair

>
> Changes from v1:
> - changed patch order
> - patch 1 (former 2):
>   - use kvm_enabled() to crop the whole block
> - patch 2 (former 1):
>   - move riscv_kvm_aplic_request() to kvm_riscv.h
>   - use kvm_enabled() to crop the whole block
> - v1 link: 
> https://lore.kernel.org/qemu-riscv/20230829122144.464489-1-dbarb...@ventanamicro.com/
>
>
> Daniel Henrique Barboza (2):
>   hw/riscv/virt.c: fix non-KVM --enable-debug build
>   hw/intc/riscv_aplic.c fix non-KVM --enable-debug build
>
>  hw/intc/riscv_aplic.c| 8 ++--
>  hw/riscv/virt.c  | 6 +++---
>  target/riscv/kvm.c   | 5 +
>  target/riscv/kvm_riscv.h | 1 +
>  4 files changed, 11 insertions(+), 9 deletions(-)
>
> --
> 2.41.0
>
>



[PATCH v2 11/33] migration: Remove qemu_host_page_size

2023-08-31 Thread Richard Henderson
Replace with the maximum of the real host page size
and the target page size.  This is an exact replacement.

Signed-off-by: Richard Henderson 
---
 migration/ram.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/migration/ram.c b/migration/ram.c
index 9040d66e61..1cabf935f2 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -3033,7 +3033,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
 {
 RAMState **rsp = opaque;
 RAMBlock *block;
-int ret;
+int ret, max_hg_page_size;
 
 if (compress_threads_save_setup()) {
 return -1;
@@ -3048,6 +3048,12 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
 }
 (*rsp)->pss[RAM_CHANNEL_PRECOPY].pss_channel = f;
 
+/*
+ * ??? Mirrors the previous use of qemu_host_page_size below,
+ * but is this really what was intended for the migration?
+ */
+max_hg_page_size = MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE);
+
 WITH_RCU_READ_LOCK_GUARD() {
 qemu_put_be64(f, ram_bytes_total_with_ignored()
  | RAM_SAVE_FLAG_MEM_SIZE);
@@ -3056,8 +3062,8 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
 qemu_put_byte(f, strlen(block->idstr));
 qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
 qemu_put_be64(f, block->used_length);
-if (migrate_postcopy_ram() && block->page_size !=
-  qemu_host_page_size) {
+if (migrate_postcopy_ram() &&
+block->page_size != max_hg_page_size) {
 qemu_put_be64(f, block->page_size);
 }
 if (migrate_ignore_shared()) {
@@ -3881,12 +3887,20 @@ static int ram_load_precopy(QEMUFile *f)
 {
 MigrationIncomingState *mis = migration_incoming_get_current();
 int flags = 0, ret = 0, invalid_flags = 0, len = 0, i = 0;
+int max_hg_page_size;
+
 /* ADVISE is earlier, it shows the source has the postcopy capability on */
 bool postcopy_advised = migration_incoming_postcopy_advised();
 if (!migrate_compress()) {
 invalid_flags |= RAM_SAVE_FLAG_COMPRESS_PAGE;
 }
 
+/*
+ * ??? Mirrors the previous use of qemu_host_page_size below,
+ * but is this really what was intended for the migration?
+ */
+max_hg_page_size = MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE);
+
 while (!ret && !(flags & RAM_SAVE_FLAG_EOS)) {
 ram_addr_t addr, total_ram_bytes;
 void *host = NULL, *host_bak = NULL;
@@ -3987,7 +4001,7 @@ static int ram_load_precopy(QEMUFile *f)
 }
 /* For postcopy we need to check hugepage sizes match */
 if (postcopy_advised && migrate_postcopy_ram() &&
-block->page_size != qemu_host_page_size) {
+block->page_size != max_hg_page_size) {
 uint64_t remote_page_size = qemu_get_be64(f);
 if (remote_page_size != block->page_size) {
 error_report("Mismatched RAM page size %s "
-- 
2.34.1




[PATCH v2 31/33] linux-user: Bound mmap_min_addr by host page size

2023-08-31 Thread Richard Henderson
Bizzarely, it is possible to set /proc/sys/vm/mmap_min_addr
to a value below the host page size.  Fix that.

Signed-off-by: Richard Henderson 
---
 linux-user/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 2334d7cc67..1925c275ed 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -904,7 +904,7 @@ int main(int argc, char **argv, char **envp)
 if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
 unsigned long tmp;
 if (fscanf(fp, "%lu", ) == 1 && tmp != 0) {
-mmap_min_addr = tmp;
+mmap_min_addr = MAX(tmp, host_page_size);
 qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
   mmap_min_addr);
 }
-- 
2.34.1




[PATCH v2 32/33] target/ppc: Enable TARGET_PAGE_BITS_VARY for user-only

2023-08-31 Thread Richard Henderson
Since ppc binaries are generally built for multiple
page sizes, it is trivial to allow the page size to vary.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/ppc/cpu-param.h | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/target/ppc/cpu-param.h b/target/ppc/cpu-param.h
index 0a0416e0a8..b7ad52de03 100644
--- a/target/ppc/cpu-param.h
+++ b/target/ppc/cpu-param.h
@@ -31,6 +31,13 @@
 # define TARGET_PHYS_ADDR_SPACE_BITS 36
 # define TARGET_VIRT_ADDR_SPACE_BITS 32
 #endif
-#define TARGET_PAGE_BITS 12
+
+#ifdef CONFIG_USER_ONLY
+/* Allow user-only to vary page size from 4k */
+# define TARGET_PAGE_BITS_VARY
+# define TARGET_PAGE_BITS_MIN 12
+#else
+# define TARGET_PAGE_BITS 12
+#endif
 
 #endif
-- 
2.34.1




[PATCH v2 07/33] linux-user/arm: Remove qemu_host_page_size from init_guest_commpage

2023-08-31 Thread Richard Henderson
Use qemu_real_host_page_size.
If the commpage is not within reserved_va, use MAP_FIXED_NOREPLACE.

Signed-off-by: Richard Henderson 
---
 linux-user/elfload.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 025747a15c..a575e811d0 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -450,6 +450,7 @@ enum {
 static bool init_guest_commpage(void)
 {
 ARMCPU *cpu = ARM_CPU(thread_cpu);
+int host_page_size = qemu_real_host_page_size();
 abi_ptr commpage;
 void *want;
 void *addr;
@@ -462,10 +463,12 @@ static bool init_guest_commpage(void)
 return true;
 }
 
-commpage = HI_COMMPAGE & -qemu_host_page_size;
+commpage = HI_COMMPAGE & -host_page_size;
 want = g2h_untagged(commpage);
-addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
-MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
+addr = mmap(want, host_page_size, PROT_READ | PROT_WRITE,
+MAP_ANONYMOUS | MAP_PRIVATE |
+(commpage < reserved_va ? MAP_FIXED : MAP_FIXED_NOREPLACE),
+-1, 0);
 
 if (addr == MAP_FAILED) {
 perror("Allocating guest commpage");
@@ -478,12 +481,12 @@ static bool init_guest_commpage(void)
 /* Set kernel helper versions; rest of page is 0.  */
 __put_user(5, (uint32_t *)g2h_untagged(0x0ffcu));
 
-if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
+if (mprotect(addr, host_page_size, PROT_READ)) {
 perror("Protecting guest commpage");
 exit(EXIT_FAILURE);
 }
 
-page_set_flags(commpage, commpage | ~qemu_host_page_mask,
+page_set_flags(commpage, commpage | (host_page_size - 1),
PAGE_READ | PAGE_EXEC | PAGE_VALID);
 return true;
 }
-- 
2.34.1




Re: [PATCH v2 26/33] *-user: Deprecate and disable -p pagesize

2023-08-31 Thread Warner Losh
On Thu, Aug 31, 2023 at 8:23 PM Richard Henderson <
richard.hender...@linaro.org> wrote:

> This option controls the host page size.  From the mis-usage in
> our own testsuite, this is easily confused with guest page size.
>
> The only thing that occurs when changing the host page size is
> that stuff breaks, because one cannot actually change the host
> page size.  Therefore reject all but the no-op setting as part
> of the deprecation process.
>
> Cc: Warner Losh 
> Signed-off-by: Richard Henderson 
> ---
>  docs/about/deprecated.rst |  7 +++
>  docs/user/main.rst|  3 ---
>  bsd-user/main.c   |  9 +
>  linux-user/main.c | 11 ++-
>  4 files changed, 18 insertions(+), 12 deletions(-)
>

Reviewed-by: Warner Losh 


[PATCH v2 29/33] linux-user: Allow TARGET_PAGE_BITS_VARY

2023-08-31 Thread Richard Henderson
If set, match the host and guest page sizes.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/main.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 3dd3310331..2334d7cc67 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -55,6 +55,7 @@
 #include "loader.h"
 #include "user-mmap.h"
 #include "accel/tcg/perf.h"
+#include "exec/page-vary.h"
 
 #ifdef CONFIG_SEMIHOSTING
 #include "semihosting/semihost.h"
@@ -683,6 +684,7 @@ int main(int argc, char **argv, char **envp)
 int i;
 int ret;
 int execfd;
+int host_page_size;
 unsigned long max_reserved_va;
 bool preserve_argv0;
 
@@ -794,6 +796,16 @@ int main(int argc, char **argv, char **envp)
  opt_one_insn_per_tb, _abort);
 ac->init_machine(NULL);
 }
+
+/*
+ * Finalize page size before creating CPUs.
+ * This will do nothing if !TARGET_PAGE_BITS_VARY.
+ * The most efficient setting is to match the host.
+ */
+host_page_size = qemu_real_host_page_size();
+set_preferred_target_page_bits(ctz32(host_page_size));
+finalize_target_page_bits();
+
 cpu = cpu_create(cpu_type);
 env = cpu->env_ptr;
 cpu_reset(cpu);
@@ -807,8 +819,6 @@ int main(int argc, char **argv, char **envp)
  */
 max_reserved_va = MAX_RESERVED_VA(cpu);
 if (reserved_va != 0) {
-int host_page_size = qemu_real_host_page_size();
-
 if ((reserved_va + 1) % host_page_size) {
 char *s = size_to_str(host_page_size);
 fprintf(stderr, "Reserved virtual address not aligned mod %s\n", 
s);
@@ -907,7 +917,7 @@ int main(int argc, char **argv, char **envp)
  * If we're in a chroot with no /proc, fall back to 1 page.
  */
 if (mmap_min_addr == 0) {
-mmap_min_addr = qemu_real_host_page_size();
+mmap_min_addr = host_page_size;
 qemu_log_mask(CPU_LOG_PAGE,
   "host mmap_min_addr=0x%lx (fallback)\n",
   mmap_min_addr);
-- 
2.34.1




[PATCH v2 15/33] linux-user: Remove qemu_host_page_size from main

2023-08-31 Thread Richard Henderson
Use qemu_real_host_page_size() instead.

Signed-off-by: Richard Henderson 
---
 linux-user/main.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 96be354897..c1058abc3c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -783,7 +783,7 @@ int main(int argc, char **argv, char **envp)
 }
 cpu_type = parse_cpu_option(cpu_model);
 
-/* init tcg before creating CPUs and to get qemu_host_page_size */
+/* init tcg before creating CPUs */
 {
 AccelState *accel = current_accel();
 AccelClass *ac = ACCEL_GET_CLASS(accel);
@@ -806,8 +806,10 @@ int main(int argc, char **argv, char **envp)
  */
 max_reserved_va = MAX_RESERVED_VA(cpu);
 if (reserved_va != 0) {
-if ((reserved_va + 1) % qemu_host_page_size) {
-char *s = size_to_str(qemu_host_page_size);
+int host_page_size = qemu_real_host_page_size();
+
+if ((reserved_va + 1) % host_page_size) {
+char *s = size_to_str(host_page_size);
 fprintf(stderr, "Reserved virtual address not aligned mod %s\n", 
s);
 g_free(s);
 exit(EXIT_FAILURE);
@@ -904,7 +906,7 @@ int main(int argc, char **argv, char **envp)
  * If we're in a chroot with no /proc, fall back to 1 page.
  */
 if (mmap_min_addr == 0) {
-mmap_min_addr = qemu_host_page_size;
+mmap_min_addr = qemu_real_host_page_size();
 qemu_log_mask(CPU_LOG_PAGE,
   "host mmap_min_addr=0x%lx (fallback)\n",
   mmap_min_addr);
-- 
2.34.1




[PATCH v2 27/33] cpu: Remove page_size_init

2023-08-31 Thread Richard Henderson
Move qemu_host_page_{size,mask} and HOST_PAGE_ALIGN into bsd-user.
It should be removed from bsd-user as well, but defer that cleanup.

Cc: Warner Losh 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 bsd-user/qemu.h   |  7 +++
 include/exec/cpu-common.h |  7 ---
 include/hw/core/cpu.h |  2 --
 accel/tcg/translate-all.c |  1 -
 bsd-user/main.c   | 12 
 cpu.c | 13 -
 softmmu/vl.c  |  1 -
 7 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index d3158bc2ed..c53f06d3f6 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -39,6 +39,13 @@ extern char **environ;
 #include "qemu/clang-tsa.h"
 
 #include "qemu-os.h"
+/*
+ * TODO: Remove these and rely only on qemu_real_host_page_size().
+ */
+extern uintptr_t qemu_host_page_size;
+extern intptr_t qemu_host_page_mask;
+#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
+
 /*
  * This struct is used to hold certain information about the image.  Basically,
  * it replicates in user space what would be certain task_struct fields in the
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 41788c0bdd..46b0abc918 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -22,13 +22,6 @@ typedef uint64_t vaddr;
 void cpu_exec_init_all(void);
 void cpu_exec_step_atomic(CPUState *cpu);
 
-/* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
- * when intptr_t is 32-bit and we are aligning a long long.
- */
-extern uintptr_t qemu_host_page_size;
-extern intptr_t qemu_host_page_mask;
-
-#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
 #define REAL_HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_real_host_page_size())
 
 /* The CPU list lock nests outside page_(un)lock or mmap_(un)lock */
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index fdcbe87352..66575eec73 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -1025,8 +1025,6 @@ bool target_words_bigendian(void);
 
 const char *target_name(void);
 
-void page_size_init(void);
-
 #ifdef NEED_CPU_H
 
 #ifndef CONFIG_USER_ONLY
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index b2d4e22c17..d84558dd95 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -255,7 +255,6 @@ bool cpu_unwind_state_data(CPUState *cpu, uintptr_t 
host_pc, uint64_t *data)
 
 void page_init(void)
 {
-page_size_init();
 page_table_config_init();
 }
 
diff --git a/bsd-user/main.c b/bsd-user/main.c
index f227d87834..ab389aa938 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -49,6 +49,13 @@
 #include "host-os.h"
 #include "target_arch_cpu.h"
 
+
+/*
+ * TODO: Remove these and rely only on qemu_real_host_page_size().
+ */
+uintptr_t qemu_host_page_size;
+intptr_t qemu_host_page_mask;
+
 static bool opt_one_insn_per_tb;
 uintptr_t guest_base;
 bool have_guest_base;
@@ -308,6 +315,9 @@ int main(int argc, char **argv)
 (void) envlist_setenv(envlist, *wrk);
 }
 
+qemu_host_page_size = getpagesize();
+qemu_host_page_size = MAX(qemu_host_page_size, TARGET_PAGE_SIZE);
+
 cpu_model = NULL;
 
 qemu_add_opts(_trace_opts);
@@ -408,6 +418,8 @@ int main(int argc, char **argv)
 }
 }
 
+qemu_host_page_mask = -qemu_host_page_size;
+
 /* init debug */
 {
 int mask = 0;
diff --git a/cpu.c b/cpu.c
index 1c948d1161..743c889ece 100644
--- a/cpu.c
+++ b/cpu.c
@@ -431,16 +431,3 @@ const char *target_name(void)
 {
 return TARGET_NAME;
 }
-
-void page_size_init(void)
-{
-/* NOTE: we can always suppose that qemu_host_page_size >=
-   TARGET_PAGE_SIZE */
-if (qemu_host_page_size == 0) {
-qemu_host_page_size = qemu_real_host_page_size();
-}
-if (qemu_host_page_size < TARGET_PAGE_SIZE) {
-qemu_host_page_size = TARGET_PAGE_SIZE;
-}
-qemu_host_page_mask = -(intptr_t)qemu_host_page_size;
-}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index b0b96f67fa..bc2aab9aaa 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2049,7 +2049,6 @@ static void qemu_create_machine(QDict *qdict)
 }
 
 cpu_exec_init_all();
-page_size_init();
 
 if (machine_class->hw_version) {
 qemu_set_hw_version(machine_class->hw_version);
-- 
2.34.1




[PATCH v2 25/33] tests/tcg: Extend file in linux-madvise.c

2023-08-31 Thread Richard Henderson
When guest page size > host page size, this test can fail
due to the SIGBUS protection hack.  Avoid this by making
sure that the file size is at least one guest page.

Visible with alpha guest on x86_64 host.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tests/tcg/multiarch/linux/linux-madvise.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tests/tcg/multiarch/linux/linux-madvise.c 
b/tests/tcg/multiarch/linux/linux-madvise.c
index 29d0997e68..539fb3b772 100644
--- a/tests/tcg/multiarch/linux/linux-madvise.c
+++ b/tests/tcg/multiarch/linux/linux-madvise.c
@@ -42,6 +42,8 @@ static void test_file(void)
 assert(ret == 0);
 written = write(fd, , sizeof(c));
 assert(written == sizeof(c));
+ret = ftruncate(fd, pagesize);
+assert(ret == 0);
 page = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE, fd, 0);
 assert(page != MAP_FAILED);
 
-- 
2.34.1




[PATCH v2 03/33] linux-user: Remove qemu_host_page_{size, mask} in probe_guest_base

2023-08-31 Thread Richard Henderson
The host SHMLBA is by definition a multiple of the host page size.
Thus the remaining component of qemu_host_page_size is the
target page size.

Signed-off-by: Richard Henderson 
---
 linux-user/elfload.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 803281a53a..7851003147 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2712,7 +2712,7 @@ static bool pgb_addr_set(PGBAddrs *ga, abi_ulong 
guest_loaddr,
 
 /* Add any HI_COMMPAGE not covered by reserved_va. */
 if (reserved_va < HI_COMMPAGE) {
-ga->bounds[n][0] = HI_COMMPAGE & qemu_host_page_mask;
+ga->bounds[n][0] = HI_COMMPAGE & -qemu_real_host_page_size();
 ga->bounds[n][1] = HI_COMMPAGE + TARGET_PAGE_SIZE - 1;
 n++;
 }
@@ -2894,7 +2894,7 @@ void probe_guest_base(const char *image_name, abi_ulong 
guest_loaddr,
   abi_ulong guest_hiaddr)
 {
 /* In order to use host shmat, we must be able to honor SHMLBA.  */
-uintptr_t align = MAX(SHMLBA, qemu_host_page_size);
+uintptr_t align = MAX(SHMLBA, TARGET_PAGE_SIZE);
 
 /* Sanity check the guest binary. */
 if (reserved_va) {
-- 
2.34.1




[PATCH v2 08/33] linux-user: Remove qemu_host_page_{size, mask} from mmap.c

2023-08-31 Thread Richard Henderson
Use qemu_real_host_page_size instead.

Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 66 +++
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 9aab48d4a3..fc23192a32 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -121,6 +121,7 @@ static int target_to_host_prot(int prot)
 /* NOTE: all the constants are the HOST ones, but addresses are target. */
 int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
 {
+int host_page_size = qemu_real_host_page_size();
 abi_ulong starts[3];
 abi_ulong lens[3];
 int prots[3];
@@ -145,13 +146,13 @@ int target_mprotect(abi_ulong start, abi_ulong len, int 
target_prot)
 }
 
 last = start + len - 1;
-host_start = start & qemu_host_page_mask;
+host_start = start & -host_page_size;
 host_last = HOST_PAGE_ALIGN(last) - 1;
 nranges = 0;
 
 mmap_lock();
 
-if (host_last - host_start < qemu_host_page_size) {
+if (host_last - host_start < host_page_size) {
 /* Single host page contains all guest pages: sum the prot. */
 prot1 = target_prot;
 for (abi_ulong a = host_start; a < start; a += TARGET_PAGE_SIZE) {
@@ -161,7 +162,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int 
target_prot)
 prot1 |= page_get_flags(a + 1);
 }
 starts[nranges] = host_start;
-lens[nranges] = qemu_host_page_size;
+lens[nranges] = host_page_size;
 prots[nranges] = prot1;
 nranges++;
 } else {
@@ -174,10 +175,10 @@ int target_mprotect(abi_ulong start, abi_ulong len, int 
target_prot)
 /* If the resulting sum differs, create a new range. */
 if (prot1 != target_prot) {
 starts[nranges] = host_start;
-lens[nranges] = qemu_host_page_size;
+lens[nranges] = host_page_size;
 prots[nranges] = prot1;
 nranges++;
-host_start += qemu_host_page_size;
+host_start += host_page_size;
 }
 }
 
@@ -189,9 +190,9 @@ int target_mprotect(abi_ulong start, abi_ulong len, int 
target_prot)
 }
 /* If the resulting sum differs, create a new range. */
 if (prot1 != target_prot) {
-host_last -= qemu_host_page_size;
+host_last -= host_page_size;
 starts[nranges] = host_last + 1;
-lens[nranges] = qemu_host_page_size;
+lens[nranges] = host_page_size;
 prots[nranges] = prot1;
 nranges++;
 }
@@ -226,6 +227,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int 
target_prot)
 static bool mmap_frag(abi_ulong real_start, abi_ulong start, abi_ulong last,
   int prot, int flags, int fd, off_t offset)
 {
+int host_page_size = qemu_real_host_page_size();
 abi_ulong real_last;
 void *host_start;
 int prot_old, prot_new;
@@ -242,7 +244,7 @@ static bool mmap_frag(abi_ulong real_start, abi_ulong 
start, abi_ulong last,
 return false;
 }
 
-real_last = real_start + qemu_host_page_size - 1;
+real_last = real_start + host_page_size - 1;
 host_start = g2h_untagged(real_start);
 
 /* Get the protection of the target pages outside the mapping. */
@@ -260,12 +262,12 @@ static bool mmap_frag(abi_ulong real_start, abi_ulong 
start, abi_ulong last,
  * outside of the fragment we need to map.  Allocate a new host
  * page to cover, discarding whatever else may have been present.
  */
-void *p = mmap(host_start, qemu_host_page_size,
+void *p = mmap(host_start, host_page_size,
target_to_host_prot(prot),
flags | MAP_ANONYMOUS, -1, 0);
 if (p != host_start) {
 if (p != MAP_FAILED) {
-munmap(p, qemu_host_page_size);
+munmap(p, host_page_size);
 errno = EEXIST;
 }
 return false;
@@ -280,7 +282,7 @@ static bool mmap_frag(abi_ulong real_start, abi_ulong 
start, abi_ulong last,
 /* Adjust protection to be able to write. */
 if (!(host_prot_old & PROT_WRITE)) {
 host_prot_old |= PROT_WRITE;
-mprotect(host_start, qemu_host_page_size, host_prot_old);
+mprotect(host_start, host_page_size, host_prot_old);
 }
 
 /* Read or zero the new guest pages. */
@@ -294,7 +296,7 @@ static bool mmap_frag(abi_ulong real_start, abi_ulong 
start, abi_ulong last,
 
 /* Put final protection */
 if (host_prot_new != host_prot_old) {
-mprotect(host_start, qemu_host_page_size, host_prot_new);
+mprotect(host_start, host_page_size, host_prot_new);
 }
 return true;
 }
@@ -329,17 +331,18 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, 
abi_ulong size,
  */
 abi_ulong 

[PATCH v2 33/33] target/alpha: Enable TARGET_PAGE_BITS_VARY for user-only

2023-08-31 Thread Richard Henderson
Since alpha binaries are generally built for multiple
page sizes, it is trivial to allow the page size to vary.

Signed-off-by: Richard Henderson 
---
 target/alpha/cpu-param.h | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/target/alpha/cpu-param.h b/target/alpha/cpu-param.h
index 68c46f7998..c969cb016b 100644
--- a/target/alpha/cpu-param.h
+++ b/target/alpha/cpu-param.h
@@ -9,10 +9,22 @@
 #define ALPHA_CPU_PARAM_H
 
 #define TARGET_LONG_BITS 64
-#define TARGET_PAGE_BITS 13
 
 /* ??? EV4 has 34 phys addr bits, EV5 has 40, EV6 has 44.  */
 #define TARGET_PHYS_ADDR_SPACE_BITS  44
-#define TARGET_VIRT_ADDR_SPACE_BITS  (30 + TARGET_PAGE_BITS)
+
+#ifdef CONFIG_USER_ONLY
+/*
+ * Allow user-only to vary page size.  Real hardware allows only 8k and 64k,
+ * but since any variance means guests cannot assume a fixed value, allow
+ * a 4k minimum to match x86 host, which can minimize emulation issues.
+ */
+# define TARGET_PAGE_BITS_VARY
+# define TARGET_PAGE_BITS_MIN 12
+# define TARGET_VIRT_ADDR_SPACE_BITS  63
+#else
+# define TARGET_PAGE_BITS 13
+# define TARGET_VIRT_ADDR_SPACE_BITS  (30 + TARGET_PAGE_BITS)
+#endif
 
 #endif
-- 
2.34.1




[PATCH v2 10/33] linux-user: Remove HOST_PAGE_ALIGN from mmap.c

2023-08-31 Thread Richard Henderson
This removes a hidden use of qemu_host_page_size, using instead
the existing host_page_size local within each function.

Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 48a6ef0af9..35f270ec2e 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -147,7 +147,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int 
target_prot)
 
 last = start + len - 1;
 host_start = start & -host_page_size;
-host_last = HOST_PAGE_ALIGN(last) - 1;
+host_last = ROUND_UP(last, host_page_size) - 1;
 nranges = 0;
 
 mmap_lock();
@@ -345,8 +345,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, 
abi_ulong align)
 start &= -host_page_size;
 }
 start = ROUND_UP(start, align);
-
-size = HOST_PAGE_ALIGN(size);
+size = ROUND_UP(size, host_page_size);
 
 if (reserved_va) {
 return mmap_find_vma_reserved(start, size, align);
@@ -506,7 +505,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
  */
 if (!(flags & (MAP_FIXED | MAP_FIXED_NOREPLACE))) {
 host_len = len + offset - host_offset;
-host_len = HOST_PAGE_ALIGN(host_len);
+host_len = ROUND_UP(host_len, host_page_size);
 start = mmap_find_vma(real_start, host_len, TARGET_PAGE_SIZE);
 if (start == (abi_ulong)-1) {
 errno = ENOMEM;
@@ -551,7 +550,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 void *p;
 
 host_len = len + offset - host_offset;
-host_len = HOST_PAGE_ALIGN(host_len);
+host_len = ROUND_UP(host_len, host_page_size);
 host_prot = target_to_host_prot(target_prot);
 
 /* Note: we prefer to control the mapping address. */
@@ -581,7 +580,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 goto fail;
 }
 last = start + len - 1;
-real_last = HOST_PAGE_ALIGN(last) - 1;
+real_last = ROUND_UP(last, host_page_size) - 1;
 
 /*
  * Test if requested memory area fits target address space
@@ -749,7 +748,7 @@ static void mmap_reserve_or_unmap(abi_ulong start, 
abi_ulong len)
 
 last = start + len - 1;
 real_start = start & -host_page_size;
-real_last = HOST_PAGE_ALIGN(last) - 1;
+real_last = ROUND_UP(last, host_page_size) - 1;
 
 /*
  * If guest pages remain on the first or last host pages,
-- 
2.34.1




[PATCH v2 19/33] linux-user: Split out mmap_end

2023-08-31 Thread Richard Henderson
Use a subroutine instead of a goto within target_mmap__locked.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 69 +++
 1 file changed, 40 insertions(+), 29 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index e905b1b8f2..caa76eb11a 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -446,6 +446,42 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, 
abi_ulong align)
 }
 }
 
+/*
+ * Record a successful mmap within the user-exec interval tree.
+ */
+static abi_long mmap_end(abi_ulong start, abi_ulong last,
+ abi_ulong passthrough_start,
+ abi_ulong passthrough_last,
+ int flags, int page_flags)
+{
+if (flags & MAP_ANONYMOUS) {
+page_flags |= PAGE_ANON;
+}
+page_flags |= PAGE_RESET;
+if (passthrough_start > passthrough_last) {
+page_set_flags(start, last, page_flags);
+} else {
+if (start < passthrough_start) {
+page_set_flags(start, passthrough_start - 1, page_flags);
+}
+page_set_flags(passthrough_start, passthrough_last,
+   page_flags | PAGE_PASSTHROUGH);
+if (passthrough_last < last) {
+page_set_flags(passthrough_last + 1, last, page_flags);
+}
+}
+trace_target_mmap_complete(start);
+if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
+FILE *f = qemu_log_trylock();
+if (f) {
+fprintf(f, "page layout changed following mmap\n");
+page_dump(f);
+qemu_log_unlock(f);
+}
+}
+return start;
+}
+
 static abi_long target_mmap__locked(abi_ulong start, abi_ulong len,
 int target_prot, int flags, int page_flags,
 int fd, off_t offset)
@@ -588,7 +624,7 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
 ret = target_mprotect(start, len, target_prot);
 assert(ret == 0);
 }
-goto the_end;
+return mmap_end(start, last, -1, 0, flags, page_flags);
 }
 
 /* handle the start of the mapping */
@@ -599,7 +635,7 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
target_prot, flags, fd, offset)) {
 return -1;
 }
-goto the_end;
+return mmap_end(start, last, -1, 0, flags, page_flags);
 }
 if (!mmap_frag(real_start, start,
real_start + host_page_size - 1,
@@ -646,33 +682,8 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
 passthrough_last = real_last;
 }
 }
- the_end:
-if (flags & MAP_ANONYMOUS) {
-page_flags |= PAGE_ANON;
-}
-page_flags |= PAGE_RESET;
-if (passthrough_start > passthrough_last) {
-page_set_flags(start, last, page_flags);
-} else {
-if (start < passthrough_start) {
-page_set_flags(start, passthrough_start - 1, page_flags);
-}
-page_set_flags(passthrough_start, passthrough_last,
-   page_flags | PAGE_PASSTHROUGH);
-if (passthrough_last < last) {
-page_set_flags(passthrough_last + 1, last, page_flags);
-}
-}
-trace_target_mmap_complete(start);
-if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
-FILE *f = qemu_log_trylock();
-if (f) {
-fprintf(f, "page layout changed following mmap\n");
-page_dump(f);
-qemu_log_unlock(f);
-}
-}
-return start;
+return mmap_end(start, last, passthrough_start, passthrough_last,
+flags, page_flags);
 }
 
 /* NOTE: all the constants are the HOST ones */
-- 
2.34.1




[PATCH v2 18/33] linux-user: Fix sub-host-page mmap

2023-08-31 Thread Richard Henderson
We cannot skip over the_end1 to the_end, because we fail to
record the validity of the guest page with the interval tree.
Remove "the_end" and rename "the_end1" to "the_end".

Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 85d16a29c1..e905b1b8f2 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -599,7 +599,7 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
target_prot, flags, fd, offset)) {
 return -1;
 }
-goto the_end1;
+goto the_end;
 }
 if (!mmap_frag(real_start, start,
real_start + host_page_size - 1,
@@ -646,7 +646,7 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
 passthrough_last = real_last;
 }
 }
- the_end1:
+ the_end:
 if (flags & MAP_ANONYMOUS) {
 page_flags |= PAGE_ANON;
 }
@@ -663,7 +663,6 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
 page_set_flags(passthrough_last + 1, last, page_flags);
 }
 }
- the_end:
 trace_target_mmap_complete(start);
 if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
 FILE *f = qemu_log_trylock();
-- 
2.34.1




[PATCH v2 23/33] linux-user: Split out mmap_h_gt_g

2023-08-31 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 288 ++
 1 file changed, 139 insertions(+), 149 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index ed82b4bb75..6ab2f35e6f 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -223,7 +223,16 @@ int target_mprotect(abi_ulong start, abi_ulong len, int 
target_prot)
 return ret;
 }
 
-/* map an incomplete host page */
+/*
+ * Map an incomplete host page.
+ *
+ * Here be dragons.  This case will not work if there is an existing
+ * overlapping host page, which is file mapped, and for which the mapping
+ * is beyond the end of the file.  In that case, we will see SIGBUS when
+ * trying to write a portion of this page.
+ *
+ * FIXME: Work around this with a temporary signal handler and longjmp.
+ */
 static bool mmap_frag(abi_ulong real_start, abi_ulong start, abi_ulong last,
   int prot, int flags, int fd, off_t offset)
 {
@@ -629,19 +638,138 @@ static abi_long mmap_h_lt_g(abi_ulong start, abi_ulong 
len, int host_prot,
 return mmap_end(start, last, start, pass_last, mmap_flags, page_flags);
 }
 
+/*
+ * Special case host page size > target page size.
+ *
+ * The two special cases are address and file offsets that are valid
+ * for the guest that cannot be directly represented by the host.
+ */
+static abi_long mmap_h_gt_g(abi_ulong start, abi_ulong len,
+int target_prot, int host_prot,
+int flags, int page_flags, int fd,
+off_t offset, int host_page_size)
+{
+void *p, *want_p = g2h_untagged(start);
+off_t host_offset = offset & -host_page_size;
+abi_ulong last, real_start, real_last;
+bool misaligned_offset = false;
+size_t host_len;
+
+if (!(flags & (MAP_FIXED | MAP_FIXED_NOREPLACE))) {
+/*
+ * Adjust the offset to something representable on the host.
+ */
+host_len = len + offset - host_offset;
+p = mmap(want_p, host_len, host_prot, flags, fd, host_offset);
+if (p == MAP_FAILED) {
+return -1;
+}
+
+/* Update start to the file position at offset. */
+p += offset - host_offset;
+
+start = h2g(p);
+last = start + len - 1;
+return mmap_end(start, last, start, last, flags, page_flags);
+}
+
+if (!(flags & MAP_ANONYMOUS)) {
+misaligned_offset = (start ^ offset) & (host_page_size - 1);
+
+/*
+ * The fallback for misalignment is a private mapping + read.
+ * This carries none of semantics required of MAP_SHARED.
+ */
+if (misaligned_offset && (flags & MAP_TYPE) != MAP_PRIVATE) {
+errno = EINVAL;
+return -1;
+}
+}
+
+last = start + len - 1;
+real_start = start & -host_page_size;
+real_last = ROUND_UP(last, host_page_size) - 1;
+
+/*
+ * Handle the start and end of the mapping.
+ */
+if (real_start < start) {
+abi_ulong real_page_last = real_start + host_page_size - 1;
+if (last <= real_page_last) {
+/* Entire allocation a subset of one host page. */
+if (!mmap_frag(real_start, start, last, target_prot,
+   flags, fd, offset)) {
+return -1;
+}
+return mmap_end(start, last, -1, 0, flags, page_flags);
+}
+
+if (!mmap_frag(real_start, start, real_page_last, target_prot,
+   flags, fd, offset)) {
+return -1;
+}
+real_start = real_page_last + 1;
+}
+
+if (last < real_last) {
+abi_ulong real_page_start = real_last - host_page_size + 1;
+if (!mmap_frag(real_page_start, real_page_start, last,
+   target_prot, flags, fd,
+   offset + real_page_start - start)) {
+return -1;
+}
+real_last = real_page_start - 1;
+}
+
+if (real_start > real_last) {
+return mmap_end(start, last, -1, 0, flags, page_flags);
+}
+
+/*
+ * Handle the middle of the mapping.
+ */
+
+host_len = real_last - real_start + 1;
+want_p += real_start - start;
+
+if (flags & MAP_ANONYMOUS) {
+p = mmap(want_p, host_len, host_prot, flags, -1, 0);
+} else if (!misaligned_offset) {
+p = mmap(want_p, host_len, host_prot, flags, fd,
+ offset + real_start - start);
+} else {
+p = mmap(want_p, host_len, host_prot | PROT_WRITE,
+ flags | MAP_ANONYMOUS, -1, 0);
+}
+if (p != want_p) {
+if (p != MAP_FAILED) {
+munmap(p, host_len);
+errno = EEXIST;
+}
+return -1;
+}
+
+if (misaligned_offset) {
+/* TODO: The read could be short. */
+if (pread(fd, p, host_len, offset + real_start - start) != host_len) {
+munmap(p, host_len);
+return 

[PATCH v2 20/33] linux-user: Do early mmap placement only for reserved_va

2023-08-31 Thread Richard Henderson
For reserved_va, place all non-fixed maps then proceed
as for MAP_FIXED.

Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index caa76eb11a..7d482df06d 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -495,17 +495,19 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
 host_offset = offset & -host_page_size;
 
 /*
- * If the user is asking for the kernel to find a location, do that
- * before we truncate the length for mapping files below.
+ * For reserved_va, we are in full control of the allocation.
+ * Find a suitible hole and convert to MAP_FIXED.
  */
-if (!(flags & (MAP_FIXED | MAP_FIXED_NOREPLACE))) {
+if (reserved_va && !(flags & (MAP_FIXED | MAP_FIXED_NOREPLACE))) {
 host_len = len + offset - host_offset;
-host_len = ROUND_UP(host_len, host_page_size);
-start = mmap_find_vma(real_start, host_len, TARGET_PAGE_SIZE);
+start = mmap_find_vma(real_start, host_len,
+  MAX(host_page_size, TARGET_PAGE_SIZE));
 if (start == (abi_ulong)-1) {
 errno = ENOMEM;
 return -1;
 }
+start += offset - host_offset;
+flags |= MAP_FIXED;
 }
 
 /*
-- 
2.34.1




[PATCH v2 04/33] linux-user: Remove qemu_host_page_size from create_elf_tables

2023-08-31 Thread Richard Henderson
AT_PAGESZ is supposed to advertise the guest page size.
The random adjustment made here using qemu_host_page_size
does not match anything else within linux-user.

The idea here is good, but should be done more systemically
via adjustment to TARGET_PAGE_SIZE.

Signed-off-by: Richard Henderson 
---
 linux-user/elfload.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 7851003147..885566c798 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2498,13 +2498,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int 
argc, int envc,
 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
-if ((info->alignment & ~qemu_host_page_mask) != 0) {
-/* Target doesn't support host page size alignment */
-NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-} else {
-NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE,
-   qemu_host_page_size)));
-}
+NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 
0));
 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
 NEW_AUX_ENT(AT_ENTRY, info->entry);
-- 
2.34.1




[PATCH v2 12/33] hw/tpm: Remove HOST_PAGE_ALIGN from tpm_ppi_init

2023-08-31 Thread Richard Henderson
The size of the allocation need not match the alignment.

Signed-off-by: Richard Henderson 
---
 hw/tpm/tpm_ppi.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 7f74e26ec6..91eeafd53a 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -47,8 +47,7 @@ void tpm_ppi_reset(TPMPPI *tpmppi)
 void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
   hwaddr addr, Object *obj)
 {
-tpmppi->buf = qemu_memalign(qemu_real_host_page_size(),
-HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE));
+tpmppi->buf = qemu_memalign(qemu_real_host_page_size(), TPM_PPI_ADDR_SIZE);
 memory_region_init_ram_device_ptr(>ram, obj, "tpm-ppi",
   TPM_PPI_ADDR_SIZE, tpmppi->buf);
 vmstate_register_ram(>ram, DEVICE(obj));
-- 
2.34.1




[PATCH v2 06/33] linux-user/nios2: Remove qemu_host_page_size from init_guest_commpage

2023-08-31 Thread Richard Henderson
Use qemu_real_host_page_size.
If !reserved_va, use MAP_FIXED_NOREPLACE.

Signed-off-by: Richard Henderson 
---
 linux-user/elfload.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 939c9b4df1..025747a15c 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1355,10 +1355,14 @@ static bool init_guest_commpage(void)
  0x3a, 0x68, 0x3b, 0x00,  /* trap 0 */
 };
 
-void *want = g2h_untagged(LO_COMMPAGE & -qemu_host_page_size);
-void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
-  MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
+int host_page_size = qemu_real_host_page_size();
+void *want, *addr;
 
+want = g2h_untagged(LO_COMMPAGE & -host_page_size);
+addr = mmap(want, host_page_size, PROT_READ | PROT_WRITE,
+MAP_ANONYMOUS | MAP_PRIVATE |
+(reserved_va ? MAP_FIXED : MAP_FIXED_NOREPLACE),
+-1, 0);
 if (addr == MAP_FAILED) {
 perror("Allocating guest commpage");
 exit(EXIT_FAILURE);
@@ -1367,9 +1371,9 @@ static bool init_guest_commpage(void)
 return false;
 }
 
-memcpy(addr, kuser_page, sizeof(kuser_page));
+memcpy(g2h_untagged(LO_COMMPAGE), kuser_page, sizeof(kuser_page));
 
-if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
+if (mprotect(addr, host_page_size, PROT_READ)) {
 perror("Protecting guest commpage");
 exit(EXIT_FAILURE);
 }
-- 
2.34.1




[PATCH v2 30/33] target/arm: Enable TARGET_PAGE_BITS_VARY for AArch64 user-only

2023-08-31 Thread Richard Henderson
Since aarch64 binaries are generally built for multiple
page sizes, it is trivial to allow the page size to vary.

Signed-off-by: Richard Henderson 
---
 target/arm/cpu-param.h |  6 -
 target/arm/cpu.c   | 51 --
 2 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
index b3b35f7aa1..7585a810b2 100644
--- a/target/arm/cpu-param.h
+++ b/target/arm/cpu-param.h
@@ -19,9 +19,13 @@
 #endif
 
 #ifdef CONFIG_USER_ONLY
-#define TARGET_PAGE_BITS 12
 # ifdef TARGET_AARCH64
 #  define TARGET_TAGGED_ADDRESSES
+/* Allow user-only to vary page size from 4k */
+#  define TARGET_PAGE_BITS_VARY
+#  define TARGET_PAGE_BITS_MIN  12
+# else
+#  define TARGET_PAGE_BITS 12
 # endif
 #else
 /*
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 0bb0585441..de2a90e23d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1677,7 +1677,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 ARMCPU *cpu = ARM_CPU(dev);
 ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev);
 CPUARMState *env = >env;
-int pagebits;
 Error *local_err = NULL;
 
 /* Use pc-relative instructions in system-mode */
@@ -1968,28 +1967,36 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
!cpu_isar_feature(aa32_vfp_simd, cpu) ||
!arm_feature(env, ARM_FEATURE_XSCALE));
 
-if (arm_feature(env, ARM_FEATURE_V7) &&
-!arm_feature(env, ARM_FEATURE_M) &&
-!arm_feature(env, ARM_FEATURE_PMSA)) {
-/* v7VMSA drops support for the old ARMv5 tiny pages, so we
- * can use 4K pages.
- */
-pagebits = 12;
-} else {
-/* For CPUs which might have tiny 1K pages, or which have an
- * MPU and might have small region sizes, stick with 1K pages.
- */
-pagebits = 10;
-}
-if (!set_preferred_target_page_bits(pagebits)) {
-/* This can only ever happen for hotplugging a CPU, or if
- * the board code incorrectly creates a CPU which it has
- * promised via minimum_page_size that it will not.
- */
-error_setg(errp, "This CPU requires a smaller page size than the "
-   "system is using");
-return;
+#ifndef CONFIG_USER_ONLY
+{
+int pagebits;
+if (arm_feature(env, ARM_FEATURE_V7) &&
+!arm_feature(env, ARM_FEATURE_M) &&
+!arm_feature(env, ARM_FEATURE_PMSA)) {
+/*
+ * v7VMSA drops support for the old ARMv5 tiny pages,
+ * so we can use 4K pages.
+ */
+pagebits = 12;
+} else {
+/*
+ * For CPUs which might have tiny 1K pages, or which have an
+ * MPU and might have small region sizes, stick with 1K pages.
+ */
+pagebits = 10;
+}
+if (!set_preferred_target_page_bits(pagebits)) {
+/*
+ * This can only ever happen for hotplugging a CPU, or if
+ * the board code incorrectly creates a CPU which it has
+ * promised via minimum_page_size that it will not.
+ */
+error_setg(errp, "This CPU requires a smaller page size "
+   "than the system is using");
+return;
+}
 }
+#endif
 
 /* This cpu-id-to-MPIDR affinity is used only for TCG; KVM will override 
it.
  * We don't support setting cluster ID ([16..23]) (known as Aff2
-- 
2.34.1




[PATCH v2 17/33] linux-user: Move some mmap checks outside the lock

2023-08-31 Thread Richard Henderson
Basic validation of operands does not require the lock.
Hoist them from target_mmap__locked back into target_mmap.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 107 +++---
 1 file changed, 53 insertions(+), 54 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 448f168df1..85d16a29c1 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -447,52 +447,14 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, 
abi_ulong align)
 }
 
 static abi_long target_mmap__locked(abi_ulong start, abi_ulong len,
-int target_prot, int flags,
+int target_prot, int flags, int page_flags,
 int fd, off_t offset)
 {
 int host_page_size = qemu_real_host_page_size();
 abi_ulong ret, last, real_start, real_last, retaddr, host_len;
 abi_ulong passthrough_start = -1, passthrough_last = 0;
-int page_flags;
 off_t host_offset;
 
-if (!len) {
-errno = EINVAL;
-return -1;
-}
-
-page_flags = validate_prot_to_pageflags(target_prot);
-if (!page_flags) {
-errno = EINVAL;
-return -1;
-}
-
-/* Also check for overflows... */
-len = TARGET_PAGE_ALIGN(len);
-if (!len) {
-errno = ENOMEM;
-return -1;
-}
-
-if (offset & ~TARGET_PAGE_MASK) {
-errno = EINVAL;
-return -1;
-}
-
-/*
- * If we're mapping shared memory, ensure we generate code for parallel
- * execution and flush old translations.  This will work up to the level
- * supported by the host -- anything that requires EXCP_ATOMIC will not
- * be atomic with respect to an external process.
- */
-if (flags & MAP_SHARED) {
-CPUState *cpu = thread_cpu;
-if (!(cpu->tcg_cflags & CF_PARALLEL)) {
-cpu->tcg_cflags |= CF_PARALLEL;
-tb_flush(cpu);
-}
-}
-
 real_start = start & -host_page_size;
 host_offset = offset & -host_page_size;
 
@@ -572,23 +534,9 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
 passthrough_start = start;
 passthrough_last = last;
 } else {
-if (start & ~TARGET_PAGE_MASK) {
-errno = EINVAL;
-return -1;
-}
 last = start + len - 1;
 real_last = ROUND_UP(last, host_page_size) - 1;
 
-/*
- * Test if requested memory area fits target address space
- * It can fail only on 64-bit host with 32-bit target.
- * On any other target/host host mmap() handles this error correctly.
- */
-if (last < start || !guest_range_valid_untagged(start, len)) {
-errno = ENOMEM;
-return -1;
-}
-
 if (flags & MAP_FIXED_NOREPLACE) {
 /* Validate that the chosen range is empty. */
 if (!page_check_range_empty(start, last)) {
@@ -733,13 +681,64 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
  int flags, int fd, off_t offset)
 {
 abi_long ret;
+int page_flags;
 
 trace_target_mmap(start, len, target_prot, flags, fd, offset);
+
+if (!len) {
+errno = EINVAL;
+return -1;
+}
+
+page_flags = validate_prot_to_pageflags(target_prot);
+if (!page_flags) {
+errno = EINVAL;
+return -1;
+}
+
+/* Also check for overflows... */
+len = TARGET_PAGE_ALIGN(len);
+if (!len || len != (size_t)len) {
+errno = ENOMEM;
+return -1;
+}
+
+if (offset & ~TARGET_PAGE_MASK) {
+errno = EINVAL;
+return -1;
+}
+if (flags & (MAP_FIXED | MAP_FIXED_NOREPLACE)) {
+if (start & ~TARGET_PAGE_MASK) {
+errno = EINVAL;
+return -1;
+}
+if (!guest_range_valid_untagged(start, len)) {
+errno = ENOMEM;
+return -1;
+}
+}
+
 mmap_lock();
 
-ret = target_mmap__locked(start, len, target_prot, flags, fd, offset);
+ret = target_mmap__locked(start, len, target_prot, flags,
+  page_flags, fd, offset);
 
 mmap_unlock();
+
+/*
+ * If we're mapping shared memory, ensure we generate code for parallel
+ * execution and flush old translations.  This will work up to the level
+ * supported by the host -- anything that requires EXCP_ATOMIC will not
+ * be atomic with respect to an external process.
+ */
+if (ret != -1 && (flags & MAP_TYPE) != MAP_PRIVATE) {
+CPUState *cpu = thread_cpu;
+if (!(cpu->tcg_cflags & CF_PARALLEL)) {
+cpu->tcg_cflags |= CF_PARALLEL;
+tb_flush(cpu);
+}
+}
+
 return ret;
 }
 
-- 
2.34.1




[PATCH v2 24/33] tests/tcg: Remove run-test-mmap-*

2023-08-31 Thread Richard Henderson
These tests are confused, because -p does not change
the guest page size, but the host page size.

Signed-off-by: Richard Henderson 
---
 tests/tcg/alpha/Makefile.target |  3 ---
 tests/tcg/arm/Makefile.target   |  3 ---
 tests/tcg/hppa/Makefile.target  |  3 ---
 tests/tcg/i386/Makefile.target  |  3 ---
 tests/tcg/m68k/Makefile.target  |  3 ---
 tests/tcg/multiarch/Makefile.target |  9 -
 tests/tcg/ppc/Makefile.target   | 12 
 tests/tcg/sh4/Makefile.target   |  3 ---
 tests/tcg/sparc64/Makefile.target   |  6 --
 9 files changed, 45 deletions(-)
 delete mode 100644 tests/tcg/ppc/Makefile.target
 delete mode 100644 tests/tcg/sparc64/Makefile.target

diff --git a/tests/tcg/alpha/Makefile.target b/tests/tcg/alpha/Makefile.target
index b94500a7d9..fdd7ddf64e 100644
--- a/tests/tcg/alpha/Makefile.target
+++ b/tests/tcg/alpha/Makefile.target
@@ -13,6 +13,3 @@ test-cmov: test-cond.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
 
 run-test-cmov: test-cmov
-
-# On Alpha Linux only supports 8k pages
-EXTRA_RUNS+=run-test-mmap-8192
diff --git a/tests/tcg/arm/Makefile.target b/tests/tcg/arm/Makefile.target
index 0038cef02c..4b8c9c334e 100644
--- a/tests/tcg/arm/Makefile.target
+++ b/tests/tcg/arm/Makefile.target
@@ -79,6 +79,3 @@ sha512-vector: sha512.c
 ARM_TESTS += sha512-vector
 
 TESTS += $(ARM_TESTS)
-
-# On ARM Linux only supports 4k pages
-EXTRA_RUNS+=run-test-mmap-4096
diff --git a/tests/tcg/hppa/Makefile.target b/tests/tcg/hppa/Makefile.target
index cdd0d572a7..ea5ae2186d 100644
--- a/tests/tcg/hppa/Makefile.target
+++ b/tests/tcg/hppa/Makefile.target
@@ -2,9 +2,6 @@
 #
 # HPPA specific tweaks - specifically masking out broken tests
 
-# On parisc Linux supports 4K/16K/64K (but currently only 4k works)
-EXTRA_RUNS+=run-test-mmap-4096 # run-test-mmap-16384 run-test-mmap-65536
-
 # This triggers failures for hppa-linux about 1% of the time
 # HPPA is the odd target that can't use the sigtramp page;
 # it requires the full vdso with dwarf2 unwind info.
diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target
index fdf757c6ce..f64d7bfbf5 100644
--- a/tests/tcg/i386/Makefile.target
+++ b/tests/tcg/i386/Makefile.target
@@ -71,9 +71,6 @@ endif
 I386_TESTS:=$(filter-out $(SKIP_I386_TESTS), $(ALL_X86_TESTS))
 TESTS=$(MULTIARCH_TESTS) $(I386_TESTS)
 
-# On i386 and x86_64 Linux only supports 4k pages (large pages are a different 
hack)
-EXTRA_RUNS+=run-test-mmap-4096
-
 sha512-sse: CFLAGS=-msse4.1 -O3
 sha512-sse: sha512.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
diff --git a/tests/tcg/m68k/Makefile.target b/tests/tcg/m68k/Makefile.target
index 1163c7ef03..73a16aedd2 100644
--- a/tests/tcg/m68k/Makefile.target
+++ b/tests/tcg/m68k/Makefile.target
@@ -5,6 +5,3 @@
 
 VPATH += $(SRC_PATH)/tests/tcg/m68k
 TESTS += trap
-
-# On m68k Linux supports 4k and 8k pages (but 8k is currently broken)
-EXTRA_RUNS+=run-test-mmap-4096 # run-test-mmap-8192
diff --git a/tests/tcg/multiarch/Makefile.target 
b/tests/tcg/multiarch/Makefile.target
index 43bddeaf21..fa1ac190f2 100644
--- a/tests/tcg/multiarch/Makefile.target
+++ b/tests/tcg/multiarch/Makefile.target
@@ -51,18 +51,9 @@ run-plugin-vma-pthread-with-%: vma-pthread
$(call skip-test, $<, "flaky on CI?")
 endif
 
-# We define the runner for test-mmap after the individual
-# architectures have defined their supported pages sizes. If no
-# additional page sizes are defined we only run the default test.
-
-# default case (host page size)
 run-test-mmap: test-mmap
$(call run-test, test-mmap, $(QEMU) $<, $< (default))
 
-# additional page sizes (defined by each architecture adding to EXTRA_RUNS)
-run-test-mmap-%: test-mmap
-   $(call run-test, test-mmap-$*, $(QEMU) -p $* $<, $< ($* byte pages))
-
 ifneq ($(HAVE_GDB_BIN),)
 ifeq ($(HOST_GDB_SUPPORTS_ARCH),y)
 GDB_SCRIPT=$(SRC_PATH)/tests/guest-debug/run-test.py
diff --git a/tests/tcg/ppc/Makefile.target b/tests/tcg/ppc/Makefile.target
deleted file mode 100644
index f5e08c7376..00
--- a/tests/tcg/ppc/Makefile.target
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- Mode: makefile -*-
-#
-# PPC - included from tests/tcg/Makefile
-#
-
-ifneq (,$(findstring 64,$(TARGET_NAME)))
-# On PPC64 Linux can be configured with 4k (default) or 64k pages (currently 
broken)
-EXTRA_RUNS+=run-test-mmap-4096 #run-test-mmap-65536
-else
-# On PPC32 Linux supports 4K/16K/64K/256K (but currently only 4k works)
-EXTRA_RUNS+=run-test-mmap-4096 #run-test-mmap-16384 run-test-mmap-65536 
run-test-mmap-262144
-endif
diff --git a/tests/tcg/sh4/Makefile.target b/tests/tcg/sh4/Makefile.target
index 47c39a44b6..16eaa850a8 100644
--- a/tests/tcg/sh4/Makefile.target
+++ b/tests/tcg/sh4/Makefile.target
@@ -3,9 +3,6 @@
 # SuperH specific tweaks
 #
 
-# On sh Linux supports 4k, 8k, 16k and 64k pages (but only 4k currently works)
-EXTRA_RUNS+=run-test-mmap-4096 # run-test-mmap-8192 run-test-mmap-16384 
run-test-mmap-65536
-
 # This triggers failures for 

[PATCH v2 28/33] accel/tcg: Disconnect TargetPageDataNode from page size

2023-08-31 Thread Richard Henderson
Dynamically size the node for the runtime target page size.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 accel/tcg/user-exec.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 4c1697500a..09dc85c851 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -863,7 +863,7 @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, 
vaddr addr,
 typedef struct TargetPageDataNode {
 struct rcu_head rcu;
 IntervalTreeNode itree;
-char data[TPD_PAGES][TARGET_PAGE_DATA_SIZE] __attribute__((aligned));
+char data[] __attribute__((aligned));
 } TargetPageDataNode;
 
 static IntervalTreeRoot targetdata_root;
@@ -901,7 +901,8 @@ void page_reset_target_data(target_ulong start, 
target_ulong last)
 n_last = MIN(last, n->last);
 p_len = (n_last + 1 - n_start) >> TARGET_PAGE_BITS;
 
-memset(t->data[p_ofs], 0, p_len * TARGET_PAGE_DATA_SIZE);
+memset(t->data + p_ofs * TARGET_PAGE_DATA_SIZE, 0,
+   p_len * TARGET_PAGE_DATA_SIZE);
 }
 }
 
@@ -909,7 +910,7 @@ void *page_get_target_data(target_ulong address)
 {
 IntervalTreeNode *n;
 TargetPageDataNode *t;
-target_ulong page, region;
+target_ulong page, region, p_ofs;
 
 page = address & TARGET_PAGE_MASK;
 region = address & TBD_MASK;
@@ -925,7 +926,8 @@ void *page_get_target_data(target_ulong address)
 mmap_lock();
 n = interval_tree_iter_first(_root, page, page);
 if (!n) {
-t = g_new0(TargetPageDataNode, 1);
+t = g_malloc0(sizeof(TargetPageDataNode)
+  + TPD_PAGES * TARGET_PAGE_DATA_SIZE);
 n = >itree;
 n->start = region;
 n->last = region | ~TBD_MASK;
@@ -935,7 +937,8 @@ void *page_get_target_data(target_ulong address)
 }
 
 t = container_of(n, TargetPageDataNode, itree);
-return t->data[(page - region) >> TARGET_PAGE_BITS];
+p_ofs = (page - region) >> TARGET_PAGE_BITS;
+return t->data + p_ofs * TARGET_PAGE_DATA_SIZE;
 }
 #else
 void page_reset_target_data(target_ulong start, target_ulong last) { }
-- 
2.34.1




[PATCH v2 16/33] linux-user: Split out target_mmap__locked

2023-08-31 Thread Richard Henderson
All "goto fail" may be transformed to "return -1".

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 62 ++-
 1 file changed, 35 insertions(+), 27 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 35f270ec2e..448f168df1 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -446,9 +446,9 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, 
abi_ulong align)
 }
 }
 
-/* NOTE: all the constants are the HOST ones */
-abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
- int flags, int fd, off_t offset)
+static abi_long target_mmap__locked(abi_ulong start, abi_ulong len,
+int target_prot, int flags,
+int fd, off_t offset)
 {
 int host_page_size = qemu_real_host_page_size();
 abi_ulong ret, last, real_start, real_last, retaddr, host_len;
@@ -456,30 +456,27 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 int page_flags;
 off_t host_offset;
 
-mmap_lock();
-trace_target_mmap(start, len, target_prot, flags, fd, offset);
-
 if (!len) {
 errno = EINVAL;
-goto fail;
+return -1;
 }
 
 page_flags = validate_prot_to_pageflags(target_prot);
 if (!page_flags) {
 errno = EINVAL;
-goto fail;
+return -1;
 }
 
 /* Also check for overflows... */
 len = TARGET_PAGE_ALIGN(len);
 if (!len) {
 errno = ENOMEM;
-goto fail;
+return -1;
 }
 
 if (offset & ~TARGET_PAGE_MASK) {
 errno = EINVAL;
-goto fail;
+return -1;
 }
 
 /*
@@ -509,7 +506,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 start = mmap_find_vma(real_start, host_len, TARGET_PAGE_SIZE);
 if (start == (abi_ulong)-1) {
 errno = ENOMEM;
-goto fail;
+return -1;
 }
 }
 
@@ -530,7 +527,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 struct stat sb;
 
 if (fstat(fd, ) == -1) {
-goto fail;
+return -1;
 }
 
 /* Are we trying to create a map beyond EOF?.  */
@@ -557,7 +554,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 p = mmap(g2h_untagged(start), host_len, host_prot,
  flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
 if (p == MAP_FAILED) {
-goto fail;
+return -1;
 }
 /* update start so that it points to the file position at 'offset' */
 host_start = (uintptr_t)p;
@@ -566,7 +563,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
  flags | MAP_FIXED, fd, host_offset);
 if (p == MAP_FAILED) {
 munmap(g2h_untagged(start), host_len);
-goto fail;
+return -1;
 }
 host_start += offset - host_offset;
 }
@@ -577,7 +574,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 } else {
 if (start & ~TARGET_PAGE_MASK) {
 errno = EINVAL;
-goto fail;
+return -1;
 }
 last = start + len - 1;
 real_last = ROUND_UP(last, host_page_size) - 1;
@@ -589,14 +586,14 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
  */
 if (last < start || !guest_range_valid_untagged(start, len)) {
 errno = ENOMEM;
-goto fail;
+return -1;
 }
 
 if (flags & MAP_FIXED_NOREPLACE) {
 /* Validate that the chosen range is empty. */
 if (!page_check_range_empty(start, last)) {
 errno = EEXIST;
-goto fail;
+return -1;
 }
 
 /*
@@ -627,17 +624,17 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
 if ((flags & MAP_TYPE) == MAP_SHARED
 && (target_prot & PROT_WRITE)) {
 errno = EINVAL;
-goto fail;
+return -1;
 }
 retaddr = target_mmap(start, len, target_prot | PROT_WRITE,
   (flags & (MAP_FIXED | MAP_FIXED_NOREPLACE))
   | MAP_PRIVATE | MAP_ANONYMOUS,
   -1, 0);
 if (retaddr == -1) {
-goto fail;
+return -1;
 }
 if (pread(fd, g2h_untagged(start), len, offset) == -1) {
-goto fail;
+return -1;
 }
 if (!(target_prot & PROT_WRITE)) {
 ret = target_mprotect(start, len, target_prot);
@@ -652,14 +649,14 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
target_prot,
   

[PATCH v2 05/33] linux-user/hppa: Simplify init_guest_commpage

2023-08-31 Thread Richard Henderson
If reserved_va, then we have already reserved the entire
guest virtual address space; no need to remap page.
If !reserved_va, then use MAP_FIXED_NOREPLACE.

Signed-off-by: Richard Henderson 
---
 linux-user/elfload.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 885566c798..939c9b4df1 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1812,16 +1812,21 @@ static inline void init_thread(struct target_pt_regs 
*regs,
 
 static bool init_guest_commpage(void)
 {
-void *want = g2h_untagged(LO_COMMPAGE);
-void *addr = mmap(want, qemu_host_page_size, PROT_NONE,
-  MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
+/* If reserved_va, then we have already mapped 0 page on the host. */
+if (!reserved_va) {
+int host_page_size = qemu_real_host_page_size();
+void *want, *addr;
 
-if (addr == MAP_FAILED) {
-perror("Allocating guest commpage");
-exit(EXIT_FAILURE);
-}
-if (addr != want) {
-return false;
+want = g2h_untagged(LO_COMMPAGE);
+addr = mmap(want, host_page_size, PROT_NONE,
+MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
+if (addr == MAP_FAILED) {
+perror("Allocating guest commpage");
+exit(EXIT_FAILURE);
+}
+if (addr != want) {
+return false;
+}
 }
 
 /*
-- 
2.34.1




[PATCH v2 22/33] linux-user: Split out mmap_h_lt_g

2023-08-31 Thread Richard Henderson
Work much harder to get alignment and mapping beyond the end
of the file correct.  Both of which are excercised by our
test-mmap for alpha (8k pages) on any 4k page host.

Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 156 +-
 1 file changed, 125 insertions(+), 31 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 7a0c0c1f35..ed82b4bb75 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -507,6 +507,128 @@ static abi_long mmap_h_eq_g(abi_ulong start, abi_ulong 
len,
 return mmap_end(start, last, start, last, flags, page_flags);
 }
 
+/*
+ * Special case host page size < target page size.
+ *
+ * The two special cases are increased guest alignment, and mapping
+ * past the end of a file.
+ *
+ * When mapping files into a memory area larger than the file,
+ * accesses to pages beyond the file size will cause a SIGBUS.
+ *
+ * For example, if mmaping a file of 100 bytes on a host with 4K
+ * pages emulating a target with 8K pages, the target expects to
+ * be able to access the first 8K. But the host will trap us on
+ * any access beyond 4K.
+ *
+ * When emulating a target with a larger page-size than the hosts,
+ * we may need to truncate file maps at EOF and add extra anonymous
+ * pages up to the targets page boundary.
+ *
+ * This workaround only works for files that do not change.
+ * If the file is later extended (e.g. ftruncate), the SIGBUS
+ * vanishes and the proper behaviour is that changes within the
+ * anon page should be reflected in the file.
+ *
+ * However, this case is rather common with executable images,
+ * so the workaround is important for even trivial tests, whereas
+ * the mmap of of a file being extended is less common.
+ */
+static abi_long mmap_h_lt_g(abi_ulong start, abi_ulong len, int host_prot,
+int mmap_flags, int page_flags, int fd,
+off_t offset, int host_page_size)
+{
+void *p, *want_p = g2h_untagged(start);
+off_t fileend_adj = 0;
+int flags = mmap_flags;
+abi_ulong last, pass_last;
+
+if (!(flags & MAP_ANONYMOUS)) {
+struct stat sb;
+
+if (fstat(fd, ) == -1) {
+return -1;
+}
+if (offset >= sb.st_size) {
+/*
+ * The entire map is beyond the end of the file.
+ * Transform it to an anonymous mapping.
+ */
+flags |= MAP_ANONYMOUS;
+fd = -1;
+offset = 0;
+} else if (offset + len > sb.st_size) {
+/*
+ * A portion of the map is beyond the end of the file.
+ * Truncate the file portion of the allocation.
+ */
+fileend_adj = offset + len - sb.st_size;
+}
+}
+
+if (flags & (MAP_FIXED | MAP_FIXED_NOREPLACE)) {
+if (fileend_adj) {
+p = mmap(want_p, len, host_prot, flags | MAP_ANONYMOUS, -1, 0);
+} else {
+p = mmap(want_p, len, host_prot, flags, fd, offset);
+}
+if (p != want_p) {
+if (p != MAP_FAILED) {
+munmap(p, len);
+errno = EEXIST;
+}
+return -1;
+}
+
+if (fileend_adj) {
+void *t = mmap(p, len - fileend_adj, host_prot,
+   (flags & ~MAP_FIXED_NOREPLACE) | MAP_FIXED,
+   fd, offset);
+assert(t != MAP_FAILED);
+}
+} else {
+size_t host_len, part_len;
+
+/*
+ * Take care to align the host memory.  Perform a larger anonymous
+ * allocation and extract the aligned portion.  Remap the file on
+ * top of that.
+ */
+host_len = len + TARGET_PAGE_SIZE - host_page_size;
+p = mmap(want_p, host_len, host_prot, flags | MAP_ANONYMOUS, -1, 0);
+if (p == MAP_FAILED) {
+return -1;
+}
+
+part_len = (uintptr_t)p & (TARGET_PAGE_SIZE - 1);
+if (part_len) {
+part_len = TARGET_PAGE_SIZE - part_len;
+munmap(p, part_len);
+p += part_len;
+host_len -= part_len;
+}
+if (len < host_len) {
+munmap(p + len, host_len - len);
+}
+
+if (!(flags & MAP_ANONYMOUS)) {
+void *t = mmap(p, len - fileend_adj, host_prot,
+   flags | MAP_FIXED, fd, offset);
+assert(t != MAP_FAILED);
+}
+
+start = h2g(p);
+}
+
+last = start + len - 1;
+if (fileend_adj) {
+pass_last = ROUND_UP(last - fileend_adj, host_page_size) - 1;
+} else {
+pass_last = last;
+}
+return mmap_end(start, last, start, pass_last, mmap_flags, page_flags);
+}
+
 static abi_long target_mmap__locked(abi_ulong start, abi_ulong len,
 int target_prot, int flags, int page_flags,
 int fd, off_t offset)
@@ 

[PATCH v2 00/33] linux-user: Improve host and guest page size handling

2023-08-31 Thread Richard Henderson
Based-on: 20230829220228.928506-1-richard.hender...@linaro.org
("[PATCH v5 00/20] linux-user: Implement VDSOs")

Changes for v2:
  * Minor adjustments to bsd-user.
  * Update docs for deprecation.
  * Philippe's r-b.

Blurb from v1:

While working on mmap issues for 8.1, I noticed a lot of corner
cases of host != guest page size that we implement poorly.
This seems to be particularly visible on Apple M1 with 16k pages,
more so than Power with 64k pages for some reason.

Objective 1 is to deprecate and (essentially) disable the -p option.

The effect of -p is apparently confusing, so much so that our own
testsuite misuses it.  One cannot really change the host page size,
and pretending otherwise means that we don't treat the host memory
system correctly, and stuff breaks.

I have not yet done the same work for bsd-user.

Objective 2 is to allow the guest page size to change to match the host.

There are corner cases of host != guest page size will fail in odd ways.
For case of host > guest page size, the issues could be solved with
softmmu, allowing a non-linear mapping between host and guest addresses
and also disconnecting host and guest page permissions.

However, host < guest page has issues with SIGBUS which I believe to be
totally unfixable.  At minimum one would need to monitor changes to all
files mapped in the address space, but I'm sure there is much more.

But as always the best behaviour is obtained when the host and guest
page sizes match -- there are no corner cases to contend with.

There are a set of guests which can be configured to use multiple page
sizes, and therefore software developed for those guests (usually) does
not hard-code a particular page size.  For those, we can allow the
page size to vary and let the guest match the host.

I have only changed aarch64, alpha and ppc guests so far, as those
are both easy to test and, especially for the case of alpha's default
8k page size, prone to failure.


r~


Richard Henderson (33):
  accel/tcg: Remove qemu_host_page_size from page_protect/page_unprotect
  linux-user: Adjust SVr4 NULL page mapping
  linux-user: Remove qemu_host_page_{size,mask} in probe_guest_base
  linux-user: Remove qemu_host_page_size from create_elf_tables
  linux-user/hppa: Simplify init_guest_commpage
  linux-user/nios2: Remove qemu_host_page_size from init_guest_commpage
  linux-user/arm: Remove qemu_host_page_size from init_guest_commpage
  linux-user: Remove qemu_host_page_{size,mask} from mmap.c
  linux-user: Remove REAL_HOST_PAGE_ALIGN from mmap.c
  linux-user: Remove HOST_PAGE_ALIGN from mmap.c
  migration: Remove qemu_host_page_size
  hw/tpm: Remove HOST_PAGE_ALIGN from tpm_ppi_init
  softmmu/physmem: Remove qemu_host_page_size
  softmmu/physmem: Remove HOST_PAGE_ALIGN
  linux-user: Remove qemu_host_page_size from main
  linux-user: Split out target_mmap__locked
  linux-user: Move some mmap checks outside the lock
  linux-user: Fix sub-host-page mmap
  linux-user: Split out mmap_end
  linux-user: Do early mmap placement only for reserved_va
  linux-user: Split out mmap_h_eq_g
  linux-user: Split out mmap_h_lt_g
  linux-user: Split out mmap_h_gt_g
  tests/tcg: Remove run-test-mmap-*
  tests/tcg: Extend file in linux-madvise.c
  *-user: Deprecate and disable -p pagesize
  cpu: Remove page_size_init
  accel/tcg: Disconnect TargetPageDataNode from page size
  linux-user: Allow TARGET_PAGE_BITS_VARY
  target/arm: Enable TARGET_PAGE_BITS_VARY for AArch64 user-only
  linux-user: Bound mmap_min_addr by host page size
  target/ppc: Enable TARGET_PAGE_BITS_VARY for user-only
  target/alpha: Enable TARGET_PAGE_BITS_VARY for user-only

 docs/about/deprecated.rst |   7 +
 docs/user/main.rst|   3 -
 bsd-user/qemu.h   |   7 +
 include/exec/cpu-common.h |   7 -
 include/hw/core/cpu.h |   2 -
 target/alpha/cpu-param.h  |  16 +-
 target/arm/cpu-param.h|   6 +-
 target/ppc/cpu-param.h|   9 +-
 accel/tcg/translate-all.c |   1 -
 accel/tcg/user-exec.c |  31 +-
 bsd-user/main.c   |  21 +-
 cpu.c |  13 -
 hw/tpm/tpm_ppi.c  |   3 +-
 linux-user/elfload.c  |  67 +-
 linux-user/main.c |  33 +-
 linux-user/mmap.c | 714 +-
 migration/ram.c   |  22 +-
 softmmu/physmem.c |  17 +-
 softmmu/vl.c  |   1 -
 target/arm/cpu.c  |  51 +-
 tests/tcg/multiarch/linux/linux-madvise.c |   2 +
 tests/tcg/alpha/Makefile.target   |   3 -
 tests/tcg/arm/Makefile.target |   3 -
 tests/tcg/hppa/Makefile.target|   3 -
 tests/tcg/i386/Makefile.target|   3 -
 tests/tcg/m68k/Makefile.target|   3 -
 

[PATCH v2 21/33] linux-user: Split out mmap_h_eq_g

2023-08-31 Thread Richard Henderson
Move the MAX_FIXED_NOREPLACE check for reserved_va earlier.
Move the computation of host_prot earlier.

Signed-off-by: Richard Henderson 
---
 linux-user/mmap.c | 66 +--
 1 file changed, 53 insertions(+), 13 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 7d482df06d..7a0c0c1f35 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -482,6 +482,31 @@ static abi_long mmap_end(abi_ulong start, abi_ulong last,
 return start;
 }
 
+/*
+ * Special case host page size == target page size,
+ * where there are no edge conditions.
+ */
+static abi_long mmap_h_eq_g(abi_ulong start, abi_ulong len,
+int host_prot, int flags, int page_flags,
+int fd, off_t offset)
+{
+void *p, *want_p = g2h_untagged(start);
+abi_ulong last;
+
+p = mmap(want_p, len, host_prot, flags, fd, offset);
+if (p == MAP_FAILED) {
+return -1;
+}
+if ((flags & MAP_FIXED_NOREPLACE) && p != want_p) {
+errno = EEXIST;
+return -1;
+}
+
+start = h2g(p);
+last = start + len - 1;
+return mmap_end(start, last, start, last, flags, page_flags);
+}
+
 static abi_long target_mmap__locked(abi_ulong start, abi_ulong len,
 int target_prot, int flags, int page_flags,
 int fd, off_t offset)
@@ -490,6 +515,7 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
 abi_ulong ret, last, real_start, real_last, retaddr, host_len;
 abi_ulong passthrough_start = -1, passthrough_last = 0;
 off_t host_offset;
+int host_prot;
 
 real_start = start & -host_page_size;
 host_offset = offset & -host_page_size;
@@ -498,16 +524,33 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
  * For reserved_va, we are in full control of the allocation.
  * Find a suitible hole and convert to MAP_FIXED.
  */
-if (reserved_va && !(flags & (MAP_FIXED | MAP_FIXED_NOREPLACE))) {
-host_len = len + offset - host_offset;
-start = mmap_find_vma(real_start, host_len,
-  MAX(host_page_size, TARGET_PAGE_SIZE));
-if (start == (abi_ulong)-1) {
-errno = ENOMEM;
-return -1;
+if (reserved_va) {
+if (flags & MAP_FIXED_NOREPLACE) {
+/* Validate that the chosen range is empty. */
+if (!page_check_range_empty(start, start + len - 1)) {
+errno = EEXIST;
+return -1;
+}
+flags = (flags & ~MAP_FIXED_NOREPLACE) | MAP_FIXED;
+} else if (!(flags & MAP_FIXED)) {
+size_t real_len = len + offset - host_offset;
+abi_ulong align = MAX(host_page_size, TARGET_PAGE_SIZE);
+
+start = mmap_find_vma(real_start, real_len, align);
+if (start == (abi_ulong)-1) {
+errno = ENOMEM;
+return -1;
+}
+start += offset - host_offset;
+flags |= MAP_FIXED;
 }
-start += offset - host_offset;
-flags |= MAP_FIXED;
+}
+
+host_prot = target_to_host_prot(target_prot);
+
+if (host_page_size == TARGET_PAGE_SIZE) {
+return mmap_h_eq_g(start, len, host_prot, flags,
+   page_flags, fd, offset);
 }
 
 /*
@@ -543,12 +586,10 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
 
 if (!(flags & (MAP_FIXED | MAP_FIXED_NOREPLACE))) {
 uintptr_t host_start;
-int host_prot;
 void *p;
 
 host_len = len + offset - host_offset;
 host_len = ROUND_UP(host_len, host_page_size);
-host_prot = target_to_host_prot(target_prot);
 
 /* Note: we prefer to control the mapping address. */
 p = mmap(g2h_untagged(start), host_len, host_prot,
@@ -671,8 +712,7 @@ static abi_long target_mmap__locked(abi_ulong start, 
abi_ulong len,
 len1 = real_last - real_start + 1;
 want_p = g2h_untagged(real_start);
 
-p = mmap(want_p, len1, target_to_host_prot(target_prot),
- flags, fd, offset1);
+p = mmap(want_p, len1, host_prot, flags, fd, offset1);
 if (p != want_p) {
 if (p != MAP_FAILED) {
 munmap(p, len1);
-- 
2.34.1




[PATCH v2 01/33] accel/tcg: Remove qemu_host_page_size from page_protect/page_unprotect

2023-08-31 Thread Richard Henderson
Use qemu_real_host_page_size instead.  Except for the final mprotect
within page_protect, we already handled host < target page size.

Signed-off-by: Richard Henderson 
---
 accel/tcg/user-exec.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index ab48cb41e4..4c1697500a 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -650,16 +650,17 @@ void page_protect(tb_page_addr_t address)
 {
 PageFlagsNode *p;
 target_ulong start, last;
+int host_page_size = qemu_real_host_page_size();
 int prot;
 
 assert_memory_lock();
 
-if (qemu_host_page_size <= TARGET_PAGE_SIZE) {
+if (host_page_size <= TARGET_PAGE_SIZE) {
 start = address & TARGET_PAGE_MASK;
 last = start + TARGET_PAGE_SIZE - 1;
 } else {
-start = address & qemu_host_page_mask;
-last = start + qemu_host_page_size - 1;
+start = address & -host_page_size;
+last = start + host_page_size - 1;
 }
 
 p = pageflags_find(start, last);
@@ -670,7 +671,7 @@ void page_protect(tb_page_addr_t address)
 
 if (unlikely(p->itree.last < last)) {
 /* More than one protection region covers the one host page. */
-assert(TARGET_PAGE_SIZE < qemu_host_page_size);
+assert(TARGET_PAGE_SIZE < host_page_size);
 while ((p = pageflags_next(p, start, last)) != NULL) {
 prot |= p->flags;
 }
@@ -678,7 +679,7 @@ void page_protect(tb_page_addr_t address)
 
 if (prot & PAGE_WRITE) {
 pageflags_set_clear(start, last, 0, PAGE_WRITE);
-mprotect(g2h_untagged(start), qemu_host_page_size,
+mprotect(g2h_untagged(start), last - start + 1,
  prot & (PAGE_READ | PAGE_EXEC) ? PROT_READ : PROT_NONE);
 }
 }
@@ -724,18 +725,19 @@ int page_unprotect(target_ulong address, uintptr_t pc)
 }
 #endif
 } else {
+int host_page_size = qemu_real_host_page_size();
 target_ulong start, len, i;
 int prot;
 
-if (qemu_host_page_size <= TARGET_PAGE_SIZE) {
+if (host_page_size <= TARGET_PAGE_SIZE) {
 start = address & TARGET_PAGE_MASK;
 len = TARGET_PAGE_SIZE;
 prot = p->flags | PAGE_WRITE;
 pageflags_set_clear(start, start + len - 1, PAGE_WRITE, 0);
 current_tb_invalidated = tb_invalidate_phys_page_unwind(start, pc);
 } else {
-start = address & qemu_host_page_mask;
-len = qemu_host_page_size;
+start = address & -host_page_size;
+len = host_page_size;
 prot = 0;
 
 for (i = 0; i < len; i += TARGET_PAGE_SIZE) {
-- 
2.34.1




Re: [PATCH 1/2] riscv: zicond: make non-experimental

2023-08-31 Thread Alistair Francis
On Wed, Aug 9, 2023 at 4:18 AM Vineet Gupta  wrote:
>
> zicond is now codegen supported in both llvm and gcc.
>
> This change allows seamless enabling/testing of zicond in downstream
> projects. e.g. currently riscv-gnu-toolchain parses elf attributes
> to create a cmdline for qemu but fails short of enabling it because of
> the "x-" prefix.
>
> Signed-off-by: Vineet Gupta 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/cpu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 6b93b04453c8..022bd9d01223 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1816,6 +1816,7 @@ static Property riscv_cpu_extensions[] = {
>  DEFINE_PROP_BOOL("zcf", RISCVCPU, cfg.ext_zcf, false),
>  DEFINE_PROP_BOOL("zcmp", RISCVCPU, cfg.ext_zcmp, false),
>  DEFINE_PROP_BOOL("zcmt", RISCVCPU, cfg.ext_zcmt, false),
> +DEFINE_PROP_BOOL("zicond", RISCVCPU, cfg.ext_zicond, false),
>
>  /* Vendor-specific custom extensions */
>  DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false),
> @@ -1832,7 +1833,6 @@ static Property riscv_cpu_extensions[] = {
>  DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, 
> false),
>
>  /* These are experimental so mark with 'x-' */
> -DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false),
>
>  /* ePMP 0.9.3 */
>  DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
> --
> 2.34.1
>
>



[PATCH 4/5] cxl/type3: add an optional mhd validation function for memory accesses

2023-08-31 Thread Gregory Price
When memory accesses are made, some MHSLD's would validate the address
is within the scope of allocated sections.  To do this, the base device
must call an optional function set by inherited devices.

Signed-off-by: Gregory Price 
---
 hw/mem/cxl_type3.c  | 15 +++
 include/hw/cxl/cxl_device.h |  3 +++
 2 files changed, 18 insertions(+)

diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index a8d4a12f3e..8e1565f2fc 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -1034,6 +1034,10 @@ void ct3_realize(PCIDevice *pci_dev, Error **errp)
 goto err_release_cdat;
 }
 }
+
+/* Devices which inherit ct3d should initialize these after ct3_realize */
+ct3d->mhd_access_valid = NULL;
+
 return;
 
 err_release_cdat:
@@ -1259,6 +1263,11 @@ MemTxResult cxl_type3_read(PCIDevice *d, hwaddr 
host_addr, uint64_t *data,
 return MEMTX_ERROR;
 }
 
+if (ct3d->mhd_access_valid &&
+!ct3d->mhd_access_valid(d, dpa_offset, size)) {
+return MEMTX_ERROR;
+}
+
 if (sanitize_running(>cci)) {
 qemu_guest_getrandom_nofail(data, size);
 return MEMTX_OK;
@@ -1279,6 +1288,12 @@ MemTxResult cxl_type3_write(PCIDevice *d, hwaddr 
host_addr, uint64_t data,
 if (res) {
 return MEMTX_ERROR;
 }
+
+if (ct3d->mhd_access_valid &&
+!ct3d->mhd_access_valid(d, dpa_offset, size)) {
+return MEMTX_ERROR;
+}
+
 if (sanitize_running(>cci)) {
 return MEMTX_OK;
 }
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 4ad38b689c..b1b39a9aa0 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -489,6 +489,9 @@ struct CXLType3Dev {
 uint8_t num_regions; /* 0-8 regions */
 CXLDCDRegion regions[DCD_MAX_REGION_NUM];
 } dc;
+
+/* Multi-headed Device */
+bool (*mhd_access_valid)(PCIDevice *d, uint64_t addr, unsigned int size);
 };
 
 #define TYPE_CXL_TYPE3 "cxl-type3"
-- 
2.39.1




[PATCH 1/5] cxl/mailbox: move mailbox effect definitions to a header

2023-08-31 Thread Gregory Price
Preparation for allowing devices to define their own CCI commands

Signed-off-by: Gregory Price 
---
 hw/cxl/cxl-mailbox-utils.c   | 35 +++
 include/hw/cxl/cxl_mailbox.h | 18 ++
 2 files changed, 37 insertions(+), 16 deletions(-)
 create mode 100644 include/hw/cxl/cxl_mailbox.h

diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 4e8651ebe2..edf39a3efb 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -12,6 +12,7 @@
 #include "hw/pci/msix.h"
 #include "hw/cxl/cxl.h"
 #include "hw/cxl/cxl_events.h"
+#include "hw/cxl/cxl_mailbox.h"
 #include "hw/pci/pci.h"
 #include "hw/pci-bridge/cxl_upstream_port.h"
 #include "qemu/cutils.h"
@@ -1561,28 +1562,28 @@ static CXLRetCode cmd_dcd_release_dyn_cap(const struct 
cxl_cmd *cmd,
 return CXL_MBOX_SUCCESS;
 }
 
-#define IMMEDIATE_CONFIG_CHANGE (1 << 1)
-#define IMMEDIATE_DATA_CHANGE (1 << 2)
-#define IMMEDIATE_POLICY_CHANGE (1 << 3)
-#define IMMEDIATE_LOG_CHANGE (1 << 4)
-#define SECURITY_STATE_CHANGE (1 << 5)
-#define BACKGROUND_OPERATION (1 << 6)
+#define CXL_MBOX_IMMEDIATE_CONFIG_CHANGE (1 << 1)
+#define CXL_MBOX_IMMEDIATE_DATA_CHANGE (1 << 2)
+#define CXL_MBOX_IMMEDIATE_POLICY_CHANGE (1 << 3)
+#define CXL_MBOX_IMMEDIATE_LOG_CHANGE (1 << 4)
+#define CXL_MBOX_SECURITY_STATE_CHANGE (1 << 5)
+#define CXL_MBOX_BACKGROUND_OPERATION (1 << 6)
 
 static const struct cxl_cmd cxl_cmd_set[256][256] = {
 [EVENTS][GET_RECORDS] = { "EVENTS_GET_RECORDS",
 cmd_events_get_records, 1, 0 },
 [EVENTS][CLEAR_RECORDS] = { "EVENTS_CLEAR_RECORDS",
-cmd_events_clear_records, ~0, IMMEDIATE_LOG_CHANGE },
+cmd_events_clear_records, ~0, CXL_MBOX_IMMEDIATE_LOG_CHANGE },
 [EVENTS][GET_INTERRUPT_POLICY] = { "EVENTS_GET_INTERRUPT_POLICY",
   cmd_events_get_interrupt_policy, 0, 0 },
 [EVENTS][SET_INTERRUPT_POLICY] = { "EVENTS_SET_INTERRUPT_POLICY",
   cmd_events_set_interrupt_policy,
-  ~0, IMMEDIATE_CONFIG_CHANGE },
+  ~0, CXL_MBOX_IMMEDIATE_CONFIG_CHANGE },
 [FIRMWARE_UPDATE][GET_INFO] = { "FIRMWARE_UPDATE_GET_INFO",
 cmd_firmware_update_get_info, 0, 0 },
 [TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },
 [TIMESTAMP][SET] = { "TIMESTAMP_SET", cmd_timestamp_set, 8,
- IMMEDIATE_POLICY_CHANGE },
+ CXL_MBOX_IMMEDIATE_POLICY_CHANGE },
 [LOGS][GET_SUPPORTED] = { "LOGS_GET_SUPPORTED", cmd_logs_get_supported, 0, 
0 },
 [LOGS][GET_LOG] = { "LOGS_GET_LOG", cmd_logs_get_log, 0x18, 0 },
 [IDENTIFY][MEMORY_DEVICE] = { "IDENTIFY_MEMORY_DEVICE",
@@ -1591,9 +1592,11 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
 cmd_ccls_get_partition_info, 0, 0 },
 [CCLS][GET_LSA] = { "CCLS_GET_LSA", cmd_ccls_get_lsa, 8, 0 },
 [CCLS][SET_LSA] = { "CCLS_SET_LSA", cmd_ccls_set_lsa,
-~0, IMMEDIATE_CONFIG_CHANGE | IMMEDIATE_DATA_CHANGE },
+~0, CXL_MBOX_IMMEDIATE_CONFIG_CHANGE | CXL_MBOX_IMMEDIATE_DATA_CHANGE 
},
 [SANITIZE][OVERWRITE] = { "SANITIZE_OVERWRITE", cmd_sanitize_overwrite, 0,
-IMMEDIATE_DATA_CHANGE | SECURITY_STATE_CHANGE | BACKGROUND_OPERATION },
+(CXL_MBOX_IMMEDIATE_DATA_CHANGE |
+ CXL_MBOX_SECURITY_STATE_CHANGE |
+ CXL_MBOX_BACKGROUND_OPERATION)},
 [PERSISTENT_MEM][GET_SECURITY_STATE] = { "GET_SECURITY_STATE",
 cmd_get_security_state, 0, 0 },
 [MEDIA_AND_POISON][GET_POISON_LIST] = { "MEDIA_AND_POISON_GET_POISON_LIST",
@@ -1612,10 +1615,10 @@ static const struct cxl_cmd cxl_cmd_set_dcd[256][256] = 
{
 8, 0 },
 [DCD_CONFIG][ADD_DYN_CAP_RSP] = {
 "ADD_DCD_DYNAMIC_CAPACITY_RESPONSE", cmd_dcd_add_dyn_cap_rsp,
-~0, IMMEDIATE_DATA_CHANGE },
+~0, CXL_MBOX_IMMEDIATE_DATA_CHANGE },
 [DCD_CONFIG][RELEASE_DYN_CAP] = {
 "RELEASE_DCD_DYNAMIC_CAPACITY", cmd_dcd_release_dyn_cap,
-~0, IMMEDIATE_DATA_CHANGE },
+~0, CXL_MBOX_IMMEDIATE_DATA_CHANGE },
 };
 
 static const struct cxl_cmd cxl_cmd_set_sw[256][256] = {
@@ -1628,7 +1631,7 @@ static const struct cxl_cmd cxl_cmd_set_sw[256][256] = {
  */
 [TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },
 [TIMESTAMP][SET] = { "TIMESTAMP_SET", cmd_timestamp_set, 8,
- IMMEDIATE_POLICY_CHANGE },
+ CXL_MBOX_IMMEDIATE_POLICY_CHANGE },
 [LOGS][GET_SUPPORTED] = { "LOGS_GET_SUPPORTED", cmd_logs_get_supported, 0,
   0 },
 [LOGS][GET_LOG] = { "LOGS_GET_LOG", cmd_logs_get_log, 0x18, 0 },
@@ -1670,7 +1673,7 @@ int cxl_process_cci_message(CXLCCI *cci, uint8_t set, 
uint8_t cmd,
 }
 
 /* Only one bg command at a time */
-if ((cxl_cmd->effect & BACKGROUND_OPERATION) &&
+if ((cxl_cmd->effect & CXL_MBOX_BACKGROUND_OPERATION) &&
 cci->bg.runtime > 0) {
 

[PATCH 0/5 v2] CXL: SK hynix Niagara MHSLD Device

2023-08-31 Thread Gregory Price
v2:
- 5 patch series, first 4 are pull-aheads that can be merged separately
- cci: rebased on 8-30 branch from jic23, dropped cci patches
- mailbox: dropped MHD commands, integrated into niagara (for now)
- mailbox: refactor CCI defines to avoid redefinition in niagara
- type3: cleanup duplicate typecasting
- type3: expose ct3 functions so inheriting devices may access them
- type3: add optional mhd validation function for memory access
- niagara: refactor to make niagara inherit type3 and override behavior
- niagara: refactor command definitions and types into header to make
   understanding the device a bit easier for users
- style and formatting

This patch set includes an emulation of the SK hynix Niagara MHSLD
platform with custom CCI commands that allow for isolation of memory
blocks between attached hosts.

This device allows hosts to request memory blocks directly from the device,
rather than requiring full the DCD command set.  As a matter of simplicity,
this is beneficial to for testing and applications of dynamic memory
pooling on top of the 1.1 and 2.0 specification.

Note that these CCI commands are not servicable without a proper driver or
the kernel allowing raw CXL commands to be passed through the mailbox
driver, so users should enable `CONFIG_CXL_MEM_RAW_COMMANDS=y` on the
kernel of their QEMU instance if they wish to test it

Signed-off-by: Gregory Price 

Gregory Price (5):
  cxl/mailbox: move mailbox effect definitions to a header
  cxl/type3: Cleanup multiple CXL_TYPE3() calls in read/write functions
  cxl/type3: Expose ct3 functions so that inheriters can call them
  cxl/type3: add an optional mhd validation function for memory accesses
  cxl/vendor: SK hynix Niagara Multi-Headed SLD Device

 hw/cxl/Kconfig  |   4 +
 hw/cxl/cxl-mailbox-utils.c  |  35 +-
 hw/cxl/meson.build  |   2 +
 hw/cxl/vendor/meson.build   |   1 +
 hw/cxl/vendor/skhynix/.gitignore|   1 +
 hw/cxl/vendor/skhynix/init_niagara.c|  99 +
 hw/cxl/vendor/skhynix/meson.build   |   1 +
 hw/cxl/vendor/skhynix/skhynix_niagara.c | 516 
 hw/cxl/vendor/skhynix/skhynix_niagara.h | 169 
 hw/mem/cxl_type3.c  |  33 +-
 include/hw/cxl/cxl_device.h |   8 +
 include/hw/cxl/cxl_mailbox.h|  18 +
 12 files changed, 863 insertions(+), 24 deletions(-)
 create mode 100644 hw/cxl/vendor/meson.build
 create mode 100644 hw/cxl/vendor/skhynix/.gitignore
 create mode 100644 hw/cxl/vendor/skhynix/init_niagara.c
 create mode 100644 hw/cxl/vendor/skhynix/meson.build
 create mode 100644 hw/cxl/vendor/skhynix/skhynix_niagara.c
 create mode 100644 hw/cxl/vendor/skhynix/skhynix_niagara.h
 create mode 100644 include/hw/cxl/cxl_mailbox.h

-- 
2.39.1




[PATCH 2/5] cxl/type3: Cleanup multiple CXL_TYPE3() calls in read/write functions

2023-08-31 Thread Gregory Price
Call CXL_TYPE3 once at top of function to avoid multiple invocations.

Signed-off-by: Gregory Price 
---
 hw/mem/cxl_type3.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index fd9d134d46..80d596ee10 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -1248,17 +1248,18 @@ static int cxl_type3_hpa_to_as_and_dpa(CXLType3Dev 
*ct3d,
 MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, uint64_t *data,
unsigned size, MemTxAttrs attrs)
 {
+CXLType3Dev *ct3d = CXL_TYPE3(d);
 uint64_t dpa_offset = 0;
 AddressSpace *as = NULL;
 int res;
 
-res = cxl_type3_hpa_to_as_and_dpa(CXL_TYPE3(d), host_addr, size,
+res = cxl_type3_hpa_to_as_and_dpa(ct3d, host_addr, size,
   , _offset);
 if (res) {
 return MEMTX_ERROR;
 }
 
-if (sanitize_running(_TYPE3(d)->cci)) {
+if (sanitize_running(>cci)) {
 qemu_guest_getrandom_nofail(data, size);
 return MEMTX_OK;
 }
@@ -1268,16 +1269,17 @@ MemTxResult cxl_type3_read(PCIDevice *d, hwaddr 
host_addr, uint64_t *data,
 MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
 unsigned size, MemTxAttrs attrs)
 {
+CXLType3Dev *ct3d = CXL_TYPE3(d);
 uint64_t dpa_offset = 0;
 AddressSpace *as = NULL;
 int res;
 
-res = cxl_type3_hpa_to_as_and_dpa(CXL_TYPE3(d), host_addr, size,
+res = cxl_type3_hpa_to_as_and_dpa(ct3d, host_addr, size,
   , _offset);
 if (res) {
 return MEMTX_ERROR;
 }
-if (sanitize_running(_TYPE3(d)->cci)) {
+if (sanitize_running(>cci)) {
 return MEMTX_OK;
 }
 return address_space_write(as, dpa_offset, attrs, , size);
-- 
2.39.1




[PATCH 3/5] cxl/type3: Expose ct3 functions so that inheriters can call them

2023-08-31 Thread Gregory Price
For devices built on top of ct3, we need the init, realize, and
exit functions exposed to correctly start up and tear down.

Signed-off-by: Gregory Price 
---
 hw/mem/cxl_type3.c  | 8 
 include/hw/cxl/cxl_device.h | 5 +
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 80d596ee10..a8d4a12f3e 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -950,7 +950,7 @@ static DOEProtocol doe_spdm_prot[] = {
 { }
 };
 
-static void ct3_realize(PCIDevice *pci_dev, Error **errp)
+void ct3_realize(PCIDevice *pci_dev, Error **errp)
 {
 CXLType3Dev *ct3d = CXL_TYPE3(pci_dev);
 CXLComponentState *cxl_cstate = >cxl_cstate;
@@ -1054,7 +1054,7 @@ err_address_space_free:
 return;
 }
 
-static void ct3_exit(PCIDevice *pci_dev)
+void ct3_exit(PCIDevice *pci_dev)
 {
 CXLType3Dev *ct3d = CXL_TYPE3(pci_dev);
 CXLComponentState *cxl_cstate = >cxl_cstate;
@@ -1285,7 +1285,7 @@ MemTxResult cxl_type3_write(PCIDevice *d, hwaddr 
host_addr, uint64_t data,
 return address_space_write(as, dpa_offset, attrs, , size);
 }
 
-static void ct3d_reset(DeviceState *dev)
+void ct3d_reset(DeviceState *dev)
 {
 CXLType3Dev *ct3d = CXL_TYPE3(dev);
 uint32_t *reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
@@ -2081,7 +2081,7 @@ void qmp_cxl_release_dynamic_capacity(const char *path,
  errp);
 }
 
-static void ct3_class_init(ObjectClass *oc, void *data)
+void ct3_class_init(ObjectClass *oc, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(oc);
 PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index e824c5ade8..4ad38b689c 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -524,6 +524,11 @@ MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, 
uint64_t *data,
 MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
 unsigned size, MemTxAttrs attrs);
 
+void ct3_realize(PCIDevice *pci_dev, Error **errp);
+void ct3_exit(PCIDevice *pci_dev);
+void ct3d_reset(DeviceState *d);
+void ct3_class_init(ObjectClass *oc, void *data);
+
 uint64_t cxl_device_get_timestamp(CXLDeviceState *cxlds);
 
 void cxl_event_init(CXLDeviceState *cxlds, int start_msg_num);
-- 
2.39.1




[PATCH 5/5] cxl/vendor: SK hynix Niagara Multi-Headed SLD Device

2023-08-31 Thread Gregory Price
Create a new device to emulate the SK hynix Niagara MHSLD platform.

This device has custom CCI commands that allow for applying isolation
to each memory block between hosts. This enables an early form of
dynamic capacity, whereby the NUMA node maps the entire region, but
the host is responsible for asking the device which memory blocks
are allocated to it, and therefore may be onlined.

To instantiate:

-device 
cxl-skh-niagara,cxl-type3,bus=rp0,volatile-memdev=mem0,id=cxl-mem0,sn=6,mhd-head=0,mhd-shmid=0

The linux kernel will require raw CXL commands enabled to allow for
passing through of Niagara CXL commands via the CCI mailbox.

The Niagara MH-SLD has a shared memory region that must be initialized
using the 'init_niagara' tool located in the vendor subdirectory

usage: init_niagara
heads : number of heads on the device
sections  : number of sections
section_size  : size of a section in 128mb increments
shmid : shmid produced by ipcmk

Example:
$shmid1=ipcmk -M 131072
./init_niagara 4 32 1 $shmid1

Signed-off-by: Gregory Price 
Signed-off-by: Junhee Ryu 
Signed-off-by: Kwangjin Ko 
---
 hw/cxl/Kconfig  |   4 +
 hw/cxl/meson.build  |   2 +
 hw/cxl/vendor/meson.build   |   1 +
 hw/cxl/vendor/skhynix/.gitignore|   1 +
 hw/cxl/vendor/skhynix/init_niagara.c|  99 +
 hw/cxl/vendor/skhynix/meson.build   |   1 +
 hw/cxl/vendor/skhynix/skhynix_niagara.c | 516 
 hw/cxl/vendor/skhynix/skhynix_niagara.h | 169 
 8 files changed, 793 insertions(+)
 create mode 100644 hw/cxl/vendor/meson.build
 create mode 100644 hw/cxl/vendor/skhynix/.gitignore
 create mode 100644 hw/cxl/vendor/skhynix/init_niagara.c
 create mode 100644 hw/cxl/vendor/skhynix/meson.build
 create mode 100644 hw/cxl/vendor/skhynix/skhynix_niagara.c
 create mode 100644 hw/cxl/vendor/skhynix/skhynix_niagara.h

diff --git a/hw/cxl/Kconfig b/hw/cxl/Kconfig
index c9b2e46bac..dd6c54b54d 100644
--- a/hw/cxl/Kconfig
+++ b/hw/cxl/Kconfig
@@ -2,5 +2,9 @@ config CXL
 bool
 default y if PCI_EXPRESS
 
+config CXL_VENDOR
+bool
+default y
+
 config I2C_MCTP_CXL
 bool
diff --git a/hw/cxl/meson.build b/hw/cxl/meson.build
index 1393821fc4..e8c8c1355a 100644
--- a/hw/cxl/meson.build
+++ b/hw/cxl/meson.build
@@ -15,3 +15,5 @@ system_ss.add(when: 'CONFIG_CXL',
 system_ss.add(when: 'CONFIG_I2C_MCTP_CXL', if_true: files('i2c_mctp_cxl.c'))
 
 system_ss.add(when: 'CONFIG_ALL', if_true: files('cxl-host-stubs.c'))
+
+subdir('vendor')
diff --git a/hw/cxl/vendor/meson.build b/hw/cxl/vendor/meson.build
new file mode 100644
index 00..12db8991f1
--- /dev/null
+++ b/hw/cxl/vendor/meson.build
@@ -0,0 +1 @@
+subdir('skhynix')
diff --git a/hw/cxl/vendor/skhynix/.gitignore b/hw/cxl/vendor/skhynix/.gitignore
new file mode 100644
index 00..6d96de38ea
--- /dev/null
+++ b/hw/cxl/vendor/skhynix/.gitignore
@@ -0,0 +1 @@
+init_niagara
diff --git a/hw/cxl/vendor/skhynix/init_niagara.c 
b/hw/cxl/vendor/skhynix/init_niagara.c
new file mode 100644
index 00..2c189dc33c
--- /dev/null
+++ b/hw/cxl/vendor/skhynix/init_niagara.c
@@ -0,0 +1,99 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (c) 2023 MemVerge Inc.
+ * Copyright (c) 2023 SK hynix Inc.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct niagara_state {
+uint8_t nr_heads;
+uint8_t nr_lds;
+uint8_t ldmap[65536];
+uint32_t total_sections;
+uint32_t free_sections;
+uint32_t section_size;
+uint32_t sections[];
+};
+
+int main(int argc, char *argv[])
+{
+int shmid = 0;
+uint32_t sections = 0;
+uint32_t section_size = 0;
+uint32_t heads = 0;
+struct niagara_state *niagara_state = NULL;
+size_t state_size;
+uint8_t i;
+
+if (argc != 5) {
+printf("usage: init_niagara
\n"
+"\theads : number of heads on the device\n"
+"\tsections  : number of sections\n"
+"\tsection_size  : size of a section in 128mb increments\n"
+"\tshmid : /tmp/mytoken.tmp\n\n"
+"It is recommended your shared memory region is at least 
128kb\n");
+return -1;
+}
+
+/* must have at least 1 head */
+heads = (uint32_t)atoi(argv[1]);
+if (heads == 0 || heads > 32) {
+printf("bad heads argument (1-32)\n");
+return -1;
+}
+
+/* Get number of sections */
+sections = (uint32_t)atoi(argv[2]);
+if (sections == 0) {
+printf("bad sections argument\n");
+return -1;
+}
+
+section_size = (uint32_t)atoi(argv[3]);
+if (sections == 0) {
+printf("bad section size argument\n");
+return -1;
+}
+
+shmid = (uint32_t)atoi(argv[4]);
+if (shmid == 0) {
+printf("bad shmid argument\n");
+return -1;
+}
+

Re: [PATCH v9 0/4] hw/ufs: Add Universal Flash Storage (UFS) support

2023-08-31 Thread Jeuk Kim



On 23. 8. 30. 20:38, Stefan Hajnoczi wrote:

On Thu, 3 Aug 2023 at 07:49, Jeuk Kim  wrote:

Dear Stefan,
I'm really sorry, but could you please put this patch series
instead of v8, which was previously merged into block-next?
The fixes from v8 are below.
Please let me know if you have any comments or issues.

The CI hit a test failure:
https://gitlab.com/qemu-project/qemu/-/jobs/4977256030

Please investigate how to fix this so this series can be merged. Thanks!

Stefan


https://gitlab.com/qemu-project/qemu/-/jobs/4977256030
https://gitlab.com/qemu-project/qemu/-/jobs/4977255992

I'll analyze and fix above issues and resend the patch.
Thanks for letting me know.

Jeuk




Re: [PATCH 01/11] tcg: Clean up local variable shadowing

2023-08-31 Thread Richard Henderson

On 8/31/23 15:55, Philippe Mathieu-Daudé wrote:

-MemOp op = get_memop(oi);
+MemOp o = get_memop(oi);


mop would be a more descriptive replacement.

Otherwise,
Reviewed-by: Richard Henderson 


r~



Re: [PATCH] arm64: Restore trapless ptimer access

2023-08-31 Thread Richard Henderson

On 8/31/23 12:00, Colton Lewis wrote:

Due to recent KVM changes, QEMU is setting a ptimer offset resulting
in unintended trap and emulate access and a consequent performance
hit. Filter out the PTIMER_CNT register to restore trapless ptimer
access.

Quoting Andrew Jones:

Simply reading the CNT register and writing back the same value is
enough to set an offset, since the timer will have certainly moved
past whatever value was read by the time it's written.  QEMU
frequently saves and restores all registers in the get-reg-list array,
unless they've been explicitly filtered out (with Linux commit
680232a94c12, KVM_REG_ARM_PTIMER_CNT is now in the array). So, to
restore trapless ptimer accesses, we need a QEMU patch to filter out
the register.

See
https://lore.kernel.org/kvmarm/gsntttsonus5@coltonlewis-kvm.c.googlers.com/T/#m0770023762a821db2a3f0dd0a7dc6aa54e0d0da9
for additional context.

Signed-off-by: Andrew Jones 


Cc: qemu-sta...@nongnu.org
Reviewed-by: Richard Henderson 



r~


---
  target/arm/kvm64.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 4d904a1d11..2dd46e0a99 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -672,6 +672,7 @@ typedef struct CPRegStateLevel {
   */
  static const CPRegStateLevel non_runtime_cpregs[] = {
  { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
+{ KVM_REG_ARM_PTIMER_CNT, KVM_PUT_FULL_STATE },
  };
  
  int kvm_arm_cpreg_level(uint64_t regidx)





Re: [PATCH v2 7/7] target/mips: Convert Loongson [D]MULT[U].G opcodes to decodetree

2023-08-31 Thread Richard Henderson

On 8/31/23 13:30, Philippe Mathieu-Daudé wrote:

From: Philippe Mathieu-Daudé 

Convert the following opcodes to decodetree:

- MULT.G - multiply 32-bit signed integers
- MULTU.G - multiply 32-bit unsigned integers
- DMULT.G - multiply 64-bit signed integers
- DMULTU.G - multiply 64-bit unsigned integers

Now that all opcodes from the extension have been converted, we
can remove completely gen_loongson_integer() and its 2 calls in
decode_opc_special2_legacy() and decode_opc_special3_legacy().

Signed-off-by: Philippe Mathieu-Daudé 


Reviewed-by: Richard Henderson 



+if (is_double) {
+if (TARGET_LONG_BITS != 64) {
+return false;
+}
+check_mips_64(s);
+}


This preserves existing behaviour vs


-#if defined(TARGET_MIPS64)
-case OPC_DMULT_G_2E:
-case OPC_DMULT_G_2F:
-tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
-break;
-case OPC_DMULTU_G_2E:
-case OPC_DMULTU_G_2F:
-tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
-break;
-#endif


this ifdef.  But it doesn't seem quite right.

It's a behaviour change between qemu-system-mips and qemu-system-mips64 for the same cpu. 
Returning false allows another insn to match instead.  But we have identified the insn, it 
just isn't legal.


Anyway, aren't all of these loongson cpus 64-bit?


r~



Re: [PATCH v2 1/7] target/mips: Simplify Loongson MULTU.G opcode

2023-08-31 Thread Richard Henderson

On 8/31/23 13:30, Philippe Mathieu-Daudé wrote:

Since MULTU opcodes don't record the most significant bits
of the infinite result, sign-extending the sources make no
difference in the result.

Once we remove the sign extension of source registers, MULT
and MULTU are identical (as are DMULT and DMULTU).

Suggested-by: Richard Henderson
Signed-off-by: Philippe Mathieu-Daudé
---
  target/mips/tcg/translate.c | 2 --
  1 file changed, 2 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 1/3] hw/misc: Introduce AMD/Xilix Versal TRNG device

2023-08-31 Thread Richard Henderson

On 8/31/23 10:18, Tong Ho wrote:

This adds a non-cryptographic grade implementation of the
model for the True Random Number Generator (TRNG) component
in AMD/Xilinx Versal device family.

This model is only intended for non-real world testing of
guest software, where cryptographically strong TRNG is not
needed.

This model supports versions 1 & 2 of the Versal TRNG, with
default to be version 2; the 'hw-version' uint32 property
can be set to 0x0100 to override the default.

Other implemented properties:
- 'forced-prng', uint64
   When set to non-zero, "true random reseed" is replaced by
   deterministic reseed based on the given value and other
   deterministic parameters, even when guest software has
   configured the TRNG as "true random reseed".  This option
   allows guest software to reproduce data-dependent defects.

- 'fips-fault-events', uint32, bit-mask
   bit 3: Triggers the SP800-90B entropy health test fault irq
   bit 1: Triggers the FIPS 140-2 continuous test fault irq

Signed-off-by: Tong Ho
---
  hw/misc/Kconfig|   3 +
  hw/misc/meson.build|   3 +
  hw/misc/xlnx-versal-trng.c | 725 +
  include/hw/misc/xlnx-versal-trng.h |  58 +++
  4 files changed, 789 insertions(+)
  create mode 100644 hw/misc/xlnx-versal-trng.c
  create mode 100644 include/hw/misc/xlnx-versal-trng.h


I don't think you should be inventing another PRNG, or related properties.

We already have qemu/guest-random.h, and the -seed command-line parameter to force the use 
of a deterministic PRNG with a given seed value.



r~



Re: [PATCH] target/mips: Simplify Loongson MULTU.G opcode

2023-08-31 Thread Richard Henderson

On 8/31/23 13:11, Philippe Mathieu-Daudé wrote:

Since MULTU opcodes don't record the most significant bits
of the infinite result, sign-extending the sources make no
difference in the result.

Once we remove the sign extension of source registers, MULT
and MULTU are identical (as are DMULT and DMULTU).

Suggested-by: Richard Henderson
Signed-off-by: Philippe Mathieu-Daudé
---
  target/mips/tcg/translate.c | 2 --
  1 file changed, 2 deletions(-)


Reviewed-by: Richard Henderson 

r~



[PATCH v3 5/5] target/arm: Enable SCTLR_EL1.TIDCP for user-only

2023-08-31 Thread Richard Henderson
The linux kernel detects and enables this bit.  Once trapped,
EC_SYSTEMREGISTERTRAP is treated like EC_UNCATEGORIZED, so
no changes required within linux-user/aarch64/cpu_loop.c.

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

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 0bb0585441..b9e09a702d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -243,6 +243,10 @@ static void arm_cpu_reset_hold(Object *obj)
   SCTLR_EnDA | SCTLR_EnDB);
 /* Trap on btype=3 for PACIxSP. */
 env->cp15.sctlr_el[1] |= SCTLR_BT0;
+/* Trap on implementation defined registers. */
+if (cpu_isar_feature(aa64_tidcp1, cpu)) {
+env->cp15.sctlr_el[1] |= SCTLR_TIDCP;
+}
 /* and to the FP/Neon instructions */
 env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
  CPACR_EL1, FPEN, 3);
-- 
2.34.1




[PATCH v3 3/5] target/arm: Implement HCR_EL2.TIDCP

2023-08-31 Thread Richard Henderson
Perform the check for EL2 enabled in the security space and the
TIDCP bit in an out-of-line helper.

Signed-off-by: Richard Henderson 
---
 target/arm/helper.h|  1 +
 target/arm/tcg/op_helper.c | 13 +
 target/arm/tcg/translate-a64.c | 16 ++--
 target/arm/tcg/translate.c | 27 +++
 4 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 95e32a697a..cf5c55a12b 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -81,6 +81,7 @@ DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, 
i32)
 
 DEF_HELPER_4(access_check_cp_reg, cptr, env, i32, i32, i32)
 DEF_HELPER_FLAGS_2(lookup_cp_reg, TCG_CALL_NO_RWG_SE, cptr, env, i32)
+DEF_HELPER_FLAGS_2(tidcp_el1, TCG_CALL_NO_WG, void, env, i32)
 DEF_HELPER_3(set_cp_reg, void, env, cptr, i32)
 DEF_HELPER_2(get_cp_reg, i32, env, cptr)
 DEF_HELPER_3(set_cp_reg64, void, env, cptr, i64)
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
index 3baf8004f6..9014c3ca46 100644
--- a/target/arm/tcg/op_helper.c
+++ b/target/arm/tcg/op_helper.c
@@ -764,6 +764,19 @@ const void *HELPER(lookup_cp_reg)(CPUARMState *env, 
uint32_t key)
 return ri;
 }
 
+/*
+ * Test for HCR_EL2.TIDCP at EL1.
+ * Since implementation defined registers are rare, and within QEMU
+ * most of them are no-op, do not waste HFLAGS space for this and
+ * always use a helper.
+ */
+void HELPER(tidcp_el1)(CPUARMState *env, uint32_t syndrome)
+{
+if (arm_hcr_el2_eff(env) & HCR_TIDCP) {
+raise_exception_ra(env, EXCP_UDEF, syndrome, 2, GETPC());
+}
+}
+
 void HELPER(set_cp_reg)(CPUARMState *env, const void *rip, uint32_t value)
 {
 const ARMCPRegInfo *ri = rip;
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 0b77c92437..786a568d31 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2154,6 +2154,20 @@ static void handle_sys(DisasContext *s, bool isread,
 bool need_exit_tb = false;
 TCGv_ptr tcg_ri = NULL;
 TCGv_i64 tcg_rt;
+uint32_t syndrome;
+
+if (crn == 11 || crn == 15) {
+/*
+ * Check for TIDCP trap, which must take precedence over
+ * the UNDEF for "no such register" etc.
+ */
+syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
+switch (s->current_el) {
+case 1:
+gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
+break;
+}
+}
 
 if (!ri) {
 /* Unknown register; this might be a guest error or a QEMU
@@ -2176,8 +2190,6 @@ static void handle_sys(DisasContext *s, bool isread,
 /* Emit code to perform further access permissions checks at
  * runtime; this may result in an exception.
  */
-uint32_t syndrome;
-
 syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
 gen_a64_update_pc(s, 0);
 tcg_ri = tcg_temp_new_ptr();
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index 38ad8dd4bd..47d3bc5fd5 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -4538,6 +4538,20 @@ void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, 
uint32_t rn_ofs,
 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, [vece]);
 }
 
+static bool aa32_cpreg_encoding_in_impdef_space(uint8_t crn, uint8_t crm)
+{
+static const uint16_t mask[3] = {
+0b00000111,  /* crn ==  9, crm == {c0-c2, c5-c8}   */
+0b000100010011,  /* crn == 10, crm == {c0, c1, c4, c8} */
+0b1001,  /* crn == 11, crm == {c0-c8, c15} */
+};
+
+if (crn >= 9 && crn <= 11) {
+return (mask[crn - 9] >> crm) & 1;
+}
+return false;
+}
+
 static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
int opc1, int crn, int crm, int opc2,
bool isread, int rt, int rt2)
@@ -4619,6 +4633,19 @@ static void do_coproc_insn(DisasContext *s, int cpnum, 
int is64,
 }
 }
 
+if (cpnum == 15 && aa32_cpreg_encoding_in_impdef_space(crn, crm)) {
+/*
+ * Check for TIDCP trap, which must take precedence over the UNDEF
+ * for "no such register" etc.  It shares precedence with HSTR,
+ * but raises the same exception, so order doesn't matter.
+ */
+switch (s->current_el) {
+case 1:
+gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
+break;
+}
+}
+
 if (!ri) {
 /*
  * Unknown register; this might be a guest error or a QEMU
-- 
2.34.1




[PATCH v3 2/5] target/arm: Implement cortex-a710

2023-08-31 Thread Richard Henderson
The cortex-a710 is a first generation ARMv9.0-A processor.

Signed-off-by: Richard Henderson 
---
 docs/system/arm/virt.rst |   1 +
 hw/arm/virt.c|   1 +
 target/arm/tcg/cpu64.c   | 212 +++
 3 files changed, 214 insertions(+)

diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
index 51cdac6841..e1697ac8f4 100644
--- a/docs/system/arm/virt.rst
+++ b/docs/system/arm/virt.rst
@@ -58,6 +58,7 @@ Supported guest CPU types:
 - ``cortex-a57`` (64-bit)
 - ``cortex-a72`` (64-bit)
 - ``cortex-a76`` (64-bit)
+- ``cortex-a710`` (64-bit)
 - ``a64fx`` (64-bit)
 - ``host`` (with KVM only)
 - ``neoverse-n1`` (64-bit)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index a13c658bbf..8ad78b23c2 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -211,6 +211,7 @@ static const char *valid_cpus[] = {
 ARM_CPU_TYPE_NAME("cortex-a55"),
 ARM_CPU_TYPE_NAME("cortex-a72"),
 ARM_CPU_TYPE_NAME("cortex-a76"),
+ARM_CPU_TYPE_NAME("cortex-a710"),
 ARM_CPU_TYPE_NAME("a64fx"),
 ARM_CPU_TYPE_NAME("neoverse-n1"),
 ARM_CPU_TYPE_NAME("neoverse-v1"),
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 0f8972950d..ab63526bea 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -745,6 +745,217 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
 aarch64_add_sve_properties(obj);
 }
 
+static const ARMCPRegInfo cortex_a710_cp_reginfo[] = {
+{ .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 0,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "CPUACTLR2_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 1,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "CPUACTLR3_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 2,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "CPUACTLR4_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 3,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 4,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "CPUECTLR2_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 5,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "CPUPPMCR_EL3", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 4,
+  .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+{ .name = "CPUPWRCTLR_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 7,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "ATCR_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 7, .opc2 = 0,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+{ .name = "CPUACTLR5_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 8, .opc2 = 0,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "CPUACTLR6_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 8, .opc2 = 1,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "CPUACTLR7_EL1", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 8, .opc2 = 2,
+  .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+  .accessfn = access_actlr_w },
+{ .name = "ATCR_EL2", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 4, .crn = 15, .crm = 7, .opc2 = 0,
+  .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+{ .name = "AVTCR_EL2", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 4, .crn = 15, .crm = 7, .opc2 = 1,
+  .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+{ .name = "CPUPPMCR_EL3", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 0,
+  .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+{ .name = "CPUPPMCR2_EL3", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 1,
+  .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+{ .name = "CPUPPMCR4_EL3", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 4,
+  .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+{ .name = "CPUPPMCR5_EL3", .state = 

[PATCH v3 1/5] target/arm: Implement RMR_ELx

2023-08-31 Thread Richard Henderson
Provide a stub implementation, as a write is a "request".

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

diff --git a/target/arm/helper.c b/target/arm/helper.c
index e3f5a7d2bd..654e7d06a8 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8682,16 +8682,25 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 };
 modify_arm_cp_regs(v8_idregs, v8_user_idregs);
 #endif
-/* RVBAR_EL1 is only implemented if EL1 is the highest EL */
+/*
+ * RVBAR_EL1 and RMR_EL1 only implemented if EL1 is the highest EL.
+ * TODO: For RMR, a write with bit 1 set should do something with
+ * cpu_reset(). In the meantime, "the bit is strictly a request",
+ * so we are in spec just ignoring writes.
+ */
 if (!arm_feature(env, ARM_FEATURE_EL3) &&
 !arm_feature(env, ARM_FEATURE_EL2)) {
-ARMCPRegInfo rvbar = {
-.name = "RVBAR_EL1", .state = ARM_CP_STATE_BOTH,
-.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
-.access = PL1_R,
-.fieldoffset = offsetof(CPUARMState, cp15.rvbar),
+ARMCPRegInfo el1_reset_regs[] = {
+{ .name = "RVBAR_EL1", .state = ARM_CP_STATE_BOTH,
+  .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
+  .access = PL1_R,
+  .fieldoffset = offsetof(CPUARMState, cp15.rvbar) },
+{ .name = "RMR_EL1", .state = ARM_CP_STATE_BOTH,
+  .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 2,
+  .access = PL1_RW, .type = ARM_CP_CONST,
+  .resetvalue = arm_feature(env, ARM_FEATURE_AARCH64) }
 };
-define_one_arm_cp_reg(cpu, );
+define_arm_cp_regs(cpu, el1_reset_regs);
 }
 define_arm_cp_regs(cpu, v8_idregs);
 define_arm_cp_regs(cpu, v8_cp_reginfo);
@@ -8775,22 +8784,25 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 if (cpu_isar_feature(aa64_sel2, cpu)) {
 define_arm_cp_regs(cpu, el2_sec_cp_reginfo);
 }
-/* RVBAR_EL2 is only implemented if EL2 is the highest EL */
+/*
+ * RVBAR_EL2 and RMR_EL2 only implemented if EL2 is the highest EL.
+ * See commentary near RMR_EL1.
+ */
 if (!arm_feature(env, ARM_FEATURE_EL3)) {
-ARMCPRegInfo rvbar[] = {
-{
-.name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
-.opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
-.access = PL2_R,
-.fieldoffset = offsetof(CPUARMState, cp15.rvbar),
-},
-{   .name = "RVBAR", .type = ARM_CP_ALIAS,
-.cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
-.access = PL2_R,
-.fieldoffset = offsetof(CPUARMState, cp15.rvbar),
-},
+static const ARMCPRegInfo el2_reset_regs[] = {
+{ .name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
+  .access = PL2_R,
+  .fieldoffset = offsetof(CPUARMState, cp15.rvbar) },
+{ .name = "RVBAR", .type = ARM_CP_ALIAS,
+  .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
+  .access = PL2_R,
+  .fieldoffset = offsetof(CPUARMState, cp15.rvbar) },
+{ .name = "RMR_EL2", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 2,
+  .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 1 },
 };
-define_arm_cp_regs(cpu, rvbar);
+define_arm_cp_regs(cpu, el2_reset_regs);
 }
 }
 
@@ -8801,8 +8813,14 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 { .name = "RVBAR_EL3", .state = ARM_CP_STATE_AA64,
   .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 1,
   .access = PL3_R,
-  .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
-},
+  .fieldoffset = offsetof(CPUARMState, cp15.rvbar), },
+{ .name = "RMR_EL3", .state = ARM_CP_STATE_AA64,
+  .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 2,
+  .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 1 },
+{ .name = "RMR", .state = ARM_CP_STATE_AA32,
+  .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 2,
+  .access = PL3_RW, .type = ARM_CP_CONST,
+  .resetvalue = arm_feature(env, ARM_FEATURE_AARCH64) },
 { .name = "SCTLR_EL3", .state = ARM_CP_STATE_AA64,
   .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 0,
   .access = PL3_RW,

[PATCH v3 0/5] target/arm: Implement cortex-a710

2023-08-31 Thread Richard Henderson
Changes for v3:
  * 9 patches upstreamed
  * Implement RMR_ELx generically, as a stub.
  * Implement TIDCP and the closely related v8.8 FEAT_TIDCP1.


r~


Richard Henderson (5):
  target/arm: Implement RMR_ELx
  target/arm: Implement cortex-a710
  target/arm: Implement HCR_EL2.TIDCP
  target/arm: Implement FEAT_TIDCP1
  target/arm: Enable SCTLR_EL1.TIDCP for user-only

 docs/system/arm/emulation.rst  |   1 +
 docs/system/arm/virt.rst   |   1 +
 target/arm/cpu.h   |   5 +
 target/arm/helper.h|   2 +
 hw/arm/virt.c  |   1 +
 target/arm/cpu.c   |   4 +
 target/arm/helper.c|  64 ++
 target/arm/tcg/cpu64.c | 213 +
 target/arm/tcg/op_helper.c |  33 +
 target/arm/tcg/translate-a64.c |  21 +++-
 target/arm/tcg/translate.c |  33 +
 11 files changed, 353 insertions(+), 25 deletions(-)

-- 
2.34.1




[PATCH v3 4/5] target/arm: Implement FEAT_TIDCP1

2023-08-31 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 docs/system/arm/emulation.rst  |  1 +
 target/arm/cpu.h   |  5 +
 target/arm/helper.h|  1 +
 target/arm/tcg/cpu64.c |  1 +
 target/arm/tcg/op_helper.c | 20 
 target/arm/tcg/translate-a64.c |  5 +
 target/arm/tcg/translate.c |  6 ++
 7 files changed, 39 insertions(+)

diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 2e6a7c8961..ce81fd82fc 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -85,6 +85,7 @@ the following architecture extensions:
 - FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product 
instructions)
 - FEAT_SPECRES (Speculation restriction instructions)
 - FEAT_SSBS (Speculative Store Bypass Safe)
+- FEAT_TIDCP1 (EL0 use of IMPLEMENTATION DEFINED functionality)
 - FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
 - FEAT_TLBIRANGE (TLB invalidate range instructions)
 - FEAT_TTCNP (Translation table Common not private translations)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 278cc135c2..c4ce1b915f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3947,6 +3947,11 @@ static inline bool isar_feature_aa64_hcx(const 
ARMISARegisters *id)
 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0;
 }
 
+static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
+{
+return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR1, TIDCP1) != 0;
+}
+
 static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
 {
 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
diff --git a/target/arm/helper.h b/target/arm/helper.h
index cf5c55a12b..2b02733305 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -81,6 +81,7 @@ DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, 
i32)
 
 DEF_HELPER_4(access_check_cp_reg, cptr, env, i32, i32, i32)
 DEF_HELPER_FLAGS_2(lookup_cp_reg, TCG_CALL_NO_RWG_SE, cptr, env, i32)
+DEF_HELPER_FLAGS_2(tidcp_el0, TCG_CALL_NO_WG, void, env, i32)
 DEF_HELPER_FLAGS_2(tidcp_el1, TCG_CALL_NO_WG, void, env, i32)
 DEF_HELPER_3(set_cp_reg, void, env, cptr, i32)
 DEF_HELPER_2(get_cp_reg, i32, env, cptr)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index ab63526bea..b9691f24f8 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1069,6 +1069,7 @@ void aarch64_max_tcg_initfn(Object *obj)
 t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1);  /* FEAT_XNX */
 t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1);  /* FEAT_ETS */
 t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1);  /* FEAT_HCX */
+t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1);   /* FEAT_TIDCP1 */
 cpu->isar.id_aa64mmfr1 = t;
 
 t = cpu->isar.id_aa64mmfr2;
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
index 9014c3ca46..403f8b09d3 100644
--- a/target/arm/tcg/op_helper.c
+++ b/target/arm/tcg/op_helper.c
@@ -777,6 +777,26 @@ void HELPER(tidcp_el1)(CPUARMState *env, uint32_t syndrome)
 }
 }
 
+/*
+ * Similarly, for FEAT_TIDCP1 at EL0.
+ * We have already checked for the presence of the feature.
+ */
+void HELPER(tidcp_el0)(CPUARMState *env, uint32_t syndrome)
+{
+/* See arm_sctlr(), but we also need the sctlr el. */
+ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
+int target_el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1;
+
+/*
+ * The bit is not valid unless the target el is aa64, but since the
+ * bit test is simpler perform that first and check validity after.
+ */
+if ((env->cp15.sctlr_el[target_el] & SCTLR_TIDCP)
+&& arm_el_is_aa64(env, target_el)) {
+raise_exception_ra(env, EXCP_UDEF, syndrome, target_el, GETPC());
+}
+}
+
 void HELPER(set_cp_reg)(CPUARMState *env, const void *rip, uint32_t value)
 {
 const ARMCPRegInfo *ri = rip;
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 786a568d31..15d985d95e 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2163,6 +2163,11 @@ static void handle_sys(DisasContext *s, bool isread,
  */
 syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
 switch (s->current_el) {
+case 0:
+if (dc_isar_feature(aa64_tidcp1, s)) {
+gen_helper_tidcp_el0(cpu_env, tcg_constant_i32(syndrome));
+}
+break;
 case 1:
 gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
 break;
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index 47d3bc5fd5..976b704200 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -4640,6 +4640,12 @@ static void do_coproc_insn(DisasContext *s, int cpnum, 
int is64,
  * but raises the same exception, so order doesn't matter.
  */
 switch (s->current_el) {
+case 0:
+if (arm_dc_feature(s, ARM_FEATURE_AARCH64)
+&& 

[PATCH 07/11] hw/arm/aspeed: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  hw/arm/aspeed_ast2600.c:391:18: error: declaration shadows a local variable 
[-Werror,-Wshadow]
qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i);
 ^
  hw/arm/aspeed_ast2600.c:283:14: note: previous declaration is here
qemu_irq irq;
 ^
  hw/arm/aspeed_ast2600.c:416:18: error: declaration shadows a local variable 
[-Werror,-Wshadow]
qemu_irq irq = qdev_get_gpio_in(DEVICE(>a7mpcore),
 ^
  hw/arm/aspeed_ast2600.c:283:14: note: previous declaration is here
qemu_irq irq;
 ^

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/aspeed_ast2600.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index a8b3a8065a..f54063445d 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -280,7 +280,6 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 AspeedSoCState *s = ASPEED_SOC(dev);
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 Error *err = NULL;
-qemu_irq irq;
 g_autofree char *sram_name = NULL;
 
 /* Default boot region (SPI memory or ROMs) */
@@ -339,6 +338,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 for (i = 0; i < sc->num_cpus; i++) {
 SysBusDevice *sbd = SYS_BUS_DEVICE(>a7mpcore);
 DeviceState  *d   = DEVICE(>cpu[i]);
+qemu_irq irq;
 
 irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
 sysbus_connect_irq(sbd, i, irq);
-- 
2.41.0




[PATCH 10/11] net/eth: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  net/eth.c:435:20: error: declaration shadows a local variable 
[-Werror,-Wshadow]
size_t input_size = iov_size(pkt, pkt_frags);
   ^
  net/eth.c:413:16: note: previous declaration is here
size_t input_size = iov_size(pkt, pkt_frags);
   ^

Signed-off-by: Philippe Mathieu-Daudé 
---
 net/eth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/eth.c b/net/eth.c
index 649e66bb1f..cf030eed7b 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -432,7 +432,7 @@ _eth_get_rss_ex_src_addr(const struct iovec *pkt, int 
pkt_frags,
 }
 
 if (opthdr.type == IP6_OPT_HOME) {
-size_t input_size = iov_size(pkt, pkt_frags);
+input_size = iov_size(pkt, pkt_frags);
 
 if (input_size < opt_offset + sizeof(opthdr)) {
 return false;
-- 
2.41.0




[PATCH 09/11] hw/ide/ahci: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
  hw/ide/ahci.c:1577:23: error: declaration shadows a local variable 
[-Werror,-Wshadow]
IDEState *s = >port.ifs[j];
  ^
  hw/ide/ahci.c:1569:29: note: previous declaration is here
void ahci_uninit(AHCIState *s)
^

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/ide/ahci.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 48d550f633..8c9a7c2117 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1573,10 +1573,8 @@ void ahci_uninit(AHCIState *s)
 for (i = 0; i < s->ports; i++) {
 AHCIDevice *ad = >dev[i];
 
-for (j = 0; j < 2; j++) {
-IDEState *s = >port.ifs[j];
-
-ide_exit(s);
+for (j = 0; j < ARRAY_SIZE(ad->port.ifs); j++) {
+ide_exit(>port.ifs[j]);
 }
 object_unparent(OBJECT(>port));
 }
-- 
2.41.0




[PATCH 01/11] tcg: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  tcg/tcg.c:2551:27: error: declaration shadows a local variable 
[-Werror,-Wshadow]
MemOp op = get_memop(oi);
  ^
  tcg/tcg.c:2437:12: note: previous declaration is here
TCGOp *op;
   ^
  accel/tcg/tb-maint.c:245:18: error: declaration shadows a local variable 
[-Werror,-Wshadow]
for (int i = 0; i < V_L2_SIZE; i++) {
 ^
  accel/tcg/tb-maint.c:210:9: note: previous declaration is here
int i;
^

Signed-off-by: Philippe Mathieu-Daudé 
---
 accel/tcg/tb-maint.c |  3 +--
 tcg/tcg.c| 16 
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
index c406b2f7b7..f1cf3ad736 100644
--- a/accel/tcg/tb-maint.c
+++ b/accel/tcg/tb-maint.c
@@ -207,13 +207,12 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, 
bool alloc)
 {
 PageDesc *pd;
 void **lp;
-int i;
 
 /* Level 1.  Always allocated.  */
 lp = l1_map + ((index >> v_l1_shift) & (v_l1_size - 1));
 
 /* Level 2..N-1.  */
-for (i = v_l2_levels; i > 0; i--) {
+for (int i = v_l2_levels; i > 0; i--) {
 void **p = qatomic_rcu_read(lp);
 
 if (p == NULL) {
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 620dbe08da..46a3a231b8 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2548,21 +2548,21 @@ static void tcg_dump_ops(TCGContext *s, FILE *f, bool 
have_prefs)
 {
 const char *s_al, *s_op, *s_at;
 MemOpIdx oi = op->args[k++];
-MemOp op = get_memop(oi);
+MemOp o = get_memop(oi);
 unsigned ix = get_mmuidx(oi);
 
-s_al = alignment_name[(op & MO_AMASK) >> MO_ASHIFT];
-s_op = ldst_name[op & (MO_BSWAP | MO_SSIZE)];
-s_at = atom_name[(op & MO_ATOM_MASK) >> MO_ATOM_SHIFT];
-op &= ~(MO_AMASK | MO_BSWAP | MO_SSIZE | MO_ATOM_MASK);
+s_al = alignment_name[(o & MO_AMASK) >> MO_ASHIFT];
+s_op = ldst_name[o & (MO_BSWAP | MO_SSIZE)];
+s_at = atom_name[(o & MO_ATOM_MASK) >> MO_ATOM_SHIFT];
+o &= ~(MO_AMASK | MO_BSWAP | MO_SSIZE | MO_ATOM_MASK);
 
 /* If all fields are accounted for, print symbolically. */
-if (!op && s_al && s_op && s_at) {
+if (!o && s_al && s_op && s_at) {
 col += ne_fprintf(f, ",%s%s%s,%u",
   s_at, s_al, s_op, ix);
 } else {
-op = get_memop(oi);
-col += ne_fprintf(f, ",$0x%x,%u", op, ix);
+o = get_memop(oi);
+col += ne_fprintf(f, ",$0x%x,%u", o, ix);
 }
 i = 1;
 }
-- 
2.41.0




[PATCH 02/11] target/arm: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  target/arm/tcg/translate-m-nocp.c:509:18: error: declaration shadows a local 
variable [-Werror,-Wshadow]
TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
 ^
  target/arm/tcg/translate-m-nocp.c:433:14: note: previous declaration is here
TCGv_i32 tmp;
 ^
  target/arm/tcg/mve_helper.c:2463:17: error: declaration shadows a local 
variable [-Werror,-Wshadow]
int64_t extval = sextract64(src << shift, 0, 48);
^
  target/arm/tcg/mve_helper.c:2443:18: note: previous declaration is here
int64_t val, extval;
 ^
  target/arm/hvf/hvf.c:1936:13: error: declaration shadows a local variable 
[-Werror,-Wshadow]
int ret = 0;
^
  target/arm/hvf/hvf.c:1807:9: note: previous declaration is here
int ret;
^

Signed-off-by: Philippe Mathieu-Daudé 
---
 target/arm/hvf/hvf.c  | 1 -
 target/arm/tcg/mve_helper.c   | 8 
 target/arm/tcg/translate-m-nocp.c | 2 +-
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 486f90be1d..20d534faef 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -1933,7 +1933,6 @@ int hvf_vcpu_exec(CPUState *cpu)
 uint32_t rt = (syndrome >> 5) & 0x1f;
 uint32_t reg = syndrome & SYSREG_MASK;
 uint64_t val;
-int ret = 0;
 
 if (isread) {
 ret = hvf_sysreg_read(cpu, reg, rt);
diff --git a/target/arm/tcg/mve_helper.c b/target/arm/tcg/mve_helper.c
index 403b345ea3..32087b6f0a 100644
--- a/target/arm/tcg/mve_helper.c
+++ b/target/arm/tcg/mve_helper.c
@@ -924,8 +924,8 @@ DO_1OP_IMM(vorri, DO_ORRI)
 bool qc = false;\
 for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) {  \
 bool sat = false;   \
-TYPE r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], );  \
-mergemask([H##ESIZE(e)], r, mask);\
+TYPE r_ = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], ); \
+mergemask([H##ESIZE(e)], r_, mask);   \
 qc |= sat & mask & 1;   \
 }   \
 if (qc) {   \
@@ -2460,7 +2460,7 @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t 
shift,
 return extval;
 }
 } else if (shift < 48) {
-int64_t extval = sextract64(src << shift, 0, 48);
+extval = sextract64(src << shift, 0, 48);
 if (!sat || src == (extval >> shift)) {
 return extval;
 }
@@ -2492,7 +2492,7 @@ static inline uint64_t do_uqrshl48_d(uint64_t src, 
int64_t shift,
 return extval;
 }
 } else if (shift < 48) {
-uint64_t extval = extract64(src << shift, 0, 48);
+extval = extract64(src << shift, 0, 48);
 if (!sat || src == (extval >> shift)) {
 return extval;
 }
diff --git a/target/arm/tcg/translate-m-nocp.c 
b/target/arm/tcg/translate-m-nocp.c
index 33f6478bb9..42308c4db5 100644
--- a/target/arm/tcg/translate-m-nocp.c
+++ b/target/arm/tcg/translate-m-nocp.c
@@ -506,7 +506,7 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
 
 gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
 /* fpInactive case: reads as FPDSCR_NS */
-TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
+tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
 storefn(s, opaque, tmp, true);
 lab_end = gen_new_label();
 tcg_gen_br(lab_end);
-- 
2.41.0




[PATCH 03/11] target/mips: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  target/mips/tcg/nanomips_translate.c.inc:4410:33: error: declaration shadows 
a local variable [-Werror,-Wshadow]
int32_t imm = extract32(ctx->opcode, 1, 13) |
^
  target/mips/tcg/nanomips_translate.c.inc:3577:9: note: previous declaration 
is here
int imm;
^
  target/mips/tcg/translate.c:15578:19: error: declaration shadows a local 
variable [-Werror,-Wshadow]
for (unsigned i = 1; i < 32; i++) {
  ^
  target/mips/tcg/translate.c:15567:9: note: previous declaration is here
int i;
^
  target/mips/tcg/msa_helper.c:7478:13: error: declaration shadows a local 
variable [-Werror,-Wshadow]
MSA_FLOAT_MAXOP(pwx->w[0], min, pws->w[0], pws->w[0], 32);
^
  target/mips/tcg/msa_helper.c:7434:23: note: expanded from macro 
'MSA_FLOAT_MAXOP'
float_status *status = >active_tc.msa_fp_status;
  ^

Signed-off-by: Philippe Mathieu-Daudé 
---
 target/mips/tcg/msa_helper.c | 8 
 target/mips/tcg/translate.c  | 8 +++-
 target/mips/tcg/nanomips_translate.c.inc | 6 +++---
 3 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c
index 29b31d70fe..391a5fca26 100644
--- a/target/mips/tcg/msa_helper.c
+++ b/target/mips/tcg/msa_helper.c
@@ -7431,15 +7431,15 @@ void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
 
 #define MSA_FLOAT_MAXOP(DEST, OP, ARG1, ARG2, BITS) \
 do {\
-float_status *status = >active_tc.msa_fp_status;   \
+float_status *status_ = >active_tc.msa_fp_status;  \
 int c;  \
 \
-set_float_exception_flags(0, status);   \
-DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status);\
+set_float_exception_flags(0, status_);  \
+DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status_);   \
 c = update_msacsr(env, 0, 0);   \
 \
 if (get_enabled_exceptions(env, c)) {   \
-DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;\
+DEST = ((FLOAT_SNAN ## BITS(status_) >> 6) << 6) | c;   \
 }   \
 } while (0)
 
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 9bb40f1849..26d741d960 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -15564,10 +15564,8 @@ void gen_intermediate_code(CPUState *cs, 
TranslationBlock *tb, int *max_insns,
 
 void mips_tcg_init(void)
 {
-int i;
-
 cpu_gpr[0] = NULL;
-for (i = 1; i < 32; i++)
+for (unsigned i = 1; i < 32; i++)
 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
 offsetof(CPUMIPSState,
  active_tc.gpr[i]),
@@ -15584,7 +15582,7 @@ void mips_tcg_init(void)
rname);
 }
 #endif /* !TARGET_MIPS64 */
-for (i = 0; i < 32; i++) {
+for (unsigned i = 0; i < 32; i++) {
 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
 
 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
@@ -15592,7 +15590,7 @@ void mips_tcg_init(void)
 msa_translate_init();
 cpu_PC = tcg_global_mem_new(cpu_env,
 offsetof(CPUMIPSState, active_tc.PC), "PC");
-for (i = 0; i < MIPS_DSP_ACC; i++) {
+for (unsigned i = 0; i < MIPS_DSP_ACC; i++) {
 cpu_HI[i] = tcg_global_mem_new(cpu_env,
offsetof(CPUMIPSState, active_tc.HI[i]),
regnames_HI[i]);
diff --git a/target/mips/tcg/nanomips_translate.c.inc 
b/target/mips/tcg/nanomips_translate.c.inc
index a98dde0d2e..d81a7c2d11 100644
--- a/target/mips/tcg/nanomips_translate.c.inc
+++ b/target/mips/tcg/nanomips_translate.c.inc
@@ -4407,8 +4407,8 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, 
DisasContext *ctx)
 case NM_BPOSGE32C:
 check_dsp_r3(ctx);
 {
-int32_t imm = extract32(ctx->opcode, 1, 13) |
-  extract32(ctx->opcode, 0, 1) << 13;
+imm = extract32(ctx->opcode, 1, 13)
+| extract32(ctx->opcode, 0, 1) << 13;
 
 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
   

[PATCH 05/11] hw/arm/virt: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  hw/arm/virt.c:821:22: error: declaration shadows a local variable 
[-Werror,-Wshadow]
qemu_irq irq = qdev_get_gpio_in(vms->gic,
 ^
  hw/arm/virt.c:803:13: note: previous declaration is here
int irq;
^

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/virt.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index a13c658bbf..32a964b572 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -800,7 +800,6 @@ static void create_gic(VirtMachineState *vms, MemoryRegion 
*mem)
 for (i = 0; i < smp_cpus; i++) {
 DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
 int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
-int irq;
 /* Mapping from the output timer irq lines from the CPU to the
  * GIC PPI inputs we use for the virt board.
  */
@@ -811,7 +810,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion 
*mem)
 [GTIMER_SEC]  = ARCH_TIMER_S_EL1_IRQ,
 };
 
-for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+for (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
 qdev_connect_gpio_out(cpudev, irq,
   qdev_get_gpio_in(vms->gic,
ppibase + timer_irq[irq]));
-- 
2.41.0




[PATCH 08/11] hw/m68k: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  hw/m68k/virt.c:263:13: error: declaration shadows a local variable 
[-Werror,-Wshadow]
BOOTINFOSTR(param_ptr, BI_COMMAND_LINE,
^
  hw/m68k/bootinfo.h:47:13: note: expanded from macro 'BOOTINFOSTR'
int i; \
^
  hw/m68k/virt.c:130:9: note: previous declaration is here
int i;
^

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/m68k/bootinfo.h | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/hw/m68k/bootinfo.h b/hw/m68k/bootinfo.h
index a3d37e3c80..0e6e3eea87 100644
--- a/hw/m68k/bootinfo.h
+++ b/hw/m68k/bootinfo.h
@@ -44,15 +44,14 @@
 
 #define BOOTINFOSTR(base, id, string) \
 do { \
-int i; \
 stw_p(base, id); \
 base += 2; \
 stw_p(base, \
  (sizeof(struct bi_record) + strlen(string) + \
   1 /* null termination */ + 3 /* padding */) & ~3); \
 base += 2; \
-for (i = 0; string[i]; i++) { \
-stb_p(base++, string[i]); \
+for (unsigned i_ = 0; string[i_]; i_++) { \
+stb_p(base++, string[i_]); \
 } \
 stb_p(base++, 0); \
 base = QEMU_ALIGN_PTR_UP(base, 4); \
@@ -60,7 +59,6 @@
 
 #define BOOTINFODATA(base, id, data, len) \
 do { \
-int i; \
 stw_p(base, id); \
 base += 2; \
 stw_p(base, \
@@ -69,8 +67,8 @@
 base += 2; \
 stw_p(base, len); \
 base += 2; \
-for (i = 0; i < len; ++i) { \
-stb_p(base++, data[i]); \
+for (unsigned i_ = 0; i_ < len; ++i_) { \
+stb_p(base++, data[i_]); \
 } \
 base = QEMU_ALIGN_PTR_UP(base, 4); \
 } while (0)
-- 
2.41.0




[PATCH 04/11] target/m68k: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  target/m68k/translate.c:828:18: error: declaration shadows a local variable 
[-Werror,-Wshadow]
TCGv tmp = tcg_temp_new();
 ^
  target/m68k/translate.c:801:15: note: previous declaration is here
TCGv reg, tmp, result;
  ^

Signed-off-by: Philippe Mathieu-Daudé 
---
 target/m68k/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 15b3701b8f..f69ae0e3b0 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -825,7 +825,7 @@ static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, 
int mode, int reg0,
 reg = get_areg(s, reg0);
 result = gen_ldst(s, opsize, reg, val, what, index);
 if (what == EA_STORE || !addrp) {
-TCGv tmp = tcg_temp_new();
+tmp = tcg_temp_new();
 if (reg0 == 7 && opsize == OS_BYTE &&
 m68k_feature(s->env, M68K_FEATURE_M68K)) {
 tcg_gen_addi_i32(tmp, reg, 2);
-- 
2.41.0




[PATCH 11/11] sysemu/device_tree: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  hw/mips/boston.c:472:5: error: declaration shadows a local variable 
[-Werror,-Wshadow]
qemu_fdt_setprop_cells(fdt, name, "reg", reg_base, reg_size);
^
  include/sysemu/device_tree.h:129:13: note: expanded from macro 
'qemu_fdt_setprop_cells'
int i;
^
  hw/mips/boston.c:461:9: note: previous declaration is here
int i;
^

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/sysemu/device_tree.h | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
index ca5339beae..8eab395934 100644
--- a/include/sysemu/device_tree.h
+++ b/include/sysemu/device_tree.h
@@ -126,10 +126,8 @@ int qemu_fdt_add_path(void *fdt, const char *path);
 #define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \
 do {  \
 uint32_t qdt_tmp[] = { __VA_ARGS__ }; \
-int i;\
-  \
-for (i = 0; i < ARRAY_SIZE(qdt_tmp); i++) {   \
-qdt_tmp[i] = cpu_to_be32(qdt_tmp[i]); \
+for (unsigned i_ = 0; i_ < ARRAY_SIZE(qdt_tmp); i_++) {   \
+qdt_tmp[i_] = cpu_to_be32(qdt_tmp[i_]);   \
 } \
 qemu_fdt_setprop(fdt, node_path, property, qdt_tmp,   \
  sizeof(qdt_tmp));\
-- 
2.41.0




[PATCH 00/11] (few more) Steps towards enabling -Wshadow

2023-08-31 Thread Philippe Mathieu-Daudé
For rational see Markus cover on
https://lore.kernel.org/qemu-devel/20230831132546.3525721-1-arm...@redhat.com/

This series contains few more, my take.

Based-on: <20230831132546.3525721-1-arm...@redhat.com>

Philippe Mathieu-Daudé (11):
  tcg: Clean up local variable shadowing
  target/arm: Clean up local variable shadowing
  target/mips: Clean up local variable shadowing
  target/m68k: Clean up local variable shadowing
  hw/arm/virt: Clean up local variable shadowing
  hw/arm/allwinner: Clean up local variable shadowing
  hw/arm/aspeed: Clean up local variable shadowing
  hw/m68k: Clean up local variable shadowing
  hw/ide/ahci: Clean up local variable shadowing
  net/eth: Clean up local variable shadowing
  sysemu/device_tree: Clean up local variable shadowing

 hw/m68k/bootinfo.h   | 10 --
 include/sysemu/device_tree.h |  6 ++
 accel/tcg/tb-maint.c |  3 +--
 hw/arm/allwinner-r40.c   |  7 +++
 hw/arm/aspeed_ast2600.c  |  2 +-
 hw/arm/virt.c|  3 +--
 hw/ide/ahci.c|  6 ++
 net/eth.c|  2 +-
 target/arm/hvf/hvf.c |  1 -
 target/arm/tcg/mve_helper.c  |  8 
 target/arm/tcg/translate-m-nocp.c|  2 +-
 target/m68k/translate.c  |  2 +-
 target/mips/tcg/msa_helper.c |  8 
 target/mips/tcg/translate.c  |  8 +++-
 tcg/tcg.c| 16 
 target/mips/tcg/nanomips_translate.c.inc |  6 +++---
 16 files changed, 39 insertions(+), 51 deletions(-)

-- 
2.41.0




[PATCH 06/11] hw/arm/allwinner: Clean up local variable shadowing

2023-08-31 Thread Philippe Mathieu-Daudé
Fix:

  hw/arm/allwinner-r40.c:412:14: error: declaration shadows a local variable 
[-Werror,-Wshadow]
for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
 ^
  hw/arm/allwinner-r40.c:299:14: note: previous declaration is here
unsigned i;
 ^

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/allwinner-r40.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index 7d29eb224f..a0d367c60d 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -296,10 +296,9 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 {
 const char *r40_nic_models[] = { "gmac", "emac", NULL };
 AwR40State *s = AW_R40(dev);
-unsigned i;
 
 /* CPUs */
-for (i = 0; i < AW_R40_NUM_CPUS; i++) {
+for (unsigned i = 0; i < AW_R40_NUM_CPUS; i++) {
 
 /*
  * Disable secondary CPUs. Guest EL3 firmware will start
@@ -335,7 +334,7 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
  * maintenance interrupt signal to the appropriate GIC PPI inputs,
  * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
  */
-for (i = 0; i < AW_R40_NUM_CPUS; i++) {
+for (unsigned i = 0; i < AW_R40_NUM_CPUS; i++) {
 DeviceState *cpudev = DEVICE(>cpus[i]);
 int ppibase = AW_R40_GIC_NUM_SPI + i * GIC_INTERNAL + GIC_NR_SGIS;
 int irq;
@@ -494,7 +493,7 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
qdev_get_gpio_in(DEVICE(>gic), AW_R40_GIC_SPI_EMAC));
 
 /* Unimplemented devices */
-for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
+for (unsigned i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
 create_unimplemented_device(r40_unimplemented[i].device_name,
 r40_unimplemented[i].base,
 r40_unimplemented[i].size);
-- 
2.41.0




Re: [PATCH v2 2/2] i386: Fix MCE support for AMD hosts

2023-08-31 Thread William Roche

John,

I also noticed something important about this specific code:

Qemu commit cb48748af7dfd7654323eb839d1f853ffa873652 introduced the use 
of the MCG_STATUS_RIPV in the case of a BUS_MCEERR_AR error, but it 
looks like your reference code is not having this flag.


According to me, we should keep this flag in the case of a non-AMD 
machine with a BUS_MCEERR_AR.


The patch should look something like that:

[...]
-    if (code == BUS_MCEERR_AR) {
-    status |= MCI_STATUS_AR | 0x134;
-    mcg_status |= MCG_STATUS_RIPV | MCG_STATUS_EIPV;
+    if (!IS_AMD_CPU(env)) {
+    status |= MCI_STATUS_S;
+    if (code == BUS_MCEERR_AR) {
+    status |= MCI_STATUS_AR | 0x134;
+    mcg_status |= MCG_STATUS_RIPV | MCG_STATUS_EIPV;
[...]


Cheers,
William.


On 7/26/23 22:41, John Allen wrote:

For the most part, AMD hosts can use the same MCE injection code as Intel but,
there are instances where the qemu implementation is Intel specific. First, MCE
deliviery works differently on AMD and does not support broadcast. Second,
kvm_mce_inject generates MCEs that include a number of Intel specific status
bits. Modify kvm_mce_inject to properly generate MCEs on AMD platforms.

Reported-by: William Roche 
Signed-off-by: John Allen 
---
  target/i386/helper.c  |  4 
  target/i386/kvm/kvm.c | 17 +++--
  2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/target/i386/helper.c b/target/i386/helper.c
index 533b29cb91..a6523858e0 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -76,6 +76,10 @@ int cpu_x86_support_mca_broadcast(CPUX86State *env)
  int family = 0;
  int model = 0;
  
+if (IS_AMD_CPU(env)) {

+return 0;
+}
+
  cpu_x86_version(env, , );
  if ((family == 6 && model >= 14) || family > 6) {
  return 1;
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 4b62138459..87a50c8aaf 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -532,16 +532,21 @@ static void kvm_mce_inject(X86CPU *cpu, hwaddr paddr, int 
code)
  CPUState *cs = CPU(cpu);
  CPUX86State *env = >env;
  uint64_t status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN |
-  MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S;
+  MCI_STATUS_MISCV | MCI_STATUS_ADDRV;
  uint64_t mcg_status = MCG_STATUS_MCIP;
  int flags = 0;
  
-if (code == BUS_MCEERR_AR) {

-status |= MCI_STATUS_AR | 0x134;
-mcg_status |= MCG_STATUS_EIPV;
+if (!IS_AMD_CPU(env)) {
+status |= MCI_STATUS_S;
+if (code == BUS_MCEERR_AR) {
+status |= MCI_STATUS_AR | 0x134;
+mcg_status |= MCG_STATUS_EIPV;
+} else {
+status |= 0xc0;
+mcg_status |= MCG_STATUS_RIPV;
+}
  } else {
-status |= 0xc0;
-mcg_status |= MCG_STATUS_RIPV;
+mcg_status |= MCG_STATUS_EIPV | MCG_STATUS_RIPV;
  }
  
  flags = cpu_x86_support_mca_broadcast(env) ? MCE_INJECT_BROADCAST : 0;




Re: [PATCH v2 0/2] Fix MCE handling on AMD hosts

2023-08-31 Thread William Roche

Hello John,

I could test your fixes and I can confirm that the BUS_MCEERR_AR is now 
working on AMD:


Before the fix, the VM panics with:

qemu-system-x86_64: Guest MCE Memory Error at QEMU addr 0x7f89573ce000 
and GUEST addr 0x10b5ce000 of type BUS_MCEERR_AR injected
[   83.562579] mce: [Hardware Error]: CPU 0: Machine Check Exception: 5 
Bank 1: a000
[   83.562585] mce: [Hardware Error]: RIP !INEXACT! 
10: {pv_native_safe_halt+0xf/0x20}

[   83.562592] mce: [Hardware Error]: TSC 3d39402bdc
[   83.562593] mce: [Hardware Error]: PROCESSOR 2:800f12 TIME 1693515449 
SOCKET 0 APIC 0 microcode 800126e
[   83.562596] mce: [Hardware Error]: Machine check: Uncorrected error 
without MCA Recovery

[   83.562597] Kernel panic - not syncing: Fatal local machine check
[   83.563401] Kernel Offset: disabled

With the fix, the same error injection doesn't kill the VM, but 
generates the following console messages:


qemu-system-x86_64: Guest MCE Memory Error at QEMU addr 0x7fa430ab9000 
and GUEST addr 0x118cb9000 of type BUS_MCEERR_AR injected

[  250.851996] Disabling lock debugging due to kernel taint
[  250.852928] mce: Uncorrected hardware memory error in user-access at 
118cb9000
[  250.853261] Memory failure: 0x118cb9: Sending SIGBUS to 
mce_process_rea:1227 due to hardware memory corruption

[  250.854933] mce: [Hardware Error]: Machine check events logged
[  250.855800] Memory failure: 0x118cb9: recovery action for dirty LRU 
page: Recovered
[  250.856661] mce: [Hardware Error]: CPU 2: Machine Check Exception: 7 
Bank 9: bc00

[  250.860552] mce: [Hardware Error]: RIP 33:<7f56b9ecbee5>
[  250.861405] mce: [Hardware Error]: TSC 8c2c664410 ADDR 118cb9000 MISC 8c
[  250.862679] mce: [Hardware Error]: PROCESSOR 2:800f12 TIME 1693508937 
SOCKET 0 APIC 2 microcode 800126e



But a problem still exists with BUS_MCEERR_AO that kills the VM with:

qemu-system-x86_64: warning: Guest MCE Memory Error at QEMU addr 
0x7f1d108e5000 and GUEST addr 0x114ae5000 of type BUS_MCEERR_AO injected
[  157.392905] mce: [Hardware Error]: CPU 0: Machine Check Exception: 7 
Bank 9: bc00
[  157.392912] mce: [Hardware Error]: RIP 10: 
{pv_native_safe_halt+0xf/0x20}

[  157.392919] mce: [Hardware Error]: TSC 60b92a54d0 ADDR 114ae5000 MISC 8c
[  157.392921] mce: [Hardware Error]: PROCESSOR 2:800f12 TIME 1693500765 
SOCKET 0 APIC 0 microcode 800126e
[  157.392924] mce: [Hardware Error]: Machine check: Uncorrected 
unrecoverable error in kernel context

[  157.392925] Kernel panic - not syncing: Fatal local machine check
[  157.402582] Kernel Offset: disabled

As AMD guests can't currently deal with BUS_MCEERR_AO MCE injection, 
according to me the fix is not complete, the 'AO' case must be handled. 
The simplest way is probably to filter it at the qemu level, to only 
inject the 'AR' case -- and it also gives the possibility to let qemu 
provide a message about an ignored 'AO' error.


I would suggest to add a 3rd patch implementing this AMD specific filter:


commit bf8cc74df3fcc7bf958a7c42b876e9c059fe4d06
Author: William Roche 
Date:   Thu Aug 31 18:54:57 2023 +

    i386: Explicitly ignore unsupported BUS_MCEERR_AO MCE on AMD guest

    AMD guests can't currently deal with BUS_MCEERR_AO MCE injection
    as it panics the VM kernel. We filter this event and provide a
    warning message.

    Signed-off-by: William Roche 

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 9ca7187628..bd60d5697b 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -606,6 +606,10 @@ static void kvm_mce_inject(X86CPU *cpu, hwaddr 
paddr, int code)

 mcg_status |= MCG_STATUS_RIPV;
 }
 } else {
+    if (code == BUS_MCEERR_AO) {
+    /* XXX we don't support BUS_MCEERR_AO injection on AMD yet */
+    return;
+    }
 mcg_status |= MCG_STATUS_EIPV | MCG_STATUS_RIPV;
 }

@@ -657,7 +661,8 @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, 
void *addr)

 if (ram_addr != RAM_ADDR_INVALID &&
 kvm_physical_memory_addr_from_host(c->kvm_state, addr, 
)) {

 kvm_hwpoison_page_add(ram_addr);
-    kvm_mce_inject(cpu, paddr, code);
+    if (!IS_AMD_CPU(env) || code != BUS_MCEERR_AO)
+    kvm_mce_inject(cpu, paddr, code);

 /*
  * Use different logging severity based on error type.
@@ -670,8 +675,9 @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, 
void *addr)

 addr, paddr, "BUS_MCEERR_AR");
 } else {
  warn_report("Guest MCE Memory Error at QEMU addr %p and "
- "GUEST addr 0x%" HWADDR_PRIx " of type %s injected",
- addr, paddr, "BUS_MCEERR_AO");
+ "GUEST addr 0x%" HWADDR_PRIx " of type %s %s",
+ addr, paddr, "BUS_MCEERR_AO",
+ IS_AMD_CPU(env) ? "ignored on AMD guest" : 
"injected");

 }

 

[PATCH] arm64: Restore trapless ptimer access

2023-08-31 Thread Colton Lewis
Due to recent KVM changes, QEMU is setting a ptimer offset resulting
in unintended trap and emulate access and a consequent performance
hit. Filter out the PTIMER_CNT register to restore trapless ptimer
access.

Quoting Andrew Jones:

Simply reading the CNT register and writing back the same value is
enough to set an offset, since the timer will have certainly moved
past whatever value was read by the time it's written.  QEMU
frequently saves and restores all registers in the get-reg-list array,
unless they've been explicitly filtered out (with Linux commit
680232a94c12, KVM_REG_ARM_PTIMER_CNT is now in the array). So, to
restore trapless ptimer accesses, we need a QEMU patch to filter out
the register.

See
https://lore.kernel.org/kvmarm/gsntttsonus5@coltonlewis-kvm.c.googlers.com/T/#m0770023762a821db2a3f0dd0a7dc6aa54e0d0da9
for additional context.

Signed-off-by: Andrew Jones 
---
 target/arm/kvm64.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 4d904a1d11..2dd46e0a99 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -672,6 +672,7 @@ typedef struct CPRegStateLevel {
  */
 static const CPRegStateLevel non_runtime_cpregs[] = {
 { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
+{ KVM_REG_ARM_PTIMER_CNT, KVM_PUT_FULL_STATE },
 };
 
 int kvm_arm_cpreg_level(uint64_t regidx)
-- 
2.42.0.283.g2d96d420d3-goog




[PATCH] add option for a multislot usb ccid device

2023-08-31 Thread Golz, Wilhelm
Signed-off-by: Wilhelm Golz 

hw/usb/dev-smartcard-reader.c:
add option for a multislot usb ccid device, similar to audio multi.

---
 hw/usb/dev-smartcard-reader.c | 106 +-
 1 file changed, 103 insertions(+), 3 deletions(-)

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-
reader.c
index be0a4fc3bc..30d8892b4e 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -90,10 +90,13 @@ OBJECT_DECLARE_SIMPLE_TYPE(USBCCIDState,
USB_CCID_DEV)
  *  usbccid.sys (winxp, others untested) is a class driver so it
doesn't care.
  *  linux has a number of class drivers, but openct filters based on
  *   vendor/product (/etc/openct.conf under fedora), hence Gemplus.
+ * Use a Omnikey/HID 3121 with multislot for distinction.
  */
 #define CCID_VENDOR_ID  0x08e6
 #define CCID_PRODUCT_ID 0x4433
 #define CCID_DEVICE_VERSION 0x
+#define CCID_VENDOR_ID_MULTI0x076b
+#define CCID_PRODUCT_ID_MULTI   0x3021
 
 /*
  * BULK_OUT messages from PC to Reader
@@ -312,7 +315,9 @@ struct USBCCIDState {
 uint8_t  bmSlotICCState;
 uint8_t  powered;
 uint8_t  notify_slot_change;
+/* properties */
 uint8_t  debug;
+bool multi;
 };
 
 /*
@@ -411,6 +416,34 @@ static const uint8_t qemu_ccid_descriptor[] = {
 0x01,   /* u8  bMaxCCIDBusySlots; */
 };
 
+static const uint8_t qemu_ccid_descriptor_multi[] = {
+/* Smart Card Device Class Descriptor */
+0x36,   /* u8  bLength; */
+0x21,   /* u8  bDescriptorType; Functional */
+0x10, 0x01, /* u16 bcdCCID; CCID Specification Release Number.
*/
+0x0e,   /* u8  bMaxSlotIndex; 14, as 16 slots can cause
trouble. */
+0x07,   /* u8  bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03
- 1.8 */
+
+0x01, 0x00, /* u32 dwProtocols;  .  = h.*/
+0x00, 0x00, /* : see above */
+0xa0, 0x0f, 0x00, 0x00, /* u32 dwMaximumClock; */
+0x00, 0x00, 0x01, 0x00,
+0x00, /* u8 bNumClockSupported; see above */
+0x80, 0x25, 0x00, 0x00, /* u32 dwMaxDataRate ; see above */
+0x00, 0xC2, 0x01, 0x00,
+0x00,   /* u8  bNumDataRatesSupported; see above */
+0xfe, 0x00, 0x00, 0x00, /* u32 dwMaxIFSD; see above */
+0x00, 0x00, 0x00, 0x00, /* u32 dwSyncProtocols; see above */
+0x00, 0x00, 0x00, 0x00, /* u32 dwMechanical; see above */
+0xfe, 0x04, 0x04, 0x00, /* u32 dwFeatures; 400 for better
compat. */
+0x12, 0x00, 0x01, 0x00, /* u32 dwMaxCCIDMessageLength; see
above */
+0xFF,   /* u8  bClassGetResponse; see above */
+0xFF,   /* u8  bClassEnvelope; see above */
+0x00, 0x00, /* u16 wLcdLayout; see above */
+0x01,   /* u8  bPINSupport; see above */
+0x0f,   /* u8  bMaxCCIDBusySlots; modified from 1 */
+};
+
 enum {
 STR_MANUFACTURER = 1,
 STR_PRODUCT,
@@ -457,6 +490,38 @@ static const USBDescIface desc_iface0 = {
 }
 };
 
+static const USBDescIface desc_iface0_multi = {
+.bInterfaceNumber  = 0,
+.bNumEndpoints = 3,
+.bInterfaceClass   = USB_CLASS_CSCID,
+.bInterfaceSubClass= USB_SUBCLASS_UNDEFINED,
+.bInterfaceProtocol= 0x00,
+.iInterface= STR_INTERFACE,
+.ndesc = 1,
+.descs = (USBDescOther[]) {
+{
+/* smartcard descriptor */
+.data = qemu_ccid_descriptor_multi,
+},
+},
+.eps = (USBDescEndpoint[]) {
+{
+.bEndpointAddress  = USB_DIR_IN | CCID_INT_IN_EP,
+.bmAttributes  = USB_ENDPOINT_XFER_INT,
+.bInterval = 255,
+.wMaxPacketSize= 64,
+},{
+.bEndpointAddress  = USB_DIR_IN | CCID_BULK_IN_EP,
+.bmAttributes  = USB_ENDPOINT_XFER_BULK,
+.wMaxPacketSize= 64,
+},{
+.bEndpointAddress  = USB_DIR_OUT | CCID_BULK_OUT_EP,
+.bmAttributes  = USB_ENDPOINT_XFER_BULK,
+.wMaxPacketSize= 64,
+},
+}
+};
+
 static const USBDescDevice desc_device = {
 .bcdUSB= 0x0110,
 .bMaxPacketSize0   = 64,
@@ -474,6 +539,23 @@ static const USBDescDevice desc_device = {
 },
 };
 
+static const USBDescDevice desc_device_multi = {
+.bcdUSB= 0x0110,
+.bMaxPacketSize0   = 64,
+.bNumConfigurations= 1,
+.confs = (USBDescConfig[]) {
+{
+.bNumInterfaces= 1,
+.bConfigurationValue   = 1,
+.bmAttributes  = USB_CFG_ATT_ONE |
USB_CFG_ATT_SELFPOWER |
+ USB_CFG_ATT_WAKEUP,
+.bMaxPower = 50,
+.nif = 1,
+.ifs = 

[PATCH v3.2 5/7] aspeed: Create flash devices only when defaults are enabled

2023-08-31 Thread Cédric Le Goater

When the -nodefaults option is set, flash devices should be created
with :

-blockdev node-name=fmc0,driver=file,filename=./flash.img \
-device mx66u51235f,cs=0x0,bus=ssi.0,drive=fmc0 \

To be noted that in this case, the ROM will not be installed and the
initial boot sequence (U-Boot loading) will fetch instructions using
SPI transactions which is significantly slower. That's exactly how HW
operates though.

Signed-off-by: Cédric Le Goater 
---
 docs/system/arm/aspeed.rst | 35 +--
 hw/arm/aspeed.c|  6 --
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst
index 80538422a1a4..b2dea54eedad 100644
--- a/docs/system/arm/aspeed.rst
+++ b/docs/system/arm/aspeed.rst
@@ -104,7 +104,7 @@ To boot a kernel directly from a Linux build tree:
 -dtb arch/arm/boot/dts/aspeed-ast2600-evb.dtb \
 -initrd rootfs.cpio
 
-The image should be attached as an MTD drive. Run :

+To boot the machine from the flash image, use an MTD drive :
 
 .. code-block:: bash
 
@@ -117,23 +117,46 @@ Options specific to Aspeed machines are :

device by using the FMC controller to load the instructions, and
not simply from RAM. This takes a little longer.
 
- * ``fmc-model`` to change the FMC Flash model. FW needs support for

-   the chip model to boot.
+ * ``fmc-model`` to change the default FMC Flash model. FW needs
+   support for the chip model to boot.
 
- * ``spi-model`` to change the SPI Flash model.

+ * ``spi-model`` to change the default SPI Flash model.
 
  * ``bmc-console`` to change the default console device. Most of the

machines use the ``UART5`` device for a boot console, which is
mapped on ``/dev/ttyS4`` under Linux, but it is not always the
case.
 
-For instance, to start the ``ast2500-evb`` machine with a different

-FMC chip and a bigger (64M) SPI chip, use :
+To use other flash models, for instance a different FMC chip and a
+bigger (64M) SPI for the ``ast2500-evb`` machine, run :
 
 .. code-block:: bash
 
   -M ast2500-evb,fmc-model=mx25l25635e,spi-model=mx66u51235f
 
+When more flexibility is needed to define the flash devices, to use

+different flash models or define all flash devices (up to 8), the
+``-nodefaults`` QEMU option can be used to avoid creating the default
+flash devices.
+
+Flash devices should then be created from the command line and attached
+to a block device :
+
+.. code-block:: bash
+
+  $ qemu-system-arm -M ast2600-evb \
+-blockdev node-name=fmc0,driver=file,filename=/path/to/fmc0.img \
+   -device mx66u51235f,bus=ssi.0,cs=0x0,drive=fmc0 \
+   -blockdev node-name=fmc1,driver=file,filename=/path/to/fmc1.img \
+   -device mx66u51235f,bus=ssi.0,cs=0x1,drive=fmc1 \
+   -blockdev node-name=spi1,driver=file,filename=/path/to/spi1.img \
+   -device mx66u51235f,cs=0x0,bus=ssi.1,drive=spi1 \
+   -nographic -nodefaults
+
+In that case, the machine boots fetching instructions from the FMC0
+device. It is slower to start but closer to what HW does. Using the
+machine option ``execute-in-place`` has a similar effect.
+
 To change the boot console and use device ``UART3`` (``/dev/ttyS2``
 under Linux), use :
 
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c

index cd92cf9ce0bb..271512ce5ced 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -396,12 +396,14 @@ static void aspeed_machine_init(MachineState *machine)
 connect_serial_hds_to_uarts(bmc);
 qdev_realize(DEVICE(>soc), NULL, _abort);
 
-aspeed_board_init_flashes(>soc.fmc,

+if (defaults_enabled()) {
+aspeed_board_init_flashes(>soc.fmc,
   bmc->fmc_model ? bmc->fmc_model : amc->fmc_model,
   amc->num_cs, 0);
-aspeed_board_init_flashes(>soc.spi[0],
+aspeed_board_init_flashes(>soc.spi[0],
   bmc->spi_model ? bmc->spi_model : amc->spi_model,
   1, amc->num_cs);
+}
 
 if (machine->kernel_filename && sc->num_cpus > 1) {

 /* With no u-boot we must set up a boot stub for the secondary CPU */
--
2.41.0





Re: [PATCH v2 11/12] hw/vmapple/virtio-blk: Add support for apple virtio-blk

2023-08-31 Thread Philippe Mathieu-Daudé

On 31/8/23 22:03, Stefan Hajnoczi wrote:

On Wed, Aug 30, 2023 at 04:14:24PM +, Alexander Graf wrote:

Apple has its own virtio-blk PCI device ID where it deviates from the
official virtio-pci spec slightly: It puts a new "apple type"
field at a static offset in config space and introduces a new barrier
command.

This patch first creates a mechanism for virtio-blk downstream classes to
handle unknown commands. It then creates such a downstream class and a new
vmapple-virtio-blk-pci class which support the additional apple type config
identifier as well as the barrier command.

It then exposes 2 subclasses from that that we can use to expose root and
aux virtio-blk devices: "vmapple-virtio-root" and "vmapple-virtio-aux".

Signed-off-by: Alexander Graf 


Aside from my comments below:

Reviewed-by: Stefan Hajnoczi 



---

v1 -> v2:

   - Rework to make all vmapple virtio-blk logic a subclass
---
  include/hw/pci/pci_ids.h|   1 +
  include/hw/virtio/virtio-blk.h  |  12 +-
  include/hw/vmapple/virtio-blk.h |  39 ++
  hw/block/virtio-blk.c   |  19 ++-
  hw/vmapple/virtio-blk.c | 212 
  hw/vmapple/Kconfig  |   3 +
  hw/vmapple/meson.build  |   1 +
  7 files changed, 282 insertions(+), 5 deletions(-)
  create mode 100644 include/hw/vmapple/virtio-blk.h
  create mode 100644 hw/vmapple/virtio-blk.c



diff --git a/include/hw/vmapple/virtio-blk.h b/include/hw/vmapple/virtio-blk.h
new file mode 100644
index 00..b23106a3df
--- /dev/null
+++ b/include/hw/vmapple/virtio-blk.h
@@ -0,0 +1,39 @@
+/*
+ * VMApple specific VirtIO Block implementation
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_VMAPPLE_CFG_H
+#define HW_VMAPPLE_CFG_H
+
+#include "hw/sysbus.h"


I'm surprised to see this header since this isn't a SysBus device. Is it
really needed?


+#include "qom/object.h"
+#include "hw/virtio/virtio-pci.h"


"virtio-pci.h" surprised me too.


+#include "hw/virtio/virtio-blk.h"
+
+#define TYPE_VMAPPLE_VIRTIO_BLK "vmapple-virtio-blk"
+#define TYPE_VMAPPLE_VIRTIO_ROOT "vmapple-virtio-root"
+#define TYPE_VMAPPLE_VIRTIO_AUX "vmapple-virtio-aux"
+
+OBJECT_DECLARE_TYPE(VMAppleVirtIOBlk, VMAppleVirtIOBlkClass, 
VMAPPLE_VIRTIO_BLK)
+
+typedef struct VMAppleVirtIOBlkClass {
+/*< private >*/
+VirtIOBlkClass parent;
+/*< public >*/
+void (*get_config)(VirtIODevice *vdev, uint8_t *config);
+} VMAppleVirtIOBlkClass;
+
+typedef struct VMAppleVirtIOBlk {
+/*  */
+VirtIOBlock parent_obj;
+
+/*  */
+uint32_t apple_type;
+} VMAppleVirtIOBlk;
+
+#endif /* HW_VMAPPLE_CFG_H */





[PATCH v2 3/7] target/mips: Convert Loongson DDIV.G opcodes to decodetree

2023-08-31 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Introduce decode_loongson() to decode all Loongson vendor
specific opcodes. Start converting a single opcode: DDIV.G
(divide 64-bit signed integers).

Reviewed-by: Richard Henderson 
Signed-off-by: Philippe Mathieu-Daudé 
---
 target/mips/tcg/translate.h   |  1 +
 target/mips/tcg/godson2.decode| 16 ++
 target/mips/tcg/loong-ext.decode  | 17 +++
 target/mips/tcg/loong_translate.c | 85 +++
 target/mips/tcg/translate.c   | 26 ++
 target/mips/tcg/meson.build   |  3 ++
 6 files changed, 125 insertions(+), 23 deletions(-)
 create mode 100644 target/mips/tcg/godson2.decode
 create mode 100644 target/mips/tcg/loong-ext.decode
 create mode 100644 target/mips/tcg/loong_translate.c

diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index db3dc932c7..a2365c3c9a 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -220,6 +220,7 @@ bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
 bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
 bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
 bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
+bool decode_ext_loongson(DisasContext *ctx, uint32_t insn);
 #if defined(TARGET_MIPS64)
 bool decode_ase_lcsr(DisasContext *ctx, uint32_t insn);
 bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
new file mode 100644
index 00..382123cc3e
--- /dev/null
+++ b/target/mips/tcg/godson2.decode
@@ -0,0 +1,16 @@
+# Godson2 Integer instructions
+#
+# Copyright (C) 2021  Philippe Mathieu-Daudé
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Reference:
+#   Godson-2E Software Manual
+#   (Document Number: godson2e-user-manual-V0.6)
+#
+
+ rs rt rd
+
+@rs_rt_rd   .. rs:5  rt:5  rd:5  . ..   
+
+DDIV_G  01 . . . 0 00   @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
new file mode 100644
index 00..407ca5c78b
--- /dev/null
+++ b/target/mips/tcg/loong-ext.decode
@@ -0,0 +1,17 @@
+# Loongson Extension instructions
+#
+# Copyright (C) 2021  Philippe Mathieu-Daudé
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Reference:
+#   STLS2F01 User Manual
+#   Appendix A: new integer instructions
+#   (Document Number: UM0447)
+#
+
+ rs rt rd !extern
+
+@rs_rt_rd   .. rs:5  rt:5  rd:5  . ..   
+
+DDIV_G  011100 . . . 0 010101   @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c 
b/target/mips/tcg/loong_translate.c
new file mode 100644
index 00..bb329ef027
--- /dev/null
+++ b/target/mips/tcg/loong_translate.c
@@ -0,0 +1,85 @@
+/*
+ * MIPS Loongson translation routines
+ *
+ *  Copyright (c) 2004-2005 Jocelyn Mayer
+ *  Copyright (c) 2006 Marius Groeger (FPU operations)
+ *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
+ *  Copyright (c) 2011 Richard Henderson 
+ *  Copyright (c) 2021 Philippe Mathieu-Daudé
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#include "qemu/osdep.h"
+#include "translate.h"
+
+/* Include the auto-generated decoder.  */
+#include "decode-godson2.c.inc"
+#include "decode-loong-ext.c.inc"
+
+/*
+ * Word or double-word Fixed-point instructions.
+ * 
+ *
+ * Fixed-point multiplies and divisions write only one result
+ * into general-purpose registers.
+ */
+
+static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, int rt)
+{
+TCGv t0, t1;
+TCGLabel *l1, *l2, *l3;
+
+if (TARGET_LONG_BITS != 64) {
+return false;
+}
+check_mips_64(s);
+
+if (rd == 0) {
+/* Treat as NOP. */
+return true;
+}
+
+t0 = tcg_temp_new();
+t1 = tcg_temp_new();
+l1 = gen_new_label();
+l2 = gen_new_label();
+l3 = gen_new_label();
+
+gen_load_gpr(t0, rs);
+gen_load_gpr(t1, rt);
+
+tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+tcg_gen_movi_tl(cpu_gpr[rd], 0);
+tcg_gen_br(l3);
+gen_set_label(l1);
+
+tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+tcg_gen_mov_tl(cpu_gpr[rd], t0);
+
+tcg_gen_br(l3);
+gen_set_label(l2);
+tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+gen_set_label(l3);
+
+return true;
+}
+
+static bool trans_DDIV_G(DisasContext *s, arg_muldiv *a)
+{
+return gen_lext_DIV_G(s, a->rt, a->rs, a->rd);
+}
+
+bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
+{
+if ((ctx->insn_flags & INSN_LOONGSON2E)
+&& decode_godson2(ctx, ctx->opcode)) {
+return true;
+}
+if ((ctx->insn_flags & ASE_LEXT)
+&& decode_loong_ext(ctx, ctx->opcode)) {
+return true;
+}
+return false;
+}
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 19e73aea60..42be1689c2 

[PATCH v2 1/7] target/mips: Simplify Loongson MULTU.G opcode

2023-08-31 Thread Philippe Mathieu-Daudé
Since MULTU opcodes don't record the most significant bits
of the infinite result, sign-extending the sources make no
difference in the result.

Once we remove the sign extension of source registers, MULT
and MULTU are identical (as are DMULT and DMULTU).

Suggested-by: Richard Henderson 
Signed-off-by: Philippe Mathieu-Daudé 
---
 target/mips/tcg/translate.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 9bb40f1849..e0a76b9432 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -3625,8 +3625,6 @@ static void gen_loongson_integer(DisasContext *ctx, 
uint32_t opc,
 break;
 case OPC_MULTU_G_2E:
 case OPC_MULTU_G_2F:
-tcg_gen_ext32u_tl(t0, t0);
-tcg_gen_ext32u_tl(t1, t1);
 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
 break;
-- 
2.41.0




[PATCH v2 7/7] target/mips: Convert Loongson [D]MULT[U].G opcodes to decodetree

2023-08-31 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Convert the following opcodes to decodetree:

- MULT.G - multiply 32-bit signed integers
- MULTU.G - multiply 32-bit unsigned integers
- DMULT.G - multiply 64-bit signed integers
- DMULTU.G - multiply 64-bit unsigned integers

Now that all opcodes from the extension have been converted, we
can remove completely gen_loongson_integer() and its 2 calls in
decode_opc_special2_legacy() and decode_opc_special3_legacy().

Signed-off-by: Philippe Mathieu-Daudé 
---
 target/mips/tcg/godson2.decode|  3 ++
 target/mips/tcg/loong-ext.decode  |  3 ++
 target/mips/tcg/loong_translate.c | 41 +
 target/mips/tcg/translate.c   | 73 +--
 4 files changed, 49 insertions(+), 71 deletions(-)

diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
index e3bf6b12e4..86015ac8e5 100644
--- a/target/mips/tcg/godson2.decode
+++ b/target/mips/tcg/godson2.decode
@@ -13,6 +13,9 @@
 
 @rs_rt_rd   .. rs:5  rt:5  rd:5  . ..   
 
+MULTu_G 01 . . . 0 01100-   @rs_rt_rd
+DMULTu_G01 . . . 0 01110-   @rs_rt_rd
+
 DIV_G   01 . . . 0 011010   @rs_rt_rd
 DIVU_G  01 . . . 0 011011   @rs_rt_rd
 DDIV_G  01 . . . 0 00   @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
index d63406e3f4..b05236eb41 100644
--- a/target/mips/tcg/loong-ext.decode
+++ b/target/mips/tcg/loong-ext.decode
@@ -14,6 +14,9 @@
 
 @rs_rt_rd   .. rs:5  rt:5  rd:5  . ..   
 
+MULTu_G 011100 . . . 0 0100-0   @rs_rt_rd
+DMULTu_G011100 . . . 0 0100-1   @rs_rt_rd
+
 DIV_G   011100 . . . 0 010100   @rs_rt_rd
 DDIV_G  011100 . . . 0 010101   @rs_rt_rd
 DIVU_G  011100 . . . 0 010110   @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c 
b/target/mips/tcg/loong_translate.c
index bddf1cb7aa..c896e64b9e 100644
--- a/target/mips/tcg/loong_translate.c
+++ b/target/mips/tcg/loong_translate.c
@@ -252,6 +252,47 @@ static bool trans_DMODU_G(DisasContext *s, arg_muldiv *a)
 return gen_lext_MODU_G(s, a->rt, a->rs, a->rd, true);
 }
 
+static bool gen_lext_MULT_G(DisasContext *s, int rd, int rs, int rt,
+bool is_double)
+{
+TCGv t0, t1;
+
+if (is_double) {
+if (TARGET_LONG_BITS != 64) {
+return false;
+}
+check_mips_64(s);
+}
+
+if (rd == 0) {
+/* Treat as NOP. */
+return true;
+}
+
+t0 = tcg_temp_new();
+t1 = tcg_temp_new();
+
+gen_load_gpr(t0, rs);
+gen_load_gpr(t1, rt);
+
+tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+if (!is_double) {
+tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+}
+
+return true;
+}
+
+static bool trans_MULTu_G(DisasContext *s, arg_muldiv *a)
+{
+return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false);
+}
+
+static bool trans_DMULTu_G(DisasContext *s, arg_muldiv *a)
+{
+return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true);
+}
+
 bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
 {
 if ((ctx->insn_flags & INSN_LOONGSON2E)
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 2cfabb3103..e770840d28 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -328,11 +328,6 @@ enum {
 OPC_MUL  = 0x02 | OPC_SPECIAL2,
 OPC_MSUB = 0x04 | OPC_SPECIAL2,
 OPC_MSUBU= 0x05 | OPC_SPECIAL2,
-/* Loongson 2F */
-OPC_MULT_G_2F   = 0x10 | OPC_SPECIAL2,
-OPC_DMULT_G_2F  = 0x11 | OPC_SPECIAL2,
-OPC_MULTU_G_2F  = 0x12 | OPC_SPECIAL2,
-OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
 /* Misc */
 OPC_CLZ  = 0x20 | OPC_SPECIAL2,
 OPC_CLO  = 0x21 | OPC_SPECIAL2,
@@ -361,12 +356,6 @@ enum {
 OPC_RDHWR= 0x3B | OPC_SPECIAL3,
 OPC_GINV = 0x3D | OPC_SPECIAL3,
 
-/* Loongson 2E */
-OPC_MULT_G_2E   = 0x18 | OPC_SPECIAL3,
-OPC_MULTU_G_2E  = 0x19 | OPC_SPECIAL3,
-OPC_DMULT_G_2E  = 0x1C | OPC_SPECIAL3,
-OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
-
 /* MIPS DSP Load */
 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
 /* MIPS DSP Arithmetic */
@@ -3582,46 +3571,6 @@ static void gen_cl(DisasContext *ctx, uint32_t opc,
 }
 }
 
-/* Godson integer instructions */
-static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
- int rd, int rs, int rt)
-{
-TCGv t0, t1;
-
-if (rd == 0) {
-/* Treat as NOP. */
-return;
-}
-
-t0 = tcg_temp_new();
-t1 = tcg_temp_new();
-gen_load_gpr(t0, rs);
-gen_load_gpr(t1, rt);
-
-switch (opc) {
-case OPC_MULT_G_2E:
-case OPC_MULT_G_2F:
-tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
-tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
-break;
-case 

[PATCH v2 4/7] target/mips: Convert Loongson DIV.G opcodes to decodetree

2023-08-31 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

DIV.G and DDIV.G are very similar. Provide gen_lext_DIV_G() a
'is_double' argument so it can generate DIV.G (divide 32-bit
signed integers).

With this commit we explicit the template used to generate
opcode for 32/64-bit word variants. Next commits will be less
verbose by providing both variants at once.

Reviewed-by: Richard Henderson 
Signed-off-by: Philippe Mathieu-Daudé 
---
 target/mips/tcg/godson2.decode|  1 +
 target/mips/tcg/loong-ext.decode  |  1 +
 target/mips/tcg/loong_translate.c | 28 ++--
 target/mips/tcg/translate.c   | 26 --
 4 files changed, 24 insertions(+), 32 deletions(-)

diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
index 382123cc3e..91940c1263 100644
--- a/target/mips/tcg/godson2.decode
+++ b/target/mips/tcg/godson2.decode
@@ -13,4 +13,5 @@
 
 @rs_rt_rd   .. rs:5  rt:5  rd:5  . ..   
 
+DIV_G   01 . . . 0 011010   @rs_rt_rd
 DDIV_G  01 . . . 0 00   @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
index 407ca5c78b..e9378abc8e 100644
--- a/target/mips/tcg/loong-ext.decode
+++ b/target/mips/tcg/loong-ext.decode
@@ -14,4 +14,5 @@
 
 @rs_rt_rd   .. rs:5  rt:5  rd:5  . ..   
 
+DIV_G   011100 . . . 0 010100   @rs_rt_rd
 DDIV_G  011100 . . . 0 010101   @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c 
b/target/mips/tcg/loong_translate.c
index bb329ef027..d42cdb7d2e 100644
--- a/target/mips/tcg/loong_translate.c
+++ b/target/mips/tcg/loong_translate.c
@@ -25,15 +25,18 @@
  * into general-purpose registers.
  */
 
-static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, int rt)
+static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, int rt,
+   bool is_double)
 {
 TCGv t0, t1;
 TCGLabel *l1, *l2, *l3;
 
-if (TARGET_LONG_BITS != 64) {
-return false;
+if (is_double) {
+if (TARGET_LONG_BITS != 64) {
+return false;
+}
+check_mips_64(s);
 }
-check_mips_64(s);
 
 if (rd == 0) {
 /* Treat as NOP. */
@@ -49,26 +52,39 @@ static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, 
int rt)
 gen_load_gpr(t0, rs);
 gen_load_gpr(t1, rt);
 
+if (!is_double) {
+tcg_gen_ext32s_tl(t0, t0);
+tcg_gen_ext32s_tl(t1, t1);
+}
 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
 tcg_gen_movi_tl(cpu_gpr[rd], 0);
 tcg_gen_br(l3);
 gen_set_label(l1);
 
-tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+tcg_gen_brcondi_tl(TCG_COND_NE, t0, is_double && TARGET_LONG_BITS == 64
+? LLONG_MIN : INT_MIN, l2);
 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
 tcg_gen_mov_tl(cpu_gpr[rd], t0);
 
 tcg_gen_br(l3);
 gen_set_label(l2);
 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+if (!is_double) {
+tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+}
 gen_set_label(l3);
 
 return true;
 }
 
+static bool trans_DIV_G(DisasContext *s, arg_muldiv *a)
+{
+return gen_lext_DIV_G(s, a->rt, a->rs, a->rd, false);
+}
+
 static bool trans_DDIV_G(DisasContext *s, arg_muldiv *a)
 {
-return gen_lext_DIV_G(s, a->rt, a->rs, a->rd);
+return gen_lext_DIV_G(s, a->rt, a->rs, a->rd, true);
 }
 
 bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 42be1689c2..59853f1d87 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -333,7 +333,6 @@ enum {
 OPC_DMULT_G_2F  = 0x11 | OPC_SPECIAL2,
 OPC_MULTU_G_2F  = 0x12 | OPC_SPECIAL2,
 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
-OPC_DIV_G_2F= 0x14 | OPC_SPECIAL2,
 OPC_DIVU_G_2F   = 0x16 | OPC_SPECIAL2,
 OPC_DDIVU_G_2F  = 0x17 | OPC_SPECIAL2,
 OPC_MOD_G_2F= 0x1c | OPC_SPECIAL2,
@@ -371,7 +370,6 @@ enum {
 /* Loongson 2E */
 OPC_MULT_G_2E   = 0x18 | OPC_SPECIAL3,
 OPC_MULTU_G_2E  = 0x19 | OPC_SPECIAL3,
-OPC_DIV_G_2E= 0x1A | OPC_SPECIAL3,
 OPC_DIVU_G_2E   = 0x1B | OPC_SPECIAL3,
 OPC_DMULT_G_2E  = 0x1C | OPC_SPECIAL3,
 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
@@ -3623,28 +3621,6 @@ static void gen_loongson_integer(DisasContext *ctx, 
uint32_t opc,
 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
 break;
-case OPC_DIV_G_2E:
-case OPC_DIV_G_2F:
-{
-TCGLabel *l1 = gen_new_label();
-TCGLabel *l2 = gen_new_label();
-TCGLabel *l3 = gen_new_label();
-tcg_gen_ext32s_tl(t0, t0);
-tcg_gen_ext32s_tl(t1, t1);
-tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
-tcg_gen_movi_tl(cpu_gpr[rd], 0);
-tcg_gen_br(l3);
-gen_set_label(l1);
-

[PATCH v2 0/7] target/mips: Convert Loongson LEXT opcodes to decodetree

2023-08-31 Thread Philippe Mathieu-Daudé
Respin of old series...

Since v1 [*]:
- Fixed '!is_double' check (rth)
- Rebased (removing tcg_temp_free calls)
- Simplified MULT[U].G (rth)
- Added R-b

Cover from v1:

  Loongson is next step in the "MIPS decodetree conversion" epic.
  Start with the simplest extension.

  The diffstat addition comes from the TCG functions expanded.
  The code is easier to review now.
  IMO this is also a good template to show how easy a decodetree
  conversion can be (and how nice the .decode file is to review) :P

Please review,

Phil.

Based-on: <20230831201140.85799-1-phi...@linaro.org>
  "target/mips: Simplify Loongson MULTU.G opcode"

[*] https://lore.kernel.org/qemu-devel/20210112215504.2093955-1-f4...@amsat.org/

Philippe Mathieu-Daudé (7):
  target/mips: Simplify Loongson MULTU.G opcode
  target/mips: Re-introduce OPC_ADDUH_QB_DSP and OPC_MUL_PH_DSP
  target/mips: Convert Loongson DDIV.G opcodes to decodetree
  target/mips: Convert Loongson DIV.G opcodes to decodetree
  target/mips: Convert Loongson [D]DIVU.G opcodes to decodetree
  target/mips: Convert Loongson [D]MOD[U].G opcodes to decodetree
  target/mips: Convert Loongson [D]MULT[U].G opcodes to decodetree

 target/mips/tcg/translate.h   |   1 +
 target/mips/tcg/godson2.decode|  27 +++
 target/mips/tcg/loong-ext.decode  |  28 +++
 target/mips/tcg/loong_translate.c | 307 ++
 target/mips/tcg/translate.c   | 264 +
 target/mips/tcg/meson.build   |   3 +
 6 files changed, 376 insertions(+), 254 deletions(-)
 create mode 100644 target/mips/tcg/godson2.decode
 create mode 100644 target/mips/tcg/loong-ext.decode
 create mode 100644 target/mips/tcg/loong_translate.c

-- 
2.41.0




[PATCH v2 6/7] target/mips: Convert Loongson [D]MOD[U].G opcodes to decodetree

2023-08-31 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Convert the following opcodes to decodetree:

- MOD.G - mod 32-bit signed integers
- MODU.G - mod 32-bit unsigned integers
- DMOD.G - mod 64-bit signed integers
- DMODU.G - mod 64-bit unsigned integers

Reviewed-by: Richard Henderson 
Signed-off-by: Philippe Mathieu-Daudé 
---
 target/mips/tcg/godson2.decode|   5 ++
 target/mips/tcg/loong-ext.decode  |   5 ++
 target/mips/tcg/loong_translate.c | 111 ++
 target/mips/tcg/translate.c   |  82 --
 4 files changed, 121 insertions(+), 82 deletions(-)

diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
index 4352d1e5e7..e3bf6b12e4 100644
--- a/target/mips/tcg/godson2.decode
+++ b/target/mips/tcg/godson2.decode
@@ -17,3 +17,8 @@ DIV_G   01 . . . 0 011010   
@rs_rt_rd
 DIVU_G  01 . . . 0 011011   @rs_rt_rd
 DDIV_G  01 . . . 0 00   @rs_rt_rd
 DDIVU_G 01 . . . 0 01   @rs_rt_rd
+
+MOD_G   01 . . . 0 100010   @rs_rt_rd
+MODU_G  01 . . . 0 100011   @rs_rt_rd
+DMOD_G  01 . . . 0 100110   @rs_rt_rd
+DMODU_G 01 . . . 0 100111   @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
index 77639227a1..d63406e3f4 100644
--- a/target/mips/tcg/loong-ext.decode
+++ b/target/mips/tcg/loong-ext.decode
@@ -18,3 +18,8 @@ DIV_G   011100 . . . 0 010100   
@rs_rt_rd
 DDIV_G  011100 . . . 0 010101   @rs_rt_rd
 DIVU_G  011100 . . . 0 010110   @rs_rt_rd
 DDIVU_G 011100 . . . 0 010111   @rs_rt_rd
+
+MOD_G   011100 . . . 0 011100   @rs_rt_rd
+DMOD_G  011100 . . . 0 011101   @rs_rt_rd
+MODU_G  011100 . . . 0 00   @rs_rt_rd
+DMODU_G 011100 . . . 0 01   @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c 
b/target/mips/tcg/loong_translate.c
index 87023696a0..bddf1cb7aa 100644
--- a/target/mips/tcg/loong_translate.c
+++ b/target/mips/tcg/loong_translate.c
@@ -141,6 +141,117 @@ static bool trans_DDIVU_G(DisasContext *s, arg_muldiv *a)
 return gen_lext_DIVU_G(s, a->rt, a->rs, a->rd, true);
 }
 
+static bool gen_lext_MOD_G(DisasContext *s, int rd, int rs, int rt,
+   bool is_double)
+{
+TCGv t0, t1;
+TCGLabel *l1, *l2, *l3;
+
+if (is_double) {
+if (TARGET_LONG_BITS != 64) {
+return false;
+}
+check_mips_64(s);
+}
+
+if (rd == 0) {
+/* Treat as NOP. */
+return true;
+}
+
+t0 = tcg_temp_new();
+t1 = tcg_temp_new();
+l1 = gen_new_label();
+l2 = gen_new_label();
+l3 = gen_new_label();
+
+gen_load_gpr(t0, rs);
+gen_load_gpr(t1, rt);
+
+if (!is_double) {
+tcg_gen_ext32u_tl(t0, t0);
+tcg_gen_ext32u_tl(t1, t1);
+}
+tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+tcg_gen_brcondi_tl(TCG_COND_NE, t0, is_double && TARGET_LONG_BITS == 64
+? LLONG_MIN : INT_MIN, l2);
+tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+gen_set_label(l1);
+tcg_gen_movi_tl(cpu_gpr[rd], 0);
+tcg_gen_br(l3);
+gen_set_label(l2);
+tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
+if (!is_double) {
+tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+}
+gen_set_label(l3);
+
+return true;
+}
+
+static bool trans_MOD_G(DisasContext *s, arg_muldiv *a)
+{
+return gen_lext_MOD_G(s, a->rt, a->rs, a->rd, false);
+}
+
+static bool trans_DMOD_G(DisasContext *s, arg_muldiv *a)
+{
+return gen_lext_MOD_G(s, a->rt, a->rs, a->rd, true);
+}
+
+static bool gen_lext_MODU_G(DisasContext *s, int rd, int rs, int rt,
+bool is_double)
+{
+TCGv t0, t1;
+TCGLabel *l1, *l2;
+
+if (is_double) {
+if (TARGET_LONG_BITS != 64) {
+return false;
+}
+check_mips_64(s);
+}
+
+if (rd == 0) {
+/* Treat as NOP. */
+return true;
+}
+
+t0 = tcg_temp_new();
+t1 = tcg_temp_new();
+l1 = gen_new_label();
+l2 = gen_new_label();
+
+gen_load_gpr(t0, rs);
+gen_load_gpr(t1, rt);
+
+if (!is_double) {
+tcg_gen_ext32u_tl(t0, t0);
+tcg_gen_ext32u_tl(t1, t1);
+}
+tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+tcg_gen_movi_tl(cpu_gpr[rd], 0);
+tcg_gen_br(l2);
+gen_set_label(l1);
+tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
+if (!is_double) {
+tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+}
+gen_set_label(l2);
+
+return true;
+}
+
+static bool trans_MODU_G(DisasContext *s, arg_muldiv *a)
+{
+return gen_lext_MODU_G(s, a->rt, a->rs, a->rd, false);
+}
+
+static bool trans_DMODU_G(DisasContext *s, 

Re: [PATCH 6/6] target/mips: Convert Loongson [D]MULT[U].G opcodes to decodetree

2023-08-31 Thread Philippe Mathieu-Daudé

On 31/8/23 21:12, Philippe Mathieu-Daudé wrote:

On 21/1/21 21:06, Richard Henderson wrote:

On 1/12/21 11:55 AM, Philippe Mathieu-Daudé wrote:

Convert the following opcodes to decodetree:

- MULT.G - multiply 32-bit signed integers
- MULTU.G - multiply 32-bit unsigned integers
- DMULT.G - multiply 64-bit signed integers
- DMULTU.G - multiply 64-bit unsigned integers

Now that all opcodes from the extension have been converted, we
can remove completely gen_loongson_integer() and its 2 calls in
decode_opc_special2_legacy() and decode_opc_special3_legacy().

Signed-off-by: Philippe Mathieu-Daudé 
---
  target/mips/godson2.decode    |  5 ++
  target/mips/loong-ext.decode  |  5 ++
  target/mips/loong_translate.c | 58 ++
  target/mips/translate.c   | 92 +--
  4 files changed, 70 insertions(+), 90 deletions(-)




+static bool gen_lext_MULT_G(DisasContext *s, int rd, int rs, int rt,
+    bool is_double, bool is_unsigned)
+{
+    TCGv t0, t1;
+
+    if (is_double) {
+    if (TARGET_LONG_BITS != 64) {
+    return false;
+    }
+    check_mips_64(s);
+    }
+
+    if (rd == 0) {
+    /* Treat as NOP. */
+    return true;
+    }
+
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
+
+    gen_load_gpr(t0, rs);
+    gen_load_gpr(t1, rt);
+
+    if (is_unsigned && !is_double) {
+    tcg_gen_ext32u_tl(t0, t0);
+    tcg_gen_ext32u_tl(t1, t1);
+    }


While this is a faithful conversion of the existing code, these 
extensions make

no difference to the result.  They are redundant with


+    tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+    if (!is_double) {
+    tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);


this one, which discards any bit that might have been set by the input 
bits

that are cleared.


I see.


There is no actual difference between MULT.G and MULTU.G, or DMULT.G and
DMULTU.G, because they don't record the most significant bits of the 
infinite

result in any way.


Right.


+static bool trans_MULT_G(DisasContext *s, arg_muldiv *a)
+{
+    return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, false);
+}
+
+static bool trans_MULTU_G(DisasContext *s, arg_muldiv *a)
+{
+    return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, true);
+}
+
+static bool trans_DMULT_G(DisasContext *s, arg_muldiv *a)
+{
+    return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, false);
+}
+
+static bool trans_DMULTU_G(DisasContext *s, arg_muldiv *a)
+{
+    return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, true);
+}


So... if you want to clean this up afterward, or before is up to you.


"before" ended being way simpler :>




[PATCH v2 5/7] target/mips: Convert Loongson [D]DIVU.G opcodes to decodetree

2023-08-31 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

Convert DIVU.G (divide 32-bit unsigned integers) and DDIVU.G
(divide 64-bit unsigned integers) opcodes to decodetree.

Reviewed-by: Richard Henderson 
Signed-off-by: Philippe Mathieu-Daudé 
---
 target/mips/tcg/godson2.decode|  2 ++
 target/mips/tcg/loong-ext.decode  |  2 ++
 target/mips/tcg/loong_translate.c | 54 +++
 target/mips/tcg/translate.c   | 37 -
 4 files changed, 58 insertions(+), 37 deletions(-)

diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
index 91940c1263..4352d1e5e7 100644
--- a/target/mips/tcg/godson2.decode
+++ b/target/mips/tcg/godson2.decode
@@ -14,4 +14,6 @@
 @rs_rt_rd   .. rs:5  rt:5  rd:5  . ..   
 
 DIV_G   01 . . . 0 011010   @rs_rt_rd
+DIVU_G  01 . . . 0 011011   @rs_rt_rd
 DDIV_G  01 . . . 0 00   @rs_rt_rd
+DDIVU_G 01 . . . 0 01   @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
index e9378abc8e..77639227a1 100644
--- a/target/mips/tcg/loong-ext.decode
+++ b/target/mips/tcg/loong-ext.decode
@@ -16,3 +16,5 @@
 
 DIV_G   011100 . . . 0 010100   @rs_rt_rd
 DDIV_G  011100 . . . 0 010101   @rs_rt_rd
+DIVU_G  011100 . . . 0 010110   @rs_rt_rd
+DDIVU_G 011100 . . . 0 010111   @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c 
b/target/mips/tcg/loong_translate.c
index d42cdb7d2e..87023696a0 100644
--- a/target/mips/tcg/loong_translate.c
+++ b/target/mips/tcg/loong_translate.c
@@ -87,6 +87,60 @@ static bool trans_DDIV_G(DisasContext *s, arg_muldiv *a)
 return gen_lext_DIV_G(s, a->rt, a->rs, a->rd, true);
 }
 
+static bool gen_lext_DIVU_G(DisasContext *s, int rd, int rs, int rt,
+bool is_double)
+{
+TCGv t0, t1;
+TCGLabel *l1, *l2;
+
+if (is_double) {
+if (TARGET_LONG_BITS != 64) {
+return false;
+}
+check_mips_64(s);
+}
+
+if (rd == 0) {
+/* Treat as NOP. */
+return true;
+}
+
+t0 = tcg_temp_new();
+t1 = tcg_temp_new();
+l1 = gen_new_label();
+l2 = gen_new_label();
+
+gen_load_gpr(t0, rs);
+gen_load_gpr(t1, rt);
+
+if (!is_double) {
+tcg_gen_ext32u_tl(t0, t0);
+tcg_gen_ext32u_tl(t1, t1);
+}
+tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+tcg_gen_movi_tl(cpu_gpr[rd], 0);
+
+tcg_gen_br(l2);
+gen_set_label(l1);
+tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
+if (!is_double) {
+tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+}
+gen_set_label(l2);
+
+return true;
+}
+
+static bool trans_DIVU_G(DisasContext *s, arg_muldiv *a)
+{
+return gen_lext_DIVU_G(s, a->rt, a->rs, a->rd, false);
+}
+
+static bool trans_DDIVU_G(DisasContext *s, arg_muldiv *a)
+{
+return gen_lext_DIVU_G(s, a->rt, a->rs, a->rd, true);
+}
+
 bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
 {
 if ((ctx->insn_flags & INSN_LOONGSON2E)
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 59853f1d87..f1c99a9218 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -333,8 +333,6 @@ enum {
 OPC_DMULT_G_2F  = 0x11 | OPC_SPECIAL2,
 OPC_MULTU_G_2F  = 0x12 | OPC_SPECIAL2,
 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
-OPC_DIVU_G_2F   = 0x16 | OPC_SPECIAL2,
-OPC_DDIVU_G_2F  = 0x17 | OPC_SPECIAL2,
 OPC_MOD_G_2F= 0x1c | OPC_SPECIAL2,
 OPC_DMOD_G_2F   = 0x1d | OPC_SPECIAL2,
 OPC_MODU_G_2F   = 0x1e | OPC_SPECIAL2,
@@ -370,10 +368,8 @@ enum {
 /* Loongson 2E */
 OPC_MULT_G_2E   = 0x18 | OPC_SPECIAL3,
 OPC_MULTU_G_2E  = 0x19 | OPC_SPECIAL3,
-OPC_DIVU_G_2E   = 0x1B | OPC_SPECIAL3,
 OPC_DMULT_G_2E  = 0x1C | OPC_SPECIAL3,
 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
-OPC_DDIVU_G_2E  = 0x1F | OPC_SPECIAL3,
 OPC_MOD_G_2E= 0x22 | OPC_SPECIAL3,
 OPC_MODU_G_2E   = 0x23 | OPC_SPECIAL3,
 OPC_DMOD_G_2E   = 0x26 | OPC_SPECIAL3,
@@ -3621,22 +3617,6 @@ static void gen_loongson_integer(DisasContext *ctx, 
uint32_t opc,
 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
 break;
-case OPC_DIVU_G_2E:
-case OPC_DIVU_G_2F:
-{
-TCGLabel *l1 = gen_new_label();
-TCGLabel *l2 = gen_new_label();
-tcg_gen_ext32u_tl(t0, t0);
-tcg_gen_ext32u_tl(t1, t1);
-tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
-tcg_gen_movi_tl(cpu_gpr[rd], 0);
-tcg_gen_br(l2);
-gen_set_label(l1);
-tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
-tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
-gen_set_label(l2);
-}
-break;
 case OPC_MOD_G_2E:
 case OPC_MOD_G_2F:
 {
@@ 

[PATCH v2 2/7] target/mips: Re-introduce OPC_ADDUH_QB_DSP and OPC_MUL_PH_DSP

2023-08-31 Thread Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé 

There is no issue having multiple enum declarations with
the same value. As we are going to remove the OPC_MULT_G_2E
definition in few commits, restore the OPC_ADDUH_QB_DSP and
OPC_MUL_PH_DSP definitions and use them where they belong.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Jiaxun Yang 
Reviewed-by: Richard Henderson 
---
 target/mips/tcg/translate.c | 18 +-
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index e0a76b9432..19e73aea60 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -390,16 +390,14 @@ enum {
 OPC_ADDU_OB_DSP= 0x14 | OPC_SPECIAL3,
 OPC_ABSQ_S_PH_DSP  = 0x12 | OPC_SPECIAL3,
 OPC_ABSQ_S_QH_DSP  = 0x16 | OPC_SPECIAL3,
-/* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E.  */
-/* OPC_ADDUH_QB_DSP   = 0x18 | OPC_SPECIAL3,  */
+OPC_ADDUH_QB_DSP   = 0x18 | OPC_SPECIAL3,
 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
 /* MIPS DSP GPR-Based Shift Sub-class */
 OPC_SHLL_QB_DSP= 0x13 | OPC_SPECIAL3,
 OPC_SHLL_OB_DSP= 0x17 | OPC_SPECIAL3,
 /* MIPS DSP Multiply Sub-class insns */
-/* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP.  */
-/* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3,  */
+OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3,
 OPC_DPA_W_PH_DSP   = 0x30 | OPC_SPECIAL3,
 OPC_DPAQ_W_QH_DSP  = 0x34 | OPC_SPECIAL3,
 /* DSP Bit/Manipulation Sub-class */
@@ -557,7 +555,6 @@ enum {
 OPC_MULQ_S_PH  = (0x1E << 6) | OPC_ADDU_QB_DSP,
 };
 
-#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
 #define MASK_ADDUH_QB(op)   (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
 /* MIPS DSP Arithmetic Sub-class */
@@ -11663,8 +11660,7 @@ static void gen_mipsdsp_arith(DisasContext *ctx, 
uint32_t op1, uint32_t op2,
 gen_load_gpr(v2_t, v2);
 
 switch (op1) {
-/* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
-case OPC_MULT_G_2E:
+case OPC_ADDUH_QB_DSP:
 check_dsp_r2(ctx);
 switch (op2) {
 case OPC_ADDUH_QB:
@@ -12347,11 +12343,7 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, 
uint32_t op1, uint32_t op2,
 gen_load_gpr(v2_t, v2);
 
 switch (op1) {
-/*
- * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
- * the same mask and op1.
- */
-case OPC_MULT_G_2E:
+case OPC_MUL_PH_DSP:
 check_dsp_r2(ctx);
 switch (op2) {
 case  OPC_MUL_PH:
@@ -13887,7 +13879,7 @@ static void decode_opc_special3_legacy(CPUMIPSState 
*env, DisasContext *ctx)
  * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
  * the same mask and op1.
  */
-if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
+if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MUL_PH_DSP)) {
 op2 = MASK_ADDUH_QB(ctx->opcode);
 switch (op2) {
 case OPC_ADDUH_QB:
-- 
2.41.0




Re: [PATCH 2/7] migration: Clean up local variable shadowing

2023-08-31 Thread Peter Xu
On Thu, Aug 31, 2023 at 03:25:41PM +0200, Markus Armbruster wrote:
> Local variables shadowing other local variables or parameters make the
> code needlessly hard to understand.  Tracked down with -Wshadow=local.
> Clean up: delete inner declarations when they are actually redundant,
> else rename variables.
> 
> Signed-off-by: Markus Armbruster 

Reviewed-by: Peter Xu 

-- 
Peter Xu




Re: [PATCH 1/7] migration/rdma: Fix save_page method to fail on polling error

2023-08-31 Thread Peter Xu
On Thu, Aug 31, 2023 at 03:25:40PM +0200, Markus Armbruster wrote:
> qemu_rdma_save_page() reports polling error with error_report(), then
> succeeds anyway.  This is because the variable holding the polling
> status *shadows* the variable the function returns.  The latter
> remains zero.
> 
> Broken since day one, and duplicated more recently.
> 
> Fixes: 2da776db4846 (rdma: core logic)
> Fixes: b390afd8c50b (migration/rdma: Fix out of order wrid)
> Signed-off-by: Markus Armbruster 

Reviewed-by: Peter Xu 

-- 
Peter Xu




  1   2   3   4   >