Re: [PATCH v7 04/14] mm/shmem: Support memfile_notifier

2022-07-13 Thread Chao Peng
On Tue, Jul 12, 2022 at 08:02:34PM +0200, Gupta, Pankaj wrote:
> On 7/6/2022 10:20 AM, Chao Peng wrote:
> > From: "Kirill A. Shutemov" 
> > 
> > Implement shmem as a memfile_notifier backing store. Essentially it
> > interacts with the memfile_notifier feature flags for userspace
> > access/page migration/page reclaiming and implements the necessary
> > memfile_backing_store callbacks.
> > 
> > Signed-off-by: Kirill A. Shutemov 
> > Signed-off-by: Chao Peng 
> > ---
> >   include/linux/shmem_fs.h |   2 +
> >   mm/shmem.c   | 109 ++-
> >   2 files changed, 110 insertions(+), 1 deletion(-)
...

> > +#ifdef CONFIG_MIGRATION
> > +static int shmem_migrate_page(struct address_space *mapping,
> > + struct page *newpage, struct page *page,
> > + enum migrate_mode mode)
> > +{
> > +   struct inode *inode = mapping->host;
> > +   struct shmem_inode_info *info = SHMEM_I(inode);
> > +
> > +   if (info->memfile_node.flags & MEMFILE_F_UNMOVABLE)
> > +   return -EOPNOTSUPP;
> > +   return migrate_page(mapping, newpage, page, mode);
> 
> Wondering how well page migrate would work for private pages
> on shmem memfd based backend?

>From high level:
  - KVM unset MEMFILE_F_UNMOVABLE bit to indicate it capable of
migrating a page.
  - Introduce new 'migrate' callback(s) to memfile_notifier_ops for KVM
to register.
  - The callback is hooked to migrate_page() here.
  - Once page migration requested, shmem calls into the 'migrate'
callback(s) to perform additional steps for encrypted memory (For
TDX we will call TDH.MEM.PAGE.RELOCATE).

Chao
> 
> > +}
> > +#endif
> > +
> >   const struct address_space_operations shmem_aops = {
> > .writepage  = shmem_writepage,
> > .dirty_folio= noop_dirty_folio,
> > @@ -3814,7 +3872,7 @@ const struct address_space_operations shmem_aops = {
> > .write_end  = shmem_write_end,
> >   #endif
> >   #ifdef CONFIG_MIGRATION
> > -   .migratepage= migrate_page,
> > +   .migratepage= shmem_migrate_page,
> >   #endif
> > .error_remove_page = shmem_error_remove_page,
> >   };
> > @@ -3931,6 +3989,51 @@ static struct file_system_type shmem_fs_type = {
> > .fs_flags   = FS_USERNS_MOUNT,
> >   };
 



[PULL 00/19] aspeed queue

2022-07-13 Thread Cédric Le Goater
The following changes since commit 8e3d85d36b77f11ad7bded3a2d48c1f0cc334f82:

  Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging 
(2022-07-12 14:12:15 +0100)

are available in the Git repository at:

  https://github.com/legoater/qemu/ tags/pull-aspeed-20220713

for you to fetch changes up to 053b2ee5629d1b822127cc454634ec272624bab2:

  aspeed: Add fby35-bmc slot GPIO's (2022-07-13 08:16:46 +0200)


aspeed queue:

* New ISL69259 device model
* New fby35 multi-SoC machine (AST1030 BIC + AST2600 BMC)
* Aspeed GPIO fixes
* Extension of m25p80 with write protect bits
* More avocado tests using the Aspeed SDK


Cédric Le Goater (3):
  aspeed: fby35: Add a bootrom for the BMC
  docs: aspeed: Minor updates
  test/avocado/machine_aspeed.py: Add SDK tests

Iris Chen (2):
  hw: m25p80: Add Block Protect and Top Bottom bits for write protect
  hw: m25p80: add tests for BP and TB bit write protect

Joel Stanley (1):
  aspeed: sbc: Allow per-machine settings

Peter Delevoryas (13):
  hw/i2c/pmbus: Add idle state to return 0xff's
  hw/sensor: Add IC_DEVICE_ID to ISL voltage regulators
  hw/sensor: Add Renesas ISL69259 device model
  aspeed: Create SRAM name from first CPU index
  aspeed: Refactor UART init for multi-SoC machines
  aspeed: Make aspeed_board_init_flashes public
  aspeed: Add fby35 skeleton
  aspeed: Add AST2600 (BMC) to fby35
  aspeed: Add AST1030 (BIC) to fby35
  docs: aspeed: Add fby35 multi-SoC machine section
  qtest/aspeed_gpio: Add input pin modification test
  hw/gpio/aspeed: Don't let guests modify input pins
  aspeed: Add fby35-bmc slot GPIO's

 docs/system/arm/aspeed.rst   |  62 -
 include/hw/arm/aspeed_soc.h  |   9 +-
 include/hw/i2c/pmbus_device.h|   7 ++
 include/hw/misc/aspeed_sbc.h |  13 +++
 include/hw/sensor/isl_pmbus_vr.h |   5 ++
 hw/arm/aspeed.c  |  38 ++--
 hw/arm/aspeed_ast10x0.c  |  13 ++-
 hw/arm/aspeed_ast2600.c  |  13 ++-
 hw/arm/aspeed_soc.c  |  55 
 hw/arm/fby35.c   | 188 +++
 hw/block/m25p80.c| 102 ++---
 hw/gpio/aspeed_gpio.c|  15 ++--
 hw/i2c/pmbus_device.c|   9 ++
 hw/misc/aspeed_sbc.c |  42 -
 hw/sensor/isl_pmbus_vr.c |  40 +
 tests/qtest/aspeed_gpio-test.c   |  27 ++
 tests/qtest/aspeed_smc-test.c| 111 +++
 MAINTAINERS  |   1 +
 hw/arm/meson.build   |   3 +-
 tests/avocado/machine_aspeed.py  |  68 ++
 20 files changed, 764 insertions(+), 57 deletions(-)
 create mode 100644 hw/arm/fby35.c



[PULL 02/19] hw/i2c/pmbus: Add idle state to return 0xff's

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

Signed-off-by: Peter Delevoryas 
Reviewed-by: Titus Rwantare 
Message-Id: <20220701000626.77395-2...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 include/hw/i2c/pmbus_device.h | 7 +++
 hw/i2c/pmbus_device.c | 9 +
 2 files changed, 16 insertions(+)

diff --git a/include/hw/i2c/pmbus_device.h b/include/hw/i2c/pmbus_device.h
index 0f4d6b3fada0..93f5d57c9dc6 100644
--- a/include/hw/i2c/pmbus_device.h
+++ b/include/hw/i2c/pmbus_device.h
@@ -155,6 +155,7 @@ enum pmbus_registers {
 PMBUS_MFR_MAX_TEMP_1= 0xC0, /* R/W word */
 PMBUS_MFR_MAX_TEMP_2= 0xC1, /* R/W word */
 PMBUS_MFR_MAX_TEMP_3= 0xC2, /* R/W word */
+PMBUS_IDLE_STATE= 0xFF,
 };
 
 /* STATUS_WORD */
@@ -527,6 +528,12 @@ int pmbus_page_config(PMBusDevice *pmdev, uint8_t 
page_index, uint64_t flags);
  */
 void pmbus_check_limits(PMBusDevice *pmdev);
 
+/**
+ * Enter an idle state where only the PMBUS_ERR_BYTE will be returned
+ * indefinitely until a new command is issued.
+ */
+void pmbus_idle(PMBusDevice *pmdev);
+
 extern const VMStateDescription vmstate_pmbus_device;
 
 #define VMSTATE_PMBUS_DEVICE(_field, _state) {   \
diff --git a/hw/i2c/pmbus_device.c b/hw/i2c/pmbus_device.c
index 749a33af827b..4071a88cfcd1 100644
--- a/hw/i2c/pmbus_device.c
+++ b/hw/i2c/pmbus_device.c
@@ -261,6 +261,11 @@ void pmbus_check_limits(PMBusDevice *pmdev)
 }
 }
 
+void pmbus_idle(PMBusDevice *pmdev)
+{
+pmdev->code = PMBUS_IDLE_STATE;
+}
+
 /* assert the status_cml error upon receipt of malformed command */
 static void pmbus_cml_error(PMBusDevice *pmdev)
 {
@@ -980,6 +985,10 @@ static uint8_t pmbus_receive_byte(SMBusDevice *smd)
 }
 break;
 
+case PMBUS_IDLE_STATE:
+pmbus_send8(pmdev, PMBUS_ERR_BYTE);
+break;
+
 case PMBUS_CLEAR_FAULTS:  /* Send Byte */
 case PMBUS_PAGE_PLUS_WRITE:   /* Block Write-only */
 case PMBUS_STORE_DEFAULT_ALL: /* Send Byte */
-- 
2.35.3




[PULL 01/19] aspeed: sbc: Allow per-machine settings

2022-07-13 Thread Cédric Le Goater
From: Joel Stanley 

In order to correctly report secure boot running firmware the values
of certain registers must be set.

We don't yet have documentation from ASPEED on what they mean. The
meaning is inferred from u-boot's use of them.

Introduce properties so the settings can be configured per-machine.

Reviewed-by: Peter Delevoryas 
Tested-by: Peter Delevoryas 
Signed-off-by: Joel Stanley 
Message-Id: <20220628154740.1117349-4-...@kaod.org>
Signed-off-by: Cédric Le Goater 
---
 include/hw/misc/aspeed_sbc.h | 13 +++
 hw/misc/aspeed_sbc.c | 42 ++--
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/include/hw/misc/aspeed_sbc.h b/include/hw/misc/aspeed_sbc.h
index 67e43b53ecc3..405e6782b97a 100644
--- a/include/hw/misc/aspeed_sbc.h
+++ b/include/hw/misc/aspeed_sbc.h
@@ -17,9 +17,22 @@ OBJECT_DECLARE_TYPE(AspeedSBCState, AspeedSBCClass, 
ASPEED_SBC)
 
 #define ASPEED_SBC_NR_REGS (0x93c >> 2)
 
+#define QSR_AES BIT(27)
+#define QSR_RSA1024 (0x0 << 12)
+#define QSR_RSA2048 (0x1 << 12)
+#define QSR_RSA3072 (0x2 << 12)
+#define QSR_RSA4096 (0x3 << 12)
+#define QSR_SHA224  (0x0 << 10)
+#define QSR_SHA256  (0x1 << 10)
+#define QSR_SHA384  (0x2 << 10)
+#define QSR_SHA512  (0x3 << 10)
+
 struct AspeedSBCState {
 SysBusDevice parent;
 
+bool emmc_abr;
+uint32_t signing_settings;
+
 MemoryRegion iomem;
 
 uint32_t regs[ASPEED_SBC_NR_REGS];
diff --git a/hw/misc/aspeed_sbc.c b/hw/misc/aspeed_sbc.c
index bfa8b81d01c7..c6f328e3be23 100644
--- a/hw/misc/aspeed_sbc.c
+++ b/hw/misc/aspeed_sbc.c
@@ -11,6 +11,7 @@
 #include "qemu/osdep.h"
 #include "qemu/log.h"
 #include "qemu/error-report.h"
+#include "hw/qdev-properties.h"
 #include "hw/misc/aspeed_sbc.h"
 #include "qapi/error.h"
 #include "migration/vmstate.h"
@@ -19,6 +20,27 @@
 #define R_STATUS(0x014 / 4)
 #define R_QSR   (0x040 / 4)
 
+/* R_STATUS */
+#define ABR_EN  BIT(14) /* Mirrors SCU510[11] */
+#define ABR_IMAGE_SOURCEBIT(13)
+#define SPI_ABR_IMAGE_SOURCEBIT(12)
+#define SB_CRYPTO_KEY_EXP_DONE  BIT(11)
+#define SB_CRYPTO_BUSY  BIT(10)
+#define OTP_WP_EN   BIT(9)
+#define OTP_ADDR_WP_EN  BIT(8)
+#define LOW_SEC_KEY_EN  BIT(7)
+#define SECURE_BOOT_EN  BIT(6)
+#define UART_BOOT_ENBIT(5)
+/* bit 4 reserved*/
+#define OTP_CHARGE_PUMP_READY   BIT(3)
+#define OTP_IDLEBIT(2)
+#define OTP_MEM_IDLEBIT(1)
+#define OTP_COMPARE_STATUS  BIT(0)
+
+/* QSR */
+#define QSR_RSA_MASK   (0x3 << 12)
+#define QSR_HASH_MASK  (0x3 << 10)
+
 static uint64_t aspeed_sbc_read(void *opaque, hwaddr addr, unsigned int size)
 {
 AspeedSBCState *s = ASPEED_SBC(opaque);
@@ -80,8 +102,17 @@ static void aspeed_sbc_reset(DeviceState *dev)
 memset(s->regs, 0, sizeof(s->regs));
 
 /* Set secure boot enabled with RSA4096_SHA256 and enable eMMC ABR */
-s->regs[R_STATUS] = 0x44C6;
-s->regs[R_QSR] = 0x07C07C89;
+s->regs[R_STATUS] = OTP_IDLE | OTP_MEM_IDLE;
+
+if (s->emmc_abr) {
+s->regs[R_STATUS] &= ABR_EN;
+}
+
+if (s->signing_settings) {
+s->regs[R_STATUS] &= SECURE_BOOT_EN;
+}
+
+s->regs[R_QSR] = s->signing_settings;
 }
 
 static void aspeed_sbc_realize(DeviceState *dev, Error **errp)
@@ -105,6 +136,12 @@ static const VMStateDescription vmstate_aspeed_sbc = {
 }
 };
 
+static Property aspeed_sbc_properties[] = {
+DEFINE_PROP_BOOL("emmc-abr", AspeedSBCState, emmc_abr, 0),
+DEFINE_PROP_UINT32("signing-settings", AspeedSBCState, signing_settings, 
0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void aspeed_sbc_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -112,6 +149,7 @@ static void aspeed_sbc_class_init(ObjectClass *klass, void 
*data)
 dc->realize = aspeed_sbc_realize;
 dc->reset = aspeed_sbc_reset;
 dc->vmsd = &vmstate_aspeed_sbc;
+device_class_set_props(dc, aspeed_sbc_properties);
 }
 
 static const TypeInfo aspeed_sbc_info = {
-- 
2.35.3




[PULL 12/19] docs: aspeed: Add fby35 multi-SoC machine section

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

Signed-off-by: Peter Delevoryas 
Reviewed-by: Joel Stanley 
Reviewed-by: Cédric Le Goater 
[ clg: - fixed URL links
   - Moved Facebook Yosemite section at the end of the file ]
Message-Id: <20220705191400.41632-10-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 docs/system/arm/aspeed.rst | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst
index 5d0a7865d3a6..445095690c04 100644
--- a/docs/system/arm/aspeed.rst
+++ b/docs/system/arm/aspeed.rst
@@ -182,3 +182,51 @@ To boot a kernel directly from a Zephyr build tree:
 
   $ qemu-system-arm -M ast1030-evb -nographic \
 -kernel zephyr.elf
+
+Facebook Yosemite v3.5 Platform and CraterLake Server (``fby35``)
+==
+
+Facebook has a series of multi-node compute server designs named
+Yosemite. The most recent version released was
+`Yosemite v3 
`__.
+
+Yosemite v3.5 is an iteration on this design, and is very similar: there's a
+baseboard with a BMC, and 4 server slots. The new server board design termed
+"CraterLake" includes a Bridge IC (BIC), with room for expansion boards to
+include various compute accelerators (video, inferencing, etc). At the moment,
+only the first server slot's BIC is included.
+
+Yosemite v3.5 is itself a sled which fits into a 40U chassis, and 3 sleds
+can be fit into a chassis. See `here 
`__
+for an example.
+
+In this generation, the BMC is an AST2600 and each BIC is an AST1030. The BMC
+runs `OpenBMC `__, and the BIC runs
+`OpenBIC `__.
+
+Firmware images can be retrieved from the Github releases or built from the
+source code, see the README's for instructions on that. This image uses the
+"fby35" machine recipe from OpenBMC, and the "yv35-cl" target from OpenBIC.
+Some reference images can also be found here:
+
+.. code-block:: bash
+
+$ wget 
https://github.com/facebook/openbmc/releases/download/openbmc-e2294ff5d31d/fby35.mtd
+$ wget 
https://github.com/peterdelevoryas/OpenBIC/releases/download/oby35-cl-2022.13.01/Y35BCL.elf
+
+Since this machine has multiple SoC's, each with their own serial console, the
+recommended way to run it is to allocate a pseudoterminal for each serial
+console and let the monitor use stdio. Also, starting in a paused state is
+useful because it allows you to attach to the pseudoterminals before the boot
+process starts.
+
+.. code-block:: bash
+
+$ qemu-system-arm -machine fby35 \
+-drive file=fby35.mtd,format=raw,if=mtd \
+-device loader,file=Y35BCL.elf,addr=0,cpu-num=2 \
+-serial pty -serial pty -serial mon:stdio \
+-display none -S
+$ screen /dev/tty0 # In a separate TMUX pane, terminal window, etc.
+$ screen /dev/tty1
+$ (qemu) c# Start the boot process once screen is setup.
-- 
2.35.3




[PULL 03/19] hw/sensor: Add IC_DEVICE_ID to ISL voltage regulators

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

This commit adds a passthrough for PMBUS_IC_DEVICE_ID to allow Renesas
voltage regulators to return the integrated circuit device ID if they
would like to.

The behavior is very device specific, so it hasn't been added to the
general PMBUS model. Additionally, if the device ID hasn't been set,
then the voltage regulator will respond with the error byte value.  The
guest error message will change slightly for IC_DEVICE_ID with this
commit.

Signed-off-by: Peter Delevoryas 
Reviewed-by: Titus Rwantare 
Message-Id: <20220701000626.77395-3...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 include/hw/sensor/isl_pmbus_vr.h |  5 +
 hw/sensor/isl_pmbus_vr.c | 12 
 2 files changed, 17 insertions(+)

diff --git a/include/hw/sensor/isl_pmbus_vr.h b/include/hw/sensor/isl_pmbus_vr.h
index 3e47ff7e48d8..aa2c2767df90 100644
--- a/include/hw/sensor/isl_pmbus_vr.h
+++ b/include/hw/sensor/isl_pmbus_vr.h
@@ -12,12 +12,17 @@
 #include "hw/i2c/pmbus_device.h"
 #include "qom/object.h"
 
+#define TYPE_ISL69259   "isl69259"
 #define TYPE_ISL69260   "isl69260"
 #define TYPE_RAA228000  "raa228000"
 #define TYPE_RAA229004  "raa229004"
+#define ISL_MAX_IC_DEVICE_ID_LEN 16
 
 struct ISLState {
 PMBusDevice parent;
+
+uint8_t ic_device_id[ISL_MAX_IC_DEVICE_ID_LEN];
+uint8_t ic_device_id_len;
 };
 
 OBJECT_DECLARE_SIMPLE_TYPE(ISLState, ISL69260)
diff --git a/hw/sensor/isl_pmbus_vr.c b/hw/sensor/isl_pmbus_vr.c
index e11e0288840d..799ea9d89edb 100644
--- a/hw/sensor/isl_pmbus_vr.c
+++ b/hw/sensor/isl_pmbus_vr.c
@@ -15,6 +15,18 @@
 
 static uint8_t isl_pmbus_vr_read_byte(PMBusDevice *pmdev)
 {
+ISLState *s = ISL69260(pmdev);
+
+switch (pmdev->code) {
+case PMBUS_IC_DEVICE_ID:
+if (!s->ic_device_id_len) {
+break;
+}
+pmbus_send(pmdev, s->ic_device_id, s->ic_device_id_len);
+pmbus_idle(pmdev);
+return 0;
+}
+
 qemu_log_mask(LOG_GUEST_ERROR,
   "%s: reading from unsupported register: 0x%02x\n",
   __func__, pmdev->code);
-- 
2.35.3




[PULL 06/19] aspeed: Refactor UART init for multi-SoC machines

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

This change moves the code that connects the SoC UART's to serial_hd's
to the machine.

It makes each UART a proper child member of the SoC, and then allows the
machine to selectively initialize the chardev for each UART with a
serial_hd.

This should preserve backwards compatibility, but also allow multi-SoC
boards to completely change the wiring of serial devices from the
command line to specific SoC UART's.

This also removes the uart-default property from the SoC, since the SoC
doesn't need to know what UART is the "default" on the machine anymore.

I tested this using the images and commands from the previous
refactoring, and another test image for the ast1030:

wget 
https://github.com/facebook/openbmc/releases/download/v2021.49.0/fuji.mtd
wget 
https://github.com/facebook/openbmc/releases/download/v2021.49.0/wedge100.mtd
wget 
https://github.com/peterdelevoryas/OpenBIC/releases/download/oby35-cl-2022.13.01/Y35BCL.elf

Fuji uses UART1:

qemu-system-arm -machine fuji-bmc \
-drive file=fuji.mtd,format=raw,if=mtd \
-nographic

ast2600-evb uses uart-default=UART5:

qemu-system-arm -machine ast2600-evb \
-drive file=fuji.mtd,format=raw,if=mtd \
-serial null -serial mon:stdio -display none

Wedge100 uses UART3:

qemu-system-arm -machine palmetto-bmc \
-drive file=wedge100.mtd,format=raw,if=mtd \
-serial null -serial null -serial null \
-serial mon:stdio -display none

AST1030 EVB uses UART5:

qemu-system-arm -machine ast1030-evb \
-kernel Y35BCL.elf -nographic

Fixes: 6827ff20b2975 ("hw: aspeed: Init all UART's with serial devices")
Signed-off-by: Peter Delevoryas 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220705191400.41632-4-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 include/hw/arm/aspeed_soc.h |  7 --
 hw/arm/aspeed.c | 22 +---
 hw/arm/aspeed_ast10x0.c |  8 +-
 hw/arm/aspeed_ast2600.c |  8 +-
 hw/arm/aspeed_soc.c | 50 +
 5 files changed, 71 insertions(+), 24 deletions(-)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index e65926a667ee..68e907cd64bb 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -36,12 +36,14 @@
 #include "hw/misc/aspeed_lpc.h"
 #include "hw/misc/unimp.h"
 #include "hw/misc/aspeed_peci.h"
+#include "hw/char/serial.h"
 
 #define ASPEED_SPIS_NUM  2
 #define ASPEED_EHCIS_NUM 2
 #define ASPEED_WDTS_NUM  4
 #define ASPEED_CPUS_NUM  2
 #define ASPEED_MACS_NUM  4
+#define ASPEED_UARTS_NUM 13
 
 struct AspeedSoCState {
 /*< private >*/
@@ -79,7 +81,7 @@ struct AspeedSoCState {
 AspeedSDHCIState emmc;
 AspeedLPCState lpc;
 AspeedPECIState peci;
-uint32_t uart_default;
+SerialMM uart[ASPEED_UARTS_NUM];
 Clock *sysclk;
 UnimplementedDeviceState iomem;
 UnimplementedDeviceState video;
@@ -175,7 +177,8 @@ enum {
 };
 
 qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
-void aspeed_soc_uart_init(AspeedSoCState *s);
+bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
+void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
 bool aspeed_soc_dram_init(AspeedSoCState *s, Error **errp);
 void aspeed_mmio_map(AspeedSoCState *s, SysBusDevice *dev, int n, hwaddr addr);
 void aspeed_mmio_map_unimplemented(AspeedSoCState *s, SysBusDevice *dev,
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 6fe9b1354804..e287a76e2843 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -26,6 +26,7 @@
 #include "qemu/error-report.h"
 #include "qemu/units.h"
 #include "hw/qdev-clock.h"
+#include "sysemu/sysemu.h"
 
 static struct arm_boot_info aspeed_board_binfo = {
 .board_id = -1, /* device-tree-only board */
@@ -301,6 +302,21 @@ static void sdhci_attach_drive(SDHCIState *sdhci, 
DriveInfo *dinfo)
&error_fatal);
 }
 
+static void connect_serial_hds_to_uarts(AspeedMachineState *bmc)
+{
+AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
+AspeedSoCState *s = &bmc->soc;
+AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+
+aspeed_soc_uart_set_chr(s, amc->uart_default, serial_hd(0));
+for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
+if (uart == amc->uart_default) {
+continue;
+}
+aspeed_soc_uart_set_chr(s, uart, serial_hd(i));
+}
+}
+
 static void aspeed_machine_init(MachineState *machine)
 {
 AspeedMachineState *bmc = ASPEED_MACHINE(machine);
@@ -346,8 +362,7 @@ static void aspeed_machine_init(MachineState *machine)
 object_property_set_int(OBJECT(&bmc->soc), "hw-prot-key",
 ASPEED_SCU_PROT_KEY, &error_abort);
 }
-qdev_prop_set_uint32(DEVICE(&bmc->soc), "uart-default",
- amc->uart_default);
+connect_serial_hds_to_uarts(bmc);
 qdev_realize(DEVICE(&bmc->soc), NULL, &error_abort);
 

[PULL 07/19] aspeed: Make aspeed_board_init_flashes public

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

Signed-off-by: Peter Delevoryas 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220705191400.41632-5-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 include/hw/arm/aspeed_soc.h | 2 ++
 hw/arm/aspeed.c | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 68e907cd64bb..8389200b2d01 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -184,5 +184,7 @@ void aspeed_mmio_map(AspeedSoCState *s, SysBusDevice *dev, 
int n, hwaddr addr);
 void aspeed_mmio_map_unimplemented(AspeedSoCState *s, SysBusDevice *dev,
const char *name, hwaddr addr,
uint64_t size);
+void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
+   unsigned int count, int unit0);
 
 #endif /* ASPEED_SOC_H */
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index e287a76e2843..b4355ee26a45 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -262,7 +262,7 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, 
size_t rom_size,
 rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr);
 }
 
-static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
+void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
   unsigned int count, int unit0)
 {
 int i;
-- 
2.35.3




[PULL 18/19] hw/gpio/aspeed: Don't let guests modify input pins

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

Up until now, guests could modify input pins by overwriting the data
value register. The guest OS should only be allowed to modify output pin
values, and the QOM property setter should only be permitted to modify
input pins.

This change also updates the gpio input pin test to match this
expectation.

Andrew suggested this particularly refactoring here:


https://lore.kernel.org/qemu-devel/23523aa1-ba81-412b-92cc-8174faba3...@www.fastmail.com/

Suggested-by: Andrew Jeffery 
Signed-off-by: Peter Delevoryas 
Fixes: 4b7f956862dc ("hw/gpio: Add basic Aspeed GPIO model for AST2400 and 
AST2500")
Reviewed-by: Cédric Le Goater 
Message-Id: <20220712023219.41065-3-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 hw/gpio/aspeed_gpio.c  | 15 ---
 tests/qtest/aspeed_gpio-test.c |  2 +-
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
index a62a673857c2..1e267dd48203 100644
--- a/hw/gpio/aspeed_gpio.c
+++ b/hw/gpio/aspeed_gpio.c
@@ -268,7 +268,7 @@ static ptrdiff_t aspeed_gpio_set_idx(AspeedGPIOState *s, 
GPIOSets *regs)
 }
 
 static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
-   uint32_t value)
+   uint32_t value, uint32_t mode_mask)
 {
 uint32_t input_mask = regs->input_mask;
 uint32_t direction = regs->direction;
@@ -277,7 +277,8 @@ static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets 
*regs,
 uint32_t diff;
 int gpio;
 
-diff = old ^ new;
+diff = (old ^ new);
+diff &= mode_mask;
 if (diff) {
 for (gpio = 0; gpio < ASPEED_GPIOS_PER_SET; gpio++) {
 uint32_t mask = 1 << gpio;
@@ -339,7 +340,7 @@ static void aspeed_gpio_set_pin_level(AspeedGPIOState *s, 
uint32_t set_idx,
 value &= ~pin_mask;
 }
 
-aspeed_gpio_update(s, &s->sets[set_idx], value);
+aspeed_gpio_update(s, &s->sets[set_idx], value, 
~s->sets[set_idx].direction);
 }
 
 /*
@@ -653,7 +654,7 @@ static void aspeed_gpio_write_index_mode(void *opaque, 
hwaddr offset,
 reg_value = update_value_control_source(set, set->data_value,
 reg_value);
 set->data_read = reg_value;
-aspeed_gpio_update(s, set, reg_value);
+aspeed_gpio_update(s, set, reg_value, set->direction);
 return;
 case gpio_reg_idx_direction:
 reg_value = set->direction;
@@ -753,7 +754,7 @@ static void aspeed_gpio_write_index_mode(void *opaque, 
hwaddr offset,
 __func__, offset, data, reg_idx_type);
 return;
 }
-aspeed_gpio_update(s, set, set->data_value);
+aspeed_gpio_update(s, set, set->data_value, UINT32_MAX);
 return;
 }
 
@@ -799,7 +800,7 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, 
uint64_t data,
 data &= props->output;
 data = update_value_control_source(set, set->data_value, data);
 set->data_read = data;
-aspeed_gpio_update(s, set, data);
+aspeed_gpio_update(s, set, data, set->direction);
 return;
 case gpio_reg_direction:
 /*
@@ -875,7 +876,7 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, 
uint64_t data,
   PRIx64"\n", __func__, offset);
 return;
 }
-aspeed_gpio_update(s, set, set->data_value);
+aspeed_gpio_update(s, set, set->data_value, UINT32_MAX);
 return;
 }
 
diff --git a/tests/qtest/aspeed_gpio-test.c b/tests/qtest/aspeed_gpio-test.c
index 8f524540998d..d38f51d71908 100644
--- a/tests/qtest/aspeed_gpio-test.c
+++ b/tests/qtest/aspeed_gpio-test.c
@@ -69,7 +69,7 @@ static void test_set_input_pins(const void *data)
 
 qtest_writel(s, AST2600_GPIO_BASE + GPIO_ABCD_DATA_VALUE, 0x);
 value = qtest_readl(s, AST2600_GPIO_BASE + GPIO_ABCD_DATA_VALUE);
-g_assert_cmphex(value, ==, 0x);
+g_assert_cmphex(value, ==, 0x);
 }
 
 int main(int argc, char **argv)
-- 
2.35.3




[PULL 08/19] aspeed: Add fby35 skeleton

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

Signed-off-by: Peter Delevoryas 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220705191400.41632-6-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 hw/arm/fby35.c | 39 +++
 MAINTAINERS|  1 +
 hw/arm/meson.build |  3 ++-
 3 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/fby35.c

diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c
new file mode 100644
index ..03b458584c26
--- /dev/null
+++ b/hw/arm/fby35.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates. (http://www.meta.com)
+ *
+ * This code is licensed under the GPL version 2 or later. See the COPYING
+ * file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/boards.h"
+
+#define TYPE_FBY35 MACHINE_TYPE_NAME("fby35")
+OBJECT_DECLARE_SIMPLE_TYPE(Fby35State, FBY35);
+
+struct Fby35State {
+MachineState parent_obj;
+};
+
+static void fby35_init(MachineState *machine)
+{
+}
+
+static void fby35_class_init(ObjectClass *oc, void *data)
+{
+MachineClass *mc = MACHINE_CLASS(oc);
+
+mc->desc = "Meta Platforms fby35";
+mc->init = fby35_init;
+}
+
+static const TypeInfo fby35_types[] = {
+{
+.name = MACHINE_TYPE_NAME("fby35"),
+.parent = TYPE_MACHINE,
+.class_init = fby35_class_init,
+.instance_size = sizeof(Fby35State),
+},
+};
+
+DEFINE_TYPES(fby35_types);
diff --git a/MAINTAINERS b/MAINTAINERS
index 450abd025271..fce6161ce506 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1065,6 +1065,7 @@ F: hw/net/ftgmac100.c
 F: include/hw/net/ftgmac100.h
 F: docs/system/arm/aspeed.rst
 F: tests/qtest/*aspeed*
+F: hw/arm/fby35.c
 
 NRF51
 M: Joel Stanley 
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 2d8381339c07..92f9f6e000ea 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -51,7 +51,8 @@ arm_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
   'aspeed_soc.c',
   'aspeed.c',
   'aspeed_ast2600.c',
-  'aspeed_ast10x0.c'))
+  'aspeed_ast10x0.c',
+  'fby35.c'))
 arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2.c'))
 arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2-tz.c'))
 arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c'))
-- 
2.35.3




[PULL 04/19] hw/sensor: Add Renesas ISL69259 device model

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

This adds the ISL69259, using all the same functionality as the existing
ISL69260 but overriding the IC_DEVICE_ID.

Signed-off-by: Peter Delevoryas 
Reviewed-by: Titus Rwantare 
Message-Id: <20220701000626.77395-4...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 hw/sensor/isl_pmbus_vr.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/hw/sensor/isl_pmbus_vr.c b/hw/sensor/isl_pmbus_vr.c
index 799ea9d89edb..eb344dd5a9d5 100644
--- a/hw/sensor/isl_pmbus_vr.c
+++ b/hw/sensor/isl_pmbus_vr.c
@@ -119,6 +119,18 @@ static void raa228000_exit_reset(Object *obj)
 pmdev->pages[0].read_temperature_3 = 0;
 }
 
+static void isl69259_exit_reset(Object *obj)
+{
+ISLState *s = ISL69260(obj);
+static const uint8_t ic_device_id[] = {0x04, 0x00, 0x81, 0xD2, 0x49, 0x3c};
+g_assert(sizeof(ic_device_id) <= sizeof(s->ic_device_id));
+
+isl_pmbus_vr_exit_reset(obj);
+
+s->ic_device_id_len = sizeof(ic_device_id);
+memcpy(s->ic_device_id, ic_device_id, sizeof(ic_device_id));
+}
+
 static void isl_pmbus_vr_add_props(Object *obj, uint64_t *flags, uint8_t pages)
 {
 PMBusDevice *pmdev = PMBUS_DEVICE(obj);
@@ -257,6 +269,21 @@ static void raa229004_class_init(ObjectClass *klass, void 
*data)
 isl_pmbus_vr_class_init(klass, data, 2);
 }
 
+static void isl69259_class_init(ObjectClass *klass, void *data)
+{
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+DeviceClass *dc = DEVICE_CLASS(klass);
+dc->desc = "Renesas ISL69259 Digital Multiphase Voltage Regulator";
+rc->phases.exit = isl69259_exit_reset;
+isl_pmbus_vr_class_init(klass, data, 2);
+}
+
+static const TypeInfo isl69259_info = {
+.name = TYPE_ISL69259,
+.parent = TYPE_ISL69260,
+.class_init = isl69259_class_init,
+};
+
 static const TypeInfo isl69260_info = {
 .name = TYPE_ISL69260,
 .parent = TYPE_PMBUS_DEVICE,
@@ -283,6 +310,7 @@ static const TypeInfo raa228000_info = {
 
 static void isl_pmbus_vr_register_types(void)
 {
+type_register_static(&isl69259_info);
 type_register_static(&isl69260_info);
 type_register_static(&raa228000_info);
 type_register_static(&raa229004_info);
-- 
2.35.3




[PULL 13/19] docs: aspeed: Minor updates

2022-07-13 Thread Cédric Le Goater
Some more controllers have been modeled recently. Reflect that in the
list of supported devices. New machines were also added.

Signed-off-by: Cédric Le Goater 
Reviewed-by: Peter Delevoryas 
Reviewed-by: Joel Stanley 
Message-Id: <20220706172131.809255-1-...@kaod.org>
Signed-off-by: Cédric Le Goater 
---
 docs/system/arm/aspeed.rst | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

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




[PULL 05/19] aspeed: Create SRAM name from first CPU index

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

To support multiple SoC's running simultaneously, we need a unique name for
each RAM region. DRAM is created by the machine, but SRAM is created by the
SoC, since in hardware it is part of the SoC's internals.

We need a way to uniquely identify each SRAM region though, for VM
migration. Since each of the SoC's CPU's has an index which identifies it
uniquely from other CPU's in the machine, we can use the index of any of the
CPU's in the SoC to uniquely identify differentiate the SRAM name from other
SoC SRAM's. In this change, I just elected to use the index of the first CPU
in each SoC.

Signed-off-by: Peter Delevoryas 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220705191400.41632-3-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 hw/arm/aspeed_ast10x0.c | 5 -
 hw/arm/aspeed_ast2600.c | 5 +++--
 hw/arm/aspeed_soc.c | 5 +++--
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index 33ef33177199..677699e54c0a 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -159,6 +159,7 @@ static void aspeed_soc_ast1030_realize(DeviceState 
*dev_soc, Error **errp)
 DeviceState *armv7m;
 Error *err = NULL;
 int i;
+g_autofree char *sram_name = NULL;
 
 if (!clock_has_source(s->sysclk)) {
 error_setg(errp, "sysclk clock must be wired up by the board code");
@@ -183,7 +184,9 @@ static void aspeed_soc_ast1030_realize(DeviceState 
*dev_soc, Error **errp)
 sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), &error_abort);
 
 /* Internal SRAM */
-memory_region_init_ram(&s->sram, NULL, "aspeed.sram", sc->sram_size, &err);
+sram_name = g_strdup_printf("aspeed.sram.%d",
+CPU(s->armv7m.cpu)->cpu_index);
+memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size, 
&err);
 if (err != NULL) {
 error_propagate(errp, err);
 return;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 3f0611ac11cd..64eb5a7b2600 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -276,6 +276,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 Error *err = NULL;
 qemu_irq irq;
+g_autofree char *sram_name = NULL;
 
 /* IO space */
 aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
@@ -335,8 +336,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 }
 
 /* SRAM */
-memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
-   sc->sram_size, &err);
+sram_name = g_strdup_printf("aspeed.sram.%d", CPU(&s->cpu[0])->cpu_index);
+memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size, 
&err);
 if (err) {
 error_propagate(errp, err);
 return;
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 0f675e7fcdf5..0bb6a2f092c9 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -239,6 +239,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error 
**errp)
 AspeedSoCState *s = ASPEED_SOC(dev);
 AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 Error *err = NULL;
+g_autofree char *sram_name = NULL;
 
 /* IO space */
 aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
@@ -259,8 +260,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error 
**errp)
 }
 
 /* SRAM */
-memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
-   sc->sram_size, &err);
+sram_name = g_strdup_printf("aspeed.sram.%d", CPU(&s->cpu[0])->cpu_index);
+memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size, 
&err);
 if (err) {
 error_propagate(errp, err);
 return;
-- 
2.35.3




[PULL 14/19] test/avocado/machine_aspeed.py: Add SDK tests

2022-07-13 Thread Cédric Le Goater
The Aspeed SDK kernel usually includes support for the lastest HW
features. This is interesting to exercise QEMU and discover the gaps
in the models.

Add extra I2C tests for the AST2600 EVB machine to check the new
register interface.

Message-Id: <20220707091239.1029561-1-...@kaod.org>
Signed-off-by: Cédric Le Goater 
---
 tests/avocado/machine_aspeed.py | 68 +
 1 file changed, 68 insertions(+)

diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index 3b8f784a57b6..b4e35a3d0743 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -170,3 +170,71 @@ def test_arm_ast2600_evb_builroot(self):
 exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year);
 
 self.do_test_arm_aspeed_buidroot_poweroff()
+
+
+def do_test_arm_aspeed_sdk_start(self, image, cpu_id):
+self.vm.set_console()
+self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
+ '-net', 'nic', '-net', 'user')
+self.vm.launch()
+
+self.wait_for_console_pattern('U-Boot 2019.04')
+self.wait_for_console_pattern('## Loading kernel from FIT Image')
+self.wait_for_console_pattern('Starting kernel ...')
+self.wait_for_console_pattern('Booting Linux on physical CPU ' + 
cpu_id)
+
+def test_arm_ast2500_evb_sdk(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:ast2500-evb
+"""
+
+image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
+ 'download/v08.01/ast2500-default-obmc.tar.gz')
+image_hash = 
('5375f82b4c43a79427909342a1e18b4e48bd663e38466862145d27bb358796fd')
+image_path = self.fetch_asset(image_url, asset_hash=image_hash,
+  algorithm='sha256')
+archive.extract(image_path, self.workdir)
+
+self.do_test_arm_aspeed_sdk_start(
+self.workdir + '/ast2500-default/image-bmc', '0x0')
+self.wait_for_console_pattern('ast2500-default login:')
+
+def test_arm_ast2600_evb_sdk(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:ast2600-evb
+"""
+
+image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
+ 'download/v08.01/ast2600-default-obmc.tar.gz')
+image_hash = 
('f12ef15e8c1f03a214df3b91c814515c5e2b2f56119021398c1dbdd626817d15')
+image_path = self.fetch_asset(image_url, asset_hash=image_hash,
+  algorithm='sha256')
+archive.extract(image_path, self.workdir)
+
+self.vm.add_args('-device',
+ 
'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test');
+self.vm.add_args('-device',
+ 'ds1338,bus=aspeed.i2c.bus.5,address=0x32');
+self.do_test_arm_aspeed_sdk_start(
+self.workdir + '/ast2600-default/image-bmc', '0xf00')
+self.wait_for_console_pattern('ast2600-default login:')
+exec_command_and_wait_for_pattern(self, 'root', 'Password:')
+exec_command_and_wait_for_pattern(self, '0penBmc', 
'root@ast2600-default:~#')
+
+exec_command_and_wait_for_pattern(self,
+ 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device',
+ 'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d');
+exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon19/temp1_input', '0')
+self.vm.command('qom-set', path='/machine/peripheral/tmp-test',
+property='temperature', value=18000);
+exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon19/temp1_input', 
'18000')
+
+exec_command_and_wait_for_pattern(self,
+ 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device',
+ 'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32');
+year = time.strftime("%Y")
+exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year);
-- 
2.35.3




[PULL 10/19] aspeed: fby35: Add a bootrom for the BMC

2022-07-13 Thread Cédric Le Goater
The BMC boots from the first flash device by fetching instructions
from the flash contents. Add an alias region on 0x0 for this
purpose. There are currently performance issues with this method (TBs
being flushed too often), so as a faster alternative, install the
flash contents as a ROM in the BMC memory space.

See commit 1a15311a12fa ("hw/arm/aspeed: add a 'execute-in-place'
property to boot directly from CE0")

Signed-off-by: Cédric Le Goater 
Signed-off-by: Peter Delevoryas 
Message-Id: <20220705191400.41632-8-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 hw/arm/fby35.c | 83 ++
 1 file changed, 83 insertions(+)

diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c
index 5c5224d37471..d3edfa3b108e 100644
--- a/hw/arm/fby35.c
+++ b/hw/arm/fby35.c
@@ -9,6 +9,7 @@
 #include "qemu/units.h"
 #include "qapi/error.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
 #include "hw/boards.h"
 #include "hw/arm/aspeed_soc.h"
 
@@ -23,12 +24,49 @@ struct Fby35State {
 MemoryRegion bmc_boot_rom;
 
 AspeedSoCState bmc;
+
+bool mmio_exec;
 };
 
 #define FBY35_BMC_RAM_SIZE (2 * GiB)
+#define FBY35_BMC_FIRMWARE_ADDR 0x0
+
+static void fby35_bmc_write_boot_rom(DriveInfo *dinfo, MemoryRegion *mr,
+ hwaddr offset, size_t rom_size,
+ Error **errp)
+{
+BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
+g_autofree void *storage = NULL;
+int64_t size;
+
+/*
+ * The block backend size should have already been 'validated' by
+ * the creation of the m25p80 object.
+ */
+size = blk_getlength(blk);
+if (size <= 0) {
+error_setg(errp, "failed to get flash size");
+return;
+}
+
+if (rom_size > size) {
+rom_size = size;
+}
+
+storage = g_malloc0(rom_size);
+if (blk_pread(blk, 0, storage, rom_size) < 0) {
+error_setg(errp, "failed to read the initial flash content");
+return;
+}
+
+/* TODO: find a better way to install the ROM */
+memcpy(memory_region_get_ram_ptr(mr) + offset, storage, rom_size);
+}
 
 static void fby35_bmc_init(Fby35State *s)
 {
+DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
+
 memory_region_init(&s->bmc_memory, OBJECT(s), "bmc-memory", UINT64_MAX);
 memory_region_init_ram(&s->bmc_dram, OBJECT(s), "bmc-dram",
FBY35_BMC_RAM_SIZE, &error_abort);
@@ -48,6 +86,28 @@ static void fby35_bmc_init(Fby35State *s)
 qdev_realize(DEVICE(&s->bmc), NULL, &error_abort);
 
 aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0);
+
+/* Install first FMC flash content as a boot rom. */
+if (drive0) {
+AspeedSMCFlash *fl = &s->bmc.fmc.flashes[0];
+MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+uint64_t size = memory_region_size(&fl->mmio);
+
+if (s->mmio_exec) {
+memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom",
+ &fl->mmio, 0, size);
+memory_region_add_subregion(&s->bmc_memory, 
FBY35_BMC_FIRMWARE_ADDR,
+boot_rom);
+} else {
+
+memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
+   size, &error_abort);
+memory_region_add_subregion(&s->bmc_memory, 
FBY35_BMC_FIRMWARE_ADDR,
+boot_rom);
+fby35_bmc_write_boot_rom(drive0, boot_rom, FBY35_BMC_FIRMWARE_ADDR,
+ size, &error_abort);
+}
+}
 }
 
 static void fby35_init(MachineState *machine)
@@ -57,6 +117,22 @@ static void fby35_init(MachineState *machine)
 fby35_bmc_init(s);
 }
 
+
+static bool fby35_get_mmio_exec(Object *obj, Error **errp)
+{
+return FBY35(obj)->mmio_exec;
+}
+
+static void fby35_set_mmio_exec(Object *obj, bool value, Error **errp)
+{
+FBY35(obj)->mmio_exec = value;
+}
+
+static void fby35_instance_init(Object *obj)
+{
+FBY35(obj)->mmio_exec = false;
+}
+
 static void fby35_class_init(ObjectClass *oc, void *data)
 {
 MachineClass *mc = MACHINE_CLASS(oc);
@@ -66,6 +142,12 @@ static void fby35_class_init(ObjectClass *oc, void *data)
 mc->no_floppy = 1;
 mc->no_cdrom = 1;
 mc->min_cpus = mc->max_cpus = mc->default_cpus = 2;
+
+object_class_property_add_bool(oc, "execute-in-place",
+   fby35_get_mmio_exec,
+   fby35_set_mmio_exec);
+object_class_property_set_description(oc, "execute-in-place",
+   "boot directly from CE0 flash device");
 }
 
 static const TypeInfo fby35_types[] = {
@@ -74,6 +156,7 @@ static const TypeInfo fby35_types[] = {
 .parent = TYPE_MACHINE,
 .class_init = fby35_class_init,
 .instance_size = sizeof(Fby35State),
+.instance_init = fby35_instance_init,
 },
 };
 
-- 
2.35.3




Re: [PATCH 1/4] Modifying ‘migrate’ qmp command to add multi-FD socket on particular source and destination pair

2022-07-13 Thread Het Gala



On 16/06/22 10:56 pm, Dr. David Alan Gilbert wrote:

* Het Gala (het.g...@nutanix.com) wrote:


> First of all, I apologise for the late reply. I was on a leave after 
internship ended


at Nutanix. Hope to learn a lot from you all in the process of 
upstreaming multifd


patches.


i) Modified the format of the qemu monitor command : 'migrate' by adding a list,
each element in the list consists of multi-FD connection parameters: source
and destination uris and of the number of multi-fd channels between each 
pair.

ii) Information of all multi-FD connection parameters’ list, length of the list
 and total number of multi-fd channels for all the connections together is
 stored in ‘OutgoingArgs’ struct.

Suggested-by: Manish Mishra 
Signed-off-by: Het Gala 
---
  include/qapi/util.h   |  9 
  migration/migration.c | 47 ++
  migration/socket.c| 53 ---
  migration/socket.h| 17 +-
  monitor/hmp-cmds.c| 22 --
  qapi/migration.json   | 43 +++
  6 files changed, 170 insertions(+), 21 deletions(-)

diff --git a/include/qapi/util.h b/include/qapi/util.h
index 81a2b13a33..3041feb3d9 100644
--- a/include/qapi/util.h
+++ b/include/qapi/util.h
@@ -56,4 +56,13 @@ int parse_qapi_name(const char *name, bool complete);
  (tail) = &(*(tail))->next; \
  } while (0)
  
+#define QAPI_LIST_LENGTH(list) ({ \

+int _len = 0; \
+typeof(list) _elem; \
+for (_elem = list; _elem != NULL; _elem = _elem->next) { \
+_len++; \
+} \
+_len; \
+})
+
  #endif

This looks like it should be a separate patch to me (and perhaps size_t
for len?)


> Sure, will try to make a seperate patch for QAPI_LIST_LENGTH, and other

such utility functions from the other patches.




diff --git a/migration/migration.c b/migration/migration.c
index 31739b2af9..c408175aeb 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -2328,13 +2328,14 @@ static bool migrate_prepare(MigrationState *s, bool 
blk, bool blk_inc,
  return true;
  }
  
-void qmp_migrate(const char *uri, bool has_blk, bool blk,

+void qmp_migrate(const char *uri, bool has_multi_fd_uri_list,
+ MigrateUriParameterList *cap, bool has_blk, bool blk,
   bool has_inc, bool inc, bool has_detach, bool detach,
   bool has_resume, bool resume, Error **errp)
  {
  Error *local_err = NULL;
  MigrationState *s = migrate_get_current();
-const char *p = NULL;
+const char *dst_ptr = NULL;
  
  if (!migrate_prepare(s, has_blk && blk, has_inc && inc,

   has_resume && resume, errp)) {
@@ -2348,20 +2349,46 @@ void qmp_migrate(const char *uri, bool has_blk, bool 
blk,
  }
  }
  
+/*

+ * In case of Multi-FD migration parameters, if uri is provided,

I think you mean 'if uri list is provided'

> Acknowledged.



+ * supports only tcp network protocol.
+ */
+if (has_multi_fd_uri_list) {
+int length = QAPI_LIST_LENGTH(cap);
+init_multifd_array(length);
+for (int i = 0; i < length; i++) {
+const char *p1 = NULL, *p2 = NULL;

Keep these as ps/pd  to make it clear which is source and dest.

> Acknowledged. Will change in the upcoming patchset.



+const char *multifd_dst_uri = cap->value->destination_uri;
+const char *multifd_src_uri = cap->value->source_uri;
+uint8_t multifd_channels = cap->value->multifd_channels;
+if (!strstart(multifd_dst_uri, "tcp:", &p1) ||
+!strstart(multifd_src_uri, "tcp:", &p2)) {

I've copied in Claudio Fontana; Claudio is fighting to make snapshots
faster and has been playing with various multithread schemes for multifd
with files and fd's;  perhaps the syntax you're proposing doesn't need
to be limited to tcp.


> For now, we are just aiming to include multifd for existing tcp 
protocol.


We would be happy to take any suggestions from Claudio Fontana and try to

include them in the upcoming patchset series.




+error_setg(errp, "multi-fd destination and multi-fd source "
+"uri, both should be present and follows tcp protocol only");
+break;
+} else {
+store_multifd_migration_params(p1 ? p1 : multifd_dst_uri,
+p2 ? p2 : multifd_src_uri,
+multifd_channels, i, &local_err);
+}
+cap = cap->next;
+}
+}
+
  migrate_protocol_allow_multi_channels(false);
-if (strstart(uri, "tcp:", &p) ||
+if (strstart(uri, "tcp:", &dst_ptr) ||
  strstart(uri, "unix:", NULL) ||
  strstart(uri, "vsock:", NULL)) {
  migrate_protocol_allow_multi_channels(true);
-socket_start_outgoing_migration(s, p ? p : uri, &local_err);
+socket_sta

[PULL 16/19] hw: m25p80: add tests for BP and TB bit write protect

2022-07-13 Thread Cédric Le Goater
From: Iris Chen 

Signed-off-by: Iris Chen 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220627185234.1911337-3-irische...@fb.com>
Signed-off-by: Cédric Le Goater 
---
 tests/qtest/aspeed_smc-test.c | 111 ++
 1 file changed, 111 insertions(+)

diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c
index 1258687eacd8..05ce941566e6 100644
--- a/tests/qtest/aspeed_smc-test.c
+++ b/tests/qtest/aspeed_smc-test.c
@@ -192,6 +192,24 @@ static void read_page_mem(uint32_t addr, uint32_t *page)
 }
 }
 
+static void write_page_mem(uint32_t addr, uint32_t write_value)
+{
+spi_ctrl_setmode(CTRL_WRITEMODE, PP);
+
+for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
+writel(ASPEED_FLASH_BASE + addr + i * 4, write_value);
+}
+}
+
+static void assert_page_mem(uint32_t addr, uint32_t expected_value)
+{
+uint32_t page[FLASH_PAGE_SIZE / 4];
+read_page_mem(addr, page);
+for (int i = 0; i < FLASH_PAGE_SIZE / 4; i++) {
+g_assert_cmphex(page[i], ==, expected_value);
+}
+}
+
 static void test_erase_sector(void)
 {
 uint32_t some_page_addr = 0x600 * FLASH_PAGE_SIZE;
@@ -501,6 +519,95 @@ static void test_status_reg_write_protection(void)
 flash_reset();
 }
 
+static void test_write_block_protect(void)
+{
+uint32_t sector_size = 65536;
+uint32_t n_sectors = 512;
+
+spi_ce_ctrl(1 << CRTL_EXTENDED0);
+spi_conf(CONF_ENABLE_W0);
+
+uint32_t bp_bits = 0b0;
+
+for (int i = 0; i < 16; i++) {
+bp_bits = ((i & 0b1000) << 3) | ((i & 0b0111) << 2);
+
+spi_ctrl_start_user();
+writeb(ASPEED_FLASH_BASE, WREN);
+writeb(ASPEED_FLASH_BASE, BULK_ERASE);
+writeb(ASPEED_FLASH_BASE, WREN);
+writeb(ASPEED_FLASH_BASE, WRSR);
+writeb(ASPEED_FLASH_BASE, bp_bits);
+writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
+writeb(ASPEED_FLASH_BASE, WREN);
+spi_ctrl_stop_user();
+
+uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
+uint32_t protection_start = n_sectors - num_protected_sectors;
+uint32_t protection_end = n_sectors;
+
+for (int sector = 0; sector < n_sectors; sector++) {
+uint32_t addr = sector * sector_size;
+
+assert_page_mem(addr, 0x);
+write_page_mem(addr, make_be32(0xabcdef12));
+
+uint32_t expected_value = protection_start <= sector
+  && sector < protection_end
+  ? 0x : 0xabcdef12;
+
+assert_page_mem(addr, expected_value);
+}
+}
+
+flash_reset();
+}
+
+static void test_write_block_protect_bottom_bit(void)
+{
+uint32_t sector_size = 65536;
+uint32_t n_sectors = 512;
+
+spi_ce_ctrl(1 << CRTL_EXTENDED0);
+spi_conf(CONF_ENABLE_W0);
+
+/* top bottom bit is enabled */
+uint32_t bp_bits = 0b00100 << 3;
+
+for (int i = 0; i < 16; i++) {
+bp_bits = (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2);
+
+spi_ctrl_start_user();
+writeb(ASPEED_FLASH_BASE, WREN);
+writeb(ASPEED_FLASH_BASE, BULK_ERASE);
+writeb(ASPEED_FLASH_BASE, WREN);
+writeb(ASPEED_FLASH_BASE, WRSR);
+writeb(ASPEED_FLASH_BASE, bp_bits);
+writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
+writeb(ASPEED_FLASH_BASE, WREN);
+spi_ctrl_stop_user();
+
+uint32_t num_protected_sectors = i ? MIN(1 << (i - 1), n_sectors) : 0;
+uint32_t protection_start = 0;
+uint32_t protection_end = num_protected_sectors;
+
+for (int sector = 0; sector < n_sectors; sector++) {
+uint32_t addr = sector * sector_size;
+
+assert_page_mem(addr, 0x);
+write_page_mem(addr, make_be32(0xabcdef12));
+
+uint32_t expected_value = protection_start <= sector
+  && sector < protection_end
+  ? 0x : 0xabcdef12;
+
+assert_page_mem(addr, expected_value);
+}
+}
+
+flash_reset();
+}
+
 static char tmp_path[] = "/tmp/qtest.m25p80.XX";
 
 int main(int argc, char **argv)
@@ -529,6 +636,10 @@ int main(int argc, char **argv)
 qtest_add_func("/ast2400/smc/read_status_reg", test_read_status_reg);
 qtest_add_func("/ast2400/smc/status_reg_write_protection",
test_status_reg_write_protection);
+qtest_add_func("/ast2400/smc/write_block_protect",
+   test_write_block_protect);
+qtest_add_func("/ast2400/smc/write_block_protect_bottom_bit",
+   test_write_block_protect_bottom_bit);
 
 flash_reset();
 ret = g_test_run();
-- 
2.35.3




[PATCH 00/11] QOM'ify PIIX3 southbridge

2022-07-13 Thread Bernhard Beschow
Similar to PIIX4 this series QOM'ifies internal device creation for PIIX3.
This reduces the delta between the implementations of PIIX3 and PIIX4 and
therefore might allow to merge both implementations in the future.

There were two challenges in this series:

First, QEMU considers the ACPI and USB functions to be optional in PIIX3.
When instantiating those with object_initialize_child(), they need to be
unparented in the realize function to prevent an assertion (see respective
commit messages).

Second, the PIC used to be instantiated outside of the southbridge while
some sub functions require a PIC with populated qemu_irqs. This has been
solved by introducing a proxy PIC which furthermore allows PIIX3 to be
agnostic towards the virtualization technology used (KVM, TCG, Xen).

Testing done:
* make check
* make check-avocado
* Boot live CD:
  * qemu-system-x86_64 -M pc -m 2G -accel kvm -cpu host -cdrom 
manjaro-kde-21.3.2-220704-linux515.iso
  * qemu-system-x86_64 -M q35 -m 2G -accel kvm -cpu host -cdrom 
manjaro-kde-21.3.2-220704-linux515.iso

Bernhard Beschow (11):
  hw/i386/pc: QOM'ify DMA creation
  hw/i386/pc_piix: Allow for setting properties before realizing PIIX3
southbridge
  hw/isa/piix3: QOM'ify USB controller creation
  hw/isa/piix3: QOM'ify ACPI controller creation
  hw/i386/pc: QOM'ify RTC creation
  hw/i386/pc: No need for rtc_state to be an out-parameter
  hw/intc/i8259: Introduce i8259 proxy "isa-pic"
  hw/isa/piix3: QOM'ify ISA PIC creation
  hw/isa/piix3: QOM'ify IDE controller creation
  hw/isa/piix3: Wire up ACPI interrupt internally
  hw/isa/piix3: Remove extra ';' outside of functions

 hw/i386/Kconfig   |  1 -
 hw/i386/pc.c  | 17 ---
 hw/i386/pc_piix.c | 70 -
 hw/i386/pc_q35.c  |  3 +-
 hw/intc/i8259.c   | 27 +++
 hw/isa/Kconfig|  1 +
 hw/isa/lpc_ich9.c | 11 +
 hw/isa/piix3.c| 84 ---
 include/hw/i386/ich9.h|  2 +
 include/hw/i386/pc.h  |  2 +-
 include/hw/intc/i8259.h   | 14 ++
 include/hw/southbridge/piix.h | 16 ++-
 12 files changed, 201 insertions(+), 47 deletions(-)

-- 
2.37.1




[PULL 09/19] aspeed: Add AST2600 (BMC) to fby35

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

You can test booting the BMC with both '-device loader' and '-drive
file'. This is necessary because of how the fb-openbmc boot sequence
works (jump to 0x2000 after U-Boot SPL).

wget 
https://github.com/facebook/openbmc/releases/download/openbmc-e2294ff5d31d/fby35.mtd
qemu-system-arm -machine fby35 -nographic \
-device loader,file=fby35.mtd,addr=0,cpu-num=0 -drive 
file=fby35.mtd,format=raw,if=mtd

Signed-off-by: Peter Delevoryas 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220705191400.41632-7-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 hw/arm/fby35.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c
index 03b458584c26..5c5224d37471 100644
--- a/hw/arm/fby35.c
+++ b/hw/arm/fby35.c
@@ -6,17 +6,55 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
 #include "hw/boards.h"
+#include "hw/arm/aspeed_soc.h"
 
 #define TYPE_FBY35 MACHINE_TYPE_NAME("fby35")
 OBJECT_DECLARE_SIMPLE_TYPE(Fby35State, FBY35);
 
 struct Fby35State {
 MachineState parent_obj;
+
+MemoryRegion bmc_memory;
+MemoryRegion bmc_dram;
+MemoryRegion bmc_boot_rom;
+
+AspeedSoCState bmc;
 };
 
+#define FBY35_BMC_RAM_SIZE (2 * GiB)
+
+static void fby35_bmc_init(Fby35State *s)
+{
+memory_region_init(&s->bmc_memory, OBJECT(s), "bmc-memory", UINT64_MAX);
+memory_region_init_ram(&s->bmc_dram, OBJECT(s), "bmc-dram",
+   FBY35_BMC_RAM_SIZE, &error_abort);
+
+object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3");
+object_property_set_int(OBJECT(&s->bmc), "ram-size", FBY35_BMC_RAM_SIZE,
+&error_abort);
+object_property_set_link(OBJECT(&s->bmc), "memory", OBJECT(&s->bmc_memory),
+ &error_abort);
+object_property_set_link(OBJECT(&s->bmc), "dram", OBJECT(&s->bmc_dram),
+ &error_abort);
+object_property_set_int(OBJECT(&s->bmc), "hw-strap1", 0x00C0,
+&error_abort);
+object_property_set_int(OBJECT(&s->bmc), "hw-strap2", 0x0003,
+&error_abort);
+aspeed_soc_uart_set_chr(&s->bmc, ASPEED_DEV_UART5, serial_hd(0));
+qdev_realize(DEVICE(&s->bmc), NULL, &error_abort);
+
+aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0);
+}
+
 static void fby35_init(MachineState *machine)
 {
+Fby35State *s = FBY35(machine);
+
+fby35_bmc_init(s);
 }
 
 static void fby35_class_init(ObjectClass *oc, void *data)
@@ -25,6 +63,9 @@ static void fby35_class_init(ObjectClass *oc, void *data)
 
 mc->desc = "Meta Platforms fby35";
 mc->init = fby35_init;
+mc->no_floppy = 1;
+mc->no_cdrom = 1;
+mc->min_cpus = mc->max_cpus = mc->default_cpus = 2;
 }
 
 static const TypeInfo fby35_types[] = {
-- 
2.35.3




[PULL 11/19] aspeed: Add AST1030 (BIC) to fby35

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

With the BIC, the easiest way to run everything is to create two pty's
for each SoC and reserve stdin/stdout for the monitor:

wget 
https://github.com/facebook/openbmc/releases/download/openbmc-e2294ff5d31d/fby35.mtd
wget 
https://github.com/peterdelevoryas/OpenBIC/releases/download/oby35-cl-2022.13.01/Y35BCL.elf
qemu-system-arm -machine fby35 \
-drive file=fby35.mtd,format=raw,if=mtd \
-device loader,file=fby35.mtd,addr=0,cpu-num=0 \
-serial pty -serial pty -serial mon:stdio -display none -S

screen /dev/ttys0
screen /dev/ttys1
(qemu) c

This commit only adds the the first server board's Bridge IC, but in the
future we'll try to include the other three server board Bridge IC's
too.

Signed-off-by: Peter Delevoryas 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220705191400.41632-9-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 hw/arm/fby35.c | 27 ++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c
index d3edfa3b108e..031602800fde 100644
--- a/hw/arm/fby35.c
+++ b/hw/arm/fby35.c
@@ -11,7 +11,9 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/block-backend.h"
 #include "hw/boards.h"
+#include "hw/qdev-clock.h"
 #include "hw/arm/aspeed_soc.h"
+#include "hw/arm/boot.h"
 
 #define TYPE_FBY35 MACHINE_TYPE_NAME("fby35")
 OBJECT_DECLARE_SIMPLE_TYPE(Fby35State, FBY35);
@@ -22,8 +24,11 @@ struct Fby35State {
 MemoryRegion bmc_memory;
 MemoryRegion bmc_dram;
 MemoryRegion bmc_boot_rom;
+MemoryRegion bic_memory;
+Clock *bic_sysclk;
 
 AspeedSoCState bmc;
+AspeedSoCState bic;
 
 bool mmio_exec;
 };
@@ -110,11 +115,31 @@ static void fby35_bmc_init(Fby35State *s)
 }
 }
 
+static void fby35_bic_init(Fby35State *s)
+{
+s->bic_sysclk = clock_new(OBJECT(s), "SYSCLK");
+clock_set_hz(s->bic_sysclk, 2ULL);
+
+memory_region_init(&s->bic_memory, OBJECT(s), "bic-memory", UINT64_MAX);
+
+object_initialize_child(OBJECT(s), "bic", &s->bic, "ast1030-a1");
+qdev_connect_clock_in(DEVICE(&s->bic), "sysclk", s->bic_sysclk);
+object_property_set_link(OBJECT(&s->bic), "memory", OBJECT(&s->bic_memory),
+ &error_abort);
+aspeed_soc_uart_set_chr(&s->bic, ASPEED_DEV_UART5, serial_hd(1));
+qdev_realize(DEVICE(&s->bic), NULL, &error_abort);
+
+aspeed_board_init_flashes(&s->bic.fmc, "sst25vf032b", 2, 2);
+aspeed_board_init_flashes(&s->bic.spi[0], "sst25vf032b", 2, 4);
+aspeed_board_init_flashes(&s->bic.spi[1], "sst25vf032b", 2, 6);
+}
+
 static void fby35_init(MachineState *machine)
 {
 Fby35State *s = FBY35(machine);
 
 fby35_bmc_init(s);
+fby35_bic_init(s);
 }
 
 
@@ -141,7 +166,7 @@ static void fby35_class_init(ObjectClass *oc, void *data)
 mc->init = fby35_init;
 mc->no_floppy = 1;
 mc->no_cdrom = 1;
-mc->min_cpus = mc->max_cpus = mc->default_cpus = 2;
+mc->min_cpus = mc->max_cpus = mc->default_cpus = 3;
 
 object_class_property_add_bool(oc, "execute-in-place",
fby35_get_mmio_exec,
-- 
2.35.3




[PATCH 01/11] hw/i386/pc: QOM'ify DMA creation

2022-07-13 Thread Bernhard Beschow
Just like in the real hardware, create the DMA in the southbridges.

Signed-off-by: Bernhard Beschow 
---
 hw/i386/pc.c  | 3 ---
 hw/i386/pc_piix.c | 2 ++
 hw/isa/lpc_ich9.c | 3 +++
 hw/isa/piix3.c| 9 +++--
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 774cb2bf07..c3602d166d 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -47,7 +47,6 @@
 #include "multiboot.h"
 #include "hw/rtc/mc146818rtc.h"
 #include "hw/intc/i8259.h"
-#include "hw/dma/i8257.h"
 #include "hw/timer/i8254.h"
 #include "hw/input/i8042.h"
 #include "hw/irq.h"
@@ -1200,8 +1199,6 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 pcspk_init(pcms->pcspk, isa_bus, pit);
 }
 
-i8257_dma_init(isa_bus, 0);
-
 /* Super I/O */
 pc_superio_init(isa_bus, create_fdctrl, pcms->i8042_enabled,
 pcms->vmport != ON_OFF_AUTO_ON);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index a234989ac3..7ad677e967 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -26,6 +26,7 @@
 #include CONFIG_DEVICES
 
 #include "qemu/units.h"
+#include "hw/dma/i8257.h"
 #include "hw/loader.h"
 #include "hw/i386/x86.h"
 #include "hw/i386/pc.h"
@@ -217,6 +218,7 @@ static void pc_init1(MachineState *machine,
 pci_bus = NULL;
 isa_bus = isa_bus_new(NULL, get_system_memory(), system_io,
   &error_abort);
+i8257_dma_init(isa_bus, 0);
 pcms->hpet_enabled = false;
 }
 isa_bus_irqs(isa_bus, x86ms->gsi);
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 4553b5925b..8694e58b21 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -34,6 +34,7 @@
 #include "qapi/error.h"
 #include "qapi/visitor.h"
 #include "qemu/range.h"
+#include "hw/dma/i8257.h"
 #include "hw/isa/isa.h"
 #include "migration/vmstate.h"
 #include "hw/irq.h"
@@ -722,6 +723,8 @@ static void ich9_lpc_realize(PCIDevice *d, Error **errp)
 qdev_init_gpio_out_named(dev, lpc->gsi, ICH9_GPIO_GSI, GSI_NUM_PINS);
 
 isa_bus_irqs(isa_bus, lpc->gsi);
+
+i8257_dma_init(isa_bus, 0);
 }
 
 static bool ich9_rst_cnt_needed(void *opaque)
diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
index 48f9ab1096..44a9998752 100644
--- a/hw/isa/piix3.c
+++ b/hw/isa/piix3.c
@@ -25,6 +25,7 @@
 #include "qemu/osdep.h"
 #include "qemu/range.h"
 #include "qapi/error.h"
+#include "hw/dma/i8257.h"
 #include "hw/southbridge/piix.h"
 #include "hw/irq.h"
 #include "hw/isa/isa.h"
@@ -295,9 +296,11 @@ static const MemoryRegionOps rcr_ops = {
 static void pci_piix3_realize(PCIDevice *dev, Error **errp)
 {
 PIIX3State *d = PIIX3_PCI_DEVICE(dev);
+ISABus *isa_bus;
 
-if (!isa_bus_new(DEVICE(d), get_system_memory(),
- pci_address_space_io(dev), errp)) {
+isa_bus = isa_bus_new(DEVICE(d), get_system_memory(),
+  pci_address_space_io(dev), errp);
+if (!isa_bus) {
 return;
 }
 
@@ -307,6 +310,8 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
 PIIX_RCR_IOPORT, &d->rcr_mem, 1);
 
 qemu_register_reset(piix3_reset, d);
+
+i8257_dma_init(isa_bus, 0);
 }
 
 static void build_pci_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
-- 
2.37.1




[PATCH 04/11] hw/isa/piix3: QOM'ify ACPI controller creation

2022-07-13 Thread Bernhard Beschow
The ACPI controller is an integral part of PIIX3 (function 3). So create
it as part of the southbridge.

Note that the ACPI function is optional in QEMU. This is why it gets
unparented if it is disabled, otherwiese QEMU will abort with:

  src/hw/core/qdev.c:357: qdev_assert_realized_properly_cb: Assertion 
`dev->realized' failed

Signed-off-by: Bernhard Beschow 
---
 hw/i386/pc_piix.c | 22 --
 hw/isa/piix3.c| 16 
 include/hw/southbridge/piix.h |  3 +++
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 96dc0db729..364c73b1bc 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -44,11 +44,11 @@
 #include "sysemu/kvm.h"
 #include "hw/kvm/clock.h"
 #include "hw/sysbus.h"
+#include "hw/i2c/i2c.h"
 #include "hw/i2c/smbus_eeprom.h"
 #include "hw/xen/xen-x86.h"
 #include "exec/memory.h"
 #include "hw/acpi/acpi.h"
-#include "hw/acpi/piix4.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "sysemu/xen.h"
@@ -83,6 +83,7 @@ static void pc_init1(MachineState *machine,
 MemoryRegion *system_io = get_system_io();
 PCIBus *pci_bus;
 ISABus *isa_bus;
+Object *piix4_pm;
 int piix3_devfn = -1;
 qemu_irq smi_irq;
 GSIState *gsi_state;
@@ -212,13 +213,21 @@ static void pc_init1(MachineState *machine,
 pci_dev = pci_new_multifunction(-1, true, type);
 object_property_set_bool(OBJECT(pci_dev), "has-usb",
  machine_usb(machine), &error_abort);
+object_property_set_bool(OBJECT(pci_dev), "has-acpi",
+ x86_machine_is_acpi_enabled(x86ms),
+ &error_abort);
+object_property_set_bool(OBJECT(pci_dev), "smm-enabled",
+ x86_machine_is_smm_enabled(x86ms),
+ &error_abort);
 pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
 piix3 = PIIX3_PCI_DEVICE(pci_dev);
 piix3->pic = x86ms->gsi;
 piix3_devfn = piix3->dev.devfn;
 isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
+piix4_pm = object_resolve_path_component(OBJECT(pci_dev), "pm");
 } else {
 pci_bus = NULL;
+piix4_pm = NULL;
 isa_bus = isa_bus_new(NULL, get_system_memory(), system_io,
   &error_abort);
 i8257_dma_init(isa_bus, 0);
@@ -283,15 +292,8 @@ static void pc_init1(MachineState *machine,
 }
 #endif
 
-if (pcmc->pci_enabled && x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) {
-PCIDevice *piix4_pm;
-
+if (piix4_pm) {
 smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
-piix4_pm = pci_new(piix3_devfn + 3, TYPE_PIIX4_PM);
-qdev_prop_set_uint32(DEVICE(piix4_pm), "smb_io_base", 0xb100);
-qdev_prop_set_bit(DEVICE(piix4_pm), "smm-enabled",
-  x86_machine_is_smm_enabled(x86ms));
-pci_realize_and_unref(piix4_pm, pci_bus, &error_fatal);
 
 qdev_connect_gpio_out(DEVICE(piix4_pm), 0, x86ms->gsi[9]);
 qdev_connect_gpio_out_named(DEVICE(piix4_pm), "smi-irq", 0, smi_irq);
@@ -305,7 +307,7 @@ static void pc_init1(MachineState *machine,
  object_property_allow_set_link,
  OBJ_PROP_LINK_STRONG);
 object_property_set_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
- OBJECT(piix4_pm), &error_abort);
+ piix4_pm, &error_abort);
 }
 
 if (machine->nvdimms_state->is_enabled) {
diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
index dd512cca84..5db0bbf7b6 100644
--- a/hw/isa/piix3.c
+++ b/hw/isa/piix3.c
@@ -324,6 +324,16 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
 } else {
 object_unparent(OBJECT(&d->uhci));
 }
+
+/* ACPI */
+if (d->has_acpi) {
+qdev_prop_set_int32(DEVICE(&d->pm), "addr", dev->devfn + 3);
+if (!qdev_realize(DEVICE(&d->pm), BUS(pci_bus), errp)) {
+return;
+}
+} else {
+object_unparent(OBJECT(&d->pm));
+}
 }
 
 static void build_pci_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
@@ -344,9 +354,15 @@ static void pci_piix3_init(Object *obj)
 PIIX3State *d = PIIX3_PCI_DEVICE(obj);
 
 object_initialize_child(obj, "uhci", &d->uhci, "piix3-usb-uhci");
+
+object_initialize_child(obj, "pm", &d->pm, TYPE_PIIX4_PM);
+qdev_prop_set_uint32(DEVICE(&d->pm), "smb_io_base", 0xb100);
+object_property_add_alias(obj, "smm-enabled",
+  OBJECT(&d->pm), "smm-enabled");
 }
 
 static Property pci_piix3_props[] = {
+DEFINE_PROP_BOOL("has-acpi", PIIX3State, has_acpi, true),
 DEFINE_PROP_BOOL("has-usb", PIIX3State, has_usb, true),
 DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.

[PULL 19/19] aspeed: Add fby35-bmc slot GPIO's

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

Signed-off-by: Peter Delevoryas 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220712023219.41065-4-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index b4355ee26a45..83150a19ea6d 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1358,11 +1358,23 @@ static void fby35_reset(MachineState *state)
 
 qemu_devices_reset();
 
-/* Board ID */
+/* Board ID: 7 (Class-1, 4 slots) */
 object_property_set_bool(OBJECT(gpio), "gpioV4", true, &error_fatal);
 object_property_set_bool(OBJECT(gpio), "gpioV5", true, &error_fatal);
 object_property_set_bool(OBJECT(gpio), "gpioV6", true, &error_fatal);
 object_property_set_bool(OBJECT(gpio), "gpioV7", false, &error_fatal);
+
+/* Slot presence pins, inverse polarity. (False means present) */
+object_property_set_bool(OBJECT(gpio), "gpioH4", false, &error_fatal);
+object_property_set_bool(OBJECT(gpio), "gpioH5", true, &error_fatal);
+object_property_set_bool(OBJECT(gpio), "gpioH6", true, &error_fatal);
+object_property_set_bool(OBJECT(gpio), "gpioH7", true, &error_fatal);
+
+/* Slot 12v power pins, normal polarity. (True means powered-on) */
+object_property_set_bool(OBJECT(gpio), "gpioB2", true, &error_fatal);
+object_property_set_bool(OBJECT(gpio), "gpioB3", false, &error_fatal);
+object_property_set_bool(OBJECT(gpio), "gpioB4", false, &error_fatal);
+object_property_set_bool(OBJECT(gpio), "gpioB5", false, &error_fatal);
 }
 
 static void aspeed_machine_fby35_class_init(ObjectClass *oc, void *data)
-- 
2.35.3




[PATCH 05/11] hw/i386/pc: QOM'ify RTC creation

2022-07-13 Thread Bernhard Beschow
Just like in the real hardware, create the RTC in the southbridges.

Signed-off-by: Bernhard Beschow 
---
 hw/i386/pc.c  | 12 ++--
 hw/i386/pc_piix.c |  8 
 hw/i386/pc_q35.c  |  1 +
 hw/isa/lpc_ich9.c |  8 
 hw/isa/piix3.c|  7 +++
 include/hw/i386/ich9.h|  2 ++
 include/hw/southbridge/piix.h |  2 ++
 7 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c3602d166d..eba1c98b5a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1181,9 +1181,17 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
 rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
 }
-*rtc_state = mc146818_rtc_init(isa_bus, 2000, rtc_irq);
 
-qemu_register_boot_set(pc_boot_set, *rtc_state);
+if (rtc_irq) {
+qdev_connect_gpio_out(DEVICE(*rtc_state), 0, rtc_irq);
+} else {
+uint32_t irq = object_property_get_uint(OBJECT(*rtc_state),
+"irq",
+&error_fatal);
+isa_connect_gpio_out(*rtc_state, 0, irq);
+}
+
+qemu_register_boot_set(pc_boot_set, rtc_state);
 
 if (!xen_enabled() &&
 (x86ms->pit == ON_OFF_AUTO_AUTO || x86ms->pit == ON_OFF_AUTO_ON)) {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 364c73b1bc..52c550f8b8 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -32,6 +32,7 @@
 #include "hw/i386/pc.h"
 #include "hw/i386/apic.h"
 #include "hw/pci-host/i440fx.h"
+#include "hw/rtc/mc146818rtc.h"
 #include "hw/southbridge/piix.h"
 #include "hw/display/ramfb.h"
 #include "hw/firmware/smbios.h"
@@ -224,12 +225,19 @@ static void pc_init1(MachineState *machine,
 piix3->pic = x86ms->gsi;
 piix3_devfn = piix3->dev.devfn;
 isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
+rtc_state = ISA_DEVICE(object_resolve_path_component(OBJECT(pci_dev),
+ "rtc"));
 piix4_pm = object_resolve_path_component(OBJECT(pci_dev), "pm");
 } else {
 pci_bus = NULL;
 piix4_pm = NULL;
 isa_bus = isa_bus_new(NULL, get_system_memory(), system_io,
   &error_abort);
+
+rtc_state = isa_new(TYPE_MC146818_RTC);
+qdev_prop_set_int32(DEVICE(rtc_state), "base_year", 2000);
+isa_realize_and_unref(rtc_state, isa_bus, &error_fatal);
+
 i8257_dma_init(isa_bus, 0);
 pcms->hpet_enabled = false;
 }
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index f96cbd04e2..d850313180 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -230,6 +230,7 @@ static void pc_q35_init(MachineState *machine)
 lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
   ICH9_LPC_FUNC), true,
   TYPE_ICH9_LPC_DEVICE);
+rtc_state = ISA_DEVICE(object_resolve_path_component(OBJECT(lpc), "rtc"));
 
 object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
  TYPE_HOTPLUG_HANDLER,
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 8694e58b21..0051fa66ab 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -660,6 +660,8 @@ static void ich9_lpc_initfn(Object *obj)
 static const uint8_t acpi_enable_cmd = ICH9_APM_ACPI_ENABLE;
 static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE;
 
+object_initialize_child(obj, "rtc", &lpc->rtc, TYPE_MC146818_RTC);
+
 object_property_add_uint8_ptr(obj, ACPI_PM_PROP_SCI_INT,
   &lpc->sci_gsi, OBJ_PROP_FLAG_READ);
 object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD,
@@ -725,6 +727,12 @@ static void ich9_lpc_realize(PCIDevice *d, Error **errp)
 isa_bus_irqs(isa_bus, lpc->gsi);
 
 i8257_dma_init(isa_bus, 0);
+
+/* RTC */
+qdev_prop_set_int32(DEVICE(&lpc->rtc), "base_year", 2000);
+if (!qdev_realize(DEVICE(&lpc->rtc), BUS(isa_bus), errp)) {
+return;
+}
 }
 
 static bool ich9_rst_cnt_needed(void *opaque)
diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
index 5db0bbf7b6..afd36178dd 100644
--- a/hw/isa/piix3.c
+++ b/hw/isa/piix3.c
@@ -315,6 +315,12 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
 
 i8257_dma_init(isa_bus, 0);
 
+/* RTC */
+qdev_prop_set_int32(DEVICE(&d->rtc), "base_year", 2000);
+if (!qdev_realize(DEVICE(&d->rtc), BUS(isa_bus), errp)) {
+return;
+}
+
 /* USB */
 if (d->has_usb) {
 qdev_prop_set_int32(DEVICE(&d->uhci), "addr", dev->devfn + 2);
@@ -353,6 +359,7 @@ static void pci_piix3_init(Object *obj)
 {
 PIIX3State *d = PIIX3_PCI_DEVICE(obj);
 
+object_initialize_child(obj, "rtc", &d->rtc, TYPE_MC146818_RTC);
 object_initialize_child(ob

[PATCH 02/11] hw/i386/pc_piix: Allow for setting properties before realizing PIIX3 southbridge

2022-07-13 Thread Bernhard Beschow
The next patches will need to take advantage of it.

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

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 7ad677e967..f129da29ac 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -209,7 +209,8 @@ static void pc_init1(MachineState *machine,
   pci_memory, ram_memory);
 pcms->bus = pci_bus;
 
-pci_dev = pci_create_simple_multifunction(pci_bus, -1, true, type);
+pci_dev = pci_new_multifunction(-1, true, type);
+pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
 piix3 = PIIX3_PCI_DEVICE(pci_dev);
 piix3->pic = x86ms->gsi;
 piix3_devfn = piix3->dev.devfn;
-- 
2.37.1




[PULL 15/19] hw: m25p80: Add Block Protect and Top Bottom bits for write protect

2022-07-13 Thread Cédric Le Goater
From: Iris Chen 

Signed-off-by: Iris Chen 
Reviewed-by: Francisco Iglesias 
Message-Id: <20220708164552.3462620-1-irische...@fb.com>
Signed-off-by: Cédric Le Goater 
---
 hw/block/m25p80.c | 102 --
 1 file changed, 90 insertions(+), 12 deletions(-)

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

[PATCH 06/11] hw/i386/pc: No need for rtc_state to be an out-parameter

2022-07-13 Thread Bernhard Beschow
Now that the RTC is created as part of the southbridges it doesn't need
to be an out-parameter any longer.

Signed-off-by: Bernhard Beschow 
---
 hw/i386/pc.c | 8 
 hw/i386/pc_piix.c| 2 +-
 hw/i386/pc_q35.c | 2 +-
 include/hw/i386/pc.h | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index eba1c98b5a..886c6b451a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1128,7 +1128,7 @@ static void pc_superio_init(ISABus *isa_bus, bool 
create_fdctrl,
 
 void pc_basic_device_init(struct PCMachineState *pcms,
   ISABus *isa_bus, qemu_irq *gsi,
-  ISADevice **rtc_state,
+  ISADevice *rtc_state,
   bool create_fdctrl,
   uint32_t hpet_irqs)
 {
@@ -1183,12 +1183,12 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 }
 
 if (rtc_irq) {
-qdev_connect_gpio_out(DEVICE(*rtc_state), 0, rtc_irq);
+qdev_connect_gpio_out(DEVICE(rtc_state), 0, rtc_irq);
 } else {
-uint32_t irq = object_property_get_uint(OBJECT(*rtc_state),
+uint32_t irq = object_property_get_uint(OBJECT(rtc_state),
 "irq",
 &error_fatal);
-isa_connect_gpio_out(*rtc_state, 0, irq);
+isa_connect_gpio_out(rtc_state, 0, irq);
 }
 
 qemu_register_boot_set(pc_boot_set, rtc_state);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 52c550f8b8..0f6cdc5bc4 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -263,7 +263,7 @@ static void pc_init1(MachineState *machine,
 }
 
 /* init basic PC hardware */
-pc_basic_device_init(pcms, isa_bus, x86ms->gsi, &rtc_state, true,
+pc_basic_device_init(pcms, isa_bus, x86ms->gsi, rtc_state, true,
  0x4);
 
 pc_nic_init(pcmc, isa_bus, pci_bus);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index d850313180..15b8b814c3 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -284,7 +284,7 @@ static void pc_q35_init(MachineState *machine)
 }
 
 /* init basic PC hardware */
-pc_basic_device_init(pcms, isa_bus, x86ms->gsi, &rtc_state, !mc->no_floppy,
+pc_basic_device_init(pcms, isa_bus, x86ms->gsi, rtc_state, !mc->no_floppy,
  0xff0104);
 
 /* connect pm stuff to lpc */
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index b7735dccfc..d1fd8969a0 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -164,7 +164,7 @@ uint64_t pc_pci_hole64_start(void);
 DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus);
 void pc_basic_device_init(struct PCMachineState *pcms,
   ISABus *isa_bus, qemu_irq *gsi,
-  ISADevice **rtc_state,
+  ISADevice *rtc_state,
   bool create_fdctrl,
   uint32_t hpet_irqs);
 void pc_cmos_init(PCMachineState *pcms,
-- 
2.37.1




[PATCH 08/11] hw/isa/piix3: QOM'ify ISA PIC creation

2022-07-13 Thread Bernhard Beschow
Use the newly introduced i8259 proxy "isa-pic" which allows for wiring
up devices in the southbridge where the virtualization technology used
(KVM, TCG, Xen) is not yet known.

Signed-off-by: Bernhard Beschow 
---
 hw/i386/pc_piix.c | 15 +--
 hw/isa/piix3.c| 10 +-
 include/hw/southbridge/piix.h |  4 ++--
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 0f6cdc5bc4..4ce215a212 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -198,10 +198,11 @@ static void pc_init1(MachineState *machine,
 gsi_state = pc_gsi_create(&x86ms->gsi, pcmc->pci_enabled);
 
 if (pcmc->pci_enabled) {
-PIIX3State *piix3;
+DeviceState *dev;
 PCIDevice *pci_dev;
 const char *type = xen_enabled() ? TYPE_PIIX3_XEN_DEVICE
  : TYPE_PIIX3_DEVICE;
+int i;
 
 pci_bus = i440fx_init(host_type,
   pci_type,
@@ -221,10 +222,12 @@ static void pc_init1(MachineState *machine,
  x86_machine_is_smm_enabled(x86ms),
  &error_abort);
 pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
-piix3 = PIIX3_PCI_DEVICE(pci_dev);
-piix3->pic = x86ms->gsi;
-piix3_devfn = piix3->dev.devfn;
-isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
+dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "pic"));
+for (i = 0; i < ISA_NUM_IRQS; ++i) {
+qdev_connect_gpio_out(dev, i, x86ms->gsi[i]);
+}
+piix3_devfn = pci_dev->devfn;
+isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(pci_dev), "isa.0"));
 rtc_state = ISA_DEVICE(object_resolve_path_component(OBJECT(pci_dev),
  "rtc"));
 piix4_pm = object_resolve_path_component(OBJECT(pci_dev), "pm");
@@ -233,6 +236,7 @@ static void pc_init1(MachineState *machine,
 piix4_pm = NULL;
 isa_bus = isa_bus_new(NULL, get_system_memory(), system_io,
   &error_abort);
+isa_bus_irqs(isa_bus, x86ms->gsi);
 
 rtc_state = isa_new(TYPE_MC146818_RTC);
 qdev_prop_set_int32(DEVICE(rtc_state), "base_year", 2000);
@@ -241,7 +245,6 @@ static void pc_init1(MachineState *machine,
 i8257_dma_init(isa_bus, 0);
 pcms->hpet_enabled = false;
 }
-isa_bus_irqs(isa_bus, x86ms->gsi);
 
 if (x86ms->pic == ON_OFF_AUTO_ON || x86ms->pic == ON_OFF_AUTO_AUTO) {
 pc_i8259_create(isa_bus, gsi_state->i8259_irq);
diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
index afd36178dd..7bf3488f76 100644
--- a/hw/isa/piix3.c
+++ b/hw/isa/piix3.c
@@ -41,7 +41,7 @@
 
 static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
 {
-qemu_set_irq(piix3->pic[pic_irq],
+qemu_set_irq(piix3->pic.in_irqs[pic_irq],
  !!(piix3->pic_levels &
 (((1ULL << PIIX_NUM_PIRQS) - 1) <<
  (pic_irq * PIIX_NUM_PIRQS;
@@ -306,6 +306,13 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
 return;
 }
 
+/* PIC */
+if (!qdev_realize(DEVICE(&d->pic), BUS(isa_bus), errp)) {
+return;
+}
+
+isa_bus_irqs(isa_bus, d->pic.in_irqs);
+
 memory_region_init_io(&d->rcr_mem, OBJECT(dev), &rcr_ops, d,
   "piix3-reset-control", 1);
 memory_region_add_subregion_overlap(pci_address_space_io(dev),
@@ -359,6 +366,7 @@ static void pci_piix3_init(Object *obj)
 {
 PIIX3State *d = PIIX3_PCI_DEVICE(obj);
 
+object_initialize_child(obj, "pic", &d->pic, TYPE_ISA_PIC);
 object_initialize_child(obj, "rtc", &d->rtc, TYPE_MC146818_RTC);
 object_initialize_child(obj, "uhci", &d->uhci, "piix3-usb-uhci");
 
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
index 15b05cfc93..cfe155ce07 100644
--- a/include/hw/southbridge/piix.h
+++ b/include/hw/southbridge/piix.h
@@ -15,6 +15,7 @@
 #include "hw/pci/pci.h"
 #include "qom/object.h"
 #include "hw/acpi/piix4.h"
+#include "hw/intc/i8259.h"
 #include "hw/rtc/mc146818rtc.h"
 #include "hw/usb/hcd-uhci.h"
 
@@ -50,11 +51,10 @@ struct PIIXState {
 #endif
 uint64_t pic_levels;
 
-qemu_irq *pic;
-
 /* This member isn't used. Just for save/load compatibility */
 int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
 
+ISAPICState pic;
 RTCState rtc;
 UHCIState uhci;
 PIIX4PMState pm;
-- 
2.37.1




[PATCH 10/11] hw/isa/piix3: Wire up ACPI interrupt internally

2022-07-13 Thread Bernhard Beschow
Now that PIIX3 has the PIC integrated, the ACPI controller can be wired
up internally.

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

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index f843a73d90..19c86b68bd 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -303,7 +303,6 @@ static void pc_init1(MachineState *machine,
 if (piix4_pm) {
 smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
 
-qdev_connect_gpio_out(DEVICE(piix4_pm), 0, x86ms->gsi[9]);
 qdev_connect_gpio_out_named(DEVICE(piix4_pm), "smi-irq", 0, smi_irq);
 pcms->smbus = I2C_BUS(qdev_get_child_bus(DEVICE(piix4_pm), "i2c"));
 /* TODO: Populate SPD eeprom data.  */
diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
index fd9c8f853a..56a741c192 100644
--- a/hw/isa/piix3.c
+++ b/hw/isa/piix3.c
@@ -351,6 +351,8 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
 if (!qdev_realize(DEVICE(&d->pm), BUS(pci_bus), errp)) {
 return;
 }
+qdev_connect_gpio_out(DEVICE(&d->pm), 0,
+  qdev_get_gpio_in(DEVICE(&d->pic), 9));
 } else {
 object_unparent(OBJECT(&d->pm));
 }
-- 
2.37.1




[PULL 17/19] qtest/aspeed_gpio: Add input pin modification test

2022-07-13 Thread Cédric Le Goater
From: Peter Delevoryas 

Verify the current behavior, which is that input pins can be modified by
guest OS register writes.

Signed-off-by: Peter Delevoryas 
Reviewed-by: Cédric Le Goater 
Message-Id: <20220712023219.41065-2-pe...@pjd.dev>
Signed-off-by: Cédric Le Goater 
---
 tests/qtest/aspeed_gpio-test.c | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/tests/qtest/aspeed_gpio-test.c b/tests/qtest/aspeed_gpio-test.c
index bac63e8742f4..8f524540998d 100644
--- a/tests/qtest/aspeed_gpio-test.c
+++ b/tests/qtest/aspeed_gpio-test.c
@@ -28,6 +28,11 @@
 #include "qapi/qmp/qdict.h"
 #include "libqtest-single.h"
 
+#define AST2600_GPIO_BASE 0x1E78
+
+#define GPIO_ABCD_DATA_VALUE 0x000
+#define GPIO_ABCD_DIRECTION  0x004
+
 static void test_set_colocated_pins(const void *data)
 {
 QTestState *s = (QTestState *)data;
@@ -46,6 +51,27 @@ static void test_set_colocated_pins(const void *data)
 g_assert(!qtest_qom_get_bool(s, "/machine/soc/gpio", "gpioV7"));
 }
 
+static void test_set_input_pins(const void *data)
+{
+QTestState *s = (QTestState *)data;
+char name[16];
+uint32_t value;
+
+qtest_writel(s, AST2600_GPIO_BASE + GPIO_ABCD_DIRECTION, 0x);
+for (char c = 'A'; c <= 'D'; c++) {
+for (int i = 0; i < 8; i++) {
+sprintf(name, "gpio%c%d", c, i);
+qtest_qom_set_bool(s, "/machine/soc/gpio", name, true);
+}
+}
+value = qtest_readl(s, AST2600_GPIO_BASE + GPIO_ABCD_DATA_VALUE);
+g_assert_cmphex(value, ==, 0x);
+
+qtest_writel(s, AST2600_GPIO_BASE + GPIO_ABCD_DATA_VALUE, 0x);
+value = qtest_readl(s, AST2600_GPIO_BASE + GPIO_ABCD_DATA_VALUE);
+g_assert_cmphex(value, ==, 0x);
+}
+
 int main(int argc, char **argv)
 {
 QTestState *s;
@@ -56,6 +82,7 @@ int main(int argc, char **argv)
 s = qtest_init("-machine ast2600-evb");
 qtest_add_data_func("/ast2600/gpio/set_colocated_pins", s,
 test_set_colocated_pins);
+qtest_add_data_func("/ast2600/gpio/set_input_pins", s, 
test_set_input_pins);
 r = g_test_run();
 qtest_quit(s);
 
-- 
2.35.3




[PATCH 07/11] hw/intc/i8259: Introduce i8259 proxy "isa-pic"

2022-07-13 Thread Bernhard Beschow
Having an i8259 proxy allows for ISA PICs to be created and wired up in
southbridges. This is especially interesting for PIIX3 for two reasons:
First, the southbridge doesn't need to care about the virtualization
technology used (KVM, TCG, Xen) due to in-IRQs (where devices get
attached) and out-IRQs (which will trigger the IRQs of the respective
virtzalization technology) are separated. Second, since the in-IRQs are
populated with fully initialized qemu_irq's, they can already be wired
up inside PIIX3.

Signed-off-by: Bernhard Beschow 
---
 hw/intc/i8259.c | 27 +++
 include/hw/intc/i8259.h | 14 ++
 2 files changed, 41 insertions(+)

diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index cc4e21ffec..531f6cca53 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -458,9 +458,36 @@ static const TypeInfo i8259_info = {
 .class_size = sizeof(PICClass),
 };
 
+static void isapic_set_irq(void *opaque, int irq, int level)
+{
+ISAPICState *s = opaque;
+
+qemu_set_irq(s->out_irqs[irq], level);
+}
+
+static void isapic_init(Object *obj)
+{
+ISAPICState *s = ISA_PIC(obj);
+
+qdev_init_gpio_in(DEVICE(s), isapic_set_irq, ISA_NUM_IRQS);
+qdev_init_gpio_out(DEVICE(s), s->out_irqs, ISA_NUM_IRQS);
+
+for (int i = 0; i < ISA_NUM_IRQS; ++i) {
+s->in_irqs[i] = qdev_get_gpio_in(DEVICE(s), i);
+}
+}
+
+static const TypeInfo isapic_info = {
+.name  = TYPE_ISA_PIC,
+.parent= TYPE_ISA_DEVICE,
+.instance_size = sizeof(ISAPICState),
+.instance_init = isapic_init,
+};
+
 static void pic_register_types(void)
 {
 type_register_static(&i8259_info);
+type_register_static(&isapic_info);
 }
 
 type_init(pic_register_types)
diff --git a/include/hw/intc/i8259.h b/include/hw/intc/i8259.h
index e2b1e8c59a..0246ab6ac6 100644
--- a/include/hw/intc/i8259.h
+++ b/include/hw/intc/i8259.h
@@ -1,6 +1,20 @@
 #ifndef HW_I8259_H
 #define HW_I8259_H
 
+#include "qom/object.h"
+#include "hw/isa/isa.h"
+#include "qemu/typedefs.h"
+
+#define TYPE_ISA_PIC "isa-pic"
+OBJECT_DECLARE_SIMPLE_TYPE(ISAPICState, ISA_PIC)
+
+struct ISAPICState {
+ISADevice parent_obj;
+
+qemu_irq in_irqs[ISA_NUM_IRQS];
+qemu_irq out_irqs[ISA_NUM_IRQS];
+};
+
 /* i8259.c */
 
 extern DeviceState *isa_pic;
-- 
2.37.1




Re: [PATCH v7 00/14] KVM: mm: fd-based approach for supporting KVM guest private memory

2022-07-13 Thread Chao Peng
On Wed, Jul 13, 2022 at 05:58:32AM +0200, Gupta, Pankaj wrote:
> 
> > This is the v7 of this series which tries to implement the fd-based KVM
> > guest private memory. The patches are based on latest kvm/queue branch
> > commit:
> > 
> >b9b71f43683a (kvm/queue) KVM: x86/mmu: Buffer nested MMU
> > split_desc_cache only by default capacity
> > 
> > Introduction
> > 
> > In general this patch series introduce fd-based memslot which provides
> > guest memory through memory file descriptor fd[offset,size] instead of
> > hva/size. The fd can be created from a supported memory filesystem
> > like tmpfs/hugetlbfs etc. which we refer as memory backing store. KVM
> 
> Thinking a bit, As host side fd on tmpfs or shmem will store memory on host
> page cache instead of mapping pages into userspace address space. Can we hit
> double (un-coordinated) page cache problem with this when guest page cache
> is also used?

This is my understanding: in host it will be indeed in page cache (in
current shmem implementation) but that's just the way it allocates and
provides the physical memory for the guest. In guest, guest OS will not
see this fd (absolutely), it only sees guest memory, on top of which it
can build its own page cache system for its own file-mapped content but
that is unrelated to host page cache.

Chao
> 
> Thanks,
> Pankaj
> 



Re: [PATCH v3 3/9] tests/style: check for mixups of bool constants with int variables

2022-07-13 Thread Daniel P . Berrangé
On Mon, Jul 11, 2022 at 06:24:22PM +0200, Philippe Mathieu-Daudé wrote:
> On 7/7/22 18:37, Daniel P. Berrangé wrote:
> > The 'true' and 'false' constants should only ever be used with the
> > 'bool' type, never 'int'.
> > 
> > Signed-off-by: Daniel P. Berrangé 
> > ---
> >   tests/style.yml | 5 +
> >   1 file changed, 5 insertions(+)
> > 
> > diff --git a/tests/style.yml b/tests/style.yml
> > index b4e7c6111f..704227d8e9 100644
> > --- a/tests/style.yml
> > +++ b/tests/style.yml
> > @@ -86,3 +86,8 @@
> >   #A match added to the front of the regex. Useful when
> >   #'terms' is a list of strings and a common prefix is
> >   #desired
> > +
> > +int_assign_bool:
> > +  files: \.c$
> 
> Why not check .c.inc and .h (for static inlined func)?

Yes, we should.

> Regardless:
> Reviewed-by: Philippe Mathieu-Daudé 
> 
> > +  prohibit: \.*= *(true|false)\b
> > +  message: use bool type for boolean values
> 

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




[PATCH 03/11] hw/isa/piix3: QOM'ify USB controller creation

2022-07-13 Thread Bernhard Beschow
The USB controller is an integral part of PIIX3 (function 2). So create
it as part of the southbridge.

Note that the USB function is optional in QEMU. This is why it gets
unparented if it is disabled, otherwiese QEMU will abort with:

  src/hw/core/qdev.c:357: qdev_assert_realized_properly_cb: Assertion 
`dev->realized' failed

Signed-off-by: Bernhard Beschow 
---
 hw/i386/pc_piix.c |  6 ++
 hw/isa/piix3.c| 26 ++
 include/hw/southbridge/piix.h |  5 +
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index f129da29ac..96dc0db729 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -210,6 +210,8 @@ static void pc_init1(MachineState *machine,
 pcms->bus = pci_bus;
 
 pci_dev = pci_new_multifunction(-1, true, type);
+object_property_set_bool(OBJECT(pci_dev), "has-usb",
+ machine_usb(machine), &error_abort);
 pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
 piix3 = PIIX3_PCI_DEVICE(pci_dev);
 piix3->pic = x86ms->gsi;
@@ -281,10 +283,6 @@ static void pc_init1(MachineState *machine,
 }
 #endif
 
-if (pcmc->pci_enabled && machine_usb(machine)) {
-pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
-}
-
 if (pcmc->pci_enabled && x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) {
 PCIDevice *piix4_pm;
 
diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
index 44a9998752..dd512cca84 100644
--- a/hw/isa/piix3.c
+++ b/hw/isa/piix3.c
@@ -27,6 +27,7 @@
 #include "qapi/error.h"
 #include "hw/dma/i8257.h"
 #include "hw/southbridge/piix.h"
+#include "hw/ide/pci.h"
 #include "hw/irq.h"
 #include "hw/isa/isa.h"
 #include "hw/xen/xen.h"
@@ -296,6 +297,7 @@ static const MemoryRegionOps rcr_ops = {
 static void pci_piix3_realize(PCIDevice *dev, Error **errp)
 {
 PIIX3State *d = PIIX3_PCI_DEVICE(dev);
+PCIBus *pci_bus = pci_get_bus(dev);
 ISABus *isa_bus;
 
 isa_bus = isa_bus_new(DEVICE(d), get_system_memory(),
@@ -312,6 +314,16 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
 qemu_register_reset(piix3_reset, d);
 
 i8257_dma_init(isa_bus, 0);
+
+/* USB */
+if (d->has_usb) {
+qdev_prop_set_int32(DEVICE(&d->uhci), "addr", dev->devfn + 2);
+if (!qdev_realize(DEVICE(&d->uhci), BUS(pci_bus), errp)) {
+return;
+}
+} else {
+object_unparent(OBJECT(&d->uhci));
+}
 }
 
 static void build_pci_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
@@ -327,6 +339,18 @@ static void build_pci_isa_aml(AcpiDevAmlIf *adev, Aml 
*scope)
 }
 }
 
+static void pci_piix3_init(Object *obj)
+{
+PIIX3State *d = PIIX3_PCI_DEVICE(obj);
+
+object_initialize_child(obj, "uhci", &d->uhci, "piix3-usb-uhci");
+}
+
+static Property pci_piix3_props[] = {
+DEFINE_PROP_BOOL("has-usb", PIIX3State, has_usb, true),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void pci_piix3_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -345,12 +369,14 @@ static void pci_piix3_class_init(ObjectClass *klass, void 
*data)
  * pc_piix.c's pc_init1()
  */
 dc->user_creatable = false;
+device_class_set_props(dc, pci_piix3_props);
 adevc->build_dev_aml = build_pci_isa_aml;
 }
 
 static const TypeInfo piix3_pci_type_info = {
 .name = TYPE_PIIX3_PCI_DEVICE,
 .parent = TYPE_PCI_DEVICE,
+.instance_init  = pci_piix3_init,
 .instance_size = sizeof(PIIX3State),
 .abstract = true,
 .class_init = pci_piix3_class_init,
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
index 2693778b23..115311d932 100644
--- a/include/hw/southbridge/piix.h
+++ b/include/hw/southbridge/piix.h
@@ -14,6 +14,7 @@
 
 #include "hw/pci/pci.h"
 #include "qom/object.h"
+#include "hw/usb/hcd-uhci.h"
 
 /* PIRQRC[A:D]: PIRQx Route Control Registers */
 #define PIIX_PIRQCA 0x60
@@ -52,11 +53,15 @@ struct PIIXState {
 /* This member isn't used. Just for save/load compatibility */
 int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
 
+UHCIState uhci;
+
 /* Reset Control Register contents */
 uint8_t rcr;
 
 /* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
 MemoryRegion rcr_mem;
+
+bool has_usb;
 };
 typedef struct PIIXState PIIX3State;
 
-- 
2.37.1




[PATCH 11/11] hw/isa/piix3: Remove extra ';' outside of functions

2022-07-13 Thread Bernhard Beschow
Fixes the "extra-semi" clang-tidy check.

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

diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
index 56a741c192..3cfd6eafcd 100644
--- a/hw/isa/piix3.c
+++ b/hw/isa/piix3.c
@@ -442,7 +442,7 @@ static void piix3_realize(PCIDevice *dev, Error **errp)
 pci_bus_irqs(pci_bus, piix3_set_irq, pci_slot_get_pirq,
  piix3, PIIX_NUM_PIRQS);
 pci_bus_set_route_irq_fn(pci_bus, piix3_route_intx_pin_to_irq);
-};
+}
 
 static void piix3_class_init(ObjectClass *klass, void *data)
 {
@@ -477,7 +477,7 @@ static void piix3_xen_realize(PCIDevice *dev, Error **errp)
  */
 pci_bus_irqs(pci_bus, xen_piix3_set_irq, xen_pci_slot_get_pirq,
  piix3, XEN_PIIX_NUM_PIRQS);
-};
+}
 
 static void piix3_xen_class_init(ObjectClass *klass, void *data)
 {
@@ -485,7 +485,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void 
*data)
 
 k->config_write = piix3_write_config_xen;
 k->realize = piix3_xen_realize;
-};
+}
 
 static const TypeInfo piix3_xen_info = {
 .name  = TYPE_PIIX3_XEN_DEVICE,
-- 
2.37.1




[PATCH 09/11] hw/isa/piix3: QOM'ify IDE controller creation

2022-07-13 Thread Bernhard Beschow
Now that PIIX3 contains the new isa-pic, it is possible to instantiate
PIIX3 IDE in the PIIX3 southbridge. PIIX3 IDE wires up its interrupts to
the ISA bus in its realize method which requires the interrupt
controller to provide fully populated qemu_irqs. This is the case for
isa-pic even though the virtualization technology not known yet.

Signed-off-by: Bernhard Beschow 
---
 hw/i386/Kconfig   |  1 -
 hw/i386/pc_piix.c | 13 +
 hw/isa/Kconfig|  1 +
 hw/isa/piix3.c|  8 
 include/hw/southbridge/piix.h |  2 ++
 5 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index d22ac4a4b9..dd247f215c 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -74,7 +74,6 @@ config I440FX
 select ACPI_SMBUS
 select PCI_I440FX
 select PIIX3
-select IDE_PIIX
 select DIMM
 select SMBIOS
 select FW_CFG_DMA
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 4ce215a212..f843a73d90 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -85,7 +85,6 @@ static void pc_init1(MachineState *machine,
 PCIBus *pci_bus;
 ISABus *isa_bus;
 Object *piix4_pm;
-int piix3_devfn = -1;
 qemu_irq smi_irq;
 GSIState *gsi_state;
 BusState *idebus[MAX_IDE_BUS];
@@ -226,11 +225,13 @@ static void pc_init1(MachineState *machine,
 for (i = 0; i < ISA_NUM_IRQS; ++i) {
 qdev_connect_gpio_out(dev, i, x86ms->gsi[i]);
 }
-piix3_devfn = pci_dev->devfn;
 isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(pci_dev), "isa.0"));
 rtc_state = ISA_DEVICE(object_resolve_path_component(OBJECT(pci_dev),
  "rtc"));
 piix4_pm = object_resolve_path_component(OBJECT(pci_dev), "pm");
+dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "ide"));
+idebus[0] = qdev_get_child_bus(dev, "ide.0");
+idebus[1] = qdev_get_child_bus(dev, "ide.1");
 } else {
 pci_bus = NULL;
 piix4_pm = NULL;
@@ -244,6 +245,8 @@ static void pc_init1(MachineState *machine,
 
 i8257_dma_init(isa_bus, 0);
 pcms->hpet_enabled = false;
+idebus[0] = NULL;
+idebus[1] = NULL;
 }
 
 if (x86ms->pic == ON_OFF_AUTO_ON || x86ms->pic == ON_OFF_AUTO_AUTO) {
@@ -272,12 +275,6 @@ static void pc_init1(MachineState *machine,
 pc_nic_init(pcmc, isa_bus, pci_bus);
 
 if (pcmc->pci_enabled) {
-PCIDevice *dev;
-
-dev = pci_create_simple(pci_bus, piix3_devfn + 1, "piix3-ide");
-pci_ide_create_devs(dev);
-idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
-idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
 pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
 }
 #ifdef CONFIG_IDE_ISA
diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig
index d42143a991..808b9a30af 100644
--- a/hw/isa/Kconfig
+++ b/hw/isa/Kconfig
@@ -34,6 +34,7 @@ config PC87312
 config PIIX3
 bool
 select ISA_BUS
+select IDE_PIIX
 
 config PIIX4
 bool
diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
index 7bf3488f76..fd9c8f853a 100644
--- a/hw/isa/piix3.c
+++ b/hw/isa/piix3.c
@@ -328,6 +328,13 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
 return;
 }
 
+/* IDE */
+qdev_prop_set_int32(DEVICE(&d->ide), "addr", dev->devfn + 1);
+if (!qdev_realize(DEVICE(&d->ide), BUS(pci_bus), errp)) {
+return;
+}
+pci_ide_create_devs(PCI_DEVICE(&d->ide));
+
 /* USB */
 if (d->has_usb) {
 qdev_prop_set_int32(DEVICE(&d->uhci), "addr", dev->devfn + 2);
@@ -368,6 +375,7 @@ static void pci_piix3_init(Object *obj)
 
 object_initialize_child(obj, "pic", &d->pic, TYPE_ISA_PIC);
 object_initialize_child(obj, "rtc", &d->rtc, TYPE_MC146818_RTC);
+object_initialize_child(obj, "ide", &d->ide, "piix3-ide");
 object_initialize_child(obj, "uhci", &d->uhci, "piix3-usb-uhci");
 
 object_initialize_child(obj, "pm", &d->pm, TYPE_PIIX4_PM);
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
index cfe155ce07..41983dfa6d 100644
--- a/include/hw/southbridge/piix.h
+++ b/include/hw/southbridge/piix.h
@@ -15,6 +15,7 @@
 #include "hw/pci/pci.h"
 #include "qom/object.h"
 #include "hw/acpi/piix4.h"
+#include "hw/ide/pci.h"
 #include "hw/intc/i8259.h"
 #include "hw/rtc/mc146818rtc.h"
 #include "hw/usb/hcd-uhci.h"
@@ -56,6 +57,7 @@ struct PIIXState {
 
 ISAPICState pic;
 RTCState rtc;
+PCIIDEState ide;
 UHCIState uhci;
 PIIX4PMState pm;
 
-- 
2.37.1




[PATCH] roms/opensbi: Upgrade from v1.0 to v1.1

2022-07-13 Thread Bin Meng
Upgrade OpenSBI from v1.0 to v1.1 and the pre-built bios images.

The v1.1 release includes the following commits:

5b99603 lib: utils/ipi: Fix size check in aclint_mswi_cold_init()
6dde435 lib: utils/sys: Extend HTIF library to allow custom base address
8257262 platform: sifive_fu740: do not use a global in da9063_reset/shutdown
fb688d9 platform: sifive_fu740: fix reset when watchdog is running
5d025eb lib: fix pointer of type 'void *' used in arithmetic
632f593 lib: sbi: Map only the counters enabled in hardware
3b7c204 lib: sbi: Disable interrupt during config matching
a26dc60 lib: sbi: Disable interrupt and inhibit counting in M-mode during init
5d53b55 Makefile: fix build with binutils 2.38
6ad8917 lib: fix compilation when strings.h is included
ce4c018 lib: utils/serial: Round UART8250 baud rate divisor to nearest integer
01250d0 include: sbi: Add AIA related CSR defines
8f96070 lib: sbi: Detect AIA CSRs at boot-time
65b4c7c lib: sbi: Use AIA CSRs for local interrupts when available
222132f lib: sbi: Add sbi_trap_set_external_irqfn() API
5f56314 lib: utils/irqchip: Allow multiple FDT irqchip drivers
1050940 include: sbi: Introduce nascent_init() platform callback
55e79f8 lib: sbi: Enable mie.MEIE bit for IPIs based on external interrupts.
9f73669 lib: utils/irqchip: Add IMSIC library
811da5c lib: utils/irqchip: Add FDT based driver for IMSIC
7127aaa lib: utils: Disable appropriate IMSIC DT nodes in fdt_fixups()
9979265 lib: utils/irqchip: Add APLIC initialization library
3461219 lib: utils/irqchip: Add FDT based driver for APLIC
8e2ef4f lib: utils: Disable appropriate APLIC DT nodes in fdt_fixups()
3a69cc1 lib: sbi: fix typo in is_region_subset
f2ccf2f lib: sbi: verbose sbi_domain_root_add_memregion
f3f4604 lib: sbi: Add a simple external interrupt handling framework
4998a71 lib: utils: serial: Initial commit of xlnx-uartlite
2dfbd3c lib: pmp_set/pmp_get moved errors from runtime to compile time
b6b7220 firmware: Fix code for accessing hart_count and stack_size
d552fc8 lib: Add error messages via conditional compilation for the future
555bdb1 include: Use static asserts for SBI_PLATFORM_xxx_OFFSET defines
1b42d3a include: Use static asserts for SBI_SCRATCH_xxx_OFFSET defines
7924a0b include: Use static asserts for FW_DYNAMIC_INFO_xxx_OFFSET defines
722f80d include: Add defines for [m|h|s]envcfg CSRs
31fecad lib: sbi: Detect menvcfg CSR at boot time
47d6765 lib: sbi: Enable Zicbo[m|z] extensions in the menvcfg CSR
794986f lib: sbi: Enable Svpbmt extension in the menvcfg CSR
499601a lib: sbi: Add Smstateen extension defines
d44568a lib: sbi: Detect Smstateen CSRs at boot-time
3383d6a lib: irqchip/imsic: configure mstateen
5c5cbb5 lib: utils/serial: support 'reg-offset' property
c1e47d0 include: correct the definition of MSTATUS_VS
9cd95e1 lib: sbi/hart: preserve csr validation value
4035ae9 docs: pmu: Improve the PMU DT bindings
d62f6da lib: sbi: Implement Sstc extension
474a9d4 lib: sbi: Fix mstatus_init() for RV32 when Sscofpmf is not available
e576b3e include: sbi: Define SBI_PMU_HW_EVENT_MAX to 256
b0c9df5 lib: sbi: Fix mhpmeventh access for rv32 in absence of sscofpmf
1a754bb lib: sbi: Detect and print privileged spec version
5a6be99 lib: sbi: Remove 's' and 'u' from misa_string() output
5b8b377 lib: sbi: Update the name of ISA string printed at boot time
d4b563c lib: sbi: Remove MCOUNTEREN and SCOUNTEREN hart features
dbc3d8f lib: sbi: Remove MCOUNTINHIBT hart feature
97a17c2 lib: sbi: Remove MENVCFG hart feature
a6ab94f lib: sbi: Fix AIA feature detection
cad6c91 lib: sbi: Convert hart features into hart extensions
be4903a lib: sbi: Detect hart features only once for each hart
994ace3 lib: sbi: Add sbi_hart_update_extension() function
023f0ad lib: sbi_platform: Add callback to populate HART extensions
f726f2d Makefile: Allow generated C source to be anywhere in build directory
7fb474b Makefile: Add support for generating C array at compile time
73cf511 lib: utils/reset: Generate FDT reset driver list at compile-time
1e62705 lib: utils/serial: Generate FDT serial driver list at compile-time
bfeb305 lib: utils/timer: Generate FDT timer driver list at compile-time
3a69d12 lib: utils/irqchip: Generate FDT irqchip driver list at compile-time
4ee0c57 lib: utils/ipi: Generate FDT ipi driver list at compile-time
998ed43 lib: utils/i2c: Generate FDT i2c adapter driver list at compile-time
4eacd82 lib: utils/gpio: Generate FDT gpio driver list at compile-time
a3a3c60 platform: generic: Generate platform override module list at 
compile-time
9a7a677 platform: generic: Move Sifive platform overrides into own directory
851c14d lib: utils/irqchip: fix typo when checking for CPU node
90a9dd2 lib: utils/fdt: introduce fdt_node_is_enabled()
616da52 lib: utils: check if CPU node is enabled
575bb4e platform: generic: check if CPU node is enabled
1bc67db lib: utils/fdt: rename fdt_parse_max_hart_id
f067bb8 lib: sbi: fix system_opcode_insn
fab0379 lib: utils/fdt: Require match data to be const
295e5f3 lib: sbi_timer

[PATCH 4/5] target/loongarch/tlb_helper: Fix coverity integer overflow error

2022-07-13 Thread Xiaojuan Yang
Replace '1 << shift' with 'MAKE_64BIT_MASK(shift, 1)' to fix
unintentional integer overflow errors in tlb_helper file.

Fix coverity CID: 1489759 1489762

Signed-off-by: Xiaojuan Yang 
---
 target/loongarch/tlb_helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/loongarch/tlb_helper.c b/target/loongarch/tlb_helper.c
index bab19c7e05..610b6d123c 100644
--- a/target/loongarch/tlb_helper.c
+++ b/target/loongarch/tlb_helper.c
@@ -298,7 +298,7 @@ static void invalidate_tlb_entry(CPULoongArchState *env, 
int index)
 } else {
 tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
 }
-pagesize = 1 << tlb_ps;
+pagesize = MAKE_64BIT_MASK(tlb_ps, 1);
 mask = MAKE_64BIT_MASK(0, tlb_ps + 1);
 
 if (tlb_v0) {
@@ -736,7 +736,7 @@ void helper_ldpte(CPULoongArchState *env, target_ulong 
base, target_ulong odd,
 (tmp0 & (~(1 << R_TLBENTRY_G_SHIFT)));
 ps = ptbase + ptwidth - 1;
 if (odd) {
-tmp0 += (1 << ps);
+tmp0 += MAKE_64BIT_MASK(ps, 1);
 }
 } else {
 /* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
-- 
2.31.1




[PATCH 3/5] target/loongarch/cpu: Fix coverity errors about excp_names

2022-07-13 Thread Xiaojuan Yang
Fix out-of-bounds errors when access excp_names[] array. the valid
boundary size of excp_names should be 0 to ARRAY_SIZE(excp_names)-1.
However, the general code do not consider the max boundary.

Fix coverity CID: 1489758

Signed-off-by: Xiaojuan Yang 
---
 target/loongarch/cpu.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index ed26f9beed..89ea971cde 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -140,7 +140,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
 
 if (cs->exception_index != EXCCODE_INT) {
 if (cs->exception_index < 0 ||
-cs->exception_index > ARRAY_SIZE(excp_names)) {
+cs->exception_index >= ARRAY_SIZE(excp_names)) {
 name = "unknown";
 } else {
 name = excp_names[cs->exception_index];
@@ -190,8 +190,8 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
 cause = cs->exception_index;
 break;
 default:
-qemu_log("Error: exception(%d) '%s' has not been supported\n",
- cs->exception_index, excp_names[cs->exception_index]);
+qemu_log("Error: exception(%d) has not been supported\n",
+ cs->exception_index);
 abort();
 }
 
-- 
2.31.1




[PATCH 2/5] hw/intc/loongarch_pch_pic: Fix coverity errors in update irq

2022-07-13 Thread Xiaojuan Yang
Fix coverity errors:
1. In find_first_bit function, the 'size' argument need
'unsigned long' type, so we change the 'size' to unsigned
long type when use the function.
2. In expression 1ULL << irq, left shifting by more than
63 bits has undefined behavior. And out-of-bounds access
error occured when 'irq' >= 64. So we add a condition to
avoid this.
3. Use 'MAKE_64BIT_MASK(irq, 1)' to replace '1ULL << shift'.

Fix coverity CID: 1489761 1489764 1489765

Signed-off-by: Xiaojuan Yang 
---
 hw/intc/loongarch_pch_pic.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c
index 3c9814a3b4..040b89861c 100644
--- a/hw/intc/loongarch_pch_pic.c
+++ b/hw/intc/loongarch_pch_pic.c
@@ -15,22 +15,27 @@
 
 static void pch_pic_update_irq(LoongArchPCHPIC *s, uint64_t mask, int level)
 {
-unsigned long val;
+unsigned long val, max_irq;
 int irq;
 
+max_irq = 64;
 if (level) {
 val = mask & s->intirr & ~s->int_mask;
 if (val) {
-irq = find_first_bit(&val, 64);
-s->intisr |= 0x1ULL << irq;
-qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1);
+irq = find_first_bit(&val, max_irq);
+if (irq < max_irq) {
+s->intisr |= MAKE_64BIT_MASK(irq, 1);
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1);
+}
 }
 } else {
 val = mask & s->intisr;
 if (val) {
-irq = find_first_bit(&val, 64);
-s->intisr &= ~(0x1ULL << irq);
-qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0);
+irq = find_first_bit(&val, max_irq);
+if (irq < max_irq) {
+s->intisr &= ~(MAKE_64BIT_MASK(irq, 1));
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0);
+}
 }
 }
 }
-- 
2.31.1




[PATCH 5/5] target/loongarch/op_helper: Fix coverity cond_at_most error

2022-07-13 Thread Xiaojuan Yang
The boundary size of cpucfg array should be 0 to 20. So,
using index bigger than 20 to access cpucfg[] must be forbidden.

Fix coverity CID: 1489760

Signed-off-by: Xiaojuan Yang 
---
 target/loongarch/op_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index 4b429b6699..568c071601 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -81,7 +81,7 @@ target_ulong helper_crc32c(target_ulong val, target_ulong m, 
uint64_t sz)
 
 target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj)
 {
-return rj > 21 ? 0 : env->cpucfg[rj];
+return rj >= ARRAY_SIZE(env->cpucfg) ? 0 : env->cpucfg[rj];
 }
 
 uint64_t helper_rdtime_d(CPULoongArchState *env)
-- 
2.31.1




[PATCH 1/5] target/loongarch/cpu: Fix cpu_class_by_name function

2022-07-13 Thread Xiaojuan Yang
In loongarch_cpu_class_by_name(char *cpu_model) function,
the argument cpu_model already has the suffix '-loongarch-cpu',
so we should remove the LOONGARCH_CPU_TYPE_NAME(cpu_model) macro.
And add the assertion that 'cpu_model' resolves to a class of the
appropriate type.

Signed-off-by: Xiaojuan Yang 
---
 target/loongarch/cpu.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index e21715592a..ed26f9beed 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -571,11 +571,12 @@ static void loongarch_cpu_init(Object *obj)
 static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
 {
 ObjectClass *oc;
-char *typename;
 
-typename = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model);
-oc = object_class_by_name(typename);
-g_free(typename);
+oc = object_class_by_name(cpu_model);
+if (!oc || !object_class_dynamic_cast(oc, TYPE_LOONGARCH_CPU) ||
+object_class_is_abstract(oc)) {
+return NULL;
+}
 return oc;
 }
 
-- 
2.31.1




[PATCH v2 0/5] Fix LoongArch coverity error and cpu name bug

2022-07-13 Thread Xiaojuan Yang
Make some changes following Richard's advice based on version v1. And the
v1 patches fix some coverity errors and loongarch_cpu_class_by_name function
for LoongArch virt machine.

1. Use MAKE_64BIT_MASK(shift, len) to replace 'xxx << shift'.
2. Use ARRAY_SIZE(arrqy) to get the array size.
3. Add the assertion that 'cpu_model' resolve to a class of the
   appropriate type.

Xiaojuan Yang (5):
  target/loongarch/cpu: Fix cpu_class_by_name function
  hw/intc/loongarch_pch_pic: Fix coverity errors in update irq
  target/loongarch/cpu: Fix coverity errors about excp_names
  target/loongarch/tlb_helper: Fix coverity integer overflow error
  target/loongarch/op_helper: Fix coverity cond_at_most error

 hw/intc/loongarch_pch_pic.c   | 19 ---
 target/loongarch/cpu.c| 15 ---
 target/loongarch/op_helper.c  |  2 +-
 target/loongarch/tlb_helper.c |  4 ++--
 4 files changed, 23 insertions(+), 17 deletions(-)

-- 
2.31.1




Re: [PATCH v7 04/14] mm/shmem: Support memfile_notifier

2022-07-13 Thread Gupta, Pankaj




+#ifdef CONFIG_MIGRATION
+static int shmem_migrate_page(struct address_space *mapping,
+ struct page *newpage, struct page *page,
+ enum migrate_mode mode)
+{
+   struct inode *inode = mapping->host;
+   struct shmem_inode_info *info = SHMEM_I(inode);
+
+   if (info->memfile_node.flags & MEMFILE_F_UNMOVABLE)
+   return -EOPNOTSUPP;
+   return migrate_page(mapping, newpage, page, mode);


Wondering how well page migrate would work for private pages
on shmem memfd based backend?


 From high level:
   - KVM unset MEMFILE_F_UNMOVABLE bit to indicate it capable of
 migrating a page.
   - Introduce new 'migrate' callback(s) to memfile_notifier_ops for KVM
 to register.
   - The callback is hooked to migrate_page() here.
   - Once page migration requested, shmem calls into the 'migrate'
 callback(s) to perform additional steps for encrypted memory (For
 TDX we will call TDH.MEM.PAGE.RELOCATE).


Yes, that would require additional (protocol specific) handling for 
private pages. Was trying to find where "MEMFILE_F_UNMOVABLE" flag is 
set currently?


Thanks,
Pankaj



[PULL 1/3] MAINTAINERS: Add myself as Guest Agent reviewer

2022-07-13 Thread Konstantin Kostiuk
Signed-off-by: Konstantin Kostiuk 
Message-Id: <20220712092715.2136898-1-kkost...@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Konstantin Kostiuk 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 450abd0252..b1e73d99f3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2880,6 +2880,7 @@ T: git https://repo.or.cz/qemu/armbru.git qapi-next
 
 QEMU Guest Agent
 M: Michael Roth 
+R: Konstantin Kostiuk 
 S: Maintained
 F: qga/
 F: docs/interop/qemu-ga.rst
-- 
2.25.1




[PULL 2/3] qapi: Avoid generating C identifier 'linux'

2022-07-13 Thread Konstantin Kostiuk
From: zhenwei pi 

'linux' is not usable as identifier, because C compilers targeting
Linux predefine it as a macro expanding to 1.  Add it to
@polluted_words. 'unix' is already there.

Suggested-by: Markus Armbruster 
Reviewed-by: Marc-André Lureau 
Signed-off-by: zhenwei pi 
Message-Id: <20220707005602.696557-2-pizhen...@bytedance.com>
Reviewed-by: Markus Armbruster 
Signed-off-by: Konstantin Kostiuk 
---
 scripts/qapi/common.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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




[PULL 0/3] Guest Agent patches 2022-07-13

2022-07-13 Thread Konstantin Kostiuk
The following changes since commit 08c8a31214e8ca29e05b9f6c3ee942b28ec58457:

  Merge tag 'pull-tcg-20220712' of https://gitlab.com/rth7680/qemu into staging 
(2022-07-12 11:52:11 +0530)

are available in the Git repository at:

  g...@github.com:kostyanf14/qemu.git tags/qga-win32-pull-2022-07-13

for you to fetch changes up to 1db8a0b0ea2fb72ecab36bd3143a9715c083d5d3:

  qga: add command 'guest-get-cpustats' (2022-07-13 12:19:18 +0300)


qga-win32-pull-2022-07-13


Konstantin Kostiuk (1):
  MAINTAINERS: Add myself as Guest Agent reviewer

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

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


--
2.25.1




[PULL 3/3] qga: add command 'guest-get-cpustats'

2022-07-13 Thread Konstantin Kostiuk
From: zhenwei pi 

A vCPU thread always reaches 100% utilization when:
- guest uses idle=poll
- disable HLT vm-exit
- enable MWAIT

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

Reviewed-by: Marc-André Lureau 
Signed-off-by: zhenwei pi 
Message-Id: <20220707005602.696557-3-pizhen...@bytedance.com>
Reviewed-by: Konstantin Kostiuk 
Signed-off-by: Konstantin Kostiuk 
---
 qga/commands-posix.c | 89 
 qga/commands-win32.c |  6 +++
 qga/qapi-schema.json | 81 
 3 files changed, 176 insertions(+)

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

Re: [PATCH v7 00/14] KVM: mm: fd-based approach for supporting KVM guest private memory

2022-07-13 Thread Gupta, Pankaj




This is the v7 of this series which tries to implement the fd-based KVM
guest private memory. The patches are based on latest kvm/queue branch
commit:

b9b71f43683a (kvm/queue) KVM: x86/mmu: Buffer nested MMU
split_desc_cache only by default capacity

Introduction

In general this patch series introduce fd-based memslot which provides
guest memory through memory file descriptor fd[offset,size] instead of
hva/size. The fd can be created from a supported memory filesystem
like tmpfs/hugetlbfs etc. which we refer as memory backing store. KVM


Thinking a bit, As host side fd on tmpfs or shmem will store memory on host
page cache instead of mapping pages into userspace address space. Can we hit
double (un-coordinated) page cache problem with this when guest page cache
is also used?


This is my understanding: in host it will be indeed in page cache (in
current shmem implementation) but that's just the way it allocates and
provides the physical memory for the guest. In guest, guest OS will not
see this fd (absolutely), it only sees guest memory, on top of which it
can build its own page cache system for its own file-mapped content but
that is unrelated to host page cache.


yes. If guest fills its page cache with file backed memory, this at host 
side(on shmem fd backend) will also fill the host page cache fast. This 
can have an impact on performance of guest VM's if host goes to memory 
pressure situation sooner. Or else we end up utilizing way less System 
RAM.


Thanks,
Pankaj





Re: [PULL 1/3] MAINTAINERS: Add myself as Guest Agent reviewer

2022-07-13 Thread Daniel P . Berrangé
On Wed, Jul 13, 2022 at 01:19:06PM +0300, Konstantin Kostiuk wrote:
> Signed-off-by: Konstantin Kostiuk 
> Message-Id: <20220712092715.2136898-1-kkost...@redhat.com>
> Reviewed-by: Philippe Mathieu-Daudé 
> Signed-off-by: Konstantin Kostiuk 
> ---
>  MAINTAINERS | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 450abd0252..b1e73d99f3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2880,6 +2880,7 @@ T: git https://repo.or.cz/qemu/armbru.git qapi-next
>  
>  QEMU Guest Agent
>  M: Michael Roth 
> +R: Konstantin Kostiuk 

This pull request contains functional changes under qga/, which
suggests you're acting as a (co-)maintainer for QGA, not merely
a reviewer. I wouldn't normally expect reviewers to send pull
requests for a subsystem. As such should this be "M:", to
indicate co-maintainership and have an explicit ACK from
Michael Roth.

>  S: Maintained
>  F: qga/
>  F: docs/interop/qemu-ga.rst


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




Re: [PATCH v9 12/14] tests: Add postcopy tls migration test

2022-07-13 Thread Dr. David Alan Gilbert
* Peter Xu (pet...@redhat.com) wrote:
> We just added TLS tests for precopy but not postcopy.  Add the
> corresponding test for vanilla postcopy.
> 
> Rename the vanilla postcopy to "postcopy/plain" because all postcopy tests
> will only use unix sockets as channel.
> 
> Signed-off-by: Peter Xu 

Reviewed-by: Dr. David Alan Gilbert 

> ---
>  tests/qtest/migration-test.c | 61 ++--
>  1 file changed, 51 insertions(+), 10 deletions(-)
> 
> diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
> index f15a7517b1..ee37ad6631 100644
> --- a/tests/qtest/migration-test.c
> +++ b/tests/qtest/migration-test.c
> @@ -566,6 +566,9 @@ typedef struct {
>  
>  /* Optional: set number of migration passes to wait for */
>  unsigned int iterations;
> +
> +/* Postcopy specific fields */
> +void *postcopy_data;
>  } MigrateCommon;
>  
>  static int test_migrate_start(QTestState **from, QTestState **to,
> @@ -1054,15 +1057,19 @@ test_migrate_tls_x509_finish(QTestState *from,
>  
>  static int migrate_postcopy_prepare(QTestState **from_ptr,
>  QTestState **to_ptr,
> -MigrateStart *args)
> +MigrateCommon *args)
>  {
>  g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
>  QTestState *from, *to;
>  
> -if (test_migrate_start(&from, &to, uri, args)) {
> +if (test_migrate_start(&from, &to, uri, &args->start)) {
>  return -1;
>  }
>  
> +if (args->start_hook) {
> +args->postcopy_data = args->start_hook(from, to);
> +}
> +
>  migrate_set_capability(from, "postcopy-ram", true);
>  migrate_set_capability(to, "postcopy-ram", true);
>  migrate_set_capability(to, "postcopy-blocktime", true);
> @@ -1082,7 +1089,8 @@ static int migrate_postcopy_prepare(QTestState 
> **from_ptr,
>  return 0;
>  }
>  
> -static void migrate_postcopy_complete(QTestState *from, QTestState *to)
> +static void migrate_postcopy_complete(QTestState *from, QTestState *to,
> +  MigrateCommon *args)
>  {
>  wait_for_migration_complete(from);
>  
> @@ -1093,25 +1101,48 @@ static void migrate_postcopy_complete(QTestState 
> *from, QTestState *to)
>  read_blocktime(to);
>  }
>  
> +if (args->finish_hook) {
> +args->finish_hook(from, to, args->postcopy_data);
> +args->postcopy_data = NULL;
> +}
> +
>  test_migrate_end(from, to, true);
>  }
>  
> -static void test_postcopy(void)
> +static void test_postcopy_common(MigrateCommon *args)
>  {
> -MigrateStart args = {};
>  QTestState *from, *to;
>  
> -if (migrate_postcopy_prepare(&from, &to, &args)) {
> +if (migrate_postcopy_prepare(&from, &to, args)) {
>  return;
>  }
>  migrate_postcopy_start(from, to);
> -migrate_postcopy_complete(from, to);
> +migrate_postcopy_complete(from, to, args);
> +}
> +
> +static void test_postcopy(void)
> +{
> +MigrateCommon args = { };
> +
> +test_postcopy_common(&args);
> +}
> +
> +static void test_postcopy_tls_psk(void)
> +{
> +MigrateCommon args = {
> +.start_hook = test_migrate_tls_psk_start_match,
> +.finish_hook = test_migrate_tls_psk_finish,
> +};
> +
> +test_postcopy_common(&args);
>  }
>  
>  static void test_postcopy_recovery(void)
>  {
> -MigrateStart args = {
> -.hide_stderr = true,
> +MigrateCommon args = {
> +.start = {
> +.hide_stderr = true,
> +},
>  };
>  QTestState *from, *to;
>  g_autofree char *uri = NULL;
> @@ -1167,7 +1198,7 @@ static void test_postcopy_recovery(void)
>  /* Restore the postcopy bandwidth to unlimited */
>  migrate_set_parameter_int(from, "max-postcopy-bandwidth", 0);
>  
> -migrate_postcopy_complete(from, to);
> +migrate_postcopy_complete(from, to, &args);
>  }
>  
>  static void test_baddest(void)
> @@ -2122,6 +2153,16 @@ int main(int argc, char **argv)
>  if (has_uffd) {
>  qtest_add_func("/migration/postcopy/unix", test_postcopy);
>  qtest_add_func("/migration/postcopy/recovery", 
> test_postcopy_recovery);
> +qtest_add_func("/migration/postcopy/plain", test_postcopy);
> +#ifdef CONFIG_GNUTLS
> +/*
> + * NOTE: psk test is enough for postcopy, as other types of TLS
> + * channels are tested under precopy.  Here what we want to test is 
> the
> + * general postcopy path that has TLS channel enabled.
> + */
> +qtest_add_func("/migration/postcopy/tls/psk", test_postcopy_tls_psk);
> +#endif /* CONFIG_GNUTLS */
> +qtest_add_func("/migration/postcopy/recovery", 
> test_postcopy_recovery);
>  }
>  qtest_add_func("/migration/bad_dest", test_baddest);
>  qtest_add_func("/migration/precopy/unix/plain", test_precopy_unix_plain);
> -- 
> 2.32.0
> 
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manc

Re: [PULL 1/3] MAINTAINERS: Add myself as Guest Agent reviewer

2022-07-13 Thread Konstantin Kostiuk
On Wed, Jul 13, 2022 at 1:38 PM Daniel P. Berrangé 
wrote:

> On Wed, Jul 13, 2022 at 01:19:06PM +0300, Konstantin Kostiuk wrote:
> > Signed-off-by: Konstantin Kostiuk 
> > Message-Id: <20220712092715.2136898-1-kkost...@redhat.com>
> > Reviewed-by: Philippe Mathieu-Daudé 
> > Signed-off-by: Konstantin Kostiuk 
> > ---
> >  MAINTAINERS | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 450abd0252..b1e73d99f3 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -2880,6 +2880,7 @@ T: git https://repo.or.cz/qemu/armbru.git
> qapi-next
> >
> >  QEMU Guest Agent
> >  M: Michael Roth 
> > +R: Konstantin Kostiuk 
>
> This pull request contains functional changes under qga/, which
> suggests you're acting as a (co-)maintainer for QGA, not merely
> a reviewer. I wouldn't normally expect reviewers to send pull
> requests for a subsystem. As such should this be "M:", to
> indicate co-maintainership and have an explicit ACK from
> Michael Roth.
>

As the maintainer of the Windows part of the Guest Agent, I have added
myself
as a reviewer so I don't miss out on general patches for the Guest Agent.
Some time ago, I asked Michael Roth if I could submit PRs for all guest
agent components and he allow me to do this.
If need I can add myself as a co-maintainer to Guest Agent not only
Guest Agent Windows.


>
> >  S: Maintained
> >  F: qga/
> >  F: docs/interop/qemu-ga.rst
>
>
> With regards,
> Daniel
> --
> |: https://berrange.com  -o-
> https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org -o-
> https://fstop138.berrange.com :|
> |: https://entangle-photo.org-o-
> https://www.instagram.com/dberrange :|
>
>


Re: [PULL 1/3] MAINTAINERS: Add myself as Guest Agent reviewer

2022-07-13 Thread Daniel P . Berrangé
On Wed, Jul 13, 2022 at 02:31:08PM +0300, Konstantin Kostiuk wrote:
> On Wed, Jul 13, 2022 at 1:38 PM Daniel P. Berrangé 
> wrote:
> 
> > On Wed, Jul 13, 2022 at 01:19:06PM +0300, Konstantin Kostiuk wrote:
> > > Signed-off-by: Konstantin Kostiuk 
> > > Message-Id: <20220712092715.2136898-1-kkost...@redhat.com>
> > > Reviewed-by: Philippe Mathieu-Daudé 
> > > Signed-off-by: Konstantin Kostiuk 
> > > ---
> > >  MAINTAINERS | 1 +
> > >  1 file changed, 1 insertion(+)
> > >
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index 450abd0252..b1e73d99f3 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -2880,6 +2880,7 @@ T: git https://repo.or.cz/qemu/armbru.git
> > qapi-next
> > >
> > >  QEMU Guest Agent
> > >  M: Michael Roth 
> > > +R: Konstantin Kostiuk 
> >
> > This pull request contains functional changes under qga/, which
> > suggests you're acting as a (co-)maintainer for QGA, not merely
> > a reviewer. I wouldn't normally expect reviewers to send pull
> > requests for a subsystem. As such should this be "M:", to
> > indicate co-maintainership and have an explicit ACK from
> > Michael Roth.
> >
> 
> As the maintainer of the Windows part of the Guest Agent, I have added
> myself
> as a reviewer so I don't miss out on general patches for the Guest Agent.
> Some time ago, I asked Michael Roth if I could submit PRs for all guest
> agent components and he allow me to do this.
> If need I can add myself as a co-maintainer to Guest Agent not only
> Guest Agent Windows.

It sounds like you're defacto a co-maintainer already then and
might as well ackowledge this in MAINTAINERS.

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




Re: [RFC v3 1/8] blkio: add io_uring block driver using libblkio

2022-07-13 Thread Hanna Reitz

On 08.07.22 06:17, Stefan Hajnoczi wrote:

libblkio (https://gitlab.com/libblkio/libblkio/) is a library for
high-performance disk I/O. It currently supports io_uring and
virtio-blk-vhost-vdpa with additional drivers under development.

One of the reasons for developing libblkio is that other applications
besides QEMU can use it. This will be particularly useful for
vhost-user-blk which applications may wish to use for connecting to
qemu-storage-daemon.

libblkio also gives us an opportunity to develop in Rust behind a C API
that is easy to consume from QEMU.

This commit adds io_uring and virtio-blk-vhost-vdpa BlockDrivers to QEMU
using libblkio. It will be easy to add other libblkio drivers since they
will share the majority of code.

For now I/O buffers are copied through bounce buffers if the libblkio
driver requires it. Later commits add an optimization for
pre-registering guest RAM to avoid bounce buffers.

The syntax is:

   --blockdev 
io_uring,node-name=drive0,filename=test.img,readonly=on|off,cache.direct=on|off

and:

   --blockdev 
virtio-blk-vhost-vdpa,node-name=drive0,path=/dev/vdpa...,readonly=on|off

Signed-off-by: Stefan Hajnoczi 
---
  MAINTAINERS   |   6 +
  meson_options.txt |   2 +
  qapi/block-core.json  |  37 +-
  meson.build   |   9 +
  block/blkio.c | 659 ++
  tests/qtest/modules-test.c|   3 +
  block/meson.build |   1 +
  scripts/meson-buildoptions.sh |   3 +
  8 files changed, 718 insertions(+), 2 deletions(-)
  create mode 100644 block/blkio.c


[...]


diff --git a/block/blkio.c b/block/blkio.c
new file mode 100644
index 00..7fbdbd7fae
--- /dev/null
+++ b/block/blkio.c
@@ -0,0 +1,659 @@


Not sure whether it’s necessary, but I would have expected a copyright 
header here.



+#include "qemu/osdep.h"
+#include 
+#include "block/block_int.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
+#include "qemu/module.h"
+
+typedef struct BlkAIOCB {
+BlockAIOCB common;
+struct blkio_mem_region mem_region;
+QEMUIOVector qiov;
+struct iovec bounce_iov;
+} BlkioAIOCB;
+
+typedef struct {
+/* Protects ->blkio and request submission on ->blkioq */
+QemuMutex lock;
+
+struct blkio *blkio;
+struct blkioq *blkioq; /* this could be multi-queue in the future */
+int completion_fd;
+
+/* Polling fetches the next completion into this field */
+struct blkio_completion poll_completion;
+
+/* The value of the "mem-region-alignment" property */
+size_t mem_region_alignment;
+
+/* Can we skip adding/deleting blkio_mem_regions? */
+bool needs_mem_regions;
+} BDRVBlkioState;
+
+static void blkio_aiocb_complete(BlkioAIOCB *acb, int ret)
+{
+/* Copy bounce buffer back to qiov */
+if (acb->qiov.niov > 0) {
+qemu_iovec_from_buf(&acb->qiov, 0,
+acb->bounce_iov.iov_base,
+acb->bounce_iov.iov_len);
+qemu_iovec_destroy(&acb->qiov);
+}
+
+acb->common.cb(acb->common.opaque, ret);
+
+if (acb->mem_region.len > 0) {
+BDRVBlkioState *s = acb->common.bs->opaque;
+
+WITH_QEMU_LOCK_GUARD(&s->lock) {
+blkio_free_mem_region(s->blkio, &acb->mem_region);
+}
+}
+
+qemu_aio_unref(&acb->common);
+}
+
+/*
+ * Only the thread that calls aio_poll() invokes fd and poll handlers.
+ * Therefore locks are not necessary except when accessing s->blkio.
+ *
+ * No locking is performed around blkioq_get_completions() although other
+ * threads may submit I/O requests on s->blkioq. We're assuming there is no
+ * inteference between blkioq_get_completions() and other s->blkioq APIs.
+ */
+
+static void blkio_completion_fd_read(void *opaque)
+{
+BlockDriverState *bs = opaque;
+BDRVBlkioState *s = bs->opaque;
+struct blkio_completion completion;
+uint64_t val;
+ssize_t ret __attribute__((unused));


I’d prefer a `(void)ret;` over this attribute, not least because that 
line would give a nice opportunity to explain in a short comment why we 
ignore this return value that the compiler tells us not to ignore, but 
if you don’t, then this’ll be fine.



+
+/* Polling may have already fetched a completion */
+if (s->poll_completion.user_data != NULL) {
+completion = s->poll_completion;
+
+/* Clear it in case blkio_aiocb_complete() has a nested event loop */
+s->poll_completion.user_data = NULL;
+
+blkio_aiocb_complete(completion.user_data, completion.ret);
+}
+
+/* Reset completion fd status */
+ret = read(s->completion_fd, &val, sizeof(val));
+
+/*
+ * Reading one completion at a time makes nested event loop re-entrancy
+ * simple. Change this loop to get multiple completions in one go if it
+ * becomes a performance bottleneck.
+ */
+while (blkioq_do_io(s->blkioq, &completion, 0, 1, NULL) == 1) {
+blkio_aiocb_complete(completion.user_data, complet

Re: [PULL 1/3] MAINTAINERS: Add myself as Guest Agent reviewer

2022-07-13 Thread Konstantin Kostiuk
On Wed, Jul 13, 2022 at 2:55 PM Daniel P. Berrangé 
wrote:

> On Wed, Jul 13, 2022 at 02:31:08PM +0300, Konstantin Kostiuk wrote:
> > On Wed, Jul 13, 2022 at 1:38 PM Daniel P. Berrangé 
> > wrote:
> >
> > > On Wed, Jul 13, 2022 at 01:19:06PM +0300, Konstantin Kostiuk wrote:
> > > > Signed-off-by: Konstantin Kostiuk 
> > > > Message-Id: <20220712092715.2136898-1-kkost...@redhat.com>
> > > > Reviewed-by: Philippe Mathieu-Daudé 
> > > > Signed-off-by: Konstantin Kostiuk 
> > > > ---
> > > >  MAINTAINERS | 1 +
> > > >  1 file changed, 1 insertion(+)
> > > >
> > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > index 450abd0252..b1e73d99f3 100644
> > > > --- a/MAINTAINERS
> > > > +++ b/MAINTAINERS
> > > > @@ -2880,6 +2880,7 @@ T: git https://repo.or.cz/qemu/armbru.git
> > > qapi-next
> > > >
> > > >  QEMU Guest Agent
> > > >  M: Michael Roth 
> > > > +R: Konstantin Kostiuk 
> > >
> > > This pull request contains functional changes under qga/, which
> > > suggests you're acting as a (co-)maintainer for QGA, not merely
> > > a reviewer. I wouldn't normally expect reviewers to send pull
> > > requests for a subsystem. As such should this be "M:", to
> > > indicate co-maintainership and have an explicit ACK from
> > > Michael Roth.
> > >
> >
> > As the maintainer of the Windows part of the Guest Agent, I have added
> > myself
> > as a reviewer so I don't miss out on general patches for the Guest Agent.
> > Some time ago, I asked Michael Roth if I could submit PRs for all guest
> > agent components and he allow me to do this.
> > If need I can add myself as a co-maintainer to Guest Agent not only
> > Guest Agent Windows.
>
> It sounds like you're defacto a co-maintainer already then and
> might as well ackowledge this in MAINTAINERS.
>

Ok. Will resend patch and pull.


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


[PATCH] scsi/lsi53c895a: really fix use-after-free in lsi_do_msgout (CVE-2022-0216)

2022-07-13 Thread Paolo Bonzini
From: Mauro Matteo Cascella 

Set current_req to NULL, not current_req->req, to prevent reusing a free'd
buffer in case of repeated SCSI cancel requests.  Also apply the fix to
CLEAR QUEUE and BUS DEVICE RESET messages as well, since they also cancel
the request.

Thanks to Alexander Bulekov for providing a reproducer.

Fixes: CVE-2022-0216
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/972
Signed-off-by: Mauro Matteo Cascella 
Tested-by: Alexander Bulekov 
Message-Id: <20220711123316.421279-1-mcasc...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
Adjust the patch from v1 to v2 since the changes crossed
with the pull request.

 hw/scsi/lsi53c895a.c   |  3 +-
 tests/qtest/fuzz-lsi53c895a-test.c | 71 ++
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 99ea42d49b..ad5f5e5f39 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -1030,7 +1030,7 @@ static void lsi_do_msgout(LSIState *s)
 trace_lsi_do_msgout_abort(current_tag);
 if (current_req && current_req->req) {
 scsi_req_cancel(current_req->req);
-current_req->req = NULL;
+current_req = NULL;
 }
 lsi_disconnect(s);
 break;
@@ -1056,6 +1056,7 @@ static void lsi_do_msgout(LSIState *s)
 /* clear the current I/O process */
 if (s->current) {
 scsi_req_cancel(s->current->req);
+current_req = NULL;
 }
 
 /* As the current implemented devices scsi_disk and scsi_generic
diff --git a/tests/qtest/fuzz-lsi53c895a-test.c 
b/tests/qtest/fuzz-lsi53c895a-test.c
index 2e8e67859e..6872c70d3a 100644
--- a/tests/qtest/fuzz-lsi53c895a-test.c
+++ b/tests/qtest/fuzz-lsi53c895a-test.c
@@ -8,6 +8,74 @@
 #include "qemu/osdep.h"
 #include "libqtest.h"
 
+/*
+ * This used to trigger a UAF in lsi_do_msgout()
+ * https://gitlab.com/qemu-project/qemu/-/issues/972
+ */
+static void test_lsi_do_msgout_cancel_req(void)
+{
+QTestState *s;
+
+s = qtest_init("-M q35 -m 4G -display none -nodefaults "
+   "-device lsi53c895a,id=scsi "
+   "-device scsi-hd,drive=disk0 "
+   "-drive file=null-co://,id=disk0,if=none,format=raw");
+
+qtest_outl(s, 0xcf8, 0x8810);
+qtest_outl(s, 0xcf8, 0xc000);
+qtest_outl(s, 0xcf8, 0x8810);
+qtest_outw(s, 0xcfc, 0x7);
+qtest_outl(s, 0xcf8, 0x8810);
+qtest_outl(s, 0xcfc, 0xc000);
+qtest_outl(s, 0xcf8, 0x8804);
+qtest_outw(s, 0xcfc, 0x05);
+qtest_writeb(s, 0x69736c10, 0x08);
+qtest_writeb(s, 0x69736c13, 0x58);
+qtest_writeb(s, 0x69736c1a, 0x01);
+qtest_writeb(s, 0x69736c1b, 0x06);
+qtest_writeb(s, 0x69736c22, 0x01);
+qtest_writeb(s, 0x69736c23, 0x07);
+qtest_writeb(s, 0x69736c2b, 0x02);
+qtest_writeb(s, 0x69736c48, 0x08);
+qtest_writeb(s, 0x69736c4b, 0x58);
+qtest_writeb(s, 0x69736c52, 0x04);
+qtest_writeb(s, 0x69736c53, 0x06);
+qtest_writeb(s, 0x69736c5b, 0x02);
+qtest_outl(s, 0xc02d, 0x697300);
+qtest_writeb(s, 0x5a554662, 0x01);
+qtest_writeb(s, 0x5a554663, 0x07);
+qtest_writeb(s, 0x5a55466a, 0x10);
+qtest_writeb(s, 0x5a55466b, 0x22);
+qtest_writeb(s, 0x5a55466c, 0x5a);
+qtest_writeb(s, 0x5a55466d, 0x5a);
+qtest_writeb(s, 0x5a55466e, 0x34);
+qtest_writeb(s, 0x5a55466f, 0x5a);
+qtest_writeb(s, 0x5a345a5a, 0x77);
+qtest_writeb(s, 0x5a345a5b, 0x55);
+qtest_writeb(s, 0x5a345a5c, 0x51);
+qtest_writeb(s, 0x5a345a5d, 0x27);
+qtest_writeb(s, 0x27515577, 0x41);
+qtest_outl(s, 0xc02d, 0x5a5500);
+qtest_writeb(s, 0x364001d0, 0x08);
+qtest_writeb(s, 0x364001d3, 0x58);
+qtest_writeb(s, 0x364001da, 0x01);
+qtest_writeb(s, 0x364001db, 0x26);
+qtest_writeb(s, 0x364001dc, 0x0d);
+qtest_writeb(s, 0x364001dd, 0xae);
+qtest_writeb(s, 0x364001de, 0x41);
+qtest_writeb(s, 0x364001df, 0x5a);
+qtest_writeb(s, 0x5a41ae0d, 0xf8);
+qtest_writeb(s, 0x5a41ae0e, 0x36);
+qtest_writeb(s, 0x5a41ae0f, 0xd7);
+qtest_writeb(s, 0x5a41ae10, 0x36);
+qtest_writeb(s, 0x36d736f8, 0x0c);
+qtest_writeb(s, 0x36d736f9, 0x80);
+qtest_writeb(s, 0x36d736fa, 0x0d);
+qtest_outl(s, 0xc02d, 0x364000);
+
+qtest_quit(s);
+}
+
 /*
  * This used to trigger the assert in lsi_do_dma()
  * https://bugs.launchpad.net/qemu/+bug/697510
@@ -44,5 +112,8 @@ int main(int argc, char **argv)
 qtest_add_func("fuzz/lsi53c895a/lsi_do_dma_empty_queue",
test_lsi_do_dma_empty_queue);
 
+qtest_add_func("fuzz/lsi53c895a/lsi_do_msgout_cancel_req",
+   test_lsi_do_msgout_cancel_req);
+
 return g_test_run();
 }
-- 
2.36.1




[PATCH] pc-bios/s390-ccw: add -Wno-array-bounds

2022-07-13 Thread Paolo Bonzini
The option generates a lot of warnings for integers casted to pointers,
for example:

/home/pbonzini/work/upstream/qemu/pc-bios/s390-ccw/dasd-ipl.c:174:19: warning: 
array subscript 0 is outside array bounds of ‘CcwSeekData[0]’ [-Warray-bounds]
  174 | seekData->cyl = 0x00;
  | ~~^~

Signed-off-by: Paolo Bonzini 
---
 pc-bios/s390-ccw/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 26ad40f94e..c8784c2a08 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -35,6 +35,7 @@ EXTRA_CFLAGS += $(call cc-option,-Werror 
$(EXTRA_CFLAGS),-Wno-stringop-overflow)
 EXTRA_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -fno-common 
-fPIE
 EXTRA_CFLAGS += -fwrapv -fno-strict-aliasing -fno-asynchronous-unwind-tables
 EXTRA_CFLAGS += $(call cc-option, $(EXTRA_CFLAGS), -fno-stack-protector)
+EXTRA_CFLAGS += $(call cc-option, $(EXTRA_CFLAGS), -Wno-array-bounds)
 EXTRA_CFLAGS += -msoft-float
 EXTRA_CFLAGS += $(call cc-option, $(EXTRA_CFLAGS),-march=z900,-march=z10)
 EXTRA_CFLAGS += -std=gnu99
-- 
2.36.1




Re: [PATCH 1/4] Modifying ‘migrate’ qmp command to add multi-FD socket on particular source and destination pair

2022-07-13 Thread Claudio Fontana
On 6/16/22 19:26, Dr. David Alan Gilbert wrote:
> * Het Gala (het.g...@nutanix.com) wrote:
>> i) Modified the format of the qemu monitor command : 'migrate' by adding a 
>> list,
>>each element in the list consists of multi-FD connection parameters: 
>> source
>>and destination uris and of the number of multi-fd channels between each 
>> pair.
>>
>> ii) Information of all multi-FD connection parameters’ list, length of the 
>> list
>> and total number of multi-fd channels for all the connections together is
>> stored in ‘OutgoingArgs’ struct.
>>
>> Suggested-by: Manish Mishra 
>> Signed-off-by: Het Gala 
>> ---
>>  include/qapi/util.h   |  9 
>>  migration/migration.c | 47 ++
>>  migration/socket.c| 53 ---
>>  migration/socket.h| 17 +-
>>  monitor/hmp-cmds.c| 22 --
>>  qapi/migration.json   | 43 +++
>>  6 files changed, 170 insertions(+), 21 deletions(-)
>>
>> diff --git a/include/qapi/util.h b/include/qapi/util.h
>> index 81a2b13a33..3041feb3d9 100644
>> --- a/include/qapi/util.h
>> +++ b/include/qapi/util.h
>> @@ -56,4 +56,13 @@ int parse_qapi_name(const char *name, bool complete);
>>  (tail) = &(*(tail))->next; \
>>  } while (0)
>>  
>> +#define QAPI_LIST_LENGTH(list) ({ \
>> +int _len = 0; \
>> +typeof(list) _elem; \
>> +for (_elem = list; _elem != NULL; _elem = _elem->next) { \
>> +_len++; \
>> +} \
>> +_len; \
>> +})
>> +
>>  #endif
> 
> This looks like it should be a separate patch to me (and perhaps size_t
> for len?)
> 
>> diff --git a/migration/migration.c b/migration/migration.c
>> index 31739b2af9..c408175aeb 100644
>> --- a/migration/migration.c
>> +++ b/migration/migration.c
>> @@ -2328,13 +2328,14 @@ static bool migrate_prepare(MigrationState *s, bool 
>> blk, bool blk_inc,
>>  return true;
>>  }
>>  
>> -void qmp_migrate(const char *uri, bool has_blk, bool blk,
>> +void qmp_migrate(const char *uri, bool has_multi_fd_uri_list,
>> + MigrateUriParameterList *cap, bool has_blk, bool blk,
>>   bool has_inc, bool inc, bool has_detach, bool detach,
>>   bool has_resume, bool resume, Error **errp)
>>  {
>>  Error *local_err = NULL;
>>  MigrationState *s = migrate_get_current();
>> -const char *p = NULL;
>> +const char *dst_ptr = NULL;
>>  
>>  if (!migrate_prepare(s, has_blk && blk, has_inc && inc,
>>   has_resume && resume, errp)) {
>> @@ -2348,20 +2349,46 @@ void qmp_migrate(const char *uri, bool has_blk, bool 
>> blk,
>>  }
>>  }
>>  
>> +/*
>> + * In case of Multi-FD migration parameters, if uri is provided,
> 
> I think you mean 'if uri list is provided'
> 
>> + * supports only tcp network protocol.
>> + */
>> +if (has_multi_fd_uri_list) {
>> +int length = QAPI_LIST_LENGTH(cap);
>> +init_multifd_array(length);
>> +for (int i = 0; i < length; i++) {
>> +const char *p1 = NULL, *p2 = NULL;
> 
> Keep these as ps/pd  to make it clear which is source and dest.
> 
>> +const char *multifd_dst_uri = cap->value->destination_uri;
>> +const char *multifd_src_uri = cap->value->source_uri;
>> +uint8_t multifd_channels = cap->value->multifd_channels;
>> +if (!strstart(multifd_dst_uri, "tcp:", &p1) ||
>> +!strstart(multifd_src_uri, "tcp:", &p2)) {
> 
> I've copied in Claudio Fontana; Claudio is fighting to make snapshots
> faster and has been playing with various multithread schemes for multifd
> with files and fd's;  perhaps the syntax you're proposing doesn't need
> to be limited to tcp.


Hi,

I will try to express our current problem, and see where there might be some 
overlap, maybe you can see more.

The current problem we are facing is, saving or restoring of VM state to disk, 
which in libvirt terms is "virsh save" or "virsh managedsave" and "virsh 
restore" or "virsh start",
is currently needlessly slow with large VMs, using upstream libvirt and qemu.

We need to get the transfer speeds of VM state (mainly RAM) to disk in the 
multiple GiB/s range with modern processors and NVMe disks; we have shown it is 
feasible.

Mainline libvirt uses QEMU migration to "fd://" to implement saving of VMs to 
disk, but adds copying though pipes via a libvirt "iohelper" process to work 
around a set of problems that are still not 100% clear to me;
(I cannot find the right email where this was discussed).

One clearly factual issue is that the QEMU migration stream is not currently 
O_DIRECT friendly, as it assumes it goes to network, and unfortunately for 
large transfers of this kind, O_DIRECT is needed due to the kernel file cache 
trashing problem.

So already, if your series were to address "fd://", it would potentially 
automatically provide an additional feature for libvirt's current sa

[PATCH v2 02/11] dump: Allocate header

2022-07-13 Thread Janosch Frank
Allocating the header lets us write it at a later time and hence also
allows us to change section and segment table offsets until we
finally write it.

Signed-off-by: Janosch Frank 
---
 dump/dump.c   | 127 +-
 include/sysemu/dump.h |   1 +
 2 files changed, 64 insertions(+), 64 deletions(-)

diff --git a/dump/dump.c b/dump/dump.c
index 6feba3cbfa..16d7474258 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -98,6 +98,7 @@ static int dump_cleanup(DumpState *s)
 memory_mapping_list_free(&s->list);
 close(s->fd);
 g_free(s->guest_note);
+g_free(s->elf_header);
 s->guest_note = NULL;
 if (s->resume) {
 if (s->detached) {
@@ -126,73 +127,49 @@ static int fd_write_vmcore(const void *buf, size_t size, 
void *opaque)
 return 0;
 }
 
-static void write_elf64_header(DumpState *s, Error **errp)
+static void prepare_elf64_header(DumpState *s)
 {
-/*
- * phnum in the elf header is 16 bit, if we have more segments we
- * set phnum to PN_XNUM and write the real number of segments to a
- * special section.
- */
-uint16_t phnum = MIN(s->phdr_num, PN_XNUM);
-Elf64_Ehdr elf_header;
-int ret;
+uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num;
+Elf64_Ehdr *elf_header = s->elf_header;
 
-memset(&elf_header, 0, sizeof(Elf64_Ehdr));
-memcpy(&elf_header, ELFMAG, SELFMAG);
-elf_header.e_ident[EI_CLASS] = ELFCLASS64;
-elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
-elf_header.e_ident[EI_VERSION] = EV_CURRENT;
-elf_header.e_type = cpu_to_dump16(s, ET_CORE);
-elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
-elf_header.e_version = cpu_to_dump32(s, EV_CURRENT);
-elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
-elf_header.e_phoff = cpu_to_dump64(s, s->phdr_offset);
-elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
-elf_header.e_phnum = cpu_to_dump16(s, phnum);
+memcpy(elf_header, ELFMAG, SELFMAG);
+elf_header->e_ident[EI_CLASS] = ELFCLASS64;
+elf_header->e_ident[EI_DATA] = s->dump_info.d_endian;
+elf_header->e_ident[EI_VERSION] = EV_CURRENT;
+elf_header->e_type = cpu_to_dump16(s, ET_CORE);
+elf_header->e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
+elf_header->e_version = cpu_to_dump32(s, EV_CURRENT);
+elf_header->e_ehsize = cpu_to_dump16(s, sizeof(*elf_header));
+elf_header->e_phoff = cpu_to_dump64(s, s->phdr_offset);
+elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
+elf_header->e_phnum = cpu_to_dump16(s, phnum);
 if (s->shdr_num) {
-elf_header.e_shoff = cpu_to_dump64(s, s->shdr_offset);
-elf_header.e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr));
-elf_header.e_shnum = cpu_to_dump16(s, s->shdr_num);
-}
-
-ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
-if (ret < 0) {
-error_setg_errno(errp, -ret, "dump: failed to write elf header");
+elf_header->e_shoff = cpu_to_dump64(s, s->shdr_offset);
+elf_header->e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr));
+elf_header->e_shnum = cpu_to_dump16(s, s->shdr_num);
 }
 }
 
-static void write_elf32_header(DumpState *s, Error **errp)
+static void prepare_elf32_header(DumpState *s)
 {
-/*
- * phnum in the elf header is 16 bit, if we have more segments we
- * set phnum to PN_XNUM and write the real number of segments to a
- * special section.
- */
-uint16_t phnum = MIN(s->phdr_num, PN_XNUM);
-Elf32_Ehdr elf_header;
-int ret;
+uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num;
+Elf32_Ehdr *elf_header = s->elf_header;
 
-memset(&elf_header, 0, sizeof(Elf32_Ehdr));
-memcpy(&elf_header, ELFMAG, SELFMAG);
-elf_header.e_ident[EI_CLASS] = ELFCLASS32;
-elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
-elf_header.e_ident[EI_VERSION] = EV_CURRENT;
-elf_header.e_type = cpu_to_dump16(s, ET_CORE);
-elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
-elf_header.e_version = cpu_to_dump32(s, EV_CURRENT);
-elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
-elf_header.e_phoff = cpu_to_dump32(s, s->phdr_offset);
-elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf32_Phdr));
-elf_header.e_phnum = cpu_to_dump16(s, phnum);
+memcpy(elf_header, ELFMAG, SELFMAG);
+elf_header->e_ident[EI_CLASS] = ELFCLASS32;
+elf_header->e_ident[EI_DATA] = s->dump_info.d_endian;
+elf_header->e_ident[EI_VERSION] = EV_CURRENT;
+elf_header->e_type = cpu_to_dump16(s, ET_CORE);
+elf_header->e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
+elf_header->e_version = cpu_to_dump32(s, EV_CURRENT);
+elf_header->e_ehsize = cpu_to_dump16(s, sizeof(*elf_header));
+elf_header->e_phoff = cpu_to_dump32(s, s->phdr_offset);
+elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf32_Phdr));
+elf_header-

[PATCH v2 01/11] dump: Cleanup memblock usage

2022-07-13 Thread Janosch Frank
The iteration over the memblocks is hard to understand so it's about
time to clean it up.

struct DumpState's next_block and start members can and should be
local variables within the iterator.

Instead of manually grabbing the next memblock we can use
QTAILQ_FOREACH to iterate over all memblocks.

The begin and length fields in the DumpState have been left untouched
since the qmp arguments share their names.

Signed-off-by: Janosch Frank 
---
 dump/dump.c   | 91 +++
 include/sysemu/dump.h | 47 +++---
 2 files changed, 65 insertions(+), 73 deletions(-)

diff --git a/dump/dump.c b/dump/dump.c
index 4d9658ffa2..6feba3cbfa 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -591,56 +591,27 @@ static void dump_begin(DumpState *s, Error **errp)
 write_elf_notes(s, errp);
 }
 
-static int get_next_block(DumpState *s, GuestPhysBlock *block)
-{
-while (1) {
-block = QTAILQ_NEXT(block, next);
-if (!block) {
-/* no more block */
-return 1;
-}
-
-s->start = 0;
-s->next_block = block;
-if (s->has_filter) {
-if (block->target_start >= s->begin + s->length ||
-block->target_end <= s->begin) {
-/* This block is out of the range */
-continue;
-}
-
-if (s->begin > block->target_start) {
-s->start = s->begin - block->target_start;
-}
-}
-
-return 0;
-}
-}
-
 /* write all memory to vmcore */
 static void dump_iterate(DumpState *s, Error **errp)
 {
 ERRP_GUARD();
 GuestPhysBlock *block;
-int64_t size;
+int64_t memblock_size, memblock_start;
 
-do {
-block = s->next_block;
-
-size = block->target_end - block->target_start;
-if (s->has_filter) {
-size -= s->start;
-if (s->begin + s->length < block->target_end) {
-size -= block->target_end - (s->begin + s->length);
-}
+QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
+memblock_start = dump_get_memblock_start(block, s->begin, s->length);
+if (memblock_start == -1) {
+continue;
 }
-write_memory(s, block, s->start, size, errp);
+
+memblock_size = dump_get_memblock_size(block, s->begin, s->length);
+
+/* Write the memory to file */
+write_memory(s, block, memblock_start, memblock_size, errp);
 if (*errp) {
 return;
 }
-
-} while (!get_next_block(s, block));
+}
 }
 
 static void create_vmcore(DumpState *s, Error **errp)
@@ -1490,30 +1461,22 @@ static void create_kdump_vmcore(DumpState *s, Error 
**errp)
 }
 }
 
-static ram_addr_t get_start_block(DumpState *s)
+static int validate_start_block(DumpState *s)
 {
 GuestPhysBlock *block;
 
 if (!s->has_filter) {
-s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
 return 0;
 }
 
 QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
+/* This block is out of the range */
 if (block->target_start >= s->begin + s->length ||
 block->target_end <= s->begin) {
-/* This block is out of the range */
 continue;
 }
-
-s->next_block = block;
-if (s->begin > block->target_start) {
-s->start = s->begin - block->target_start;
-} else {
-s->start = 0;
-}
-return s->start;
-}
+return 0;
+   }
 
 return -1;
 }
@@ -1540,25 +1503,17 @@ bool qemu_system_dump_in_progress(void)
 return (qatomic_read(&state->status) == DUMP_STATUS_ACTIVE);
 }
 
-/* calculate total size of memory to be dumped (taking filter into
- * acoount.) */
+/*
+ * calculate total size of memory to be dumped (taking filter into
+ * account.)
+ */
 static int64_t dump_calculate_size(DumpState *s)
 {
 GuestPhysBlock *block;
-int64_t size = 0, total = 0, left = 0, right = 0;
+int64_t total = 0;
 
 QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
-if (s->has_filter) {
-/* calculate the overlapped region. */
-left = MAX(s->begin, block->target_start);
-right = MIN(s->begin + s->length, block->target_end);
-size = right - left;
-size = size > 0 ? size : 0;
-} else {
-/* count the whole region in */
-size = (block->target_end - block->target_start);
-}
-total += size;
+total += dump_get_memblock_size(block, s->begin, s->length);
 }
 
 return total;
@@ -1660,8 +1615,8 @@ static void dump_init(DumpState *s, int fd, bool 
has_format,
 goto cleanup;
 }
 
-s->start = get_start_block(s);
-if (s->start == -1) {
+/* Is the filter filtering everything? */
+if (validate_start_block(s) == -1) {
 error_setg(errp, QERR_INVALID_PARAMETER, "begin");
 goto

[PATCH v2 03/11] dump: Split write of section headers and data and add a prepare step

2022-07-13 Thread Janosch Frank
By splitting the writing of the section headers and (future) section
data we prepare for the addition of a string table section and
architecture sections.

Signed-off-by: Janosch Frank 
---
 dump/dump.c   | 116 --
 include/sysemu/dump.h |   4 ++
 2 files changed, 94 insertions(+), 26 deletions(-)

diff --git a/dump/dump.c b/dump/dump.c
index 16d7474258..467d934bc1 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -342,30 +342,73 @@ static void write_elf_phdr_note(DumpState *s, Error 
**errp)
 }
 }
 
-static void write_elf_section(DumpState *s, int type, Error **errp)
+static size_t write_elf_section_hdr_zero(DumpState *s, void *buff)
 {
-Elf32_Shdr shdr32;
-Elf64_Shdr shdr64;
-int shdr_size;
-void *shdr;
-int ret;
+if (dump_is_64bit(s)) {
+Elf64_Shdr *shdr64 = buff;
 
-if (type == 0) {
-shdr_size = sizeof(Elf32_Shdr);
-memset(&shdr32, 0, shdr_size);
-shdr32.sh_info = cpu_to_dump32(s, s->phdr_num);
-shdr = &shdr32;
+memset(buff, 0, sizeof(Elf64_Shdr));
+shdr64->sh_info = cpu_to_dump32(s, s->phdr_num);
 } else {
-shdr_size = sizeof(Elf64_Shdr);
-memset(&shdr64, 0, shdr_size);
-shdr64.sh_info = cpu_to_dump32(s, s->phdr_num);
-shdr = &shdr64;
+Elf32_Shdr *shdr32 = buff;
+
+memset(buff, 0, sizeof(Elf32_Shdr));
+shdr32->sh_info = cpu_to_dump32(s, s->phdr_num);
 }
 
-ret = fd_write_vmcore(shdr, shdr_size, s);
+return dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
+}
+
+static void prepare_elf_section_hdrs(DumpState *s)
+{
+uint8_t *buff_hdr;
+size_t len, sizeof_shdr;
+
+/*
+ * Section ordering:
+ * - HDR zero (if needed)
+ */
+sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
+len = sizeof_shdr * s->shdr_num;
+s->elf_section_hdrs = g_malloc0(len);
+buff_hdr = s->elf_section_hdrs;
+
+/* Write special section first */
+if (s->phdr_num == PN_XNUM) {
+write_elf_section_hdr_zero(s, buff_hdr);
+}
+}
+
+static void prepare_elf_sections(DumpState *s, Error **errp)
+{
+if (!s->shdr_num) {
+return;
+}
+
+prepare_elf_section_hdrs(s);
+}
+
+static void write_elf_section_headers(DumpState *s, Error **errp)
+{
+size_t sizeof_shdr;
+int ret;
+
+sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
+
+ret = fd_write_vmcore(s->elf_section_hdrs, s->shdr_num * sizeof_shdr, s);
 if (ret < 0) {
-error_setg_errno(errp, -ret,
- "dump: failed to write section header table");
+error_setg_errno(errp, -ret, "dump: failed to write section data");
+}
+}
+
+static void write_elf_sections(DumpState *s, Error **errp)
+{
+int ret;
+
+/* Write section zero */
+ret = fd_write_vmcore(s->elf_section_data, s->elf_section_data_size, s);
+if (ret < 0) {
+error_setg_errno(errp, -ret, "dump: failed to write section data");
 }
 }
 
@@ -557,12 +600,22 @@ static void dump_begin(DumpState *s, Error **errp)
 /* Write elf header to buffer */
 prepare_elf_header(s);
 
+prepare_elf_sections(s, errp);
+if (*errp) {
+return;
+}
+
 /* Start to write stuff into files*/
 write_elf_header(s, errp);
 if (*errp) {
 return;
 }
 
+write_elf_section_headers(s, errp);
+if (*errp) {
+return;
+}
+
 /* write PT_NOTE to vmcore */
 write_elf_phdr_note(s, errp);
 if (*errp) {
@@ -575,14 +628,6 @@ static void dump_begin(DumpState *s, Error **errp)
 return;
 }
 
-/* write section to vmcore */
-if (s->shdr_num) {
-write_elf_section(s, 1, errp);
-if (*errp) {
-return;
-}
-}
-
 /* write notes to vmcore */
 write_elf_notes(s, errp);
 }
@@ -610,6 +655,19 @@ static void dump_iterate(DumpState *s, Error **errp)
 }
 }
 
+static void dump_end(DumpState *s, Error **errp)
+{
+ERRP_GUARD();
+
+if (!s->elf_section_data_size) {
+return;
+}
+s->elf_section_data = g_malloc0(s->elf_section_data_size);
+
+/* write sections to vmcore */
+write_elf_sections(s, errp);
+}
+
 static void create_vmcore(DumpState *s, Error **errp)
 {
 ERRP_GUARD();
@@ -620,6 +678,12 @@ static void create_vmcore(DumpState *s, Error **errp)
 }
 
 dump_iterate(s, errp);
+if (*errp) {
+return;
+}
+
+/* Write section data after memory has been dumped */
+dump_end(s, errp);
 }
 
 static int write_start_flat_header(int fd)
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 736f681d01..bd49532232 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -172,6 +172,10 @@ typedef struct DumpState {
 int64_t length;/* Length of the dump we want to dump */
 
 void *elf_header;
+void *elf_section_hdrs;
+uint64_t elf_section_data_size;
+ 

[PATCH v2 11/11] s390x: pv: Add dump support

2022-07-13 Thread Janosch Frank
Sometimes dumping a guest from the outside is the only way to get the
data that is needed. This can be the case if a dumping mechanism like
KDUMP hasn't been configured or data needs to be fetched at a specific
point. Dumping a protected guest from the outside without help from
fw/hw doesn't yield sufficient data to be useful. Hence we now
introduce PV dump support.

The PV dump support works by integrating the firmware into the dump
process. New Ultravisor calls are used to initiate the dump process,
dump cpu data, dump memory state and lastly complete the dump process.
The UV calls are exposed by KVM via the new KVM_PV_DUMP command and
its subcommands. The guest's data is fully encrypted and can only be
decrypted by the entity that owns the customer communication key for
the dumped guest. Also dumping needs to be allowed via a flag in the
SE header.

On the QEMU side of things we store the PV dump data in the newly
introduced architecture ELF sections (storage state and completion
data) and the cpu notes (for cpu dump data).

Users can use the zgetdump tool to convert the encrypted QEMU dump to an
unencrypted one.

Signed-off-by: Janosch Frank 
---
 include/elf.h|   1 +
 target/s390x/arch_dump.c | 248 ++-
 2 files changed, 219 insertions(+), 30 deletions(-)

diff --git a/include/elf.h b/include/elf.h
index 3a4bcb646a..58f76fd5b4 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1649,6 +1649,7 @@ typedef struct elf64_shdr {
 #define NT_TASKSTRUCT  4
 #define NT_AUXV6
 #define NT_PRXFPREG 0x46e62b7f  /* copied from 
gdb5.1/include/elf/common.h */
+#define NT_S390_PV_DATA 0x30e   /* s390 protvirt cpu dump data */
 #define NT_S390_GS_CB   0x30b   /* s390 guarded storage registers */
 #define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31 */
 #define NT_S390_VXRS_LOW  0x309 /* s390 vector registers 0-15 (lower 
half) */
diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c
index 08daf93ae1..e081aa9483 100644
--- a/target/s390x/arch_dump.c
+++ b/target/s390x/arch_dump.c
@@ -16,7 +16,8 @@
 #include "s390x-internal.h"
 #include "elf.h"
 #include "sysemu/dump.h"
-
+#include "hw/s390x/pv.h"
+#include "kvm/kvm_s390x.h"
 
 struct S390xUserRegsStruct {
 uint64_t psw[2];
@@ -76,9 +77,16 @@ typedef struct noteStruct {
 uint64_t todcmp;
 uint32_t todpreg;
 uint64_t ctrs[16];
+uint8_t dynamic[1];  /*
+  * Would be a flexible array member, if
+  * that was legal inside a union. Real
+  * size comes from PV info interface.
+  */
 } contents;
 } QEMU_PACKED Note;
 
+static bool pv_dump_initialized;
+
 static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu, int id)
 {
 int i;
@@ -177,52 +185,82 @@ static void s390x_write_elf64_prefix(Note *note, S390CPU 
*cpu, int id)
 note->contents.prefix = cpu_to_be32((uint32_t)(cpu->env.psa));
 }
 
+static void s390x_write_elf64_pv(Note *note, S390CPU *cpu, int id)
+{
+note->hdr.n_type = cpu_to_be32(NT_S390_PV_DATA);
+if (!pv_dump_initialized) {
+return;
+}
+kvm_s390_dump_cpu(cpu, ¬e->contents.dynamic);
+}
 
 typedef struct NoteFuncDescStruct {
 int contents_size;
+uint64_t (*note_size_func)(void); /* NULL for non-dynamic sized contents */
 void (*note_contents_func)(Note *note, S390CPU *cpu, int id);
+bool pvonly;
 } NoteFuncDesc;
 
 static const NoteFuncDesc note_core[] = {
-{sizeof_field(Note, contents.prstatus), s390x_write_elf64_prstatus},
-{sizeof_field(Note, contents.fpregset), s390x_write_elf64_fpregset},
-{ 0, NULL}
+{sizeof_field(Note, contents.prstatus), NULL, s390x_write_elf64_prstatus, 
false},
+{sizeof_field(Note, contents.fpregset), NULL, s390x_write_elf64_fpregset, 
false},
+{ 0, NULL, NULL}
 };
 
 static const NoteFuncDesc note_linux[] = {
-{sizeof_field(Note, contents.prefix),   s390x_write_elf64_prefix},
-{sizeof_field(Note, contents.ctrs), s390x_write_elf64_ctrs},
-{sizeof_field(Note, contents.timer),s390x_write_elf64_timer},
-{sizeof_field(Note, contents.todcmp),   s390x_write_elf64_todcmp},
-{sizeof_field(Note, contents.todpreg),  s390x_write_elf64_todpreg},
-{sizeof_field(Note, contents.vregslo),  s390x_write_elf64_vregslo},
-{sizeof_field(Note, contents.vregshi),  s390x_write_elf64_vregshi},
-{sizeof_field(Note, contents.gscb), s390x_write_elf64_gscb},
-{ 0, NULL}
+{sizeof_field(Note, contents.prefix),   NULL, s390x_write_elf64_prefix,  
false},
+{sizeof_field(Note, contents.ctrs), NULL, s390x_write_elf64_ctrs,
false},
+{sizeof_field(Note, contents.timer),NULL, s390x_write_elf64_timer,   
false},
+{sizeof_field(Note, contents.todcmp),   NULL, s390x_write_elf64_todcmp,  
false},
+{sizeof_field(Note, contents.todpreg),  NULL, s390x_write

[PATCH v2 06/11] dump/dump: Add arch section support

2022-07-13 Thread Janosch Frank
Add hooks which architectures can use to add arbitrary data to custom
sections.

Signed-off-by: Janosch Frank 
---
 dump/dump.c| 21 ++---
 include/sysemu/dump-arch.h | 27 +++
 2 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/dump/dump.c b/dump/dump.c
index 31e2a85372..02de00b6de 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -400,6 +400,7 @@ static void prepare_elf_section_hdrs(DumpState *s)
 /*
  * Section ordering:
  * - HDR zero (if needed)
+ * - Arch section hdrs
  * - String table hdr
  */
 sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
@@ -417,6 +418,9 @@ static void prepare_elf_section_hdrs(DumpState *s)
 return;
 }
 
+size = dump_arch_sections_write_hdr(&s->dump_info, s, buff_hdr);
+buff_hdr += size;
+
 /*
  * String table needs to be last section since strings are added
  * via arch_sections_write_hdr().
@@ -567,14 +571,23 @@ static void get_offset_range(hwaddr phys_addr,
 }
 }
 
-static void write_elf_loads(DumpState *s, Error **errp)
+static void write_elf_phdr_loads(DumpState *s, Error **errp)
 {
 ERRP_GUARD();
 hwaddr offset, filesz;
 MemoryMapping *memory_mapping;
 uint32_t phdr_index = 1;
+hwaddr min = 0, max = 0;
 
 QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
+if (memory_mapping->phys_addr < min) {
+min = memory_mapping->phys_addr;
+}
+if (memory_mapping->phys_addr + memory_mapping->length > max) {
+max = memory_mapping->phys_addr + memory_mapping->length;
+}
+
+
 get_offset_range(memory_mapping->phys_addr,
  memory_mapping->length,
  s, &offset, &filesz);
@@ -682,8 +695,8 @@ static void dump_begin(DumpState *s, Error **errp)
 return;
 }
 
-/* write all PT_LOAD to vmcore */
-write_elf_loads(s, errp);
+/* write all PT_LOADs to vmcore */
+write_elf_phdr_loads(s, errp);
 if (*errp) {
 return;
 }
@@ -723,6 +736,7 @@ static void dump_end(DumpState *s, Error **errp)
 return;
 }
 s->elf_section_data = g_malloc0(s->elf_section_data_size);
+dump_arch_sections_write(&s->dump_info, s, s->elf_section_data);
 
 /* write sections to vmcore */
 write_elf_sections(s, errp);
@@ -1894,6 +1908,7 @@ static void dump_init(DumpState *s, int fd, bool 
has_format,
  * If phdr_num overflowed we have at least one section header
  * More sections/hdrs can be added by the architectures
  */
+dump_arch_sections_add(&s->dump_info, (void *)s);
 if (s->shdr_num > 1) {
 /* Reserve the string table */
 s->shdr_num += 1;
diff --git a/include/sysemu/dump-arch.h b/include/sysemu/dump-arch.h
index e25b02e990..de77908424 100644
--- a/include/sysemu/dump-arch.h
+++ b/include/sysemu/dump-arch.h
@@ -21,6 +21,9 @@ typedef struct ArchDumpInfo {
 uint32_t page_size;  /* The target's page size. If it's variable and
   * unknown, then this should be the maximum. */
 uint64_t phys_base;  /* The target's physmem base. */
+void (*arch_sections_add_fn)(void *opaque);
+uint64_t (*arch_sections_write_hdr_fn)(void *opaque, uint8_t *buff);
+void (*arch_sections_write_fn)(void *opaque, uint8_t *buff);
 } ArchDumpInfo;
 
 struct GuestPhysBlockList; /* memory_mapping.h */
@@ -28,4 +31,28 @@ int cpu_get_dump_info(ArchDumpInfo *info,
   const struct GuestPhysBlockList *guest_phys_blocks);
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
 
+static inline void dump_arch_sections_add(ArchDumpInfo *info, void *opaque)
+{
+if (info->arch_sections_add_fn) {
+info->arch_sections_add_fn(opaque);
+}
+}
+
+static inline uint64_t dump_arch_sections_write_hdr(ArchDumpInfo *info,
+void *opaque, uint8_t *buff)
+{
+if (info->arch_sections_write_hdr_fn) {
+return info->arch_sections_write_hdr_fn(opaque, buff);
+}
+return 0;
+}
+
+static inline void dump_arch_sections_write(ArchDumpInfo *info, void *opaque,
+uint8_t *buff)
+{
+if (info->arch_sections_write_fn) {
+info->arch_sections_write_fn(opaque, buff);
+}
+}
+
 #endif
-- 
2.34.1




[PATCH v2 05/11] dump/dump: Add section string table support

2022-07-13 Thread Janosch Frank
Time to add a bit more descriptiveness to the dumps.

Signed-off-by: Janosch Frank 
Reviewed-by: Richard Henderson 
---
 dump/dump.c   | 106 --
 include/sysemu/dump.h |   1 +
 2 files changed, 94 insertions(+), 13 deletions(-)

diff --git a/dump/dump.c b/dump/dump.c
index 467d934bc1..31e2a85372 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -99,6 +99,7 @@ static int dump_cleanup(DumpState *s)
 close(s->fd);
 g_free(s->guest_note);
 g_free(s->elf_header);
+g_array_unref(s->string_table_buf);
 s->guest_note = NULL;
 if (s->resume) {
 if (s->detached) {
@@ -359,14 +360,47 @@ static size_t write_elf_section_hdr_zero(DumpState *s, 
void *buff)
 return dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
 }
 
+static void write_elf_section_hdr_string(DumpState *s, void *buff)
+{
+Elf32_Shdr shdr32;
+Elf64_Shdr shdr64;
+int shdr_size;
+void *shdr = buff;
+
+if (dump_is_64bit(s)) {
+shdr_size = sizeof(Elf64_Shdr);
+memset(&shdr64, 0, shdr_size);
+shdr64.sh_type = SHT_STRTAB;
+shdr64.sh_offset = s->section_offset + s->elf_section_data_size;
+shdr64.sh_name = s->string_table_buf->len;
+g_array_append_vals(s->string_table_buf, ".strtab", sizeof(".strtab"));
+shdr64.sh_size = s->string_table_buf->len;
+shdr = &shdr64;
+} else {
+shdr_size = sizeof(Elf32_Shdr);
+memset(&shdr32, 0, shdr_size);
+shdr32.sh_type = SHT_STRTAB;
+shdr32.sh_offset = s->section_offset + s->elf_section_data_size;
+shdr32.sh_name = s->string_table_buf->len;
+g_array_append_vals(s->string_table_buf, ".strtab", sizeof(".strtab"));
+shdr32.sh_size = s->string_table_buf->len;
+shdr = &shdr32;
+}
+
+memcpy(buff, shdr, shdr_size);
+}
+
 static void prepare_elf_section_hdrs(DumpState *s)
 {
 uint8_t *buff_hdr;
-size_t len, sizeof_shdr;
+size_t len, size = 0, sizeof_shdr;
+Elf64_Ehdr *hdr64 = s->elf_header;
+Elf32_Ehdr *hdr32 = s->elf_header;
 
 /*
  * Section ordering:
  * - HDR zero (if needed)
+ * - String table hdr
  */
 sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
 len = sizeof_shdr * s->shdr_num;
@@ -377,6 +411,22 @@ static void prepare_elf_section_hdrs(DumpState *s)
 if (s->phdr_num == PN_XNUM) {
 write_elf_section_hdr_zero(s, buff_hdr);
 }
+buff_hdr += size;
+
+if (s->shdr_num < 2) {
+return;
+}
+
+/*
+ * String table needs to be last section since strings are added
+ * via arch_sections_write_hdr().
+ */
+write_elf_section_hdr_string(s, buff_hdr);
+if (dump_is_64bit(s)) {
+hdr64->e_shstrndx = cpu_to_dump16(s, s->shdr_num - 1);
+} else {
+hdr32->e_shstrndx = cpu_to_dump16(s, s->shdr_num - 1);
+}
 }
 
 static void prepare_elf_sections(DumpState *s, Error **errp)
@@ -405,11 +455,18 @@ static void write_elf_sections(DumpState *s, Error **errp)
 {
 int ret;
 
-/* Write section zero */
+/* Write section zero and arch sections */
 ret = fd_write_vmcore(s->elf_section_data, s->elf_section_data_size, s);
 if (ret < 0) {
 error_setg_errno(errp, -ret, "dump: failed to write section data");
 }
+
+/* Write string table data */
+ret = fd_write_vmcore(s->string_table_buf->data,
+  s->string_table_buf->len, s);
+if (ret < 0) {
+error_setg_errno(errp, -ret, "dump: failed to write string table 
data");
+}
 }
 
 static void write_data(DumpState *s, void *buf, int length, Error **errp)
@@ -592,6 +649,9 @@ static void dump_begin(DumpState *s, Error **errp)
  *   --
  *   |  memory |
  *   --
+ *   |  sectn data |
+ *   --
+
  *
  * we only know where the memory is saved after we write elf note into
  * vmcore.
@@ -677,6 +737,7 @@ static void create_vmcore(DumpState *s, Error **errp)
 return;
 }
 
+/* Iterate over memory and dump it to file */
 dump_iterate(s, errp);
 if (*errp) {
 return;
@@ -1659,6 +1720,13 @@ static void dump_init(DumpState *s, int fd, bool 
has_format,
 s->has_filter = has_filter;
 s->begin = begin;
 s->length = length;
+/* First index is 0, it's the special null name */
+s->string_table_buf = g_array_new(FALSE, TRUE, 1);
+/*
+ * Allocate the null name, due to the clearing option set to true
+ * it will be 0.
+ */
+g_array_set_size(s->string_table_buf, 1);
 
 memory_mapping_list_init(&s->list);
 
@@ -1819,19 +1887,31 @@ static void dump_init(DumpState *s, int fd, bool 
has_format,
 }
 }
 
-if (dump_is_64bit(s)) {
-s->phdr_offset = sizeof(Elf64_Ehdr);
-s->shdr_offset = s->phdr_offset + sizeof(Elf64_Phdr) * s->phdr_num;
-s->note_offset = s->shdr_offset + sizeof(Elf64_Shdr) * s->

[PATCH v2 07/11] linux header sync

2022-07-13 Thread Janosch Frank
Signed-off-by: Janosch Frank 
---
 linux-headers/linux/kvm.h | 55 +++
 1 file changed, 55 insertions(+)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 0d05d02ee4..ae5db2e44c 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1150,6 +1150,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_DISABLE_QUIRKS2 213
 /* #define KVM_CAP_VM_TSC_CONTROL 214 */
 #define KVM_CAP_SYSTEM_EVENT_DATA 215
+#define KVM_CAP_S390_PROTECTED_DUMP 217
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1651,6 +1652,55 @@ struct kvm_s390_pv_unp {
__u64 tweak;
 };
 
+enum pv_cmd_info_id {
+   KVM_PV_INFO_VM,
+   KVM_PV_INFO_DUMP,
+};
+
+struct kvm_s390_pv_info_dump {
+   __u64 dump_cpu_buffer_len;
+   __u64 dump_config_mem_buffer_per_1m;
+   __u64 dump_config_finalize_len;
+};
+
+struct kvm_s390_pv_info_vm {
+   __u64 inst_calls_list[4];
+   __u64 max_cpus;
+   __u64 max_guests;
+   __u64 max_guest_addr;
+   __u64 feature_indication;
+};
+
+struct kvm_s390_pv_info_header {
+   __u32 id;
+   __u32 len_max;
+   __u32 len_written;
+   __u32 reserved;
+};
+
+struct kvm_s390_pv_info {
+   struct kvm_s390_pv_info_header header;
+   union {
+   struct kvm_s390_pv_info_dump dump;
+   struct kvm_s390_pv_info_vm vm;
+   };
+};
+
+enum pv_cmd_dmp_id {
+KVM_PV_DUMP_INIT,
+KVM_PV_DUMP_CONFIG_STATE,
+KVM_PV_DUMP_COMPLETE,
+KVM_PV_DUMP_CPU,
+};
+
+struct kvm_s390_pv_dmp {
+__u64 subcmd;
+__u64 buff_addr;
+__u64 buff_len;
+__u64 gaddr;
+__u64 reserved[4];
+};
+
 enum pv_cmd_id {
KVM_PV_ENABLE,
KVM_PV_DISABLE,
@@ -1659,6 +1709,8 @@ enum pv_cmd_id {
KVM_PV_VERIFY,
KVM_PV_PREP_RESET,
KVM_PV_UNSHARE_ALL,
+KVM_PV_INFO,
+KVM_PV_DUMP,
 };
 
 struct kvm_pv_cmd {
@@ -1733,6 +1785,7 @@ struct kvm_xen_vcpu_attr {
 #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA   0x4
 #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
 
+
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {
/* Guest initialization commands */
@@ -2066,4 +2119,6 @@ struct kvm_stats_desc {
 /* Available with KVM_CAP_XSAVE2 */
 #define KVM_GET_XSAVE2   _IOR(KVMIO,  0xcf, struct kvm_xsave)
 
+#define KVM_S390_PV_CPU_COMMAND _IOWR(KVMIO, 0xd0, struct kvm_pv_cmd)
+
 #endif /* __LINUX_KVM_H */
-- 
2.34.1




[PATCH v2 10/11] s390x: Add KVM PV dump interface

2022-07-13 Thread Janosch Frank
Let's add a few bits of code which hide the new KVM PV dump API from
us via new functions.

Signed-off-by: Janosch Frank 
---
 hw/s390x/pv.c | 51 +++
 include/hw/s390x/pv.h |  8 +++
 2 files changed, 59 insertions(+)

diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c
index a5af4ddf46..48591c387d 100644
--- a/hw/s390x/pv.c
+++ b/hw/s390x/pv.c
@@ -175,6 +175,57 @@ bool kvm_s390_pv_info_basic_valid(void)
 return info_valid;
 }
 
+static int s390_pv_dump_cmd(uint64_t subcmd, uint64_t uaddr, uint64_t gaddr,
+uint64_t len)
+{
+struct kvm_s390_pv_dmp dmp = {
+.subcmd = subcmd,
+.buff_addr = uaddr,
+.buff_len = len,
+.gaddr = gaddr,
+};
+int ret;
+
+ret = s390_pv_cmd(KVM_PV_DUMP, (void *)&dmp);
+if (ret) {
+error_report("KVM DUMP command %ld failed", subcmd);
+}
+return ret;
+}
+
+int kvm_s390_dump_cpu(S390CPU *cpu, void *buff)
+{
+struct kvm_s390_pv_dmp dmp = {
+.subcmd = KVM_PV_DUMP_CPU,
+.buff_addr = (uint64_t)buff,
+.gaddr = 0,
+.buff_len = info_dump.dump_cpu_buffer_len,
+};
+struct kvm_pv_cmd pv = {
+.cmd = KVM_PV_DUMP,
+.data = (uint64_t)&dmp,
+};
+
+return kvm_vcpu_ioctl(CPU(cpu), KVM_S390_PV_CPU_COMMAND, &pv);
+}
+
+int kvm_s390_dump_init(void)
+{
+return s390_pv_dump_cmd(KVM_PV_DUMP_INIT, 0, 0, 0);
+}
+
+int kvm_s390_dump_mem(uint64_t gaddr, size_t len, void *dest)
+{
+return s390_pv_dump_cmd(KVM_PV_DUMP_CONFIG_STATE, (uint64_t)dest,
+gaddr, len);
+}
+
+int kvm_s390_dump_finish(void *buff)
+{
+return s390_pv_dump_cmd(KVM_PV_DUMP_COMPLETE, (uint64_t)buff, 0,
+info_dump.dump_config_finalize_len);
+}
+
 #define TYPE_S390_PV_GUEST "s390-pv-guest"
 OBJECT_DECLARE_SIMPLE_TYPE(S390PVGuest, S390_PV_GUEST)
 
diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h
index 6fa55bf70e..f37021e189 100644
--- a/include/hw/s390x/pv.h
+++ b/include/hw/s390x/pv.h
@@ -51,6 +51,10 @@ uint64_t kvm_s390_pv_dmp_get_size_cpu(void);
 uint64_t kvm_s390_pv_dmp_get_size_mem(void);
 uint64_t kvm_s390_pv_dmp_get_size_complete(void);
 bool kvm_s390_pv_info_basic_valid(void);
+int kvm_s390_dump_init(void);
+int kvm_s390_dump_cpu(S390CPU *cpu, void *buff);
+int kvm_s390_dump_mem(uint64_t addr, size_t len, void *dest);
+int kvm_s390_dump_finish(void *buff);
 #else /* CONFIG_KVM */
 static inline bool s390_is_pv(void) { return false; }
 static inline int s390_pv_query_info(void) { return 0; }
@@ -66,6 +70,10 @@ static inline uint64_t kvm_s390_pv_dmp_get_size_cpu(void) { 
return 0; }
 static inline uint64_t kvm_s390_pv_dmp_get_size_mem(void) { return 0; }
 static inline uint64_t kvm_s390_pv_dmp_get_size_complete(void) { return 0; }
 static inline bool kvm_s390_pv_info_basic_valid(void) { return false; }
+static inline int kvm_s390_dump_init(void) { return 0; }
+static inline int kvm_s390_dump_cpu(S390CPU *cpu, void *buff, size_t len) { 
return 0; }
+static inline int kvm_s390_dump_mem(uint64_t addr, size_t len, void *dest) { 
return 0; }
+static inline int kvm_s390_dump_finish(void *buff) { return 0; }
 #endif /* CONFIG_KVM */
 
 int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
-- 
2.34.1




[PATCH v2 04/11] dump: Reorder struct DumpState

2022-07-13 Thread Janosch Frank
Let's move ELF related members into one block and guest memory related
ones into another to improve readability.

Signed-off-by: Janosch Frank 
Reviewed-by: Richard Henderson 
---
 include/sysemu/dump.h | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index bd49532232..8379e29ef6 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -154,15 +154,8 @@ typedef struct DumpState {
 GuestPhysBlockList guest_phys_blocks;
 ArchDumpInfo dump_info;
 MemoryMappingList list;
-uint32_t phdr_num;
-uint32_t shdr_num;
 bool resume;
 bool detached;
-ssize_t note_size;
-hwaddr shdr_offset;
-hwaddr phdr_offset;
-hwaddr section_offset;
-hwaddr note_offset;
 hwaddr memory_offset;
 int fd;
 
@@ -171,6 +164,16 @@ typedef struct DumpState {
 int64_t begin; /* Start address of the chunk we want to dump */
 int64_t length;/* Length of the dump we want to dump */
 
+/* Elf dump related data */
+uint32_t phdr_num;
+uint32_t shdr_num;
+uint32_t sh_info;
+ssize_t note_size;
+hwaddr shdr_offset;
+hwaddr phdr_offset;
+hwaddr note_offset;
+hwaddr section_offset;
+
 void *elf_header;
 void *elf_section_hdrs;
 uint64_t elf_section_data_size;
-- 
2.34.1




[PATCH v2 08/11] s390x: Add protected dump cap

2022-07-13 Thread Janosch Frank
Add a protected dump capability for later feature checking.

Signed-off-by: Janosch Frank 
---
 target/s390x/kvm/kvm.c   | 7 +++
 target/s390x/kvm/kvm_s390x.h | 1 +
 2 files changed, 8 insertions(+)

diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index 7bd8db0e7b..cbd8c91424 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -157,6 +157,7 @@ static int cap_ri;
 static int cap_hpage_1m;
 static int cap_vcpu_resets;
 static int cap_protected;
+static int cap_protected_dump;
 
 static bool mem_op_storage_key_support;
 
@@ -362,6 +363,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ);
 cap_vcpu_resets = kvm_check_extension(s, KVM_CAP_S390_VCPU_RESETS);
 cap_protected = kvm_check_extension(s, KVM_CAP_S390_PROTECTED);
+cap_protected_dump = kvm_check_extension(s, KVM_CAP_S390_PROTECTED_DUMP);
 
 kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0);
 kvm_vm_enable_cap(s, KVM_CAP_S390_VECTOR_REGISTERS, 0);
@@ -2043,6 +2045,11 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier 
*notifier, uint32_t sch,
 return kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
 }
 
+int kvm_s390_get_protected_dump(void)
+{
+return cap_protected_dump;
+}
+
 int kvm_s390_get_ri(void)
 {
 return cap_ri;
diff --git a/target/s390x/kvm/kvm_s390x.h b/target/s390x/kvm/kvm_s390x.h
index 05a5e1e6f4..31a69f9ce2 100644
--- a/target/s390x/kvm/kvm_s390x.h
+++ b/target/s390x/kvm/kvm_s390x.h
@@ -26,6 +26,7 @@ int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state);
 void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu);
 int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu);
 int kvm_s390_get_hpage_1m(void);
+int kvm_s390_get_protected_dump(void);
 int kvm_s390_get_ri(void);
 int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
 int kvm_s390_get_clock_ext(uint8_t *tod_high, uint64_t *tod_clock);
-- 
2.34.1




[PATCH v2 00/11] dump: Add arch section and s390x PV dump

2022-07-13 Thread Janosch Frank
Previously this series was two separate series:
 * Arch section support
   Adds the possibility for arch code to add custom section data.

 * s390 PV dump support
   Adds PV dump data to the custom arch sections.

I've chosen to merge them so it's easier to understand why the arch
section support has been implement the way it is.

Additionally I've added a cleanup patch beforehand which cleans up the
GuestPhysBlock usage.

v2:
* Added "dump: Cleanup memblock usage"
* Fixed whitespace problems and review comments
* Added missing *errp check in dump_end


Janosch Frank (11):
  dump: Cleanup memblock usage
  dump: Allocate header
  dump: Split write of section headers and data and add a prepare step
  dump: Reorder struct DumpState
  dump/dump: Add section string table support
  dump/dump: Add arch section support
  linux header sync
  s390x: Add protected dump cap
  s390x: Introduce PV query interface
  s390x: Add KVM PV dump interface
  s390x: pv: Add dump support

 dump/dump.c  | 443 ++-
 hw/s390x/pv.c| 112 +
 hw/s390x/s390-virtio-ccw.c   |   5 +
 include/elf.h|   1 +
 include/hw/s390x/pv.h|  18 ++
 include/sysemu/dump-arch.h   |  27 +++
 include/sysemu/dump.h|  70 +-
 linux-headers/linux/kvm.h|  55 +
 target/s390x/arch_dump.c | 248 +---
 target/s390x/kvm/kvm.c   |   7 +
 target/s390x/kvm/kvm_s390x.h |   1 +
 11 files changed, 780 insertions(+), 207 deletions(-)

-- 
2.34.1




[PATCH v2 09/11] s390x: Introduce PV query interface

2022-07-13 Thread Janosch Frank
Introduce an interface over which we can get information about UV data.

Signed-off-by: Janosch Frank 
---
 hw/s390x/pv.c  | 61 ++
 hw/s390x/s390-virtio-ccw.c |  5 
 include/hw/s390x/pv.h  | 10 +++
 3 files changed, 76 insertions(+)

diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c
index 401b63d6cb..a5af4ddf46 100644
--- a/hw/s390x/pv.c
+++ b/hw/s390x/pv.c
@@ -20,6 +20,11 @@
 #include "exec/confidential-guest-support.h"
 #include "hw/s390x/ipl.h"
 #include "hw/s390x/pv.h"
+#include "target/s390x/kvm/kvm_s390x.h"
+
+static bool info_valid;
+static struct kvm_s390_pv_info_vm info_vm;
+static struct kvm_s390_pv_info_dump info_dump;
 
 static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
 {
@@ -56,6 +61,42 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, 
void *data)
 }  \
 }
 
+int s390_pv_query_info(void)
+{
+struct kvm_s390_pv_info info = {
+.header.id = KVM_PV_INFO_VM,
+.header.len_max = sizeof(info.header) + sizeof(info.vm),
+};
+int rc;
+
+/* Info API's first user is dump so they are bundled */
+if (!kvm_s390_get_protected_dump()) {
+return 0;
+}
+
+rc = s390_pv_cmd(KVM_PV_INFO, &info);
+if (rc) {
+error_report("KVM PV INFO cmd %x failed: %s",
+ info.header.id, strerror(rc));
+return rc;
+}
+memcpy(&info_vm, &info.vm, sizeof(info.vm));
+
+info.header.id = KVM_PV_INFO_DUMP;
+info.header.len_max = sizeof(info.header) + sizeof(info.dump);
+rc = s390_pv_cmd(KVM_PV_INFO, &info);
+if (rc) {
+error_report("KVM PV INFO cmd %x failed: %s",
+ info.header.id, strerror(rc));
+return rc;
+}
+
+memcpy(&info_dump, &info.dump, sizeof(info.dump));
+info_valid = true;
+
+return rc;
+}
+
 int s390_pv_vm_enable(void)
 {
 return s390_pv_cmd(KVM_PV_ENABLE, NULL);
@@ -114,6 +155,26 @@ void s390_pv_inject_reset_error(CPUState *cs)
 env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV;
 }
 
+uint64_t kvm_s390_pv_dmp_get_size_cpu(void)
+{
+return info_dump.dump_cpu_buffer_len;
+}
+
+uint64_t kvm_s390_pv_dmp_get_size_complete(void)
+{
+return info_dump.dump_config_finalize_len;
+}
+
+uint64_t kvm_s390_pv_dmp_get_size_mem(void)
+{
+return info_dump.dump_config_mem_buffer_per_1m;
+}
+
+bool kvm_s390_pv_info_basic_valid(void)
+{
+return info_valid;
+}
+
 #define TYPE_S390_PV_GUEST "s390-pv-guest"
 OBJECT_DECLARE_SIMPLE_TYPE(S390PVGuest, S390_PV_GUEST)
 
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index cc3097bfee..f9401e392b 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -366,6 +366,11 @@ static int s390_machine_protect(S390CcwMachineState *ms)
 
 ms->pv = true;
 
+rc = s390_pv_query_info();
+if (rc) {
+goto out_err;
+}
+
 /* Set SE header and unpack */
 rc = s390_ipl_prepare_pv_header();
 if (rc) {
diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h
index 1f1f545bfc..6fa55bf70e 100644
--- a/include/hw/s390x/pv.h
+++ b/include/hw/s390x/pv.h
@@ -38,6 +38,7 @@ static inline bool s390_is_pv(void)
 return ccw->pv;
 }
 
+int s390_pv_query_info(void);
 int s390_pv_vm_enable(void);
 void s390_pv_vm_disable(void);
 int s390_pv_set_sec_parms(uint64_t origin, uint64_t length);
@@ -46,8 +47,13 @@ void s390_pv_prep_reset(void);
 int s390_pv_verify(void);
 void s390_pv_unshare(void);
 void s390_pv_inject_reset_error(CPUState *cs);
+uint64_t kvm_s390_pv_dmp_get_size_cpu(void);
+uint64_t kvm_s390_pv_dmp_get_size_mem(void);
+uint64_t kvm_s390_pv_dmp_get_size_complete(void);
+bool kvm_s390_pv_info_basic_valid(void);
 #else /* CONFIG_KVM */
 static inline bool s390_is_pv(void) { return false; }
+static inline int s390_pv_query_info(void) { return 0; }
 static inline int s390_pv_vm_enable(void) { return 0; }
 static inline void s390_pv_vm_disable(void) {}
 static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { 
return 0; }
@@ -56,6 +62,10 @@ static inline void s390_pv_prep_reset(void) {}
 static inline int s390_pv_verify(void) { return 0; }
 static inline void s390_pv_unshare(void) {}
 static inline void s390_pv_inject_reset_error(CPUState *cs) {};
+static inline uint64_t kvm_s390_pv_dmp_get_size_cpu(void) { return 0; }
+static inline uint64_t kvm_s390_pv_dmp_get_size_mem(void) { return 0; }
+static inline uint64_t kvm_s390_pv_dmp_get_size_complete(void) { return 0; }
+static inline bool kvm_s390_pv_info_basic_valid(void) { return false; }
 #endif /* CONFIG_KVM */
 
 int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
-- 
2.34.1




[PATCH] MAINTAINERS: Add myself as Guest Agent co-maintainer

2022-07-13 Thread Konstantin Kostiuk
Signed-off-by: Konstantin Kostiuk 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 450abd0252..22a4ffe0a2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2880,6 +2880,7 @@ T: git https://repo.or.cz/qemu/armbru.git qapi-next
 
 QEMU Guest Agent
 M: Michael Roth 
+M: Konstantin Kostiuk 
 S: Maintained
 F: qga/
 F: docs/interop/qemu-ga.rst
-- 
2.25.1




Re: [RFC v3 3/8] block: pass size to bdrv_unregister_buf()

2022-07-13 Thread Hanna Reitz

On 08.07.22 06:17, Stefan Hajnoczi wrote:

The only implementor of bdrv_register_buf() is block/nvme.c, where the
size is not needed when unregistering a buffer. This is because
util/vfio-helpers.c can look up mappings by address.

Future block drivers that implement bdrv_register_buf() may not be able
to do their job given only the buffer address. Add a size argument to
bdrv_unregister_buf().

Also document the assumptions about
bdrv_register_buf()/bdrv_unregister_buf() calls. The same 
values that were given to bdrv_register_buf() must be given to
bdrv_unregister_buf().

gcc 11.2.1 emits a spurious warning that img_bench()'s buf_size local
variable might be uninitialized, so it's necessary to silence the
compiler.

Signed-off-by: Stefan Hajnoczi 
---
  include/block/block-global-state.h  | 5 -
  include/block/block_int-common.h| 2 +-
  include/sysemu/block-backend-global-state.h | 2 +-
  block/block-backend.c   | 4 ++--
  block/io.c  | 6 +++---
  block/nvme.c| 2 +-
  qemu-img.c  | 4 ++--
  7 files changed, 14 insertions(+), 11 deletions(-)


Reviewed-by: Hanna Reitz 




Re: [PATCH 2/4] Adding multi-interface support for multi-FD on destination side

2022-07-13 Thread Het Gala



On 17/06/22 12:10 am, Dr. David Alan Gilbert wrote:

* Het Gala (het.g...@nutanix.com) wrote:

i) Modified the format of qemu monitor command: ‘migrate-incoming’ by adding
a list, each element in the list is to open listeners with a given number
of multiFD channels.

ii) Qemu starts with -incoming flag defer and -multi-fd-incoming defer to
 allow the modified 'migrate-incoming' command to be used.

iii) Format for -multi-fd-incoming flag as a comma separated string has been
  added with each substring containing listener socket address and number
  of sockets to open.

Suggested-by: Manish Mishra 
Signed-off-by: Het Gala 
---
  include/qapi/util.h   |   1 +
  migration/migration.c | 149 --
  migration/migration.h |   2 +
  migration/socket.c|  11 ++--
  migration/socket.h|   3 +-
  monitor/hmp-cmds.c|  42 
  qapi/migration.json   |  43 ++--
  qapi/qapi-util.c  |  27 
  qemu-options.hx   |  18 +
  softmmu/vl.c  |  30 -
  10 files changed, 265 insertions(+), 61 deletions(-)

diff --git a/include/qapi/util.h b/include/qapi/util.h
index 3041feb3d9..88fb2270db 100644
--- a/include/qapi/util.h
+++ b/include/qapi/util.h
@@ -29,6 +29,7 @@ bool qapi_bool_parse(const char *name, const char *value, 
bool *obj,
   Error **errp);
  
  int parse_qapi_name(const char *name, bool complete);

+struct strList *strList_from_string(const char *in, char c);
  
  /*

   * For any GenericList @list, insert @element at the front.
diff --git a/migration/migration.c b/migration/migration.c
index c408175aeb..9b0ad732e7 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -477,28 +477,39 @@ void migrate_add_address(SocketAddress *address)
QAPI_CLONE(SocketAddress, address));
  }
  
-static void qemu_start_incoming_migration(const char *uri, Error **errp)

+static void qemu_start_incoming_migration(const char *uri, uint8_t number,
+  int idx, Error **errp)
  {
  const char *p = NULL;
  
-migrate_protocol_allow_multi_channels(false); /* reset it anyway */

-qapi_event_send_migration(MIGRATION_STATUS_SETUP);
-if (strstart(uri, "tcp:", &p) ||
-strstart(uri, "unix:", NULL) ||
-strstart(uri, "vsock:", NULL)) {
-migrate_protocol_allow_multi_channels(true);
-socket_start_incoming_migration(p ? p : uri, errp);
-#ifdef CONFIG_RDMA
-} else if (strstart(uri, "rdma:", &p)) {
-rdma_start_incoming_migration(p, errp);
-#endif
-} else if (strstart(uri, "exec:", &p)) {
-exec_start_incoming_migration(p, errp);
-} else if (strstart(uri, "fd:", &p)) {
-fd_start_incoming_migration(p, errp);
+if (number ==  0) {
+migrate_protocol_allow_multi_channels(false); /* reset it anyway */
+qapi_event_send_migration(MIGRATION_STATUS_SETUP);
+if (strstart(uri, "tcp:", &p) ||
+strstart(uri, "unix:", NULL) ||
+strstart(uri, "vsock:", NULL)) {
+migrate_protocol_allow_multi_channels(true);
+#ifdef CONFIG_RDMA
+} else if (strstart(uri, "rdma:", &p)) {
+rdma_start_incoming_migration(p, errp);
+#endif
+} else if (strstart(uri, "exec:", &p)) {
+exec_start_incoming_migration(p, errp);
+} else if (strstart(uri, "fd:", &p)) {
+fd_start_incoming_migration(p, errp);
+} else {
+error_setg(errp, "unknown migration protocol: %s", uri);
+}
  } else {
-error_setg(errp, "unknown migration protocol: %s", uri);
+/* multi-FD parameters only support tcp network protocols */
+if (!strstart(uri, "tcp:", &p)) {
+error_setg(errp, "multifd-destination uri supports "
+"tcp protocol only");
+return;
+}
+store_multifd_migration_params(p ? p : uri, NULL, number, idx, errp);
  }
+socket_start_incoming_migration(p ? p : uri, number, errp);
  }
  
  static void process_incoming_migration_bh(void *opaque)

@@ -2140,7 +2151,17 @@ void migrate_del_blocker(Error *reason)
  migration_blockers = g_slist_remove(migration_blockers, reason);
  }
  
-void qmp_migrate_incoming(const char *uri, Error **errp)

+static inline int incoming_multi_fd_uri_parse(const char *str, char delim)
+{
+int count = 0;
+for (int i = 0; i < strlen(str); i++) {
+count += (str[i] == delim);
+}
+return count;
+}

That's a bit more general little helper function; I guess it could go in
util/ somewhere (something like qemu_string_count_delim ???)


> Yes David, I will include this helper function in util folder, in the 
same patch


with all other helper functions I am trying to include.




+/* migrate_incoming comes from -incoming flag in qemu process */
+void migrate_incoming(const char *uri, Error **errp)
  {
  Error *local_err = N

Re: [PATCH v8 02/12] s390x/cpu_topology: CPU topology objects and structures

2022-07-13 Thread Pierre Morel




On 7/12/22 17:40, Janis Schoetterl-Glausch wrote:

On 6/20/22 16:03, Pierre Morel wrote:

We use new objects to have a dynamic administration of the CPU topology.
The highest level object in this implementation is the s390 book and
in this first implementation of CPU topology for S390 we have a single
book.
The book is built as a SYSBUS bridge during the CPU initialization.
Other objects, sockets and core will be built after the parsing
of the QEMU -smp argument.

Every object under this single book will be build dynamically
immediately after a CPU has be realized if it is needed.
The CPU will fill the sockets once after the other, according to the
number of core per socket defined during the smp parsing.

Each CPU inside a socket will be represented by a bit in a 64bit
unsigned long. Set on plug and clear on unplug of a CPU.

For the S390 CPU topology, thread and cores are merged into
topology cores and the number of topology cores is the multiplication
of cores by the numbers of threads.

Signed-off-by: Pierre Morel 
---
  hw/s390x/cpu-topology.c | 391 
  hw/s390x/meson.build|   1 +
  hw/s390x/s390-virtio-ccw.c  |   6 +
  include/hw/s390x/cpu-topology.h |  74 ++
  target/s390x/cpu.h  |  47 
  5 files changed, 519 insertions(+)
  create mode 100644 hw/s390x/cpu-topology.c
  create mode 100644 include/hw/s390x/cpu-topology.h

diff --git a/hw/s390x/cpu-topology.c b/hw/s390x/cpu-topology.c
new file mode 100644
index 00..0fd6f08084
--- /dev/null
+++ b/hw/s390x/cpu-topology.c
@@ -0,0 +1,391 @@
+/*
+ * CPU Topology
+ *
+ * Copyright 2022 IBM Corp.


Should be Copyright IBM Corp. 2022, and maybe even have a year range.


OK




+ * Author(s): Pierre Morel 
+
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "hw/s390x/cpu-topology.h"
+#include "hw/qdev-properties.h"
+#include "hw/boards.h"
+#include "qemu/typedefs.h"
+#include "target/s390x/cpu.h"
+#include "hw/s390x/s390-virtio-ccw.h"
+
+/*
+ * s390_create_cores:
+ * @ms: Machine state
+ * @socket: the socket on which to create the core set
+ * @origin: the origin offset of the first core of the set
+ * @errp: Error pointer
+ *
+ * returns a pointer to the created S390TopologyCores structure
+ *
+ * On error: return NULL
+ */
+static S390TopologyCores *s390_create_cores(MachineState *ms,
+S390TopologySocket *socket,
+int origin, Error **errp)
+{
+DeviceState *dev;
+S390TopologyCores *cores;
+
+if (socket->bus->num_children >= ms->smp.cores * ms->smp.threads) {
+error_setg(errp, "Unable to create more cores.");
+return NULL;
+}


Why/How can this happen?
The "location" of the CPU is a function of core_id and the same CPU should not 
be added twice.
If it's to enforce a limit on the smp arguments that should happen earlier in 
my opinion.
If it's necessary, you could also make the message more verbose and add ", maximum 
number reached".


should not happen.


+
+dev = qdev_new(TYPE_S390_TOPOLOGY_CORES);
+qdev_realize_and_unref(dev, socket->bus, &error_fatal);


As a result of this, the order of cores in the socket bus is the creation 
order, correct?
So newest first and not ordered by the origin (since we can hot plug CPUs), 
correct?


yes


+
+cores = S390_TOPOLOGY_CORES(dev);
+cores->origin = origin;


I must admit that I haven't fully grokked the qemu object model, yet, but I'd 
be more comfortable
if you unref'ed cores after you set the origin.
Does the socket bus own the object after you unref it? Does it then make sense 
to return cores
after unref'ing it?


AFAIU yes the bus owns it.


But then we don't support CPU unplug, so the object shouldn't just vanish.


+socket->cnt += 1;


cnt++ to be consistent with create_socket below.


OK


+
+return cores;
+}
+
+/*
+ * s390_create_socket:
+ * @ms: Machine state
+ * @book: the book on which to create the socket
+ * @id: the socket id
+ * @errp: Error pointer
+ *
+ * returns a pointer to the created S390TopologySocket structure
+ *
+ * On error: return NULL
+ */
+static S390TopologySocket *s390_create_socket(MachineState *ms,
+  S390TopologyBook *book,
+  int id, Error **errp)
+{


Same questions/comments as above.


Same answer, should not happen.
I will remove the check.




+DeviceState *dev;
+S390TopologySocket *socket;
+
+if (book->bus->num_children >= ms->smp.sockets) {
+error_setg(errp, "Unable to create more sockets.");
+return NULL;
+}
+
+dev = qdev_new(TYPE_S390_TOPOLOGY_SOCKET);
+qdev_realize_and_unref(dev, book->

Re: [PATCH v2 01/11] dump: Cleanup memblock usage

2022-07-13 Thread Marc-André Lureau
Hi

On Wed, Jul 13, 2022 at 5:07 PM Janosch Frank  wrote:
>
> The iteration over the memblocks is hard to understand so it's about
> time to clean it up.
>
> struct DumpState's next_block and start members can and should be
> local variables within the iterator.
>
> Instead of manually grabbing the next memblock we can use
> QTAILQ_FOREACH to iterate over all memblocks.
>
> The begin and length fields in the DumpState have been left untouched
> since the qmp arguments share their names.
>
> Signed-off-by: Janosch Frank 

After this patch:
./qemu-system-x86_64 -monitor stdio -S
(qemu) dump-guest-memory foo
Error: dump: failed to save memory: Bad address


> ---
>  dump/dump.c   | 91 +++
>  include/sysemu/dump.h | 47 +++---
>  2 files changed, 65 insertions(+), 73 deletions(-)
>
> diff --git a/dump/dump.c b/dump/dump.c
> index 4d9658ffa2..6feba3cbfa 100644
> --- a/dump/dump.c
> +++ b/dump/dump.c
> @@ -591,56 +591,27 @@ static void dump_begin(DumpState *s, Error **errp)
>  write_elf_notes(s, errp);
>  }
>
> -static int get_next_block(DumpState *s, GuestPhysBlock *block)
> -{
> -while (1) {
> -block = QTAILQ_NEXT(block, next);
> -if (!block) {
> -/* no more block */
> -return 1;
> -}
> -
> -s->start = 0;
> -s->next_block = block;
> -if (s->has_filter) {
> -if (block->target_start >= s->begin + s->length ||
> -block->target_end <= s->begin) {
> -/* This block is out of the range */
> -continue;
> -}
> -
> -if (s->begin > block->target_start) {
> -s->start = s->begin - block->target_start;
> -}
> -}
> -
> -return 0;
> -}
> -}
> -
>  /* write all memory to vmcore */
>  static void dump_iterate(DumpState *s, Error **errp)
>  {
>  ERRP_GUARD();
>  GuestPhysBlock *block;
> -int64_t size;
> +int64_t memblock_size, memblock_start;
>
> -do {
> -block = s->next_block;
> -
> -size = block->target_end - block->target_start;
> -if (s->has_filter) {
> -size -= s->start;
> -if (s->begin + s->length < block->target_end) {
> -size -= block->target_end - (s->begin + s->length);
> -}
> +QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
> +memblock_start = dump_get_memblock_start(block, s->begin, s->length);
> +if (memblock_start == -1) {
> +continue;
>  }
> -write_memory(s, block, s->start, size, errp);
> +
> +memblock_size = dump_get_memblock_size(block, s->begin, s->length);
> +
> +/* Write the memory to file */
> +write_memory(s, block, memblock_start, memblock_size, errp);
>  if (*errp) {
>  return;
>  }
> -
> -} while (!get_next_block(s, block));
> +}
>  }
>
>  static void create_vmcore(DumpState *s, Error **errp)
> @@ -1490,30 +1461,22 @@ static void create_kdump_vmcore(DumpState *s, Error 
> **errp)
>  }
>  }
>
> -static ram_addr_t get_start_block(DumpState *s)
> +static int validate_start_block(DumpState *s)
>  {
>  GuestPhysBlock *block;
>
>  if (!s->has_filter) {
> -s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
>  return 0;
>  }
>
>  QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
> +/* This block is out of the range */
>  if (block->target_start >= s->begin + s->length ||
>  block->target_end <= s->begin) {
> -/* This block is out of the range */
>  continue;
>  }
> -
> -s->next_block = block;
> -if (s->begin > block->target_start) {
> -s->start = s->begin - block->target_start;
> -} else {
> -s->start = 0;
> -}
> -return s->start;
> -}
> +return 0;
> +   }
>
>  return -1;
>  }
> @@ -1540,25 +1503,17 @@ bool qemu_system_dump_in_progress(void)
>  return (qatomic_read(&state->status) == DUMP_STATUS_ACTIVE);
>  }
>
> -/* calculate total size of memory to be dumped (taking filter into
> - * acoount.) */
> +/*
> + * calculate total size of memory to be dumped (taking filter into
> + * account.)

thanks for fixing the typo

> + */
>  static int64_t dump_calculate_size(DumpState *s)
>  {
>  GuestPhysBlock *block;
> -int64_t size = 0, total = 0, left = 0, right = 0;
> +int64_t total = 0;
>
>  QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
> -if (s->has_filter) {
> -/* calculate the overlapped region. */
> -left = MAX(s->begin, block->target_start);
> -right = MIN(s->begin + s->length, block->target_end);
> -size = right - left;
> -size = size > 0 ? size : 0;
> -} else {
> -/* count the whole region in */
> -size = (block->ta

Re: [PATCH v2 02/11] dump: Allocate header

2022-07-13 Thread Marc-André Lureau
On Wed, Jul 13, 2022 at 5:07 PM Janosch Frank  wrote:
>
> Allocating the header lets us write it at a later time and hence also
> allows us to change section and segment table offsets until we
> finally write it.
>
> Signed-off-by: Janosch Frank 

Reviewed-by: Marc-André Lureau 


> ---
>  dump/dump.c   | 127 +-
>  include/sysemu/dump.h |   1 +
>  2 files changed, 64 insertions(+), 64 deletions(-)
>
> diff --git a/dump/dump.c b/dump/dump.c
> index 6feba3cbfa..16d7474258 100644
> --- a/dump/dump.c
> +++ b/dump/dump.c
> @@ -98,6 +98,7 @@ static int dump_cleanup(DumpState *s)
>  memory_mapping_list_free(&s->list);
>  close(s->fd);
>  g_free(s->guest_note);
> +g_free(s->elf_header);
>  s->guest_note = NULL;
>  if (s->resume) {
>  if (s->detached) {
> @@ -126,73 +127,49 @@ static int fd_write_vmcore(const void *buf, size_t 
> size, void *opaque)
>  return 0;
>  }
>
> -static void write_elf64_header(DumpState *s, Error **errp)
> +static void prepare_elf64_header(DumpState *s)
>  {
> -/*
> - * phnum in the elf header is 16 bit, if we have more segments we
> - * set phnum to PN_XNUM and write the real number of segments to a
> - * special section.
> - */
> -uint16_t phnum = MIN(s->phdr_num, PN_XNUM);
> -Elf64_Ehdr elf_header;
> -int ret;
> +uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num;
> +Elf64_Ehdr *elf_header = s->elf_header;
>
> -memset(&elf_header, 0, sizeof(Elf64_Ehdr));
> -memcpy(&elf_header, ELFMAG, SELFMAG);
> -elf_header.e_ident[EI_CLASS] = ELFCLASS64;
> -elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
> -elf_header.e_ident[EI_VERSION] = EV_CURRENT;
> -elf_header.e_type = cpu_to_dump16(s, ET_CORE);
> -elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
> -elf_header.e_version = cpu_to_dump32(s, EV_CURRENT);
> -elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
> -elf_header.e_phoff = cpu_to_dump64(s, s->phdr_offset);
> -elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
> -elf_header.e_phnum = cpu_to_dump16(s, phnum);
> +memcpy(elf_header, ELFMAG, SELFMAG);
> +elf_header->e_ident[EI_CLASS] = ELFCLASS64;
> +elf_header->e_ident[EI_DATA] = s->dump_info.d_endian;
> +elf_header->e_ident[EI_VERSION] = EV_CURRENT;
> +elf_header->e_type = cpu_to_dump16(s, ET_CORE);
> +elf_header->e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
> +elf_header->e_version = cpu_to_dump32(s, EV_CURRENT);
> +elf_header->e_ehsize = cpu_to_dump16(s, sizeof(*elf_header));
> +elf_header->e_phoff = cpu_to_dump64(s, s->phdr_offset);
> +elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
> +elf_header->e_phnum = cpu_to_dump16(s, phnum);
>  if (s->shdr_num) {
> -elf_header.e_shoff = cpu_to_dump64(s, s->shdr_offset);
> -elf_header.e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr));
> -elf_header.e_shnum = cpu_to_dump16(s, s->shdr_num);
> -}
> -
> -ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
> -if (ret < 0) {
> -error_setg_errno(errp, -ret, "dump: failed to write elf header");
> +elf_header->e_shoff = cpu_to_dump64(s, s->shdr_offset);
> +elf_header->e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr));
> +elf_header->e_shnum = cpu_to_dump16(s, s->shdr_num);
>  }
>  }
>
> -static void write_elf32_header(DumpState *s, Error **errp)
> +static void prepare_elf32_header(DumpState *s)
>  {
> -/*
> - * phnum in the elf header is 16 bit, if we have more segments we
> - * set phnum to PN_XNUM and write the real number of segments to a
> - * special section.
> - */
> -uint16_t phnum = MIN(s->phdr_num, PN_XNUM);
> -Elf32_Ehdr elf_header;
> -int ret;
> +uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num;
> +Elf32_Ehdr *elf_header = s->elf_header;
>
> -memset(&elf_header, 0, sizeof(Elf32_Ehdr));
> -memcpy(&elf_header, ELFMAG, SELFMAG);
> -elf_header.e_ident[EI_CLASS] = ELFCLASS32;
> -elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
> -elf_header.e_ident[EI_VERSION] = EV_CURRENT;
> -elf_header.e_type = cpu_to_dump16(s, ET_CORE);
> -elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
> -elf_header.e_version = cpu_to_dump32(s, EV_CURRENT);
> -elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
> -elf_header.e_phoff = cpu_to_dump32(s, s->phdr_offset);
> -elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf32_Phdr));
> -elf_header.e_phnum = cpu_to_dump16(s, phnum);
> +memcpy(elf_header, ELFMAG, SELFMAG);
> +elf_header->e_ident[EI_CLASS] = ELFCLASS32;
> +elf_header->e_ident[EI_DATA] = s->dump_info.d_endian;
> +elf_header->e_ident[EI_VERSION] = EV_CURRENT;
> +elf_header->e_type = cpu_to_dump16(s, ET_CORE);
> +elf_header->e_machine = cpu_to_dump

Re: [PATCH v2 01/11] dump: Cleanup memblock usage

2022-07-13 Thread Janosch Frank

On 7/13/22 17:09, Marc-André Lureau wrote:

Hi

On Wed, Jul 13, 2022 at 5:07 PM Janosch Frank  wrote:


The iteration over the memblocks is hard to understand so it's about
time to clean it up.

struct DumpState's next_block and start members can and should be
local variables within the iterator.

Instead of manually grabbing the next memblock we can use
QTAILQ_FOREACH to iterate over all memblocks.

The begin and length fields in the DumpState have been left untouched
since the qmp arguments share their names.

Signed-off-by: Janosch Frank 


After this patch:
./qemu-system-x86_64 -monitor stdio -S
(qemu) dump-guest-memory foo
Error: dump: failed to save memory: Bad address


If you have more ways to check for dump errors then please send them to 
me. I'm aware that this might not have been a 100% conversion and I'm a 
bit terrified about the fact that this will affect all architectures.



Anyway, I'll have a look.

[...]


+static inline int64_t dump_get_memblock_start(GuestPhysBlock *block, int64_t 
filter_area_start,
+  int64_t filter_area_length)
+{
+if (filter_area_length) {
+/*
+ * Check if block is within guest memory dump area. If not
+ * go to next one.
+ */


Or rather "return -1 if the block is not within filter area"


Sure




+if (block->target_start >= filter_area_start + filter_area_length ||
+block->target_end <= filter_area_start) {
+return -1;
+}
+if (filter_area_start > block->target_start) {
+return filter_area_start - block->target_start;
+}
+}
+return block->target_start;


This used to be 0. Changing that, I think the patch looks good.
Although it could perhaps be splitted to introduce the two functions.


Yes but the 0 was used to indicate that we would have needed continue 
iterating and the iteration is done via other means in this patch.


Or am I missing something?




+}
  #endif
--
2.34.1








Re: [PATCH v2 03/11] dump: Split write of section headers and data and add a prepare step

2022-07-13 Thread Marc-André Lureau
Hi

On Wed, Jul 13, 2022 at 5:07 PM Janosch Frank  wrote:
>
> By splitting the writing of the section headers and (future) section
> data we prepare for the addition of a string table section and
> architecture sections.
>
> Signed-off-by: Janosch Frank 
> ---
>  dump/dump.c   | 116 --
>  include/sysemu/dump.h |   4 ++
>  2 files changed, 94 insertions(+), 26 deletions(-)
>
> diff --git a/dump/dump.c b/dump/dump.c
> index 16d7474258..467d934bc1 100644
> --- a/dump/dump.c
> +++ b/dump/dump.c
> @@ -342,30 +342,73 @@ static void write_elf_phdr_note(DumpState *s, Error 
> **errp)
>  }
>  }
>
> -static void write_elf_section(DumpState *s, int type, Error **errp)
> +static size_t write_elf_section_hdr_zero(DumpState *s, void *buff)

Since the function no longer write, I'd suggest to rename it with
prepare_ prefix

>  {
> -Elf32_Shdr shdr32;
> -Elf64_Shdr shdr64;
> -int shdr_size;
> -void *shdr;
> -int ret;
> +if (dump_is_64bit(s)) {
> +Elf64_Shdr *shdr64 = buff;
>
> -if (type == 0) {
> -shdr_size = sizeof(Elf32_Shdr);
> -memset(&shdr32, 0, shdr_size);
> -shdr32.sh_info = cpu_to_dump32(s, s->phdr_num);
> -shdr = &shdr32;
> +memset(buff, 0, sizeof(Elf64_Shdr));

You can drop this

> +shdr64->sh_info = cpu_to_dump32(s, s->phdr_num);
>  } else {
> -shdr_size = sizeof(Elf64_Shdr);
> -memset(&shdr64, 0, shdr_size);
> -shdr64.sh_info = cpu_to_dump32(s, s->phdr_num);
> -shdr = &shdr64;
> +Elf32_Shdr *shdr32 = buff;
> +
> +memset(buff, 0, sizeof(Elf32_Shdr));

and this

> +shdr32->sh_info = cpu_to_dump32(s, s->phdr_num);
>  }
>
> -ret = fd_write_vmcore(shdr, shdr_size, s);
> +return dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
> +}
> +
> +static void prepare_elf_section_hdrs(DumpState *s)
> +{
> +uint8_t *buff_hdr;
> +size_t len, sizeof_shdr;
> +
> +/*
> + * Section ordering:
> + * - HDR zero (if needed)
> + */
> +sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
> +len = sizeof_shdr * s->shdr_num;
> +s->elf_section_hdrs = g_malloc0(len);

since you alloc0 here

> +buff_hdr = s->elf_section_hdrs;
> +
> +/* Write special section first */
> +if (s->phdr_num == PN_XNUM) {
> +write_elf_section_hdr_zero(s, buff_hdr);

Eventually, drop buff_hdr, and pass only "s" as argument

+ Indentation is off

> +}
> +}
> +
> +static void prepare_elf_sections(DumpState *s, Error **errp)
> +{
> +if (!s->shdr_num) {
> +return;
> +}
> +
> +prepare_elf_section_hdrs(s);
> +}
> +
> +static void write_elf_section_headers(DumpState *s, Error **errp)
> +{
> +size_t sizeof_shdr;
> +int ret;
> +
> +sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
> +
> +ret = fd_write_vmcore(s->elf_section_hdrs, s->shdr_num * sizeof_shdr, s);
>  if (ret < 0) {
> -error_setg_errno(errp, -ret,
> - "dump: failed to write section header table");
> +error_setg_errno(errp, -ret, "dump: failed to write section data");

nit: data->header


> +}
> +}
> +
> +static void write_elf_sections(DumpState *s, Error **errp)
> +{
> +int ret;
> +
> +/* Write section zero */
> +ret = fd_write_vmcore(s->elf_section_data, s->elf_section_data_size, s);
> +if (ret < 0) {
> +error_setg_errno(errp, -ret, "dump: failed to write section data");
>  }
>  }
>
> @@ -557,12 +600,22 @@ static void dump_begin(DumpState *s, Error **errp)
>  /* Write elf header to buffer */
>  prepare_elf_header(s);
>
> +prepare_elf_sections(s, errp);
> +if (*errp) {
> +return;
> +}
> +
>  /* Start to write stuff into files*/
>  write_elf_header(s, errp);
>  if (*errp) {
>  return;
>  }
>
> +write_elf_section_headers(s, errp);

Why do you reorder the sections? Could you explain in the commit
message why? Is this is format compliant? and update the comment
above? thanks

> +if (*errp) {
> +return;
> +}
> +
>  /* write PT_NOTE to vmcore */
>  write_elf_phdr_note(s, errp);
>  if (*errp) {
> @@ -575,14 +628,6 @@ static void dump_begin(DumpState *s, Error **errp)
>  return;
>  }
>
> -/* write section to vmcore */
> -if (s->shdr_num) {
> -write_elf_section(s, 1, errp);
> -if (*errp) {
> -return;
> -}
> -}
> -
>  /* write notes to vmcore */
>  write_elf_notes(s, errp);
>  }
> @@ -610,6 +655,19 @@ static void dump_iterate(DumpState *s, Error **errp)
>  }
>  }
>
> +static void dump_end(DumpState *s, Error **errp)
> +{
> +ERRP_GUARD();
> +
> +if (!s->elf_section_data_size) {
> +return;
> +}
> +s->elf_section_data = g_malloc0(s->elf_section_data_size);
> +
> +/* write sections to vmcore */
> +write_elf_secti

Re: [PATCH v2 01/11] dump: Cleanup memblock usage

2022-07-13 Thread Marc-André Lureau
Hi

On Wed, Jul 13, 2022 at 7:30 PM Janosch Frank  wrote:
>
> On 7/13/22 17:09, Marc-André Lureau wrote:
> > Hi
> >
> > On Wed, Jul 13, 2022 at 5:07 PM Janosch Frank  wrote:
> >>
> >> The iteration over the memblocks is hard to understand so it's about
> >> time to clean it up.
> >>
> >> struct DumpState's next_block and start members can and should be
> >> local variables within the iterator.
> >>
> >> Instead of manually grabbing the next memblock we can use
> >> QTAILQ_FOREACH to iterate over all memblocks.
> >>
> >> The begin and length fields in the DumpState have been left untouched
> >> since the qmp arguments share their names.
> >>
> >> Signed-off-by: Janosch Frank 
> >
> > After this patch:
> > ./qemu-system-x86_64 -monitor stdio -S
> > (qemu) dump-guest-memory foo
> > Error: dump: failed to save memory: Bad address
>
> If you have more ways to check for dump errors then please send them to
> me. I'm aware that this might not have been a 100% conversion and I'm a
> bit terrified about the fact that this will affect all architectures.

Same feeling here. Maybe it's about time to write real dump tests!

>
>
> Anyway, I'll have a look.
>
> [...]
>
> >> +static inline int64_t dump_get_memblock_start(GuestPhysBlock *block, 
> >> int64_t filter_area_start,
> >> +  int64_t filter_area_length)
> >> +{
> >> +if (filter_area_length) {
> >> +/*
> >> + * Check if block is within guest memory dump area. If not
> >> + * go to next one.
> >> + */
> >
> > Or rather "return -1 if the block is not within filter area"
>
> Sure
>
> >
> >> +if (block->target_start >= filter_area_start + filter_area_length 
> >> ||
> >> +block->target_end <= filter_area_start) {
> >> +return -1;
> >> +}
> >> +if (filter_area_start > block->target_start) {
> >> +return filter_area_start - block->target_start;
> >> +}
> >> +}
> >> +return block->target_start;
> >
> > This used to be 0. Changing that, I think the patch looks good.
> > Although it could perhaps be splitted to introduce the two functions.
>
> Yes but the 0 was used to indicate that we would have needed continue
> iterating and the iteration is done via other means in this patch.
>
> Or am I missing something?

Well, you changed the way the loop used to work. it used to return 1/0
to indicate stop/continue and rely on s->start / s->next_block. Now
you return memblock_start.

>
> >
> >> +}
> >>   #endif
> >> --
> >> 2.34.1
> >>
> >
> >
>




Re: [PATCH v3] multifd: Copy pages before compressing them with zlib

2022-07-13 Thread Dr. David Alan Gilbert
* Ilya Leoshkevich (i...@linux.ibm.com) wrote:
> zlib_send_prepare() compresses pages of a running VM. zlib does not
> make any thread-safety guarantees with respect to changing deflate()
> input concurrently with deflate() [1].
> 
> One can observe problems due to this with the IBM zEnterprise Data
> Compression accelerator capable zlib [2]. When the hardware
> acceleration is enabled, migration/multifd/tcp/plain/zlib test fails
> intermittently [3] due to sliding window corruption. The accelerator's
> architecture explicitly discourages concurrent accesses [4]:
> 
> Page 26-57, "Other Conditions":
> 
> As observed by this CPU, other CPUs, and channel
> programs, references to the parameter block, first,
> second, and third operands may be multiple-access
> references, accesses to these storage locations are
> not necessarily block-concurrent, and the sequence
> of these accesses or references is undefined.
> 
> Mark Adler pointed out that vanilla zlib performs double fetches under
> certain circumstances as well [5], therefore we need to copy data
> before passing it to deflate().
> 
> [1] https://zlib.net/manual.html
> [2] https://github.com/madler/zlib/pull/410
> [3] https://lists.nongnu.org/archive/html/qemu-devel/2022-03/msg03988.html
> [4] http://publibfp.dhe.ibm.com/epubs/pdf/a227832c.pdf
> [5] https://lists.gnu.org/archive/html/qemu-devel/2022-07/msg00889.html
> 
> Signed-off-by: Ilya Leoshkevich 

Thanks!


Reviewed-by: Dr. David Alan Gilbert 

> ---
> 
> v1: https://lists.gnu.org/archive/html/qemu-devel/2022-03/msg06841.html
> v1 -> v2: Rebase, mention Mark Adler's reply in the commit message.
> 
> v2: https://lists.gnu.org/archive/html/qemu-devel/2022-07/msg00627.html
> v2 -> v3: Get rid of pointer maths (David).
>   Use a more relevant link to Mark Adler's comment (Peter).
> 
>  migration/multifd-zlib.c | 38 ++
>  1 file changed, 30 insertions(+), 8 deletions(-)
> 
> diff --git a/migration/multifd-zlib.c b/migration/multifd-zlib.c
> index 3a7ae44485..18213a9513 100644
> --- a/migration/multifd-zlib.c
> +++ b/migration/multifd-zlib.c
> @@ -27,6 +27,8 @@ struct zlib_data {
>  uint8_t *zbuff;
>  /* size of compressed buffer */
>  uint32_t zbuff_len;
> +/* uncompressed buffer of size qemu_target_page_size() */
> +uint8_t *buf;
>  };
>  
>  /* Multifd zlib compression */
> @@ -45,26 +47,38 @@ static int zlib_send_setup(MultiFDSendParams *p, Error 
> **errp)
>  {
>  struct zlib_data *z = g_new0(struct zlib_data, 1);
>  z_stream *zs = &z->zs;
> +const char *err_msg;
>  
>  zs->zalloc = Z_NULL;
>  zs->zfree = Z_NULL;
>  zs->opaque = Z_NULL;
>  if (deflateInit(zs, migrate_multifd_zlib_level()) != Z_OK) {
> -g_free(z);
> -error_setg(errp, "multifd %u: deflate init failed", p->id);
> -return -1;
> +err_msg = "deflate init failed";
> +goto err_free_z;
>  }
>  /* This is the maxium size of the compressed buffer */
>  z->zbuff_len = compressBound(MULTIFD_PACKET_SIZE);
>  z->zbuff = g_try_malloc(z->zbuff_len);
>  if (!z->zbuff) {
> -deflateEnd(&z->zs);
> -g_free(z);
> -error_setg(errp, "multifd %u: out of memory for zbuff", p->id);
> -return -1;
> +err_msg = "out of memory for zbuff";
> +goto err_deflate_end;
> +}
> +z->buf = g_try_malloc(qemu_target_page_size());
> +if (!z->buf) {
> +err_msg = "out of memory for buf";
> +goto err_free_zbuff;
>  }
>  p->data = z;
>  return 0;
> +
> +err_free_zbuff:
> +g_free(z->zbuff);
> +err_deflate_end:
> +deflateEnd(&z->zs);
> +err_free_z:
> +g_free(z);
> +error_setg(errp, "multifd %u: %s", p->id, err_msg);
> +return -1;
>  }
>  
>  /**
> @@ -82,6 +96,8 @@ static void zlib_send_cleanup(MultiFDSendParams *p, Error 
> **errp)
>  deflateEnd(&z->zs);
>  g_free(z->zbuff);
>  z->zbuff = NULL;
> +g_free(z->buf);
> +z->buf = NULL;
>  g_free(p->data);
>  p->data = NULL;
>  }
> @@ -114,8 +130,14 @@ static int zlib_send_prepare(MultiFDSendParams *p, Error 
> **errp)
>  flush = Z_SYNC_FLUSH;
>  }
>  
> +/*
> + * Since the VM might be running, the page may be changing 
> concurrently
> + * with compression. zlib does not guarantee that this is safe,
> + * therefore copy the page before calling deflate().
> + */
> +memcpy(z->buf, p->pages->block->host + p->normal[i], page_size);
>  zs->avail_in = page_size;
> -zs->next_in = p->pages->block->host + p->normal[i];
> +zs->next_in = z->buf;
>  
>  zs->avail_out = available;
>  zs->next_out = z->zbuff + out_size;
> -- 
> 2.35.3
> 
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




Re: [PATCH 3/3] tests/tcg/s390x: test signed vfmin/vfmax

2022-07-13 Thread Richard Henderson

On 7/12/22 18:02, Ilya Leoshkevich wrote:

This works, of course.  It could be simpler using EXECUTE, to store
just the one
instruction and not worry about an executable mapped page, but I
guess it doesn't matter.


I thought about this too, but EX/EXRL operate only on the second byte,
and I need to modify bytes 3-5 here.


I didn't mean modify the instruction via EX, but something like

  static char minmax[6] __attribute__((aligned(2)))
= { xx, yy, zz, 0, 0, 0 };

  minmax[3] = m6 ...
  minmax[4] = ...
  minmax[5] = op;

  asm("vl %%v25,0(%1)\n"
  "vl %%v26,0(%2)\n"
  "ex 0,0(%3)\n"
  "vst %%v24,0(%0)"
  : : "a"(v1), "a"(v2), "a"(v3), "a"(minmax)
  : "memory", "v24", "v25", "v26);


r~



Re: [PATCH v2 04/11] dump: Reorder struct DumpState

2022-07-13 Thread Marc-André Lureau
On Wed, Jul 13, 2022 at 5:07 PM Janosch Frank  wrote:
>
> Let's move ELF related members into one block and guest memory related
> ones into another to improve readability.
>
> Signed-off-by: Janosch Frank 
> Reviewed-by: Richard Henderson 

Reviewed-by: Marc-André Lureau 

> ---
>  include/sysemu/dump.h | 17 ++---
>  1 file changed, 10 insertions(+), 7 deletions(-)
>
> diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
> index bd49532232..8379e29ef6 100644
> --- a/include/sysemu/dump.h
> +++ b/include/sysemu/dump.h
> @@ -154,15 +154,8 @@ typedef struct DumpState {
>  GuestPhysBlockList guest_phys_blocks;
>  ArchDumpInfo dump_info;
>  MemoryMappingList list;
> -uint32_t phdr_num;
> -uint32_t shdr_num;
>  bool resume;
>  bool detached;
> -ssize_t note_size;
> -hwaddr shdr_offset;
> -hwaddr phdr_offset;
> -hwaddr section_offset;
> -hwaddr note_offset;
>  hwaddr memory_offset;
>  int fd;
>
> @@ -171,6 +164,16 @@ typedef struct DumpState {
>  int64_t begin; /* Start address of the chunk we want to dump 
> */
>  int64_t length;/* Length of the dump we want to dump */
>
> +/* Elf dump related data */
> +uint32_t phdr_num;
> +uint32_t shdr_num;
> +uint32_t sh_info;
> +ssize_t note_size;
> +hwaddr shdr_offset;
> +hwaddr phdr_offset;
> +hwaddr note_offset;
> +hwaddr section_offset;
> +
>  void *elf_header;
>  void *elf_section_hdrs;
>  uint64_t elf_section_data_size;
> --
> 2.34.1
>




Re: [PATCH v2] memory: prevent dma-reentracy issues

2022-07-13 Thread Alexander Bulekov
On 220712 1034, Stefan Hajnoczi wrote:
> On Tue, Jun 21, 2022 at 11:53:06AM -0400, Alexander Bulekov wrote:
> > On 220621 1630, Peter Maydell wrote:
> > > On Thu, 9 Jun 2022 at 14:59, Alexander Bulekov  wrote:
> > > > diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> > > > index 44dacfa224..ab1ad0f7a8 100644
> > > > --- a/include/hw/pci/pci.h
> > > > +++ b/include/hw/pci/pci.h
> > > > @@ -834,8 +834,17 @@ static inline MemTxResult pci_dma_rw(PCIDevice 
> > > > *dev, dma_addr_t addr,
> > > >   void *buf, dma_addr_t len,
> > > >   DMADirection dir, MemTxAttrs 
> > > > attrs)
> > > >  {
> > > > -return dma_memory_rw(pci_get_address_space(dev), addr, buf, len,
> > > > - dir, attrs);
> > > > +bool prior_engaged_state;
> > > > +MemTxResult result;
> > > > +
> > > > +prior_engaged_state = dev->qdev.engaged_in_io;
> > > > +
> > > > +dev->qdev.engaged_in_io = true;
> > > > +result = dma_memory_rw(pci_get_address_space(dev), addr, buf, len,
> > > > +   dir, attrs);
> > > > +dev->qdev.engaged_in_io = prior_engaged_state;
> > > > +
> > > > +return result;
> > > 
> > > Why do we need to do something in this pci-specific function ?
> > > I was expecting this to only need changes at the generic-to-all-devices
> > > level.
> > 
> > Both of these handle the BH->DMA->MMIO case. Unlike MMIO, I don't think
> > there is any neat way to set the engaged_in_io flag as we enter a BH. So
> > instead, we try to set it when a device initiates DMA.
> > 
> > The pci function lets us do that since we get a glimpse of the dev/qdev
> > (unlike the dma_memory_...  functions).
> ...
> > > > @@ -302,6 +310,10 @@ static MemTxResult dma_buf_rw(void *buf, 
> > > > dma_addr_t len, dma_addr_t *residual,
> > > >  xresidual -= xfer;
> > > >  }
> > > >
> > > > +if (dev) {
> > > > +dev->engaged_in_io = prior_engaged_state;
> > > > +}
> > > 
> > > Not all DMA goes through dma_buf_rw() -- why does it need changes?
> > 
> > This one has the same goal, but accesses the qdev through sg, instead of
> > PCI.
> 
> Should dma_*() APIs take a reentrancy guard argument so that all DMA
> accesses are systematically covered?

That seems like it would be the best option, though it carries the cost
of needing to tweak a lot of code in hw/. Maybe some refactoring tool
could help with this.
-Alex

> 
>   /* Define this in the memory API */
>   typedef struct {
>   bool engaged_in_io;
>   } MemReentrancyGuard;
> 
>   /* Embed MemReentrancyGuard in DeviceState */
>   ...
> 
>   /* Require it in dma_*() APIs */
>   static inline MemTxResult dma_memory_rw(AddressSpace *as, dma_addr_t addr,
>   void *buf, dma_addr_t len,
>   DMADirection dir, MemTxAttrs attrs,
> MemReentrancyGuard *guard);
> 
>   /* Call dma_*() APIs like this... */
>   static inline MemTxResult pci_dma_rw(PCIDevice *dev, dma_addr_t addr,
>void *buf, dma_addr_t len,
>DMADirection dir, MemTxAttrs attrs)
>   {
>   return dma_memory_rw(pci_get_address_space(dev), addr, buf, len,
>dir, attrs, &dev->qdev.reentrancy_guard);
>   }
> 
> Stefan





Re: [PATCH v2 05/11] dump/dump: Add section string table support

2022-07-13 Thread Marc-André Lureau
Hi

On Wed, Jul 13, 2022 at 5:07 PM Janosch Frank  wrote:
>
> Time to add a bit more descriptiveness to the dumps.

Please add some more description & motivation to the patch (supposedly
necessary for next patches), and explain that it currently doesn't
change the dump (afaict).

>
> Signed-off-by: Janosch Frank 
> Reviewed-by: Richard Henderson 
> ---
>  dump/dump.c   | 106 --
>  include/sysemu/dump.h |   1 +
>  2 files changed, 94 insertions(+), 13 deletions(-)
>
> diff --git a/dump/dump.c b/dump/dump.c
> index 467d934bc1..31e2a85372 100644
> --- a/dump/dump.c
> +++ b/dump/dump.c
> @@ -99,6 +99,7 @@ static int dump_cleanup(DumpState *s)
>  close(s->fd);
>  g_free(s->guest_note);
>  g_free(s->elf_header);
> +g_array_unref(s->string_table_buf);
>  s->guest_note = NULL;
>  if (s->resume) {
>  if (s->detached) {
> @@ -359,14 +360,47 @@ static size_t write_elf_section_hdr_zero(DumpState *s, 
> void *buff)
>  return dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
>  }
>
> +static void write_elf_section_hdr_string(DumpState *s, void *buff)
> +{
> +Elf32_Shdr shdr32;
> +Elf64_Shdr shdr64;
> +int shdr_size;
> +void *shdr = buff;
> +
> +if (dump_is_64bit(s)) {
> +shdr_size = sizeof(Elf64_Shdr);
> +memset(&shdr64, 0, shdr_size);
> +shdr64.sh_type = SHT_STRTAB;
> +shdr64.sh_offset = s->section_offset + s->elf_section_data_size;
> +shdr64.sh_name = s->string_table_buf->len;
> +g_array_append_vals(s->string_table_buf, ".strtab", 
> sizeof(".strtab"));
> +shdr64.sh_size = s->string_table_buf->len;
> +shdr = &shdr64;
> +} else {
> +shdr_size = sizeof(Elf32_Shdr);
> +memset(&shdr32, 0, shdr_size);
> +shdr32.sh_type = SHT_STRTAB;
> +shdr32.sh_offset = s->section_offset + s->elf_section_data_size;
> +shdr32.sh_name = s->string_table_buf->len;
> +g_array_append_vals(s->string_table_buf, ".strtab", 
> sizeof(".strtab"));
> +shdr32.sh_size = s->string_table_buf->len;
> +shdr = &shdr32;
> +}
> +
> +memcpy(buff, shdr, shdr_size);
> +}
> +
>  static void prepare_elf_section_hdrs(DumpState *s)
>  {
>  uint8_t *buff_hdr;
> -size_t len, sizeof_shdr;
> +size_t len, size = 0, sizeof_shdr;
> +Elf64_Ehdr *hdr64 = s->elf_header;
> +Elf32_Ehdr *hdr32 = s->elf_header;
>
>  /*
>   * Section ordering:
>   * - HDR zero (if needed)
> + * - String table hdr
>   */
>  sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
>  len = sizeof_shdr * s->shdr_num;
> @@ -377,6 +411,22 @@ static void prepare_elf_section_hdrs(DumpState *s)
>  if (s->phdr_num == PN_XNUM) {
>  write_elf_section_hdr_zero(s, buff_hdr);
>  }
> +buff_hdr += size;
> +
> +if (s->shdr_num < 2) {
> +return;
> +}
> +
> +/*
> + * String table needs to be last section since strings are added
> + * via arch_sections_write_hdr().
> + */
> +write_elf_section_hdr_string(s, buff_hdr);
> +if (dump_is_64bit(s)) {
> +hdr64->e_shstrndx = cpu_to_dump16(s, s->shdr_num - 1);
> +} else {
> +hdr32->e_shstrndx = cpu_to_dump16(s, s->shdr_num - 1);
> +}
>  }
>
>  static void prepare_elf_sections(DumpState *s, Error **errp)
> @@ -405,11 +455,18 @@ static void write_elf_sections(DumpState *s, Error 
> **errp)
>  {
>  int ret;
>
> -/* Write section zero */
> +/* Write section zero and arch sections */
>  ret = fd_write_vmcore(s->elf_section_data, s->elf_section_data_size, s);
>  if (ret < 0) {
>  error_setg_errno(errp, -ret, "dump: failed to write section data");
>  }
> +
> +/* Write string table data */
> +ret = fd_write_vmcore(s->string_table_buf->data,
> +  s->string_table_buf->len, s);
> +if (ret < 0) {
> +error_setg_errno(errp, -ret, "dump: failed to write string table 
> data");
> +}
>  }
>
>  static void write_data(DumpState *s, void *buf, int length, Error **errp)
> @@ -592,6 +649,9 @@ static void dump_begin(DumpState *s, Error **errp)
>   *   --
>   *   |  memory |
>   *   --
> + *   |  sectn data |
> + *   --
> +
>   *
>   * we only know where the memory is saved after we write elf note into
>   * vmcore.
> @@ -677,6 +737,7 @@ static void create_vmcore(DumpState *s, Error **errp)
>  return;
>  }
>
> +/* Iterate over memory and dump it to file */
>  dump_iterate(s, errp);
>  if (*errp) {
>  return;
> @@ -1659,6 +1720,13 @@ static void dump_init(DumpState *s, int fd, bool 
> has_format,
>  s->has_filter = has_filter;
>  s->begin = begin;
>  s->length = length;
> +/* First index is 0, it's the special null name */
> +s->string_table_buf = g_array_new(FALSE, TRUE, 1);
> +/*
> + * Alloca

Re: [PATCH 4/5] target/loongarch/tlb_helper: Fix coverity integer overflow error

2022-07-13 Thread Richard Henderson

On 7/13/22 15:20, Xiaojuan Yang wrote:

Replace '1 << shift' with 'MAKE_64BIT_MASK(shift, 1)' to fix
unintentional integer overflow errors in tlb_helper file.

Fix coverity CID: 1489759 1489762

Signed-off-by: Xiaojuan Yang
---
  target/loongarch/tlb_helper.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 1/5] target/loongarch/cpu: Fix cpu_class_by_name function

2022-07-13 Thread Richard Henderson

On 7/13/22 15:20, Xiaojuan Yang wrote:

In loongarch_cpu_class_by_name(char *cpu_model) function,
the argument cpu_model already has the suffix '-loongarch-cpu',
so we should remove the LOONGARCH_CPU_TYPE_NAME(cpu_model) macro.
And add the assertion that 'cpu_model' resolves to a class of the
appropriate type.

Signed-off-by: Xiaojuan Yang 
---
  target/loongarch/cpu.c | 9 +
  1 file changed, 5 insertions(+), 4 deletions(-)


Reviewed-by: Richard Henderson 

r~


diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index e21715592a..ed26f9beed 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -571,11 +571,12 @@ static void loongarch_cpu_init(Object *obj)
  static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
  {
  ObjectClass *oc;
-char *typename;
  
-typename = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model);

-oc = object_class_by_name(typename);
-g_free(typename);
+oc = object_class_by_name(cpu_model);
+if (!oc || !object_class_dynamic_cast(oc, TYPE_LOONGARCH_CPU) ||
+object_class_is_abstract(oc)) {
+return NULL;
+}
  return oc;
  }
  





Re: [PATCH 3/5] target/loongarch/cpu: Fix coverity errors about excp_names

2022-07-13 Thread Richard Henderson

On 7/13/22 15:20, Xiaojuan Yang wrote:

Fix out-of-bounds errors when access excp_names[] array. the valid
boundary size of excp_names should be 0 to ARRAY_SIZE(excp_names)-1.
However, the general code do not consider the max boundary.

Fix coverity CID: 1489758

Signed-off-by: Xiaojuan Yang 
---
  target/loongarch/cpu.c | 6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)


I gave you a reviewed-by for this patch in v1.
You must copy those into v2 so that I don't have to do it again.


r~



diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index ed26f9beed..89ea971cde 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -140,7 +140,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
  
  if (cs->exception_index != EXCCODE_INT) {

  if (cs->exception_index < 0 ||
-cs->exception_index > ARRAY_SIZE(excp_names)) {
+cs->exception_index >= ARRAY_SIZE(excp_names)) {
  name = "unknown";
  } else {
  name = excp_names[cs->exception_index];
@@ -190,8 +190,8 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
  cause = cs->exception_index;
  break;
  default:
-qemu_log("Error: exception(%d) '%s' has not been supported\n",
- cs->exception_index, excp_names[cs->exception_index]);
+qemu_log("Error: exception(%d) has not been supported\n",
+ cs->exception_index);
  abort();
  }
  





Re: [PATCH v2 06/11] dump/dump: Add arch section support

2022-07-13 Thread Marc-André Lureau
Hi

On Wed, Jul 13, 2022 at 5:07 PM Janosch Frank  wrote:
>
> Add hooks which architectures can use to add arbitrary data to custom
> sections.
>
> Signed-off-by: Janosch Frank 
> ---
>  dump/dump.c| 21 ++---
>  include/sysemu/dump-arch.h | 27 +++
>  2 files changed, 45 insertions(+), 3 deletions(-)
>
> diff --git a/dump/dump.c b/dump/dump.c
> index 31e2a85372..02de00b6de 100644
> --- a/dump/dump.c
> +++ b/dump/dump.c
> @@ -400,6 +400,7 @@ static void prepare_elf_section_hdrs(DumpState *s)
>  /*
>   * Section ordering:
>   * - HDR zero (if needed)
> + * - Arch section hdrs
>   * - String table hdr
>   */
>  sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
> @@ -417,6 +418,9 @@ static void prepare_elf_section_hdrs(DumpState *s)
>  return;
>  }
>
> +size = dump_arch_sections_write_hdr(&s->dump_info, s, buff_hdr);
> +buff_hdr += size;
> +
>  /*
>   * String table needs to be last section since strings are added
>   * via arch_sections_write_hdr().
> @@ -567,14 +571,23 @@ static void get_offset_range(hwaddr phys_addr,
>  }
>  }
>
> -static void write_elf_loads(DumpState *s, Error **errp)
> +static void write_elf_phdr_loads(DumpState *s, Error **errp)
>  {
>  ERRP_GUARD();
>  hwaddr offset, filesz;
>  MemoryMapping *memory_mapping;
>  uint32_t phdr_index = 1;
> +hwaddr min = 0, max = 0;
>
>  QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
> +if (memory_mapping->phys_addr < min) {
> +min = memory_mapping->phys_addr;
> +}
> +if (memory_mapping->phys_addr + memory_mapping->length > max) {
> +max = memory_mapping->phys_addr + memory_mapping->length;
> +}
> +
> +

Extra line & this belongs to a different patch.

>  get_offset_range(memory_mapping->phys_addr,
>   memory_mapping->length,
>   s, &offset, &filesz);
> @@ -682,8 +695,8 @@ static void dump_begin(DumpState *s, Error **errp)
>  return;
>  }
>
> -/* write all PT_LOAD to vmcore */
> -write_elf_loads(s, errp);
> +/* write all PT_LOADs to vmcore */
> +write_elf_phdr_loads(s, errp);
>  if (*errp) {
>  return;
>  }
> @@ -723,6 +736,7 @@ static void dump_end(DumpState *s, Error **errp)
>  return;
>  }
>  s->elf_section_data = g_malloc0(s->elf_section_data_size);
> +dump_arch_sections_write(&s->dump_info, s, s->elf_section_data);
>
>  /* write sections to vmcore */
>  write_elf_sections(s, errp);
> @@ -1894,6 +1908,7 @@ static void dump_init(DumpState *s, int fd, bool 
> has_format,
>   * If phdr_num overflowed we have at least one section header
>   * More sections/hdrs can be added by the architectures
>   */
> +dump_arch_sections_add(&s->dump_info, (void *)s);
>  if (s->shdr_num > 1) {
>  /* Reserve the string table */
>  s->shdr_num += 1;
> diff --git a/include/sysemu/dump-arch.h b/include/sysemu/dump-arch.h
> index e25b02e990..de77908424 100644
> --- a/include/sysemu/dump-arch.h
> +++ b/include/sysemu/dump-arch.h
> @@ -21,6 +21,9 @@ typedef struct ArchDumpInfo {
>  uint32_t page_size;  /* The target's page size. If it's variable and
>* unknown, then this should be the maximum. */
>  uint64_t phys_base;  /* The target's physmem base. */
> +void (*arch_sections_add_fn)(void *opaque);
> +uint64_t (*arch_sections_write_hdr_fn)(void *opaque, uint8_t *buff);
> +void (*arch_sections_write_fn)(void *opaque, uint8_t *buff);
>  } ArchDumpInfo;
>
>  struct GuestPhysBlockList; /* memory_mapping.h */
> @@ -28,4 +31,28 @@ int cpu_get_dump_info(ArchDumpInfo *info,
>const struct GuestPhysBlockList *guest_phys_blocks);
>  ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
>
> +static inline void dump_arch_sections_add(ArchDumpInfo *info, void *opaque)
> +{
> +if (info->arch_sections_add_fn) {
> +info->arch_sections_add_fn(opaque);
> +}
> +}
> +
> +static inline uint64_t dump_arch_sections_write_hdr(ArchDumpInfo *info,
> +void *opaque, uint8_t *buff)
> +{
> +if (info->arch_sections_write_hdr_fn) {
> +return info->arch_sections_write_hdr_fn(opaque, buff);
> +}
> +return 0;
> +}
> +
> +static inline void dump_arch_sections_write(ArchDumpInfo *info, void *opaque,
> +uint8_t *buff)
> +{
> +if (info->arch_sections_write_fn) {
> +info->arch_sections_write_fn(opaque, buff);
> +}
> +}
> +
>  #endif
> --
> 2.34.1
>

otherwise, seems ok to me




Re: [PATCH v2 07/11] linux header sync

2022-07-13 Thread Marc-André Lureau
On Wed, Jul 13, 2022 at 5:07 PM Janosch Frank  wrote:
>
> Signed-off-by: Janosch Frank 

Please tell which version this update come from. Otherwise, it should be fine
Reviewed-by: Marc-André Lureau 

> ---
>  linux-headers/linux/kvm.h | 55 +++
>  1 file changed, 55 insertions(+)
>
> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
> index 0d05d02ee4..ae5db2e44c 100644
> --- a/linux-headers/linux/kvm.h
> +++ b/linux-headers/linux/kvm.h
> @@ -1150,6 +1150,7 @@ struct kvm_ppc_resize_hpt {
>  #define KVM_CAP_DISABLE_QUIRKS2 213
>  /* #define KVM_CAP_VM_TSC_CONTROL 214 */
>  #define KVM_CAP_SYSTEM_EVENT_DATA 215
> +#define KVM_CAP_S390_PROTECTED_DUMP 217
>
>  #ifdef KVM_CAP_IRQ_ROUTING
>
> @@ -1651,6 +1652,55 @@ struct kvm_s390_pv_unp {
> __u64 tweak;
>  };
>
> +enum pv_cmd_info_id {
> +   KVM_PV_INFO_VM,
> +   KVM_PV_INFO_DUMP,
> +};
> +
> +struct kvm_s390_pv_info_dump {
> +   __u64 dump_cpu_buffer_len;
> +   __u64 dump_config_mem_buffer_per_1m;
> +   __u64 dump_config_finalize_len;
> +};
> +
> +struct kvm_s390_pv_info_vm {
> +   __u64 inst_calls_list[4];
> +   __u64 max_cpus;
> +   __u64 max_guests;
> +   __u64 max_guest_addr;
> +   __u64 feature_indication;
> +};
> +
> +struct kvm_s390_pv_info_header {
> +   __u32 id;
> +   __u32 len_max;
> +   __u32 len_written;
> +   __u32 reserved;
> +};
> +
> +struct kvm_s390_pv_info {
> +   struct kvm_s390_pv_info_header header;
> +   union {
> +   struct kvm_s390_pv_info_dump dump;
> +   struct kvm_s390_pv_info_vm vm;
> +   };
> +};
> +
> +enum pv_cmd_dmp_id {
> +KVM_PV_DUMP_INIT,
> +KVM_PV_DUMP_CONFIG_STATE,
> +KVM_PV_DUMP_COMPLETE,
> +KVM_PV_DUMP_CPU,
> +};
> +
> +struct kvm_s390_pv_dmp {
> +__u64 subcmd;
> +__u64 buff_addr;
> +__u64 buff_len;
> +__u64 gaddr;
> +__u64 reserved[4];
> +};
> +
>  enum pv_cmd_id {
> KVM_PV_ENABLE,
> KVM_PV_DISABLE,
> @@ -1659,6 +1709,8 @@ enum pv_cmd_id {
> KVM_PV_VERIFY,
> KVM_PV_PREP_RESET,
> KVM_PV_UNSHARE_ALL,
> +KVM_PV_INFO,
> +KVM_PV_DUMP,
>  };
>
>  struct kvm_pv_cmd {
> @@ -1733,6 +1785,7 @@ struct kvm_xen_vcpu_attr {
>  #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA   0x4
>  #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
>
> +
>  /* Secure Encrypted Virtualization command */
>  enum sev_cmd_id {
> /* Guest initialization commands */
> @@ -2066,4 +2119,6 @@ struct kvm_stats_desc {
>  /* Available with KVM_CAP_XSAVE2 */
>  #define KVM_GET_XSAVE2   _IOR(KVMIO,  0xcf, struct kvm_xsave)
>
> +#define KVM_S390_PV_CPU_COMMAND _IOWR(KVMIO, 0xd0, struct kvm_pv_cmd)
> +
>  #endif /* __LINUX_KVM_H */
> --
> 2.34.1
>




Re: [PATCH 5/5] target/loongarch/op_helper: Fix coverity cond_at_most error

2022-07-13 Thread Richard Henderson

On 7/13/22 15:20, Xiaojuan Yang wrote:

The boundary size of cpucfg array should be 0 to 20. So,
using index bigger than 20 to access cpucfg[] must be forbidden.


You must update the comment to match the code,
which no longer mentions "20" at all.  With that change,

Reviewed-by: Richard Henderson 

r~



Fix coverity CID: 1489760

Signed-off-by: Xiaojuan Yang 
---
  target/loongarch/op_helper.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index 4b429b6699..568c071601 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -81,7 +81,7 @@ target_ulong helper_crc32c(target_ulong val, target_ulong m, 
uint64_t sz)
  
  target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj)

  {
-return rj > 21 ? 0 : env->cpucfg[rj];
+return rj >= ARRAY_SIZE(env->cpucfg) ? 0 : env->cpucfg[rj];
  }
  
  uint64_t helper_rdtime_d(CPULoongArchState *env)





Re: [PATCH 2/5] hw/intc/loongarch_pch_pic: Fix coverity errors in update irq

2022-07-13 Thread Richard Henderson

On 7/13/22 15:20, Xiaojuan Yang wrote:

Fix coverity errors:
1. In find_first_bit function, the 'size' argument need
'unsigned long' type, so we change the 'size' to unsigned
long type when use the function.
2. In expression 1ULL << irq, left shifting by more than
63 bits has undefined behavior. And out-of-bounds access
error occured when 'irq' >= 64. So we add a condition to
avoid this.
3. Use 'MAKE_64BIT_MASK(irq, 1)' to replace '1ULL << shift'.

Fix coverity CID: 1489761 1489764 1489765

Signed-off-by: Xiaojuan Yang 
---
  hw/intc/loongarch_pch_pic.c | 19 ---
  1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c
index 3c9814a3b4..040b89861c 100644
--- a/hw/intc/loongarch_pch_pic.c
+++ b/hw/intc/loongarch_pch_pic.c
@@ -15,22 +15,27 @@
  
  static void pch_pic_update_irq(LoongArchPCHPIC *s, uint64_t mask, int level)

  {
-unsigned long val;
+unsigned long val, max_irq;


You did not follow any of my direction from v1.

(1) val must be uint64_t.

(and, generally, any use of 'unsigned long' is probably a bug)


+irq = find_first_bit(&val, max_irq);


Use ctz64().


+if (irq < max_irq) {


This, really, should be a test of val != 0 before the ctz.



+s->intisr |= MAKE_64BIT_MASK(irq, 1);
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1);
+}
  }
  } else {
  val = mask & s->intisr;
  if (val) {
-irq = find_first_bit(&val, 64);
-s->intisr &= ~(0x1ULL << irq);
-qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0);
+irq = find_first_bit(&val, max_irq);
+if (irq < max_irq) {
+s->intisr &= ~(MAKE_64BIT_MASK(irq, 1));
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0);


etc.


r~


+}
  }
  }
  }





Re: [PATCH 3/3] tests/tcg/s390x: test signed vfmin/vfmax

2022-07-13 Thread Ilya Leoshkevich
On Wed, 2022-07-13 at 21:14 +0530, Richard Henderson wrote:
> On 7/12/22 18:02, Ilya Leoshkevich wrote:
> > > This works, of course.  It could be simpler using EXECUTE, to
> > > store
> > > just the one
> > > instruction and not worry about an executable mapped page, but I
> > > guess it doesn't matter.
> > 
> > I thought about this too, but EX/EXRL operate only on the second
> > byte,
> > and I need to modify bytes 3-5 here.
> 
> I didn't mean modify the instruction via EX, but something like
> 
>    static char minmax[6] __attribute__((aligned(2)))
>  = { xx, yy, zz, 0, 0, 0 };
> 
>    minmax[3] = m6 ...
>    minmax[4] = ...
>    minmax[5] = op;
> 
>    asm("vl %%v25,0(%1)\n"
>    "vl %%v26,0(%2)\n"
>    "ex 0,0(%3)\n"
>    "vst %%v24,0(%0)"
>    : : "a"(v1), "a"(v2), "a"(v3), "a"(minmax)
>    : "memory", "v24", "v25", "v26);
> 
> 
> r~

Nice trick!

This works in qemu, but not natively: EX target must be executable.
I'd still like to try to find a way to establish an rwx section, and
send a v2 with this improvement.

I guess we'll need to fix the access check discrepancy some day.



Re: [PATCH v6 12/13] qemu-sockets: update socket_uri() to be consistent with socket_parse()

2022-07-13 Thread Laurent Vivier

On 12/07/2022 14:05, Dr. David Alan Gilbert wrote:

* Laurent Vivier (lviv...@redhat.com) wrote:

Remove 'tcp:' prefix for inet type (because inet can be 'tcp' or 'udp'
and socket_parse() doesn't recognize it), the format is 'host:port'.


I don't think I understand why tests/qtest/migration-test.c
test_precopy_common is happy with this; it does:

 if (!args->connect_uri) {
 g_autofree char *local_connect_uri =
 migrate_get_socket_address(to, "socket-address");
 migrate_qmp(from, local_connect_uri, "{}");

which hmm, is the code you're changing what was in SocketAddress_to_str
which is what migrate_get_socket_address uses; but then the migrate_qmp
I don't think will take a migrate uri without the tcp: on the front.


It's a good point.

I think socket_parse() should accept the 'tcp:' prefix, and thus socket_uri() should 
generate it, so it will be usable with the qmp migrate command.


I'm going to add 'tcp:' case in socket_parse() and make socket_uri() to 
generate it.

Thanks,
Laurent




Ping: [PATCH] hw/nvme: Add options to override hardcoded values

2022-07-13 Thread Mauricio Sandt

https://patchew.org/QEMU/20220611223509.32280-1-mauri...@mailbox.org/
https://lore.kernel.org/qemu-devel/20220611223509.32280-1-mauri...@mailbox.org/

On 12/06/2022 00:35, Mauricio Sandt wrote:

This small patch is the result of some recent malware research I did
in a QEMU VM. The malware used multiple ways of querying info from
the VM disk and I needed a clean way to change those values from the
hypervisor.

I believe this functionality could be useful to more people from multiple
fields, sometimes you just want to change some default values and having
them hardcoded in the sourcecode makes that much harder.

This patch adds three config parameters to the nvme device, all of them
are optional to not break anything. If any of them are not specified,
the previous (before this patch) default is used.

-model - This takes a string and sets it as the devices model name.
If you don't specify this parameter, the default is "QEMU NVMe Ctrl".

-firmware - The firmware version string, max 8 ascii characters.
The default is whatever `QEMU_VERSION` evaluates to.

-nqn_override - Allows to set a custom nqn on the nvme device.
Only used if there is no subsystem. This string should be in the same
format as the default "nqn.2019-08.org.qemu:...", but there is no
validation for that. Its up to the user to provide a valid string.

Signed-off-by: Mauricio Sandt
---
  hw/nvme/ctrl.c | 16 +---
  hw/nvme/nvme.h |  3 +++
  2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 1e6e0fcad9..0e67217a63 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -6697,8 +6697,13 @@ static void nvme_init_subnqn(NvmeCtrl *n)
  NvmeIdCtrl *id = &n->id_ctrl;
  
  if (!subsys) {

-snprintf((char *)id->subnqn, sizeof(id->subnqn),
+if (n->params.nqn_override) {
+snprintf((char *)id->subnqn, sizeof(id->subnqn),
+ "%s", n->params.nqn_override);
+} else {
+snprintf((char *)id->subnqn, sizeof(id->subnqn),
   "nqn.2019-08.org.qemu:%s", n->params.serial);
+}
  } else {
  pstrcpy((char *)id->subnqn, sizeof(id->subnqn), 
(char*)subsys->subnqn);
  }
@@ -6712,8 +6717,10 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
  
  id->vid = cpu_to_le16(pci_get_word(pci_conf + PCI_VENDOR_ID));

  id->ssvid = cpu_to_le16(pci_get_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID));
-strpadcpy((char *)id->mn, sizeof(id->mn), "QEMU NVMe Ctrl", ' ');
-strpadcpy((char *)id->fr, sizeof(id->fr), QEMU_VERSION, ' ');
+strpadcpy((char *)id->mn, sizeof(id->mn),
+n->params.model ? n->params.model : "QEMU NVMe Ctrl", ' ');
+strpadcpy((char *)id->fr, sizeof(id->fr),
+n->params.firmware ? n->params.firmware : QEMU_VERSION, ' ');
  strpadcpy((char *)id->sn, sizeof(id->sn), n->params.serial, ' ');
  
  id->cntlid = cpu_to_le16(n->cntlid);

@@ -6913,6 +6920,9 @@ static Property nvme_props[] = {
  DEFINE_PROP_LINK("subsys", NvmeCtrl, subsys, TYPE_NVME_SUBSYS,
   NvmeSubsystem *),
  DEFINE_PROP_STRING("serial", NvmeCtrl, params.serial),
+DEFINE_PROP_STRING("model", NvmeCtrl, params.model),
+DEFINE_PROP_STRING("nqn_override", NvmeCtrl, params.nqn_override),
+DEFINE_PROP_STRING("firmware", NvmeCtrl, params.firmware),
  DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, params.cmb_size_mb, 0),
  DEFINE_PROP_UINT32("num_queues", NvmeCtrl, params.num_queues, 0),
  DEFINE_PROP_UINT32("max_ioqpairs", NvmeCtrl, params.max_ioqpairs, 64),
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index e41771604f..45bcf3e02e 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -394,6 +394,9 @@ typedef struct NvmeCQueue {
  
  typedef struct NvmeParams {

  char *serial;
+char *model;
+char *firmware;
+char *nqn_override;
  uint32_t num_queues; /* deprecated since 5.1 */
  uint32_t max_ioqpairs;
  uint16_t msix_qsize;


[RFC PATCH v3 0/3] Implement Power ISA 3.1B hash insns

2022-07-13 Thread Víctor Colombo
This patch series implements the 4 instructions added in Power ISA
3.1B:

- hashchk
- hashst
- hashchkp
- hashstp

To build it, you need to apply the following patches on top of master:
<20220701133507.740619-2-lucas.couti...@eldorado.org.br>
<20220701133507.740619-3-lucas.couti...@eldorado.org.br>
<20220712193741.59134-2-leandro.lup...@eldorado.org.br>
<20220712193741.59134-3-leandro.lup...@eldorado.org.br>

Working branch for ease of use can be found here:
https://github.com/PPC64/qemu/tree/vccolombo-hash-to-send-v3

What do you think about the choice to implement the hash algorithm
from the ground up, following the SIMON-like algorithm presented in
Power ISA? IIUC, this algorithm is not the same as the original[1].
Other options would be to use other algorithm already implemented
in QEMU, or even make this instruction a nop for all Power versions.

Also, I was thinking about using the call to spr_register_kvm() in
init_proc_POWER10 to initialize the registers with a random value.
I'm not sure what is the behavior here, I would expect that is the job
of the OS to set the regs, but looks like KVM is not exporting them,
so they are always 0 (?). Does anyone have any insight on this?

v1->v2:
- Split the patch in 2
- Rebase to master

v2->v3:
- Split patches in 3
- the new patch (patch 1) is separating the kvm header 
  changes [Cornelia]

[1] https://eprint.iacr.org/2013/404.pdf

Víctor Colombo (3):
  linux-headers/asm-powerpc/kvm.h: Add HASHKEYR and HASHPKEYR in headers
  target/ppc: Implement hashst and hashchk
  target/ppc: Implement hashstp and hashchkp

 linux-headers/asm-powerpc/kvm.h|  3 +
 target/ppc/cpu.h   |  2 +
 target/ppc/cpu_init.c  |  7 ++
 target/ppc/excp_helper.c   | 82 ++
 target/ppc/helper.h|  4 ++
 target/ppc/insn32.decode   | 10 +++
 target/ppc/translate.c |  5 ++
 target/ppc/translate/fixedpoint-impl.c.inc | 34 +
 8 files changed, 147 insertions(+)

-- 
2.25.1




[RFC PATCH v3 1/3] linux-headers/asm-powerpc/kvm.h: Add HASHKEYR and HASHPKEYR in headers

2022-07-13 Thread Víctor Colombo
Linux KVM currently does not export these registers. Create
placeholders for them to allow implementing hashchk(p) and
hashst(p) instructions from PowerISA 3.1B.

Signed-off-by: Víctor Colombo 
---
 linux-headers/asm-powerpc/kvm.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 9f18fa090f..4ae4718143 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -646,6 +646,9 @@ struct kvm_ppc_cpu_char {
 #define KVM_REG_PPC_SIER3  (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc3)
 #define KVM_REG_PPC_DAWR1  (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc4)
 #define KVM_REG_PPC_DAWRX1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc5)
+/* FIXME: KVM hasn't exposed these registers yet */
+#define KVM_REG_PPC_HASHKEYR(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x00)
+#define KVM_REG_PPC_HASHPKEYR   (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x00)
 
 /* Transactional Memory checkpointed state:
  * This is all GPRs, all VSX regs and a subset of SPRs
-- 
2.25.1




[RFC PATCH v3 2/3] target/ppc: Implement hashst and hashchk

2022-07-13 Thread Víctor Colombo
Implementation for instructions hashst and hashchk, which were added
in Power ISA 3.1B.

It was decided to implement the hash algorithm from ground up in this
patch exactly as described in Power ISA.

Signed-off-by: Víctor Colombo 
---
 target/ppc/cpu.h   |  1 +
 target/ppc/cpu_init.c  |  4 ++
 target/ppc/excp_helper.c   | 80 ++
 target/ppc/helper.h|  2 +
 target/ppc/insn32.decode   |  8 +++
 target/ppc/translate.c |  5 ++
 target/ppc/translate/fixedpoint-impl.c.inc | 32 +
 7 files changed, 132 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 7aaff9dcc5..f3f98d7a01 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1677,6 +1677,7 @@ void ppc_compat_add_property(Object *obj, const char 
*name,
 #define SPR_BOOKE_GIVOR14 (0x1BD)
 #define SPR_TIR   (0x1BE)
 #define SPR_PTCR  (0x1D0)
+#define SPR_POWER_HASHKEYR(0x1D4)
 #define SPR_BOOKE_SPEFSCR (0x200)
 #define SPR_Exxx_BBEAR(0x201)
 #define SPR_Exxx_BBTAR(0x202)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 1da5f1f1d8..a2bbb84d47 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6490,6 +6490,10 @@ static void init_proc_POWER10(CPUPPCState *env)
 spr_read_generic, spr_write_generic,
 KVM_REG_PPC_PSSCR, 0);
 
+spr_register_kvm(env, SPR_POWER_HASHKEYR, "HASHKEYR",
+SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic,
+KVM_REG_PPC_HASHKEYR, 0x0);
+
 /* env variables */
 env->dcache_line_size = 128;
 env->icache_line_size = 128;
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index cb752b184a..34893bdf9f 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -2174,6 +2174,86 @@ void helper_td(CPUPPCState *env, target_ulong arg1, 
target_ulong arg2,
 #endif
 #endif
 
+static uint32_t helper_SIMON_LIKE_32_64(uint32_t x, uint64_t key, uint32_t 
lane)
+{
+const uint16_t c = 0xfffc;
+const uint64_t z0 = 0xfa2561cdf44ac398ULL;
+uint16_t z = 0, temp;
+uint16_t k[32], eff_k[32], xleft[33], xright[33], fxleft[32];
+
+for (int i = 3; i >= 0; i--) {
+k[i] = key & 0x;
+key >>= 16;
+}
+xleft[0] = x & 0x;
+xright[0] = (x >> 16) & 0x;
+
+for (int i = 0; i < 28; i++) {
+z = (z0 >> (63 - i)) & 1;
+temp = ror16(k[i + 3], 3) ^ k[i + 1];
+k[i + 4] = c ^ z ^ k[i] ^ temp ^ ror16(temp, 1);
+}
+
+for (int i = 0; i < 8; i++) {
+eff_k[4 * i + 0] = k[4 * i + ((0 + lane) % 4)];
+eff_k[4 * i + 1] = k[4 * i + ((1 + lane) % 4)];
+eff_k[4 * i + 2] = k[4 * i + ((2 + lane) % 4)];
+eff_k[4 * i + 3] = k[4 * i + ((3 + lane) % 4)];
+}
+
+for (int i = 0; i < 32; i++) {
+fxleft[i] = (rol16(xleft[i], 1) &
+rol16(xleft[i], 8)) ^ rol16(xleft[i], 2);
+xleft[i + 1] = xright[i] ^ fxleft[i] ^ eff_k[i];
+xright[i + 1] = xleft[i];
+}
+
+return (((uint32_t)xright[32]) << 16) | xleft[32];
+}
+
+static uint64_t hash_digest(uint64_t ra, uint64_t rb, uint64_t key)
+{
+uint64_t stage0_h = 0ULL, stage0_l = 0ULL;
+uint64_t stage1_h, stage1_l;
+
+for (int i = 0; i < 4; i++) {
+stage0_h |= ror64(rb & 0xff, 8 * (2 * i + 1));
+stage0_h |= ((ra >> 32) & 0xff) << (8 * 2 * i);
+stage0_l |= ror64((rb >> 32) & 0xff, 8 * (2 * i + 1));
+stage0_l |= (ra & 0xff) << (8 * 2 * i);
+rb >>= 8;
+ra >>= 8;
+}
+
+stage1_h = (uint64_t)helper_SIMON_LIKE_32_64(stage0_h >> 32, key, 0) << 32;
+stage1_h |= helper_SIMON_LIKE_32_64(stage0_h, key, 1);
+stage1_l = (uint64_t)helper_SIMON_LIKE_32_64(stage0_l >> 32, key, 2) << 32;
+stage1_l |= helper_SIMON_LIKE_32_64(stage0_l, key, 3);
+
+return stage1_h ^ stage1_l;
+}
+
+#define HELPER_HASH(op, key, store)   \
+void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra,  \
+ target_ulong rb) \
+{ \
+uint64_t chash = hash_digest(ra, rb, key), lhash; \
+  \
+if (store) {  \
+cpu_stq_data_ra(env, ea, chash, GETPC()); \
+} else {  \
+lhash = cpu_ldq_data_ra(env, ea, GETPC());\
+if (lhash != chash) { \
+/* hashes don't match, trap */\
+raise_exception_err_ra(e

[RFC PATCH v3 3/3] target/ppc: Implement hashstp and hashchkp

2022-07-13 Thread Víctor Colombo
Implementation for instructions hashstp and hashchkp, the privileged
versions of hashst and hashchk, which were added in Power ISA 3.1B.

Signed-off-by: Víctor Colombo 
---
 target/ppc/cpu.h   | 1 +
 target/ppc/cpu_init.c  | 3 +++
 target/ppc/excp_helper.c   | 2 ++
 target/ppc/helper.h| 2 ++
 target/ppc/insn32.decode   | 2 ++
 target/ppc/translate/fixedpoint-impl.c.inc | 2 ++
 6 files changed, 12 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index f3f98d7a01..e6fc9c41f0 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1678,6 +1678,7 @@ void ppc_compat_add_property(Object *obj, const char 
*name,
 #define SPR_TIR   (0x1BE)
 #define SPR_PTCR  (0x1D0)
 #define SPR_POWER_HASHKEYR(0x1D4)
+#define SPR_POWER_HASHPKEYR   (0x1D5)
 #define SPR_BOOKE_SPEFSCR (0x200)
 #define SPR_Exxx_BBEAR(0x201)
 #define SPR_Exxx_BBTAR(0x202)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index a2bbb84d47..3e704304b1 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6493,6 +6493,9 @@ static void init_proc_POWER10(CPUPPCState *env)
 spr_register_kvm(env, SPR_POWER_HASHKEYR, "HASHKEYR",
 SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic,
 KVM_REG_PPC_HASHKEYR, 0x0);
+spr_register_kvm(env, SPR_POWER_HASHPKEYR, "HASHPKEYR",
+SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic,
+KVM_REG_PPC_HASHPKEYR, 0x0);
 
 /* env variables */
 env->dcache_line_size = 128;
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 34893bdf9f..0998e8374e 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -2253,6 +2253,8 @@ void helper_##op(CPUPPCState *env, target_ulong ea, 
target_ulong ra,  \
 
 HELPER_HASH(HASHST, env->spr[SPR_POWER_HASHKEYR], true)
 HELPER_HASH(HASHCHK, env->spr[SPR_POWER_HASHKEYR], false)
+HELPER_HASH(HASHSTP, env->spr[SPR_POWER_HASHPKEYR], true)
+HELPER_HASH(HASHCHKP, env->spr[SPR_POWER_HASHPKEYR], false)
 
 #if !defined(CONFIG_USER_ONLY)
 
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index d455b9d97a..cf68ba458d 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -6,6 +6,8 @@ DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
 #endif
 DEF_HELPER_4(HASHST, void, env, tl, tl, tl)
 DEF_HELPER_4(HASHCHK, void, env, tl, tl, tl)
+DEF_HELPER_4(HASHSTP, void, env, tl, tl, tl)
+DEF_HELPER_4(HASHCHKP, void, env, tl, tl, tl)
 #if !defined(CONFIG_USER_ONLY)
 DEF_HELPER_2(store_msr, void, env, tl)
 DEF_HELPER_1(rfi, void, env)
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 37ec6b2681..64f92a0524 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -321,6 +321,8 @@ PEXTD   01 . . . 001000 -   @X
 
 HASHST  01 . . . 1011010010 .   @X_DW
 HASHCHK 01 . . . 100010 .   @X_DW
+HASHSTP 01 . . . 1010010010 .   @X_DW
+HASHCHKP01 . . . 1010110010 .   @X_DW
 
 ## BCD Assist
 
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 41c06de8a2..1ba56cbed5 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -572,3 +572,5 @@ static bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
 
 TRANS(HASHST, do_hash, false, gen_helper_HASHST)
 TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)
+TRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP)
+TRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP)
-- 
2.25.1




Re: [PATCH] hw/nvme: Add options to override hardcoded values

2022-07-13 Thread Keith Busch
On Sun, Jun 12, 2022 at 12:35:09AM +0200, Mauricio Sandt wrote:
> This small patch is the result of some recent malware research I did
> in a QEMU VM. The malware used multiple ways of querying info from
> the VM disk and I needed a clean way to change those values from the
> hypervisor.
> 
> I believe this functionality could be useful to more people from multiple
> fields, sometimes you just want to change some default values and having
> them hardcoded in the sourcecode makes that much harder.
> 
> This patch adds three config parameters to the nvme device, all of them
> are optional to not break anything. If any of them are not specified,
> the previous (before this patch) default is used.
> 
> -model - This takes a string and sets it as the devices model name.
> If you don't specify this parameter, the default is "QEMU NVMe Ctrl".
> 
> -firmware - The firmware version string, max 8 ascii characters.
> The default is whatever `QEMU_VERSION` evaluates to.
> 
> -nqn_override - Allows to set a custom nqn on the nvme device.
> Only used if there is no subsystem. This string should be in the same
> format as the default "nqn.2019-08.org.qemu:...", but there is no
> validation for that. Its up to the user to provide a valid string.

I guess the nqn can be user tunable just like it is when used with subsystems,
but what's the point of messing with model and firmware? That could mess with
host drivers' ability to detect what quirks it needs to apply to specific
instances of this virtual controller.



Re: [PATCH v6 12/13] qemu-sockets: update socket_uri() to be consistent with socket_parse()

2022-07-13 Thread Daniel P . Berrangé
On Wed, Jul 13, 2022 at 06:46:17PM +0200, Laurent Vivier wrote:
> On 12/07/2022 14:05, Dr. David Alan Gilbert wrote:
> > * Laurent Vivier (lviv...@redhat.com) wrote:
> > > Remove 'tcp:' prefix for inet type (because inet can be 'tcp' or 'udp'
> > > and socket_parse() doesn't recognize it), the format is 'host:port'.
> > 
> > I don't think I understand why tests/qtest/migration-test.c
> > test_precopy_common is happy with this; it does:
> > 
> >  if (!args->connect_uri) {
> >  g_autofree char *local_connect_uri =
> >  migrate_get_socket_address(to, "socket-address");
> >  migrate_qmp(from, local_connect_uri, "{}");
> > 
> > which hmm, is the code you're changing what was in SocketAddress_to_str
> > which is what migrate_get_socket_address uses; but then the migrate_qmp
> > I don't think will take a migrate uri without the tcp: on the front.
> 
> It's a good point.
> 
> I think socket_parse() should accept the 'tcp:' prefix, and thus
> socket_uri() should generate it, so it will be usable with the qmp migrate
> command.
> 
> I'm going to add 'tcp:' case in socket_parse() and make socket_uri() to 
> generate it.

I'd say any code in util/qemu-sockets.c should only work in terms of
generic concepts. If we're formattting/parsing a migration URI, the
helper APIs should live in the migration/ subdir.


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




  1   2   >