Re: [PATCH 1/2] tests/acceptance: Test ast2400 and ast2500 machines
On 3/3/21 2:22 AM, Joel Stanley wrote: > Test MTD images from the OpenBMC project on AST2400 and AST2500 SoCs > from ASPEED, by booting Palmetto and Romulus BMC machines. > > The images are fetched from OpenBMC's release directory on github. > > Co-developed-by: Cédric Le Goater > Signed-off-by: Joel Stanley Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater Thanks, C. > --- > tests/acceptance/boot_linux_console.py | 46 ++ > 1 file changed, 46 insertions(+) > > diff --git a/tests/acceptance/boot_linux_console.py > b/tests/acceptance/boot_linux_console.py > index eb012867997f..2f46a08fdc10 100644 > --- a/tests/acceptance/boot_linux_console.py > +++ b/tests/acceptance/boot_linux_console.py > @@ -1048,6 +1048,52 @@ def test_arm_vexpressa9(self): > self.vm.add_args('-dtb', self.workdir + > '/day16/vexpress-v2p-ca9.dtb') > self.do_test_advcal_2018('16', tar_hash, 'winter.zImage') > > +def test_arm_ast2400_palmetto_openbmc_v2_9_0(self): > +""" > +:avocado: tags=arch:arm > +:avocado: tags=machine:palmetto-bmc > +""" > + > +image_url = > ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' > + 'obmc-phosphor-image-palmetto.static.mtd') > +image_hash = > ('3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d') > +image_path = self.fetch_asset(image_url, asset_hash=image_hash, > + algorithm='sha256') > + > +self.do_test_arm_aspeed(image_path) > + > +def test_arm_ast2500_romulus_openbmc_v2_9_0(self): > +""" > +:avocado: tags=arch:arm > +:avocado: tags=machine:romulus-bmc > +""" > + > +image_url = > ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' > + 'obmc-phosphor-image-romulus.static.mtd') > +image_hash = > ('820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25') > +image_path = self.fetch_asset(image_url, asset_hash=image_hash, > + algorithm='sha256') > + > +self.do_test_arm_aspeed(image_path) > + > +def do_test_arm_aspeed(self, image): > +self.vm.set_console() > +self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', > + '-net', 'nic') > +self.vm.launch() > + > +self.wait_for_console_pattern("U-Boot 2016.07") > +self.wait_for_console_pattern("## Loading kernel from FIT Image at > 2008") > +self.wait_for_console_pattern("Starting kernel ...") > +self.wait_for_console_pattern("Booting Linux on physical CPU 0x0") > +self.wait_for_console_pattern( > +"aspeed-smc 1e62.spi: read control register: 203b0641") > +self.wait_for_console_pattern("ftgmac100 1e66.ethernet eth0: irq > ") > +self.wait_for_console_pattern("systemd[1]: Set hostname to") > +# This often takes longer than the 90s timeout > +# self.wait_for_console_pattern("login:") > +self.vm.shutdown() > + > def test_m68k_mcf5208evb(self): > """ > :avocado: tags=arch:m68k >
Re: [PATCH 2/2] tests/acceptance: Test ast2600 machine
On 3/3/21 2:22 AM, Joel Stanley wrote: > This tests a Debian multi-soc arm32 Linux kernel on the AST2600 based > Tacoma BMC machine. > > There is no root file system so the test terminates when boot reaches > the stage where it attempts and fails to mount something. because of that, the test always fails : console: [3.615193] No filesystem could mount root, tried: console: [3.615269] console: [3.615688] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) FAIL: Failure message found in console: Kernel panic - not syncing (22.45 s) RESULTS: PASS 0 | ERROR 0 | FAIL 1 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0 Is there a way around this problem ? C. > > Signed-off-by: Joel Stanley > --- > tests/acceptance/boot_linux_console.py | 26 ++ > 1 file changed, 26 insertions(+) > > diff --git a/tests/acceptance/boot_linux_console.py > b/tests/acceptance/boot_linux_console.py > index 2f46a08fdc10..6b7d7f5df984 100644 > --- a/tests/acceptance/boot_linux_console.py > +++ b/tests/acceptance/boot_linux_console.py > @@ -1094,6 +1094,32 @@ def do_test_arm_aspeed(self, image): > # self.wait_for_console_pattern("login:") > self.vm.shutdown() > > +def test_arm_ast2600_debian(self): > +""" > +:avocado: tags=arch:arm > +:avocado: tags=machine:tacoma-bmc > +""" > +deb_url = ('http://snapshot.debian.org/archive/debian/' > + '20210302T203551Z/' > + 'pool/main/l/linux/' > + 'linux-image-5.10.0-3-armmp_5.10.13-1_armhf.deb') > +deb_hash = > 'db40d32fe39255d05482bea48d72467b67d6225bb2a2a4d6f618cb8976f1e09e' > +deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash, > +algorithm='sha256') > +kernel_path = self.extract_from_deb(deb_path, > '/boot/vmlinuz-5.10.0-3-armmp') > +dtb_path = self.extract_from_deb(deb_path, > + > '/usr/lib/linux-image-5.10.0-3-armmp/aspeed-bmc-opp-tacoma.dtb') > + > +self.vm.set_console() > +self.vm.add_args('-kernel', kernel_path, > + '-dtb', dtb_path) > +self.vm.launch() > +self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00") > +self.wait_for_console_pattern("SMP: Total of 2 processors activated") > +self.wait_for_console_pattern("ftgmac100 1e67.ftgmac eth0: irq") > +self.wait_for_console_pattern("VFS: Cannot open root device") > +self.vm.shutdown() > + > def test_m68k_mcf5208evb(self): > """ > :avocado: tags=arch:m68k >
Re: [PATCH V2 1/1] hw/block/nvme: support command retry delay
On Feb 14 23:28, Minwoo Im wrote: > Set CRDT1(Command Retry Delay Time 1) in the Identify controller data > structure to milliseconds units of 100ms by the given value of > 'cmd-retry-delay' parameter which is newly added. If > cmd-retry-delay=1000, it will be set CRDT1 to 10. This patch only > considers the CRDT1 without CRDT2 and 3 for the simplicity. > > This patch also introduced set/get feature command handler for Host > Behavior feature (16h). In this feature, ACRE(Advanced Command Retry > Enable) will be set by the host based on the Identify controller data > structure, especially by CRDTs. > > Signed-off-by: Minwoo Im > --- LGTM. Reviewed-by: Klaus Jensen signature.asc Description: PGP signature
Re: [PATCH] hw/arm/aspeed: Fix location of firmware images in documentation
On Wed, 3 Mar 2021 at 07:28, Cédric Le Goater wrote: > > Firmware images can be found on the OpenBMC jenkins site and on the > OpenBMC GitHub release page. > > Signed-off-by: Cédric Le Goater Reviewed-by: Joel Stanley
[PATCH] hw/arm/aspeed: Fix location of firmware images in documentation
Firmware images can be found on the OpenBMC jenkins site and on the OpenBMC GitHub release page. Signed-off-by: Cédric Le Goater --- docs/system/arm/aspeed.rst | 14 +- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index 690bada7842b..8972aa3f7bbe 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -72,18 +72,22 @@ Missing devices Boot options -The Aspeed machines can be started using the -kernel option to load a -Linux kernel or from a firmware image which can be downloaded from the -OpenPOWER jenkins : +The Aspeed machines can be started using the ``-kernel`` option to +load a Linux kernel or from a firmware. Images can be downloaded from +the OpenBMC jenkins : - https://openpower.xyz/ + https://jenkins.openbmc.org/job/ci-openbmc/lastSuccessfulBuild/distro=ubuntu,label=docker-builder + +or directly from the OpenBMC GitHub release repository : + + https://github.com/openbmc/openbmc/releases The image should be attached as an MTD drive. Run : .. code-block:: bash $ qemu-system-arm -M romulus-bmc -nic user \ - -drive file=flash-romulus,format=raw,if=mtd -nographic + -drive file=obmc-phosphor-image-romulus.static.mtd,format=raw,if=mtd -nographic Options specific to Aspeed machines are : -- 2.26.2
Re: [PATCH v3] vl: deprecate -writeconfig
On Tue, Mar 02, 2021 at 07:00:23PM +0100, Paolo Bonzini wrote: > The functionality of -writeconfig is limited and the code > does not even try to detect cases where it prints incorrect > syntax (for example if values have a quote in them, since > qemu_config_parse does not support any kind of escaping) > so remove it. > > Signed-off-by: Paolo Bonzini Acked-by: Gerd Hoffmann
Re: [PATCH v2] Autoconnect jack ports by default
Hi, > JACK clients with consumer purpose often auto connect to system ports by > default because their users mostly use JACK just as a consumer desktop sound > server. And I assume this applies to José as well. Hmm, ok. I'd suggest to simply change the default for connect-ports then, that'll allow the user to easily change the behavior by setting connect-ports to something else (including the empty string to disable autoconnect). take care, Gerd
[PATCH] multi-process: Initialize variables declared with g_auto*
Quote docs/devel/style.rst (section "Automatic memory deallocation"): * Variables declared with g_auto* MUST always be initialized, otherwise the cleanup function will use uninitialized stack memory Initialize @name properly to get rid of the compilation error: ../hw/remote/proxy.c: In function 'pci_proxy_dev_realize': /usr/include/glib-2.0/glib/glib-autocleanups.h:28:3: error: 'name' may be used uninitialized in this function [-Werror=maybe-uninitialized] g_free (*pp); ^~~~ ../hw/remote/proxy.c:350:30: note: 'name' was declared here g_autofree char *name; ^~~~ Signed-off-by: Zenghui Yu --- hw/remote/memory.c | 3 +-- hw/remote/proxy.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/remote/memory.c b/hw/remote/memory.c index 32085b1e05..f5f735c15a 100644 --- a/hw/remote/memory.c +++ b/hw/remote/memory.c @@ -43,9 +43,8 @@ void remote_sysmem_reconfig(MPQemuMsg *msg, Error **errp) remote_sysmem_reset(); for (region = 0; region < msg->num_fds; region++) { -g_autofree char *name; +g_autofree char *name = g_strdup_printf("remote-mem-%u", suffix++); subregion = g_new(MemoryRegion, 1); -name = g_strdup_printf("remote-mem-%u", suffix++); memory_region_init_ram_from_fd(subregion, NULL, name, sysmem_info->sizes[region], true, msg->fds[region], diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c index 4fa4be079d..6dda705fc2 100644 --- a/hw/remote/proxy.c +++ b/hw/remote/proxy.c @@ -347,13 +347,12 @@ static void probe_pci_info(PCIDevice *dev, Error **errp) PCI_BASE_ADDRESS_SPACE_IO : PCI_BASE_ADDRESS_SPACE_MEMORY; if (size) { -g_autofree char *name; +g_autofree char *name = g_strdup_printf("bar-region-%d", i); pdev->region[i].dev = pdev; pdev->region[i].present = true; if (type == PCI_BASE_ADDRESS_SPACE_MEMORY) { pdev->region[i].memory = true; } -name = g_strdup_printf("bar-region-%d", i); memory_region_init_io(>region[i].mr, OBJECT(pdev), _mr_ops, >region[i], name, size); -- 2.19.1
[PATCH 2/2] aspeed: Integrate HACE
Add the hash and crypto engine model to the aspeed socs. Signed-off-by: Joel Stanley [ clg: documentation update ] Signed-off-by: Cédric Le Goater --- docs/system/arm/aspeed.rst | 2 +- include/hw/arm/aspeed_soc.h | 3 +++ hw/arm/aspeed_ast2600.c | 14 ++ hw/arm/aspeed_soc.c | 15 +++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index 690bada7842b..ec30cad88a58 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -48,6 +48,7 @@ Supported devices * UART * Ethernet controllers * Front LEDs (PCA9552 on I2C bus) + * Hash/Crypto Engine (HACE) - SHA support only, no scatter-gather Missing devices @@ -59,7 +60,6 @@ Missing devices * LPC Bus Controller * Slave GPIO Controller * Super I/O Controller - * Hash/Crypto Engine * PCI-Express 1 Controller * Graphic Display Controller * PECI Controller diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 11cfe6e3585b..a8c9a22e5882 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -21,6 +21,7 @@ #include "hw/rtc/aspeed_rtc.h" #include "hw/i2c/aspeed_i2c.h" #include "hw/ssi/aspeed_smc.h" +#include "hw/misc/aspeed_hace.h" #include "hw/watchdog/wdt_aspeed.h" #include "hw/net/ftgmac100.h" #include "target/arm/cpu.h" @@ -49,6 +50,7 @@ struct AspeedSoCState { AspeedTimerCtrlState timerctrl; AspeedI2CState i2c; AspeedSCUState scu; +AspeedHACEState hace; AspeedXDMAState xdma; AspeedSMCState fmc; AspeedSMCState spi[ASPEED_SPIS_NUM]; @@ -130,6 +132,7 @@ enum { ASPEED_DEV_SDRAM, ASPEED_DEV_XDMA, ASPEED_DEV_EMMC, +ASPEED_DEV_HACE, }; #endif /* ASPEED_SOC_H */ diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index bf31ca351feb..7aba3effd7bc 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -42,6 +42,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_ETH2] = 0x1E68, [ASPEED_DEV_ETH4] = 0x1E69, [ASPEED_DEV_VIC] = 0x1E6C, +[ASPEED_DEV_HACE] = 0x1E6D, [ASPEED_DEV_SDMC] = 0x1E6E, [ASPEED_DEV_SCU] = 0x1E6E2000, [ASPEED_DEV_XDMA] = 0x1E6E7000, @@ -102,6 +103,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_DEV_I2C] = 110, /* 110 -> 125 */ [ASPEED_DEV_ETH1] = 2, [ASPEED_DEV_ETH2] = 3, +[ASPEED_DEV_HACE] = 4, [ASPEED_DEV_ETH3] = 32, [ASPEED_DEV_ETH4] = 33, @@ -211,6 +213,8 @@ static void aspeed_soc_ast2600_init(Object *obj) object_initialize_child(obj, "emmc-controller.sdhci", >emmc.slots[0], TYPE_SYSBUS_SDHCI); + +object_initialize_child(obj, "hace", >hace, TYPE_ASPEED_HACE); } /* @@ -469,6 +473,16 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>emmc), 0, sc->memmap[ASPEED_DEV_EMMC]); sysbus_connect_irq(SYS_BUS_DEVICE(>emmc), 0, aspeed_soc_get_irq(s, ASPEED_DEV_EMMC)); + +/* HACE */ +object_property_set_link(OBJECT(>hace), "dram", OBJECT(s->dram_mr), + _abort); +if (!sysbus_realize(SYS_BUS_DEVICE(>hace), errp)) { +return; +} +sysbus_mmio_map(SYS_BUS_DEVICE(>hace), 0, sc->memmap[ASPEED_DEV_HACE]); +sysbus_connect_irq(SYS_BUS_DEVICE(>hace), 0, + aspeed_soc_get_irq(s, ASPEED_DEV_HACE)); } static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 7eefd54ac07a..ce9b8f8c5d6f 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -34,6 +34,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = { [ASPEED_DEV_VIC]= 0x1E6C, [ASPEED_DEV_SDMC] = 0x1E6E, [ASPEED_DEV_SCU]= 0x1E6E2000, +[ASPEED_DEV_HACE] = 0x1E6E3000, [ASPEED_DEV_XDMA] = 0x1E6E7000, [ASPEED_DEV_VIDEO] = 0x1E70, [ASPEED_DEV_ADC]= 0x1E6E9000, @@ -65,6 +66,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_DEV_VIC]= 0x1E6C, [ASPEED_DEV_SDMC] = 0x1E6E, [ASPEED_DEV_SCU]= 0x1E6E2000, +[ASPEED_DEV_HACE] = 0x1E6E3000, [ASPEED_DEV_XDMA] = 0x1E6E7000, [ASPEED_DEV_ADC]= 0x1E6E9000, [ASPEED_DEV_VIDEO] = 0x1E70, @@ -118,6 +120,7 @@ static const int aspeed_soc_ast2400_irqmap[] = { [ASPEED_DEV_ETH2] = 3, [ASPEED_DEV_XDMA] = 6, [ASPEED_DEV_SDHCI] = 26, +[ASPEED_DEV_HACE] = 4, }; #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -211,6 +214,8 @@ static void aspeed_soc_init(Object *obj) object_initialize_child(obj, "sdhci[*]", >sdhci.slots[i], TYPE_SYSBUS_SDHCI); } + +object_initialize_child(obj, "hace", >hace, TYPE_ASPEED_HACE); }
Re: [PATCH v2 1/1] hw/s390x: modularize virtio-gpu-ccw
Hi, > The only approaches I can think of to make type_register_mayfail() > "work" involve adding a dependency check in type_register_internal() > before the call to type_table_add() is made. This can "work" for modules, > because for types loaded from we can hope, that all dependencies are > already, as modules are loaded relatively late. Yes, for modules the lazy binding should not be needed and we should be able to check for the parent at registration time. module.c keeps track of whenever phase1 init for builtin qom objects did happen already, so we can use that instead of passing mayfail through a bunch of function calls. Quick & dirty test hack below. BTW: "qemu-system-x86_64 -device help" tries to load all modules and is a nice test case ;) HTH, Gerd commit 75ca3012e626318b562bcb51ecdc34400e25f2d0 Author: Gerd Hoffmann Date: Tue Mar 2 16:26:39 2021 +0100 [hack] modular type init check diff --git a/qom/object.c b/qom/object.c index 491823db4a2d..01785e73f495 100644 --- a/qom/object.c +++ b/qom/object.c @@ -135,11 +135,22 @@ static TypeImpl *type_new(const TypeInfo *info) return ti; } +/* HACK: util/module.c */ +extern bool modules_init_done[MODULE_INIT_MAX]; +static TypeImpl *type_get_by_name(const char *name); + static TypeImpl *type_register_internal(const TypeInfo *info) { TypeImpl *ti; ti = type_new(info); +if (modules_init_done[MODULE_INIT_QOM]) { +if (ti->parent && !type_get_by_name(ti->parent)) { +g_free(ti); +return NULL; +} +} + type_table_add(ti); return ti; } diff --git a/util/module.c b/util/module.c index cbe89fede628..b7b519eed62c 100644 --- a/util/module.c +++ b/util/module.c @@ -34,7 +34,7 @@ typedef struct ModuleEntry typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList; static ModuleTypeList init_type_list[MODULE_INIT_MAX]; -static bool modules_init_done[MODULE_INIT_MAX]; +bool modules_init_done[MODULE_INIT_MAX]; static ModuleTypeList dso_init_list;
[PATCH 1/2] hw: Model ASPEED's Hash and Crypto Engine
The HACE (Hash and Crpyto Engine) is a device that offloads MD5, SHA1, SHA2, RSA and other cryptographic algorithms. This initial model implements a subset of the device's functionality; currently only direct access (non-scatter gather) hashing. Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater --- include/hw/misc/aspeed_hace.h | 33 hw/misc/aspeed_hace.c | 302 ++ hw/misc/meson.build | 2 +- 3 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 include/hw/misc/aspeed_hace.h create mode 100644 hw/misc/aspeed_hace.c diff --git a/include/hw/misc/aspeed_hace.h b/include/hw/misc/aspeed_hace.h new file mode 100644 index ..e1fce670ef9e --- /dev/null +++ b/include/hw/misc/aspeed_hace.h @@ -0,0 +1,33 @@ +/* + * ASPEED Hash and Crypto Engine + * + * Copyright (C) 2021 IBM Corp. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ASPEED_HACE_H +#define ASPEED_HACE_H + +#include "hw/sysbus.h" + +#define TYPE_ASPEED_HACE "aspeed.hace" +#define ASPEED_HACE(obj) OBJECT_CHECK(AspeedHACEState, (obj), TYPE_ASPEED_HACE) + +#define ASPEED_HACE_NR_REGS (0x64 >> 2) + +typedef struct AspeedHACEState { +/* */ +SysBusDevice parent; + +/*< public >*/ +MemoryRegion iomem; +qemu_irq irq; + +uint32_t regs[ASPEED_HACE_NR_REGS]; + +MemoryRegion *dram_mr; +AddressSpace dram_as; +} AspeedHACEState; + +#endif /* _ASPEED_HACE_H_ */ diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c new file mode 100644 index ..0e402a0adea9 --- /dev/null +++ b/hw/misc/aspeed_hace.c @@ -0,0 +1,302 @@ +/* + * ASPEED Hash and Crypto Engine + * + * Copyright (C) 2021 IBM Corp. + * + * Joel Stanley + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_hace.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "crypto/hash.h" +#include "hw/qdev-properties.h" +#include "hw/irq.h" + +#define R_STATUS(0x1c / 4) +#define HASH_IRQBIT(9) +#define CRYPT_IRQ BIT(12) +#define TAG_IRQ BIT(15) + +#define R_HASH_CMD (0x30 / 4) +/* Hash algorithim selection */ +#define HASH_ALGO_MASK (BIT(4) | BIT(5) | BIT(6)) +#define HASH_ALGO_MD5 0 +#define HASH_ALGO_SHA1 BIT(5) +#define HASH_ALGO_SHA224 BIT(6) +#define HASH_ALGO_SHA256 (BIT(4) | BIT(6)) +#define HASH_ALGO_SHA512_SERIES(BIT(5) | BIT(6)) +/* SHA512 algorithim selection */ +#define SHA512_HASH_ALGO_MASK (BIT(10) | BIT(11) | BIT(12)) +#define HASH_ALGO_SHA512_SHA5120 +#define HASH_ALGO_SHA512_SHA384BIT(10) +#define HASH_ALGO_SHA512_SHA256BIT(11) +#define HASH_ALGO_SHA512_SHA224(BIT(10) | BIT(11)) +/* HMAC modes */ +#define HASH_HMAC_MASK (BIT(7) | BIT(8)) +#define HASH_DIGEST0 +#define HASH_DIGEST_HMAC BIT(7) +#define HASH_DIGEST_ACCUM BIT(8) +#define HASH_HMAC_KEY (BIT(7) | BIT(8)) +/* Cascscaed operation modes */ +#define HASH_ONLY 0 +#define HASH_ONLY2 BIT(0) +#define HASH_CRYPT_THEN_HASH BIT(1) +#define HASH_HASH_THEN_CRYPT (BIT(0) | BIT(1)) +/* Other cmd bits */ +#define HASH_IRQ_ENBIT(9) +#define HASH_SG_EN BIT(18) + +#define R_CRYPT_CMD (0x10 / 4) + +#define R_HASH_SRC (0x20 / 4) +#define R_HASH_DEST (0x24 / 4) +#define R_HASH_SRC_LEN (0x2c / 4) + +static int do_hash_operation(AspeedHACEState *s, int algo) +{ +hwaddr src, len, dest; +uint8_t *digest_buf = NULL; +size_t digest_len = 0; +char *src_buf; +int rc; + +src = s->regs[R_HASH_SRC]; +len = s->regs[R_HASH_SRC_LEN]; +dest = s->regs[R_HASH_DEST]; + +src_buf = address_space_map(>dram_as, src, , false, +MEMTXATTRS_UNSPECIFIED); +if (!src_buf) { +qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map dram\n", __func__); +return -EACCES; +} + +rc = qcrypto_hash_bytes(algo, src_buf, len, _buf, _len, +_fatal); +if (rc < 0) { +qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto failed\n", __func__); +return rc; +} + +rc = address_space_write(>dram_as, dest, MEMTXATTRS_UNSPECIFIED, + digest_buf, digest_len); +if (rc) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: address space write failed\n", __func__); +} +g_free(digest_buf); + +address_space_unmap(>dram_as, src_buf, len, false, len); + +/* + * Set status bits to indicate completion. Testing shows hardware sets + * these irrespective of HASH_IRQ_EN. + */ +s->regs[R_STATUS] |= HASH_IRQ; + +return 0; +} +
[PATCH 0/2] hw/misc: Model ASPEED hash and crpyto engine
This adds a model for the ASPEED hash and crypto engine (HACE) found on all supported ASPEED SoCs. The model uses Qemu's gcrypto API to perform the SHA and MD5 hashing directly in the machine's emulated memory space, which I found a neat use of Qemu's features. It has been tested using u-boot and from Linux userspace. Joel Stanley (2): hw: Model ASPEED's Hash and Crypto Engine aspeed: Integrate HACE docs/system/arm/aspeed.rst| 2 +- include/hw/arm/aspeed_soc.h | 3 + include/hw/misc/aspeed_hace.h | 33 hw/arm/aspeed_ast2600.c | 14 ++ hw/arm/aspeed_soc.c | 15 ++ hw/misc/aspeed_hace.c | 302 ++ hw/misc/meson.build | 2 +- 7 files changed, 369 insertions(+), 2 deletions(-) create mode 100644 include/hw/misc/aspeed_hace.h create mode 100644 hw/misc/aspeed_hace.c -- 2.30.1
Re: [PATCH 2/3] qapi, audio: respect build time conditions in audio schema
On Tue, Mar 02, 2021 at 05:55:23PM +, Daniel P. Berrangé wrote: > Currently the -audiodev accepts any audiodev type regardless of what is > built in to QEMU. An error only occurs later at runtime when a sound > device tries to use the audio backend. > > With this change QEMU will immediately reject -audiodev args that are > not compiled into the binary. The QMP schema will also be introspectable > to identify what is compiled in. Note that audio backends are modularized, so "compiled with CONFIG_AUDIO_ALSA" doesn't imply "alsa support is available". take care, Gerd
Re: [PATCH v3] vl: deprecate -writeconfig
Paolo Bonzini writes: > The functionality of -writeconfig is limited and the code > does not even try to detect cases where it prints incorrect > syntax (for example if values have a quote in them, since > qemu_config_parse does not support any kind of escaping) > so remove it. > > Signed-off-by: Paolo Bonzini Acked-by: Markus Armbruster
Re: [PATCH v3] target/s390x: Implement the MVPG condition-code-option bit
On 03/03/2021 03.44, Richard Henderson wrote: If the CCO bit is set, MVPG should not generate an exception but report page translation faults via a CC code. Create a new helper, access_prepare_nf, which can use probe_access_flags in non-faulting mode, and then handle watchpoints. Cc: David Hildenbrand Reported-by: Thomas Huth Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 87 --- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 25cfede806..b397333c0b 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -130,28 +130,62 @@ typedef struct S390Access { int mmu_idx; } S390Access; +static bool access_prepare_nf(S390Access *access, CPUS390XState *env, + bool nofault, vaddr vaddr1, int size, + MMUAccessType access_type, + int mmu_idx, uintptr_t ra) +{ +void *haddr1, *haddr2 = NULL; +int size1, size2; +vaddr vaddr2 = 0; +int flags; + +assert(size > 0 && size <= 4096); + +size1 = MIN(size, -(vaddr1 | TARGET_PAGE_MASK)), +size2 = size - size1; + +flags = probe_access_flags(env, vaddr1, access_type, mmu_idx, + nofault, , ra); +if (unlikely(size2)) { +/* The access crosses page boundaries. */ +vaddr2 = wrap_address(env, vaddr1 + size1); +flags |= probe_access_flags(env, vaddr2, access_type, mmu_idx, +nofault, , ra); +} + +if (unlikely(flags & TLB_INVALID_MASK)) { +return false; +} +if (unlikely(flags & TLB_WATCHPOINT)) { +/* S390 does not presently use transaction attributes. */ +cpu_check_watchpoint(env_cpu(env), vaddr1, size, + MEMTXATTRS_UNSPECIFIED, + (access_type == MMU_DATA_STORE + ? BP_MEM_WRITE : BP_MEM_READ), ra); +} + +*access = (S390Access) { +.vaddr1 = vaddr1, +.vaddr2 = vaddr2, +.haddr1 = haddr1, +.haddr2 = haddr2, +.size1 = size1, +.size2 = size2, +.mmu_idx = mmu_idx +}; +return true; +} + static S390Access access_prepare(CPUS390XState *env, vaddr vaddr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t ra) { -S390Access access = { -.vaddr1 = vaddr, -.size1 = MIN(size, -(vaddr | TARGET_PAGE_MASK)), -.mmu_idx = mmu_idx, -}; - -g_assert(size > 0 && size <= 4096); -access.haddr1 = probe_access(env, access.vaddr1, access.size1, access_type, - mmu_idx, ra); - -if (unlikely(access.size1 != size)) { -/* The access crosses page boundaries. */ -access.vaddr2 = wrap_address(env, vaddr + access.size1); -access.size2 = size - access.size1; -access.haddr2 = probe_access(env, access.vaddr2, access.size2, - access_type, mmu_idx, ra); -} -return access; +S390Access ret; +bool ok = access_prepare_nf(, env, false, vaddr, size, +access_type, mmu_idx, ra); +assert(ok); +return ret; } /* Helper to handle memset on a single page. */ @@ -845,8 +879,10 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) const int mmu_idx = cpu_mmu_index(env, false); const bool f = extract64(r0, 11, 1); const bool s = extract64(r0, 10, 1); +const bool cco = extract64(r0, 8, 1); uintptr_t ra = GETPC(); S390Access srca, desta; +bool ok; if ((f && s) || extract64(r0, 12, 4)) { tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC()); @@ -858,13 +894,18 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) /* * TODO: * - Access key handling - * - CC-option with surpression of page-translation exceptions * - Store r1/r2 register identifiers at real location 162 */ -srca = access_prepare(env, r2, TARGET_PAGE_SIZE, MMU_DATA_LOAD, mmu_idx, - ra); -desta = access_prepare(env, r1, TARGET_PAGE_SIZE, MMU_DATA_STORE, mmu_idx, - ra); +ok = access_prepare_nf(, env, cco, r2, TARGET_PAGE_SIZE, + MMU_DATA_LOAD, mmu_idx, ra); +if (!ok) { +return 2; +} +ok = access_prepare_nf(, env, cco, r1, TARGET_PAGE_SIZE, + MMU_DATA_STORE, mmu_idx, ra); +if (!ok) { +return 1; +} Thanks, this looks promising, but one of the MVPG kvm-unit-tests is still failing with this patch - the one that checks for an exception if the destination page is marked as read-only. MVPG only returns CC1 for invalid page table
[Bug 1917565] Re: Windows 10 fails with "Boot device inaccessible"
** Description changed: The issue is happening on all versions I tried after the following commit. I can also remove this individual change from master and it starts to work. + + OVMF_CODE.fd is what comes with Ubuntu 20.04 through package manager. + git diff af1b80ae56c9495999e8ccf7b70ef894378de642~ af1b80ae56c9495999e8ccf7b70ef894378de642 diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b7bc2a..7a5a8b3521 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1497,7 +1497,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, dev = aml_device("PCI0"); aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); aml_append(dev, aml_name_decl("_ADR", aml_int(0))); -aml_append(dev, aml_name_decl("_UID", aml_int(1))); +aml_append(dev, aml_name_decl("_UID", aml_int(0))); aml_append(sb_scope, dev); aml_append(dsdt, sb_scope); @@ -1512,7 +1512,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); aml_append(dev, aml_name_decl("_ADR", aml_int(0))); -aml_append(dev, aml_name_decl("_UID", aml_int(1))); +aml_append(dev, aml_name_decl("_UID", aml_int(0))); aml_append(dev, build_q35_osc_method()); aml_append(sb_scope, dev); aml_append(dsdt, sb_scope); The virtual machine start command: x86_64-softmmu/qemu-system-x86_64 -name guest=win10-dev,debug-threads=on -blockdev '{"driver":"file","filename":"/usr/share/OVMF/OVMF_CODE.fd","node-name":"libvirt-pflash0-storage","auto-read-only":true,"discard":"unmap"}' -blockdev '{"node-name":"libvirt-pflash0-format","read-only":true,"driver":"raw","file":"libvirt-pflash0-storage"}' -blockdev '{"driver":"file","filename":"/var/lib/libvirt/qemu/nvram/win10-dev_VARS.fd","node-name":"libvirt-pflash1-storage","auto-read-only":true,"discard":"unmap"}' -blockdev '{"node-name":"libvirt-pflash1-format","read-only":false,"driver":"raw","file":"libvirt-pflash1-storage"}' -machine pc-q35-4.2,accel=kvm,usb=off,vmport=off,dump-guest-core=off,pflash0=libvirt-pflash0-format,pflash1=libvirt-pflash1-format -cpu Skylake-Client-IBRS,ss=on,vmx=on,pdcm=on,hypervisor=on,tsc-adjust=on,clflushopt=on,umip=on,md-clear=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,pdpe1gb=on,ibpb=on,amd-ssbd=on,skip-l1dfl-vmentry=on,pschange-mc-no=on,hv-time,hv-relaxed,hv-vapic,hv-spinlocks=0x1fff -m 6144 -overcommit mem-lock=off -smp 4,sockets=4,cores=1,threads=1 -uuid 5646e540-5022-4ace-8d6a-d7c4b61a6d3d -no-user-config -nodefaults -rtc base=localtime,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -global ICH9-LPC.disable_s3=1 -global ICH9-LPC.disable_s4=1 -boot strict=on -device pcie-root-port,port=0x10,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,addr=0x2 -device pcie-root-port,port=0x11,chassis=2,id=pci.2,bus=pcie.0,addr=0x2.0x1 -device pcie-root-port,port=0x12,chassis=3,id=pci.3,bus=pcie.0,addr=0x2.0x2 -device pcie-root-port,port=0x13,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x3 -device pcie-root-port,port=0x14,chassis=5,id=pci.5,bus=pcie.0,addr=0x2.0x4 -device qemu-xhci,p2=15,p3=15,id=usb,bus=pci.2,addr=0x0 -device virtio-serial-pci,id=virtio-serial0,bus=pci.3,addr=0x0 -blockdev '{"driver":"host_device","filename":"/dev/disk/by-id/scsi-1SanDisk_Extreme_SSD_20072F404043","aio":"native","node-name":"libvirt-2-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' -blockdev '{"node-name":"libvirt-2-format","read-only":false,"cache":{"direct":true,"no-flush":false},"driver":"raw","file":"libvirt-2-storage"}' -device ide-hd,bus=ide.0,drive=libvirt-2-format,id=sata0-0-0,bootindex=1,write-cache=on -device ide-cd,bus=ide.1,id=sata0-0-1 -netdev user,id=hostnet0 -device e1000e,netdev=hostnet0,id=net0,mac=52:54:00:10:5b:55,bus=pci.1,addr=0x0 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev spicevmc,id=charchannel0,name=vdagent -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=com.redhat.spice.0 -device usb-tablet,id=input0,bus=usb.0,port=1 -spice port=5900,addr=127.0.0.1,disable-ticketing=on,image-compression=off,seamless-migration=on -device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=16,max_outputs=1,bus=pcie.0,addr=0x1 -device ich9-intel-hda,id=sound0,bus=pcie.0,addr=0x1b -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -chardev spicevmc,id=charredir0,name=usbredir -device usb-redir,chardev=charredir0,id=redir0,bus=usb.0,port=2 -chardev spicevmc,id=charredir1,name=usbredir -device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=3 -device virtio-balloon-pci,id=balloon0,bus=pci.4,addr=0x0 -msg timestamp=on -D ./log.txt -monitor stdio -d -- You
[Bug 1917565] Re: Windows 10 fails with "Boot device inaccessible"
** Description changed: The issue is happening on all versions I tried after the following - commit. + commit. I can also remove this individual from master and it starts to + work. git diff af1b80ae56c9495999e8ccf7b70ef894378de642~ af1b80ae56c9495999e8ccf7b70ef894378de642 diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b7bc2a..7a5a8b3521 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1497,7 +1497,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, - dev = aml_device("PCI0"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); - aml_append(dev, aml_name_decl("_ADR", aml_int(0))); + dev = aml_device("PCI0"); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); + aml_append(dev, aml_name_decl("_ADR", aml_int(0))); -aml_append(dev, aml_name_decl("_UID", aml_int(1))); +aml_append(dev, aml_name_decl("_UID", aml_int(0))); - aml_append(sb_scope, dev); - aml_append(dsdt, sb_scope); - + aml_append(sb_scope, dev); + aml_append(dsdt, sb_scope); + @@ -1512,7 +1512,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); - aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); - aml_append(dev, aml_name_decl("_ADR", aml_int(0))); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); + aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); + aml_append(dev, aml_name_decl("_ADR", aml_int(0))); -aml_append(dev, aml_name_decl("_UID", aml_int(1))); +aml_append(dev, aml_name_decl("_UID", aml_int(0))); - aml_append(dev, build_q35_osc_method()); - aml_append(sb_scope, dev); - aml_append(dsdt, sb_scope); + aml_append(dev, build_q35_osc_method()); + aml_append(sb_scope, dev); + aml_append(dsdt, sb_scope); The virtual machine start command: x86_64-softmmu/qemu-system-x86_64 -name guest=win10-dev,debug-threads=on -blockdev '{"driver":"file","filename":"/usr/share/OVMF/OVMF_CODE.fd","node-name":"libvirt-pflash0-storage","auto-read-only":true,"discard":"unmap"}' -blockdev '{"node-name":"libvirt-pflash0-format","read-only":true,"driver":"raw","file":"libvirt-pflash0-storage"}' -blockdev '{"driver":"file","filename":"/var/lib/libvirt/qemu/nvram/win10-dev_VARS.fd","node-name":"libvirt-pflash1-storage","auto-read-only":true,"discard":"unmap"}' -blockdev '{"node-name":"libvirt-pflash1-format","read-only":false,"driver":"raw","file":"libvirt-pflash1-storage"}' -machine pc-q35-4.2,accel=kvm,usb=off,vmport=off,dump-guest-core=off,pflash0=libvirt-pflash0-format,pflash1=libvirt-pflash1-format -cpu Skylake-Client-IBRS,ss=on,vmx=on,pdcm=on,hypervisor=on,tsc-adjust=on,clflushopt=on,umip=on,md-clear=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,pdpe1gb=on,ibpb=on,amd-ssbd=on,skip-l1dfl-vmentry=on,pschange-mc-no=on,hv-time,hv-relaxed,hv-vapic,hv-spinlocks=0x1fff -m 6144 -overcommit mem-lock=off -smp 4,sockets=4,cores=1,threads=1 -uuid 5646e540-5022-4ace-8d6a-d7c4b61a6d3d -no-user-config -nodefaults -rtc base=localtime,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -global ICH9-LPC.disable_s3=1 -global ICH9-LPC.disable_s4=1 -boot strict=on -device pcie-root-port,port=0x10,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,addr=0x2 -device pcie-root-port,port=0x11,chassis=2,id=pci.2,bus=pcie.0,addr=0x2.0x1 -device pcie-root-port,port=0x12,chassis=3,id=pci.3,bus=pcie.0,addr=0x2.0x2 -device pcie-root-port,port=0x13,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x3 -device pcie-root-port,port=0x14,chassis=5,id=pci.5,bus=pcie.0,addr=0x2.0x4 -device qemu-xhci,p2=15,p3=15,id=usb,bus=pci.2,addr=0x0 -device virtio-serial-pci,id=virtio-serial0,bus=pci.3,addr=0x0 -blockdev '{"driver":"host_device","filename":"/dev/disk/by-id/scsi-1SanDisk_Extreme_SSD_20072F404043","aio":"native","node-name":"libvirt-2-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' -blockdev '{"node-name":"libvirt-2-format","read-only":false,"cache":{"direct":true,"no-flush":false},"driver":"raw","file":"libvirt-2-storage"}' -device ide-hd,bus=ide.0,drive=libvirt-2-format,id=sata0-0-0,bootindex=1,write-cache=on -device ide-cd,bus=ide.1,id=sata0-0-1 -netdev user,id=hostnet0 -device e1000e,netdev=hostnet0,id=net0,mac=52:54:00:10:5b:55,bus=pci.1,addr=0x0 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev spicevmc,id=charchannel0,name=vdagent -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=com.redhat.spice.0 -device usb-tablet,id=input0,bus=usb.0,port=1 -spice port=5900,addr=127.0.0.1,disable-ticketing=on,image-compression=off,seamless-migration=on -device
Re: [PATCH v3 07/27] cpu: Introduce SysemuCPUOps structure
On 3/2/21 6:57 AM, Philippe Mathieu-Daudé wrote: +static struct SysemuCPUOps alpha_sysemu_ops = { const, for all of them. r~
Re: [Bug 1917565] [NEW] Windows 10 fails with "Boot device inaccessible"
Patchew URL: https://patchew.org/QEMU/161474788220.8516.15014999465847517073.malone...@gac.canonical.com/ Hi, This series seems to have some coding style problems. See output below for more information: Type: series Message-id: 161474788220.8516.15014999465847517073.malone...@gac.canonical.com Subject: [Bug 1917565] [NEW] Windows 10 fails with "Boot device inaccessible" === TEST SCRIPT BEGIN === #!/bin/bash git rev-parse base > /dev/null || exit 0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram ./scripts/checkpatch.pl --mailback base.. === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 From https://github.com/patchew-project/qemu * [new tag] patchew/161474788220.8516.15014999465847517073.malone...@gac.canonical.com -> patchew/161474788220.8516.15014999465847517073.malone...@gac.canonical.com Switched to a new branch 'test' === OUTPUT BEGIN === checkpatch.pl: no revisions returned for revlist 'base..' === OUTPUT END === Test command exited with code: 255 The full log is available at http://patchew.org/logs/161474788220.8516.15014999465847517073.malone...@gac.canonical.com/testing.checkpatch/?type=message. --- Email generated automatically by Patchew [https://patchew.org/]. Please send your feedback to patchew-de...@redhat.com
[Bug 1917565] [NEW] Windows 10 fails with "Boot device inaccessible"
Public bug reported: The issue is happening on all versions I tried after the following commit. git diff af1b80ae56c9495999e8ccf7b70ef894378de642~ af1b80ae56c9495999e8ccf7b70ef894378de642 diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b7bc2a..7a5a8b3521 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1497,7 +1497,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, dev = aml_device("PCI0"); aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); aml_append(dev, aml_name_decl("_ADR", aml_int(0))); -aml_append(dev, aml_name_decl("_UID", aml_int(1))); +aml_append(dev, aml_name_decl("_UID", aml_int(0))); aml_append(sb_scope, dev); aml_append(dsdt, sb_scope); @@ -1512,7 +1512,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); aml_append(dev, aml_name_decl("_ADR", aml_int(0))); -aml_append(dev, aml_name_decl("_UID", aml_int(1))); +aml_append(dev, aml_name_decl("_UID", aml_int(0))); aml_append(dev, build_q35_osc_method()); aml_append(sb_scope, dev); aml_append(dsdt, sb_scope); The virtual machine start command: x86_64-softmmu/qemu-system-x86_64 -name guest=win10-dev,debug-threads=on -blockdev '{"driver":"file","filename":"/usr/share/OVMF/OVMF_CODE.fd","node-name":"libvirt-pflash0-storage","auto-read-only":true,"discard":"unmap"}' -blockdev '{"node-name":"libvirt-pflash0-format","read-only":true,"driver":"raw","file":"libvirt-pflash0-storage"}' -blockdev '{"driver":"file","filename":"/var/lib/libvirt/qemu/nvram/win10-dev_VARS.fd","node-name":"libvirt-pflash1-storage","auto-read-only":true,"discard":"unmap"}' -blockdev '{"node-name":"libvirt-pflash1-format","read-only":false,"driver":"raw","file":"libvirt-pflash1-storage"}' -machine pc-q35-4.2,accel=kvm,usb=off,vmport=off,dump-guest-core=off,pflash0=libvirt-pflash0-format,pflash1=libvirt-pflash1-format -cpu Skylake-Client-IBRS,ss=on,vmx=on,pdcm=on,hypervisor=on,tsc-adjust=on,clflushopt=on,umip=on,md-clear=on,stibp=on,arch-capabilities=on,ssbd=on,xsaves=on,pdpe1gb=on,ibpb=on,amd-ssbd=on,skip-l1dfl-vmentry=on,pschange-mc-no=on,hv-time,hv-relaxed,hv-vapic,hv-spinlocks=0x1fff -m 6144 -overcommit mem-lock=off -smp 4,sockets=4,cores=1,threads=1 -uuid 5646e540-5022-4ace-8d6a-d7c4b61a6d3d -no-user-config -nodefaults -rtc base=localtime,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -global ICH9-LPC.disable_s3=1 -global ICH9-LPC.disable_s4=1 -boot strict=on -device pcie-root-port,port=0x10,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,addr=0x2 -device pcie-root-port,port=0x11,chassis=2,id=pci.2,bus=pcie.0,addr=0x2.0x1 -device pcie-root-port,port=0x12,chassis=3,id=pci.3,bus=pcie.0,addr=0x2.0x2 -device pcie-root-port,port=0x13,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x3 -device pcie-root-port,port=0x14,chassis=5,id=pci.5,bus=pcie.0,addr=0x2.0x4 -device qemu-xhci,p2=15,p3=15,id=usb,bus=pci.2,addr=0x0 -device virtio-serial-pci,id=virtio-serial0,bus=pci.3,addr=0x0 -blockdev '{"driver":"host_device","filename":"/dev/disk/by-id/scsi-1SanDisk_Extreme_SSD_20072F404043","aio":"native","node-name":"libvirt-2-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' -blockdev '{"node-name":"libvirt-2-format","read-only":false,"cache":{"direct":true,"no-flush":false},"driver":"raw","file":"libvirt-2-storage"}' -device ide-hd,bus=ide.0,drive=libvirt-2-format,id=sata0-0-0,bootindex=1,write-cache=on -device ide-cd,bus=ide.1,id=sata0-0-1 -netdev user,id=hostnet0 -device e1000e,netdev=hostnet0,id=net0,mac=52:54:00:10:5b:55,bus=pci.1,addr=0x0 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev spicevmc,id=charchannel0,name=vdagent -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=com.redhat.spice.0 -device usb-tablet,id=input0,bus=usb.0,port=1 -spice port=5900,addr=127.0.0.1,disable-ticketing=on,image-compression=off,seamless-migration=on -device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=16,max_outputs=1,bus=pcie.0,addr=0x1 -device ich9-intel-hda,id=sound0,bus=pcie.0,addr=0x1b -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -chardev spicevmc,id=charredir0,name=usbredir -device usb-redir,chardev=charredir0,id=redir0,bus=usb.0,port=2 -chardev spicevmc,id=charredir1,name=usbredir -device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=3 -device virtio-balloon-pci,id=balloon0,bus=pci.4,addr=0x0 -msg timestamp=on -D ./log.txt -monitor stdio -d ** Affects: qemu Importance: Undecided Status: New ** Tags: 10 boot device inaccessible windows -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU.
[PATCH V2 7/7] net/net.c: Add handler for COLO passthrough connection
From: Zhang Chen Use connection protocol,src port,dst port,src ip,dst ip as the key to bypass certain network traffic in COLO compare. Signed-off-by: Zhang Chen --- net/net.c | 147 ++ 1 file changed, 147 insertions(+) diff --git a/net/net.c b/net/net.c index 037dcc5973..bb2fb1d8b5 100644 --- a/net/net.c +++ b/net/net.c @@ -55,6 +55,8 @@ #include "sysemu/sysemu.h" #include "net/filter.h" #include "qapi/string-output-visitor.h" +#include "net/colo-compare.h" +#include "qom/object_interfaces.h" /* Net bridge is currently not supported for W32. */ #if !defined(_WIN32) @@ -1151,14 +1153,159 @@ void qmp_netdev_del(const char *id, Error **errp) qemu_del_net_client(nc); } +static CompareState *colo_passthrough_check(L4_Connection *conn, Error **errp) +{ +Object *container; +Object *obj; +CompareState *s; + +if (!conn->id) { +error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id", + "Need input colo-compare object id"); +return NULL; +} + +container = object_get_objects_root(); +obj = object_resolve_path_component(container, conn->id); +if (!obj) { +error_setg(errp, "colo-compare '%s' not found", conn->id); +return NULL; +} + +s = COLO_COMPARE(obj); + +if (conn->protocol == -1) { +error_setg(errp, "COLO pass through get wrong protocol"); +return NULL; +} + +if ((conn->src_ip && !qemu_isdigit(conn->src_ip[0])) || +(conn->dst_ip && !qemu_isdigit(conn->dst_ip[0]))) { +error_setg(errp, "COLO pass through get wrong IP"); +return NULL; +} + +if (conn->src_port > 65536 || conn->src_port < 0 || +conn->dst_port > 65536 || conn->dst_port < 0) { +error_setg(errp, "COLO pass through get wrong port"); +return NULL; +} + +return s; +} + +static void compare_passthrough_add(CompareState *s, +L4_Connection *conn, +Error **errp) +{ +PassthroughEntry *bypass = NULL, *next = NULL, *origin = NULL; + +bypass = g_new0(PassthroughEntry, 1); + +bypass->l4_protocol = conn->protocol; +bypass->src_port = conn->src_port; +bypass->dst_port = conn->dst_port; + +if (!inet_aton(conn->src_ip, >src_ip)) { +bypass->src_ip.s_addr = 0; +} + +if (!inet_aton(conn->dst_ip, >dst_ip)) { +bypass->dst_ip.s_addr = 0; +} + +if (!QLIST_EMPTY(>passthroughlist)) { +QLIST_FOREACH_SAFE(origin, >passthroughlist, node, next) { +if ((bypass->l4_protocol == origin->l4_protocol) && +(bypass->src_port == origin->src_port) && +(bypass->src_ip.s_addr == origin->src_ip.s_addr) && +(bypass->dst_ip.s_addr == origin->dst_ip.s_addr)) { +error_setg(errp, "The pass through connection already exists"); +g_free(bypass); +return; +} +} +} + +QLIST_INSERT_HEAD(>passthroughlist, bypass, node); +} + +static void compare_passthrough_del(CompareState *s, +L4_Connection *conn, +Error **errp) +{ +PassthroughEntry *bypass = NULL, *next = NULL, *origin = NULL; + +bypass = g_new0(PassthroughEntry, 1); + +bypass->l4_protocol = conn->protocol; +bypass->src_port = conn->src_port; +bypass->dst_port = conn->dst_port; + +if (!inet_aton(conn->src_ip, >src_ip)) { +bypass->src_ip.s_addr = 0; +} + +if (!inet_aton(conn->dst_ip, >dst_ip)) { +bypass->dst_ip.s_addr = 0; +} + +if (!QLIST_EMPTY(>passthroughlist)) { +QLIST_FOREACH_SAFE(origin, >passthroughlist, node, next) { +if ((bypass->l4_protocol == origin->l4_protocol) && +(bypass->src_port == origin->src_port) && +(bypass->src_ip.s_addr == origin->src_ip.s_addr) && +(bypass->dst_ip.s_addr == origin->dst_ip.s_addr)) { +QLIST_REMOVE(origin, node); +g_free(origin); +g_free(bypass); +return; +} +} +error_setg(errp, "The pass through list can't find the connection"); +} else { +error_setg(errp, "The pass through connection list is empty"); +} + +g_free(bypass); +} + void qmp_colo_passthrough_add(L4_Connection *conn, Error **errp) { /* Setup passthrough connection */ +CompareState *s; +Error *err = NULL; + +s = colo_passthrough_check(conn, ); +if (err) { +error_propagate(errp, err); +return; +} + +compare_passthrough_add(s, conn, ); +if (err) { +error_propagate(errp, err); +return; +} } void qmp_colo_passthrough_del(L4_Connection *conn, Error **errp) { /* Delete passthrough connection */ +CompareState *s; +Error *err = NULL; + +s =
[PATCH V2 6/7] net/colo-compare: Add passthrough list to CompareState
From: Zhang Chen Add passthrough list for each CompareState. Signed-off-by: Zhang Chen --- net/colo-compare.c | 25 + net/colo-compare.h | 10 ++ 2 files changed, 35 insertions(+) diff --git a/net/colo-compare.c b/net/colo-compare.c index a803f8b888..80cea32c20 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -141,6 +141,7 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) ConnectionKey key; Packet *pkt = NULL; Connection *conn; +PassthroughEntry *bypass, *next; int ret; if (mode == PRIMARY_IN) { @@ -160,6 +161,29 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) } fill_connection_key(pkt, ); +/* Check COLO passthrough connenction */ +if (!QLIST_EMPTY(>passthroughlist)) { +QLIST_FOREACH_SAFE(bypass, >passthroughlist, node, next) { +if (((key.ip_proto == IPPROTO_TCP) && (bypass->l4_protocol == 0)) || +((key.ip_proto == IPPROTO_UDP) && (bypass->l4_protocol == 1))) { +if (bypass->src_port == 0 || bypass->src_port == key.dst_port) { +if (bypass->src_ip.s_addr == 0 || +bypass->src_ip.s_addr == key.src.s_addr) { +if (bypass->dst_port == 0 || +bypass->dst_port == key.src_port) { +if (bypass->dst_ip.s_addr == 0 || +bypass->dst_ip.s_addr == key.dst.s_addr) { +packet_destroy(pkt, NULL); +pkt = NULL; +return -1; +} +} +} +} +} +} +} + conn = connection_get(s->connection_track_table, , >conn_list); @@ -1224,6 +1248,7 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) } g_queue_init(>conn_list); +QLIST_INIT(>passthroughlist); s->connection_track_table = g_hash_table_new_full(connection_key_hash, connection_key_equal, diff --git a/net/colo-compare.h b/net/colo-compare.h index 2a9dcac0a7..31644f145b 100644 --- a/net/colo-compare.h +++ b/net/colo-compare.h @@ -54,6 +54,15 @@ typedef struct SendEntry { uint8_t *buf; } SendEntry; +typedef struct PassthroughEntry { +int l4_protocol; +int src_port; +int dst_port; +struct in_addr src_ip; +struct in_addr dst_ip; +QLIST_ENTRY(PassthroughEntry) node; +} PassthroughEntry; + /* * + CompareState ++ * | | @@ -110,6 +119,7 @@ struct CompareState { QEMUBH *event_bh; enum colo_event event; +QLIST_HEAD(, PassthroughEntry) passthroughlist; QTAILQ_ENTRY(CompareState) next; }; -- 2.25.1
[PATCH V2 0/7] Bypass specific network traffic in COLO
From: Zhang Chen Since the real user scenario does not need to monitor all traffic. This series give user ability to bypass kinds of network stream. V2: - Add some qapi definitions. - Support multi colo-compare objects. - Support setup each rules for each objects individually. - Clean up COLO compare definition to .h file. - Rebase HMP command for stable tree. - Add redundant rules check. Zhang Chen (7): qapi/net.json: Add IP_PROTOCOL definition qapi/net.json: Add L4_Connection definition qapi/net: Add new QMP command for COLO passthrough hmp-commands: Add new HMP command for COLO passthrough net/colo-compare: Move data structure and define to .h file. net/colo-compare: Add passthrough list to CompareState net/net.c: Add handler for COLO passthrough connection hmp-commands.hx | 26 +++ include/monitor/hmp.h | 2 + monitor/hmp-cmds.c| 34 + net/colo-compare.c| 131 +++ net/colo-compare.h| 116 +++ net/net.c | 157 ++ qapi/net.json | 96 ++ 7 files changed, 456 insertions(+), 106 deletions(-) -- 2.25.1
[PATCH V2 5/7] net/colo-compare: Move data structure and define to .h file.
From: Zhang Chen Make other modules can reuse COLO code. Signed-off-by: Zhang Chen --- net/colo-compare.c | 106 - net/colo-compare.h | 106 + 2 files changed, 106 insertions(+), 106 deletions(-) diff --git a/net/colo-compare.c b/net/colo-compare.c index 84db4978ac..a803f8b888 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -17,44 +17,24 @@ #include "qemu/error-report.h" #include "trace.h" #include "qapi/error.h" -#include "net/net.h" #include "net/eth.h" #include "qom/object_interfaces.h" #include "qemu/iov.h" #include "qom/object.h" #include "net/queue.h" -#include "chardev/char-fe.h" #include "qemu/sockets.h" -#include "colo.h" -#include "sysemu/iothread.h" #include "net/colo-compare.h" -#include "migration/colo.h" -#include "migration/migration.h" #include "util.h" #include "block/aio-wait.h" #include "qemu/coroutine.h" -#define TYPE_COLO_COMPARE "colo-compare" -typedef struct CompareState CompareState; -DECLARE_INSTANCE_CHECKER(CompareState, COLO_COMPARE, - TYPE_COLO_COMPARE) - static QTAILQ_HEAD(, CompareState) net_compares = QTAILQ_HEAD_INITIALIZER(net_compares); static NotifierList colo_compare_notifiers = NOTIFIER_LIST_INITIALIZER(colo_compare_notifiers); -#define COMPARE_READ_LEN_MAX NET_BUFSIZE -#define MAX_QUEUE_SIZE 1024 - -#define COLO_COMPARE_FREE_PRIMARY 0x01 -#define COLO_COMPARE_FREE_SECONDARY 0x02 - -#define REGULAR_PACKET_CHECK_MS 1000 -#define DEFAULT_TIME_OUT_MS 3000 - /* #define DEBUG_COLO_PACKETS */ static QemuMutex colo_compare_mutex; @@ -64,92 +44,6 @@ static QemuCond event_complete_cond; static int event_unhandled_count; static uint32_t max_queue_size; -/* - * + CompareState ++ - * | | - * +---+ +---+ +---+ - * | conn list + - > conn + --- > conn + -- > .. - * +---+ +---+ +---+ - * | | | | | | - * +---+ +---v+ +---v++---v+ +---v+ - *|primary | |secondary|primary | |secondary - *|packet | |packet +|packet | |packet + - *++ ++++ ++ - *| | | | - *+---v+ +---v++---v+ +---v+ - *|primary | |secondary|primary | |secondary - *|packet | |packet +|packet | |packet + - *++ ++++ ++ - *| | | | - *+---v+ +---v++---v+ +---v+ - *|primary | |secondary|primary | |secondary - *|packet | |packet +|packet | |packet + - *++ ++++ ++ - */ - -typedef struct SendCo { -Coroutine *co; -struct CompareState *s; -CharBackend *chr; -GQueue send_list; -bool notify_remote_frame; -bool done; -int ret; -} SendCo; - -typedef struct SendEntry { -uint32_t size; -uint32_t vnet_hdr_len; -uint8_t *buf; -} SendEntry; - -struct CompareState { -Object parent; - -char *pri_indev; -char *sec_indev; -char *outdev; -char *notify_dev; -CharBackend chr_pri_in; -CharBackend chr_sec_in; -CharBackend chr_out; -CharBackend chr_notify_dev; -SocketReadState pri_rs; -SocketReadState sec_rs; -SocketReadState notify_rs; -SendCo out_sendco; -SendCo notify_sendco; -bool vnet_hdr; -uint64_t compare_timeout; -uint32_t expired_scan_cycle; - -/* - * Record the connection that through the NIC - * Element type: Connection - */ -GQueue conn_list; -/* Record the connection without repetition */ -GHashTable *connection_track_table; - -IOThread *iothread; -GMainContext *worker_context; -QEMUTimer *packet_check_timer; - -QEMUBH *event_bh; -enum colo_event event; - -QTAILQ_ENTRY(CompareState) next; -}; - -typedef struct CompareClass { -ObjectClass parent_class; -} CompareClass; - -enum { -PRIMARY_IN = 0, -SECONDARY_IN, -}; - static const char *colo_mode[] = { [PRIMARY_IN] = "primary", [SECONDARY_IN] = "secondary", diff --git a/net/colo-compare.h b/net/colo-compare.h index 22ddd512e2..2a9dcac0a7 100644 --- a/net/colo-compare.h +++ b/net/colo-compare.h @@ -17,6 +17,112 @@ #ifndef QEMU_COLO_COMPARE_H #define QEMU_COLO_COMPARE_H +#include "net/net.h" +#include "chardev/char-fe.h" +#include "migration/colo.h" +#include "migration/migration.h" +#include "sysemu/iothread.h" +#include "colo.h" + +#define TYPE_COLO_COMPARE "colo-compare" +typedef struct
[PATCH V2 4/7] hmp-commands: Add new HMP command for COLO passthrough
From: Zhang Chen Add hmp_colo_passthrough_add and hmp_colo_passthrough_del make user can maintain COLO network passthrough list in human monitor. Signed-off-by: Zhang Chen --- hmp-commands.hx | 26 ++ include/monitor/hmp.h | 2 ++ monitor/hmp-cmds.c| 34 ++ 3 files changed, 62 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index 73e0832ea1..c71521303c 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1341,6 +1341,32 @@ SRST Remove host network device. ERST +{ +.name = "colo_passthrough_add", +.args_type = "protocol:s,id:s?,src_ip:s?,dst_ip:s?,src_port:i?,dst_port:i?", +.params = "protocol [id] [src_ip] [dst_ip] [src_port] [dst_port]", +.help = "Add network stream to colo passthrough list", +.cmd= hmp_colo_passthrough_add, +}, + +SRST +``colo_passthrough_add`` + Add network stream to colo passthrough list. +ERST + +{ +.name = "colo_passthrough_del", +.args_type = "protocol:s,id:s?,src_ip:s?,dst_ip:s?,src_port:i?,dst_port:i?", +.params = "protocol [id] [src_ip] [dst_ip] [src_port] [dst_port]", +.help = "Delete network stream from colo passthrough list", +.cmd= hmp_colo_passthrough_del, +}, + +SRST +``colo_passthrough_del`` + Delete network stream from colo passthrough list. +ERST + { .name = "object_add", .args_type = "object:O", diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index ed2913fd18..3c4943b09f 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -81,6 +81,8 @@ void hmp_device_del(Monitor *mon, const QDict *qdict); void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict); void hmp_netdev_add(Monitor *mon, const QDict *qdict); void hmp_netdev_del(Monitor *mon, const QDict *qdict); +void hmp_colo_passthrough_add(Monitor *mon, const QDict *qdict); +void hmp_colo_passthrough_del(Monitor *mon, const QDict *qdict); void hmp_getfd(Monitor *mon, const QDict *qdict); void hmp_closefd(Monitor *mon, const QDict *qdict); void hmp_sendkey(Monitor *mon, const QDict *qdict); diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index fd4d77e246..de675d16e7 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -1660,6 +1660,40 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } +void hmp_colo_passthrough_add(Monitor *mon, const QDict *qdict) +{ +const char *prot = qdict_get_str(qdict, "protocol"); +L4_Connection *l4_conn = g_new0(L4_Connection, 1); +Error *err = NULL; + +l4_conn->id = g_strdup(qdict_get_try_str(qdict, "id")); +l4_conn->protocol = qapi_enum_parse(_PROTOCOL_lookup, prot, -1, ); +l4_conn->src_ip = g_strdup(qdict_get_try_str(qdict, "src_ip")); +l4_conn->dst_ip = g_strdup(qdict_get_try_str(qdict, "dst_ip")); +l4_conn->src_port = qdict_get_try_int(qdict, "src_port", 0); +l4_conn->dst_port = qdict_get_try_int(qdict, "dst_port", 0); + +qmp_colo_passthrough_add(l4_conn, ); +hmp_handle_error(mon, err); +} + +void hmp_colo_passthrough_del(Monitor *mon, const QDict *qdict) +{ +const char *prot = qdict_get_str(qdict, "protocol"); +L4_Connection *l4_conn = g_new0(L4_Connection, 1); +Error *err = NULL; + +l4_conn->id = g_strdup(qdict_get_try_str(qdict, "id")); +l4_conn->protocol = qapi_enum_parse(_PROTOCOL_lookup, prot, -1, ); +l4_conn->src_ip = g_strdup(qdict_get_try_str(qdict, "src_ip")); +l4_conn->dst_ip = g_strdup(qdict_get_try_str(qdict, "dst_ip")); +l4_conn->src_port = qdict_get_try_int(qdict, "src_port", 0); +l4_conn->dst_port = qdict_get_try_int(qdict, "dst_port", 0); + +qmp_colo_passthrough_del(l4_conn, ); +hmp_handle_error(mon, err); +} + void hmp_object_add(Monitor *mon, const QDict *qdict) { Error *err = NULL; -- 2.25.1
[PATCH V2 2/7] qapi/net.json: Add L4_Connection definition
From: Zhang Chen Add L4_Connection struct for other QMP commands. Except protocol field is necessary, other fields are optional. Signed-off-by: Zhang Chen --- qapi/net.json | 26 ++ 1 file changed, 26 insertions(+) diff --git a/qapi/net.json b/qapi/net.json index dc4c87dc7b..b4958447f2 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -744,3 +744,29 @@ ## { 'enum': 'IP_PROTOCOL', 'data': [ 'tcp', 'udp', 'dccp', 'sctp', 'udplite', 'icmp', 'igmp', 'ipv6' ] } + +## +# @L4_Connection: +# +# Layer 4 network connection. +# +# Just for IPv4. +# +# @protocol: Transport layer protocol like TCP/UDP... +# +# @id: For specific module with Qemu object ID, If there is no such part, +# it means global rules. +# +# @src_ip: Source IP. +# +# @dst_ip: Destination IP. +# +# @src_port: Source port. +# +# @dst_port: Destination port. +# +# Since: 6.0 +## +{ 'struct': 'L4_Connection', + 'data': { 'protocol': 'IP_PROTOCOL', '*id': 'str', '*src_ip': 'str', '*dst_ip': 'str', +'*src_port': 'int', '*dst_port': 'int' } } -- 2.25.1
[PATCH V2 1/7] qapi/net.json: Add IP_PROTOCOL definition
From: Zhang Chen Add IP_PROTOCOL as enum include TCP,UDP, ICMP... for other QMP commands. Signed-off-by: Zhang Chen --- qapi/net.json | 30 ++ 1 file changed, 30 insertions(+) diff --git a/qapi/net.json b/qapi/net.json index c31748c87f..dc4c87dc7b 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -714,3 +714,33 @@ ## { 'event': 'FAILOVER_NEGOTIATED', 'data': {'device-id': 'str'} } + +## +# @IP_PROTOCOL: +# +# Transport layer protocol. +# +# Just for IPv4. +# +# @tcp: Transmission Control Protocol. +# +# @udp: User Datagram Protocol. +# +# @dccp: Datagram Congestion Control Protocol. +# +# @sctp: Stream Control Transmission Protocol. +# +# @udplite: Lightweight User Datagram Protocol. +# +# @icmp: Internet Control Message Protocol. +# +# @igmp: Internet Group Management Protocol. +# +# @ipv6: IPv6 Encapsulation. +# +# TODO: Need to add more transport layer protocol. +# +# Since: 6.0 +## +{ 'enum': 'IP_PROTOCOL', 'data': [ 'tcp', 'udp', 'dccp', 'sctp', 'udplite', +'icmp', 'igmp', 'ipv6' ] } -- 2.25.1
[PATCH V2 3/7] qapi/net: Add new QMP command for COLO passthrough
From: Zhang Chen Since the real user scenario does not need COLO to monitor all traffic. Add colo-passthrough-add and colo-passthrough-del to maintain a COLO network passthrough list. Signed-off-by: Zhang Chen --- net/net.c | 10 ++ qapi/net.json | 40 2 files changed, 50 insertions(+) diff --git a/net/net.c b/net/net.c index e1035f21d1..037dcc5973 100644 --- a/net/net.c +++ b/net/net.c @@ -1151,6 +1151,16 @@ void qmp_netdev_del(const char *id, Error **errp) qemu_del_net_client(nc); } +void qmp_colo_passthrough_add(L4_Connection *conn, Error **errp) +{ +/* Setup passthrough connection */ +} + +void qmp_colo_passthrough_del(L4_Connection *conn, Error **errp) +{ +/* Delete passthrough connection */ +} + static void netfilter_print_info(Monitor *mon, NetFilterState *nf) { char *str; diff --git a/qapi/net.json b/qapi/net.json index b4958447f2..e0c6e1d8f3 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -770,3 +770,43 @@ { 'struct': 'L4_Connection', 'data': { 'protocol': 'IP_PROTOCOL', '*id': 'str', '*src_ip': 'str', '*dst_ip': 'str', '*src_port': 'int', '*dst_port': 'int' } } + +## +# @colo-passthrough-add: +# +# Add passthrough entry according to customer's needs in COLO-compare. +# +# Returns: Nothing on success +# +# Since: 6.0 +# +# Example: +# +# -> { "execute": "colo-passthrough-add", +# "arguments": { "protocol": "tcp", "id": "object0", "src_ip": "192.168.1.1", +# "dst_ip": "192.168.1.2", "src_port": 1234, "dst_port": 4321 } } +# <- { "return": {} } +# +## +{ 'command': 'colo-passthrough-add', 'boxed': true, + 'data': 'L4_Connection' } + +## +# @colo-passthrough-del: +# +# Delete passthrough entry according to customer's needs in COLO-compare. +# +# Returns: Nothing on success +# +# Since: 6.0 +# +# Example: +# +# -> { "execute": "colo-passthrough-del", +# "arguments": { "protocol": "tcp", "id": "object0", "src_ip": "192.168.1.1", +# "dst_ip": "192.168.1.2", "src_port": 1234, "dst_port": 4321 } } +# <- { "return": {} } +# +## +{ 'command': 'colo-passthrough-del', 'boxed': true, + 'data': 'L4_Connection' } -- 2.25.1
RE: [PATCH v3 02/21] sd: emmc: Add support for eMMC cards
Hi Cedric, > -Original Message- > From: Cédric Le Goater > Sent: Monday, March 1, 2021 4:32 PM > To: Sai Pavan Boddu ; Markus Armbruster > ; Kevin Wolf ; Max Reitz > ; Vladimir Sementsov-Ogievskiy > ; Eric Blake ; Joel Stanley > ; Vincent Palatin ; Dr. David Alan > Gilbert ; Thomas Huth ; Stefan > Hajnoczi ; Peter Maydell ; > Alistair Francis ; Edgar Iglesias > ; > Luc Michel ; Paolo Bonzini > > Cc: qemu-bl...@nongnu.org; qemu-devel@nongnu.org; Sai Pavan Boddu > > Subject: Re: [PATCH v3 02/21] sd: emmc: Add support for eMMC cards > > On 2/28/21 8:33 PM, Sai Pavan Boddu wrote: > > Add eMMC device built on top of SD card. > > > > Signed-off-by: Sai Pavan Boddu > > --- > > include/hw/sd/sd.h | 2 ++ > > hw/sd/sd.c | 20 > > 2 files changed, 22 insertions(+) > > > > diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index > > 05ef9b7..b402dad 100644 > > --- a/include/hw/sd/sd.h > > +++ b/include/hw/sd/sd.h > > @@ -90,6 +90,8 @@ typedef struct { > > } SDRequest; > > > > > > +#define TYPE_EMMC "emmc" > > +OBJECT_DECLARE_SIMPLE_TYPE(EMMCState, EMMC) > > #define TYPE_SD_CARD "sd-card" > > OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD) > > > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > > index 74b9162..a23af6d 100644 > > --- a/hw/sd/sd.c > > +++ b/hw/sd/sd.c > > @@ -108,6 +108,7 @@ struct SDState { > > uint8_t spec_version; > > BlockBackend *blk; > > bool spi; > > +bool emmc; > > > > /* Runtime changeables */ > > > > @@ -143,6 +144,10 @@ struct SDState { > > bool cmd_line; > > }; > > > > +struct EMMCState { > > +SDState parent; > > +}; > > + > > static void sd_realize(DeviceState *dev, Error **errp); > > > > static const char *sd_state_name(enum SDCardStates state) @@ -2105,6 > > +2110,13 @@ static void sd_instance_init(Object *obj) > > sd->ocr_power_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, > > sd_ocr_powerup, sd); } > > > > +static void emmc_instance_init(Object *obj) { > > +SDState *sd = SD_CARD(obj); > > + > > +sd->emmc = true; > > +} > I think field 'emmc' would fit better in SDCardClass since it is a device > constant. > You should not need 'struct EMMCState'. So something like below. > Then you can add handlers for specific emmc commands. > > Thanks, > > C. > > > diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index > 47360ba4ee98..80e7cd526a57 100644 > --- a/include/hw/sd/sd.h > +++ b/include/hw/sd/sd.h > @@ -93,6 +93,8 @@ typedef struct { > #define TYPE_SD_CARD "sd-card" > OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD) > > +#define TYPE_EMMC "emmc" > + > struct SDCardClass { > /*< private >*/ > DeviceClass parent_class; > @@ -124,6 +126,8 @@ struct SDCardClass { > void (*enable)(SDState *sd, bool enable); > bool (*get_inserted)(SDState *sd); > bool (*get_readonly)(SDState *sd); > + > +bool emmc; > }; > > #define TYPE_SD_BUS "sd-bus" > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > index 660026f2a667..95608f11b36e 100644 > --- a/hw/sd/sd.c > +++ b/hw/sd/sd.c > @@ -2447,9 +2447,24 @@ static const TypeInfo sd_info = { > .instance_finalize = sd_instance_finalize, }; > > +static void emmc_class_init(ObjectClass *klass, void *data) { > +SDCardClass *sc = SD_CARD_CLASS(klass); > + > +sc->emmc = true; > +} > + > +static const TypeInfo emmc_info = { > +.name = TYPE_EMMC, > +.parent = TYPE_SD_CARD, > +.instance_size = sizeof(SDState), > +.class_init = emmc_class_init, > +}; > + [Sai Pavan Boddu] Yes, I see your point. Let me try, I was preferring a simpler approach just to not disturb the code much but lets see how this workout. Thanks, Sai Pavan > static void sd_register_types(void) > { > type_register_static(_info); > +type_register_static(_info); > } > > type_init(sd_register_types)
RE: [PATCH v3 12/21] sd: emmc: add CMD21 tuning sequence
Hi David, > -Original Message- > From: Dr. David Alan Gilbert > Sent: Monday, March 1, 2021 4:12 PM > To: Sai Pavan Boddu > Cc: Markus Armbruster ; Kevin Wolf > ; Max Reitz ; Vladimir Sementsov- > Ogievskiy ; Eric Blake ; > Joel Stanley ; Cédric Le Goater ; Vincent > Palatin ; Thomas Huth ; Stefan > Hajnoczi ; Peter Maydell ; > Alistair Francis ; Edgar Iglesias > ; > Luc Michel ; Paolo Bonzini > ; qemu-bl...@nongnu.org; qemu-devel@nongnu.org; > Sai Pavan Boddu > Subject: Re: [PATCH v3 12/21] sd: emmc: add CMD21 tuning sequence > > * Sai Pavan Boddu (sai.pavan.bo...@xilinx.com) wrote: > > eMMC cards support tuning sequence for entering HS200 mode. > > > > Signed-off-by: Sai Pavan Boddu > > Signed-off-by: Edgar E. Iglesias > > --- > > hw/sd/sd.c | 47 +++ > > 1 file changed, 47 insertions(+) > > > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > > index bf963ec..174c28e 100644 > > --- a/hw/sd/sd.c > > +++ b/hw/sd/sd.c > > @@ -1386,6 +1386,14 @@ static sd_rsp_type_t > sd_normal_command(SDState *sd, SDRequest req) > > } > > break; > > > > +case 21:/* CMD21: mmc SEND TUNING_BLOCK */ > > +if (sd->emmc && (sd->state == sd_transfer_state)) { > > +sd->state = sd_sendingdata_state; > > +sd->data_offset = 0; > > +return sd_r1; > > +} > > +break; > > + > > case 23:/* CMD23: SET_BLOCK_COUNT */ > > if (sd->spec_version < SD_PHY_SPECv3_01_VERS) { > > break; > > @@ -2120,6 +2128,30 @@ static const uint8_t > sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { > > 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, > > }; > > > > +#define EXCSD_BUS_WIDTH_OFFSET 183 > > +#define BUS_WIDTH_8_MASK0x4 > > +#define BUS_WIDTH_4_MASK0x2 > > +#define MMC_TUNING_BLOCK_SIZE 128 > > + > > +static const uint8_t mmc_tunning_block_pattern[128] = { > > + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, > > + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, > > + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, > > + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, > > + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, > > + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, > > + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, > > + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, > > + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, > > + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, > > + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, > > + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, > > + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, > > + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, > > + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, > > + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, > > Where does this magic pattern come from? Is it part of some spec? [Sai Pavan Boddu] Yes its part of JEDEC eMMC spec. It's the tuning sequence for HS200 mode. Regards, Sai Pavan > > Dave > > > +}; > > + > > uint8_t sd_read_byte(SDState *sd) > > { > > /* TODO: Append CRCs */ > > @@ -2213,6 +2245,21 @@ uint8_t sd_read_byte(SDState *sd) > > ret = sd_tuning_block_pattern[sd->data_offset++]; > > break; > > > > +case 21:/* CMD21: SEND_TUNNING_BLOCK (MMC) */ > > +if (sd->data_offset >= MMC_TUNING_BLOCK_SIZE - 1) { > > +sd->state = sd_transfer_state; > > +} > > +if (sd->ext_csd[EXCSD_BUS_WIDTH_OFFSET] & BUS_WIDTH_8_MASK) { > > +ret = mmc_tunning_block_pattern[sd->data_offset++]; > > +} else { > > +/* Return LSB Nibbles of two byte from the 8bit tuning block > > + * for 4bit mode > > + */ > > +ret = mmc_tunning_block_pattern[sd->data_offset++] & 0x0F; > > +ret |= (mmc_tunning_block_pattern[sd->data_offset++] & 0x0F) > > << 4; > > +} > > +break; > > + > > case 22:/* ACMD22: SEND_NUM_WR_BLOCKS */ > > ret = sd->data[sd->data_offset ++]; > > > > -- > > 2.7.4 > > > -- > Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK
[Bug 1916501] Re: qemu-img convert segfaults with specific URL
Guys, when I run with valgrind, I always get this when segfault occurs: ==74885== Invalid read of size 8 ==74885==at 0x1DC87D: curl_multi_do (curl.c:410) ==74885==by 0x23B949: aio_dispatch_handler (aio-posix.c:329) ==74885==by 0x23C0A1: aio_dispatch_handlers (aio-posix.c:372) ==74885==by 0x23C0A1: aio_dispatch (aio-posix.c:382) ==74885==by 0x22DEE1: aio_ctx_dispatch (async.c:306) ==74885==by 0x4A854DA: g_main_context_dispatch (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6600.1) ==74885==by 0x236097: glib_pollfds_poll (main-loop.c:232) ==74885==by 0x236097: os_host_main_loop_wait (main-loop.c:255) ==74885==by 0x236097: main_loop_wait (main-loop.c:531) ==74885==by 0x13E30C: convert_do_copy (qemu-img.c:2139) ==74885==by 0x13E30C: img_convert (qemu-img.c:2738) ==74885==by 0x134660: main (qemu-img.c:5536) ==74885== Address 0xf9779b8 is 8 bytes inside a block of size 32 free'd ==74885==at 0x483DA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==74885==by 0x1DC5BC: curl_clean_state (curl.c:529) ==74885==by 0x1DC5BC: curl_clean_state (curl.c:515) ==74885==by 0x1DC7E4: curl_multi_check_completion (curl.c:385) ==74885==by 0x1DC8D4: curl_multi_do (curl.c:414) ==74885==by 0x23B949: aio_dispatch_handler (aio-posix.c:329) ==74885==by 0x23C0A1: aio_dispatch_handlers (aio-posix.c:372) ==74885==by 0x23C0A1: aio_dispatch (aio-posix.c:382) ==74885==by 0x22DEE1: aio_ctx_dispatch (async.c:306) ==74885==by 0x4A854DA: g_main_context_dispatch (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6600.1) ==74885==by 0x236097: glib_pollfds_poll (main-loop.c:232) ==74885==by 0x236097: os_host_main_loop_wait (main-loop.c:255) ==74885==by 0x236097: main_loop_wait (main-loop.c:531) ==74885==by 0x13E30C: convert_do_copy (qemu-img.c:2139) ==74885==by 0x13E30C: img_convert (qemu-img.c:2738) ==74885==by 0x134660: main (qemu-img.c:5536) ==74885== Block was alloc'd at ==74885==at 0x483ED99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==74885==by 0x4A8B5A0: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6600.1) ==74885==by 0x1DBDC9: curl_sock_cb (curl.c:156) ==74885==by 0x55402C1: ??? (in /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.6.0) ==74885==by 0x5543D33: ??? (in /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.6.0) ==74885==by 0x5543E77: curl_multi_socket_action (in /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.6.0) ==74885==by 0x1DC8C7: curl_multi_do_locked (curl.c:403) ==74885==by 0x1DC8C7: curl_multi_do (curl.c:413) ==74885==by 0x23B949: aio_dispatch_handler (aio-posix.c:329) ==74885==by 0x23C0A1: aio_dispatch_handlers (aio-posix.c:372) ==74885==by 0x23C0A1: aio_dispatch (aio-posix.c:382) ==74885==by 0x22DEE1: aio_ctx_dispatch (async.c:306) ==74885==by 0x4A854DA: g_main_context_dispatch (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6600.1) ==74885==by 0x236097: glib_pollfds_poll (main-loop.c:232) ==74885==by 0x236097: os_host_main_loop_wait (main-loop.c:255) ==74885==by 0x236097: main_loop_wait (main-loop.c:531) It seems that sockets are being free'd in a non-expecting situation. -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1916501 Title: qemu-img convert segfaults with specific URL Status in QEMU: New Bug description: Using what is currently the latest git: (commit 00d8ba9e0d62ea1c7459c25aeabf9c8bb7659462, Date: Sun Feb 21 19:52:58 2021 +) $ ./build/qemu-img convert -f qcow2 -O raw https://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img out.img Segmentation fault (core dumped) Backtrace for convenience: qemu: qemu_mutex_lock_impl: Invalid argument Thread 1 "qemu-img" received signal SIGABRT, Aborted. 0x777c59d5 in raise () from /lib64/libc.so.6 (gdb) bt #0 0x777c59d5 in raise () from /lib64/libc.so.6 #1 0x777ae8a4 in abort () from /lib64/libc.so.6 #2 0x556705b2 in error_exit (err=, msg=msg@entry=0x556b69a0 <__func__.31> "qemu_mutex_lock_impl") at ../util/qemu-thread-posix.c:37 #3 0x55670945 in qemu_mutex_lock_impl (mutex=0x55ae3758, file=0x556827a2 "../block/curl.c", line=406) at ../util/qemu-thread-posix.c:81 #4 0x5559a05b in curl_multi_do (arg=0x55aad2a0) at ../block/curl.c:406 #5 0x5566193a in aio_dispatch_handler (ctx=ctx@entry=0x55737790, node=0x55b14150) at ../util/aio-posix.c:329 #6 0x55662072 in aio_dispatch_handlers (ctx=0x55737790) at ../util/aio-posix.c:372 #7 aio_dispatch (ctx=0x55737790) at ../util/aio-posix.c:382 #8 0x5564442e in aio_ctx_dispatch (source=, callback=, user_data=) at ../util/async.c:306 #9 0x77cfda9f in g_main_context_dispatch () from
[PATCH V2] file-posix: allow -EBUSY -EINVAL errors during write zeros on block
Since Linux 5.10, write zeros to a multipath device using ioctl(fd, BLKZEROOUT, range) with cache none or directsync return -EBUSY permanently. Similar to handle_aiocb_write_zeroes_unmap, handle_aiocb_write_zeroes_block allow -EBUSY and -EINVAL errors during ioctl(fd, BLKZEROOUT, range). Reference commit in Linux 5.10: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=384d87ef2c954fc58e6c5fd8253e4a1984f5fe02 Signed-off-by: ChangLimin --- block/file-posix.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index 05079b40ca..4e132db929 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1629,8 +1629,13 @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb) } while (errno == EINTR); ret = translate_err(-errno); -if (ret == -ENOTSUP) { -s->has_write_zeroes = false; +switch (ret) { +case -ENOTSUP: +s->has_write_zeroes = false; /* fall through */ +case -EINVAL: +case -EBUSY: +return -ENOTSUP; +break; } } #endif -- 2.27.0
Re: [PATCH v1] vhost-vdpa: Set discarding of RAM broken when initializing the backend
On 2021/3/3 12:21 上午, David Hildenbrand wrote: Similar to VFIO, vDPA will go ahead an map+pin all guest memory. Memory that used to be discarded will get re-populated and if we discard+re-access memory after mapping+pinning, the pages mapped into the vDPA IOMMU will go out of sync with the actual pages mapped into the user space page tables. Set discarding of RAM broken such that: - virtio-mem and vhost-vdpa run mutually exclusive - virtio-balloon is inhibited and no memory discards will get issued In the future, we might be able to support coordinated discarding of RAM as used by virtio-mem and as planned for VFIO. Cc: Jason Wang Cc: Michael S. Tsirkin Cc: Cindy Lu Signed-off-by: David Hildenbrand Acked-by: Jason Wang --- Note: I was not actually able to reproduce/test as I fail to get the vdpa_sim/vdpa_sim_net running on upstream Linux (whetever vdpa, vhost_vdpa, vdpa_sim, vdpa_sim_net modules I probe, and in which order, no vdpa devices appear under /sys/bus/vdpa/devices/ or /dev/). The device creation was switched to use vdpa tool that is integrated with iproue2[1]. [1] https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=143610383da51e1f868c6d5a2a5e2fb552293d18 --- hw/virtio/vhost-vdpa.c | 13 + 1 file changed, 13 insertions(+) diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 01d2101d09..86058d4041 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -278,6 +278,17 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque) uint64_t features; assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); trace_vhost_vdpa_init(dev, opaque); +int ret; + +/* + * Similar to VFIO, we end up pinning all guest memory and have to + * disable discarding of RAM. + */ +ret = ram_block_discard_disable(true); +if (ret) { +error_report("Cannot set discarding of RAM broken"); +return ret; +} vDPA will support non pinning (shared VM) backend soon[2]. So I guess we need a flag to be advertised to usersapce then we can conditionly enable the discard here. [2] https://www.spinics.net/lists/netdev/msg723944.html Thanks v = opaque; v->dev = dev; @@ -302,6 +313,8 @@ static int vhost_vdpa_cleanup(struct vhost_dev *dev) memory_listener_unregister(>listener); dev->opaque = NULL; +ram_block_discard_disable(false); + return 0; }
[PATCH v3] target/s390x: Implement the MVPG condition-code-option bit
If the CCO bit is set, MVPG should not generate an exception but report page translation faults via a CC code. Create a new helper, access_prepare_nf, which can use probe_access_flags in non-faulting mode, and then handle watchpoints. Cc: David Hildenbrand Reported-by: Thomas Huth Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 87 --- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 25cfede806..b397333c0b 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -130,28 +130,62 @@ typedef struct S390Access { int mmu_idx; } S390Access; +static bool access_prepare_nf(S390Access *access, CPUS390XState *env, + bool nofault, vaddr vaddr1, int size, + MMUAccessType access_type, + int mmu_idx, uintptr_t ra) +{ +void *haddr1, *haddr2 = NULL; +int size1, size2; +vaddr vaddr2 = 0; +int flags; + +assert(size > 0 && size <= 4096); + +size1 = MIN(size, -(vaddr1 | TARGET_PAGE_MASK)), +size2 = size - size1; + +flags = probe_access_flags(env, vaddr1, access_type, mmu_idx, + nofault, , ra); +if (unlikely(size2)) { +/* The access crosses page boundaries. */ +vaddr2 = wrap_address(env, vaddr1 + size1); +flags |= probe_access_flags(env, vaddr2, access_type, mmu_idx, +nofault, , ra); +} + +if (unlikely(flags & TLB_INVALID_MASK)) { +return false; +} +if (unlikely(flags & TLB_WATCHPOINT)) { +/* S390 does not presently use transaction attributes. */ +cpu_check_watchpoint(env_cpu(env), vaddr1, size, + MEMTXATTRS_UNSPECIFIED, + (access_type == MMU_DATA_STORE + ? BP_MEM_WRITE : BP_MEM_READ), ra); +} + +*access = (S390Access) { +.vaddr1 = vaddr1, +.vaddr2 = vaddr2, +.haddr1 = haddr1, +.haddr2 = haddr2, +.size1 = size1, +.size2 = size2, +.mmu_idx = mmu_idx +}; +return true; +} + static S390Access access_prepare(CPUS390XState *env, vaddr vaddr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t ra) { -S390Access access = { -.vaddr1 = vaddr, -.size1 = MIN(size, -(vaddr | TARGET_PAGE_MASK)), -.mmu_idx = mmu_idx, -}; - -g_assert(size > 0 && size <= 4096); -access.haddr1 = probe_access(env, access.vaddr1, access.size1, access_type, - mmu_idx, ra); - -if (unlikely(access.size1 != size)) { -/* The access crosses page boundaries. */ -access.vaddr2 = wrap_address(env, vaddr + access.size1); -access.size2 = size - access.size1; -access.haddr2 = probe_access(env, access.vaddr2, access.size2, - access_type, mmu_idx, ra); -} -return access; +S390Access ret; +bool ok = access_prepare_nf(, env, false, vaddr, size, +access_type, mmu_idx, ra); +assert(ok); +return ret; } /* Helper to handle memset on a single page. */ @@ -845,8 +879,10 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) const int mmu_idx = cpu_mmu_index(env, false); const bool f = extract64(r0, 11, 1); const bool s = extract64(r0, 10, 1); +const bool cco = extract64(r0, 8, 1); uintptr_t ra = GETPC(); S390Access srca, desta; +bool ok; if ((f && s) || extract64(r0, 12, 4)) { tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC()); @@ -858,13 +894,18 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) /* * TODO: * - Access key handling - * - CC-option with surpression of page-translation exceptions * - Store r1/r2 register identifiers at real location 162 */ -srca = access_prepare(env, r2, TARGET_PAGE_SIZE, MMU_DATA_LOAD, mmu_idx, - ra); -desta = access_prepare(env, r1, TARGET_PAGE_SIZE, MMU_DATA_STORE, mmu_idx, - ra); +ok = access_prepare_nf(, env, cco, r2, TARGET_PAGE_SIZE, + MMU_DATA_LOAD, mmu_idx, ra); +if (!ok) { +return 2; +} +ok = access_prepare_nf(, env, cco, r1, TARGET_PAGE_SIZE, + MMU_DATA_STORE, mmu_idx, ra); +if (!ok) { +return 1; +} access_memmove(env, , , ra); return 0; /* data moved */ } -- 2.25.1
Re: [PATCH v2] target/s390x: Implement the MVPG condition-code-option bit
On 3/2/21 5:39 PM, Richard Henderson wrote: +ok = probe_access_flags(env, vaddr1, access_type, mmu_idx, +nofault, , ra); Bah, I confused myself and remembered the wrong interface. Expect a v3. r~
Re: [PATCH v2] target/s390x: Implement the MVPG condition-code-option bit
On 3/2/21 5:39 PM, Richard Henderson wrote: If the CCO bit is set, MVPG should not generate an exception but report page translation faults via a CC code. Create a new helper, access_prepare_nf, which can use probe_access_flags in non-faulting mode. Cc: David Hildenbrand Reported-by: Thomas Huth Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 76 +++ 1 file changed, 53 insertions(+), 23 deletions(-) Oh, I meant to say that this is untested, but is what I was talking about wrt performing only a single lookup per page. r~
[PATCH v2] target/s390x: Implement the MVPG condition-code-option bit
If the CCO bit is set, MVPG should not generate an exception but report page translation faults via a CC code. Create a new helper, access_prepare_nf, which can use probe_access_flags in non-faulting mode. Cc: David Hildenbrand Reported-by: Thomas Huth Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 76 +++ 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 25cfede806..9e359b0d19 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -130,28 +130,51 @@ typedef struct S390Access { int mmu_idx; } S390Access; +static bool access_prepare_nf(S390Access *access, CPUS390XState *env, + bool nofault, vaddr vaddr1, int size, + MMUAccessType access_type, + int mmu_idx, uintptr_t ra) +{ +void *haddr1, *haddr2 = NULL; +int size1, size2; +vaddr vaddr2 = 0; +bool ok; + +g_assert(size > 0 && size <= 4096); + +size1 = MIN(size, -(vaddr1 | TARGET_PAGE_MASK)), +size2 = size - size1; + +ok = probe_access_flags(env, vaddr1, access_type, mmu_idx, +nofault, , ra); +if (likely(ok) && unlikely(size2)) { +/* The access crosses page boundaries. */ +vaddr2 = wrap_address(env, vaddr1 + size1); +ok = probe_access_flags(env, vaddr2, access_type, mmu_idx, +nofault, , ra); +} + +*access = (S390Access) { +.vaddr1 = vaddr1, +.vaddr2 = vaddr2, +.haddr1 = haddr1, +.haddr2 = haddr2, +.size1 = size1, +.size2 = size2, +.mmu_idx = mmu_idx +}; +return ok; +} + static S390Access access_prepare(CPUS390XState *env, vaddr vaddr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t ra) { -S390Access access = { -.vaddr1 = vaddr, -.size1 = MIN(size, -(vaddr | TARGET_PAGE_MASK)), -.mmu_idx = mmu_idx, -}; - -g_assert(size > 0 && size <= 4096); -access.haddr1 = probe_access(env, access.vaddr1, access.size1, access_type, - mmu_idx, ra); - -if (unlikely(access.size1 != size)) { -/* The access crosses page boundaries. */ -access.vaddr2 = wrap_address(env, vaddr + access.size1); -access.size2 = size - access.size1; -access.haddr2 = probe_access(env, access.vaddr2, access.size2, - access_type, mmu_idx, ra); -} -return access; +S390Access ret; +bool ok = access_prepare_nf(, env, false, vaddr, size, +access_type, mmu_idx, ra); +g_assert(ok); +return ret; } /* Helper to handle memset on a single page. */ @@ -845,8 +868,10 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) const int mmu_idx = cpu_mmu_index(env, false); const bool f = extract64(r0, 11, 1); const bool s = extract64(r0, 10, 1); +const bool cco = extract64(r0, 8, 1); uintptr_t ra = GETPC(); S390Access srca, desta; +bool ok; if ((f && s) || extract64(r0, 12, 4)) { tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC()); @@ -858,13 +883,18 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) /* * TODO: * - Access key handling - * - CC-option with surpression of page-translation exceptions * - Store r1/r2 register identifiers at real location 162 */ -srca = access_prepare(env, r2, TARGET_PAGE_SIZE, MMU_DATA_LOAD, mmu_idx, - ra); -desta = access_prepare(env, r1, TARGET_PAGE_SIZE, MMU_DATA_STORE, mmu_idx, - ra); +ok = access_prepare_nf(, env, cco, r2, TARGET_PAGE_SIZE, + MMU_DATA_LOAD, mmu_idx, ra); +if (!ok) { +return 2; +} +ok = access_prepare_nf(, env, cco, r1, TARGET_PAGE_SIZE, + MMU_DATA_STORE, mmu_idx, ra); +if (!ok) { +return 1; +} access_memmove(env, , , ra); return 0; /* data moved */ } -- 2.25.1
Re: [PATCH v4 6/6] hw/ppc: Add emulation of Genesi/bPlan Pegasos II
On Tue, Mar 02, 2021 at 10:13:19AM +0100, BALATON Zoltan wrote: > On Tue, 2 Mar 2021, Philippe Mathieu-Daudé wrote: > > On 2/25/21 8:47 PM, BALATON Zoltan wrote: > > > Add new machine called pegasos2 emulating the Genesi/bPlan Pegasos II, > > > a PowerPC board based on the Marvell MV64361 system controller and the > > > VIA VT8231 integrated south bridge/superio chips. It can run Linux, > > > AmigaOS and a wide range of MorphOS versions. Currently a firmware ROM > > > image is needed to boot and only MorphOS has a video driver to produce > > > graphics output. Linux could work too but distros that supported this > > > machine don't include usual video drivers so those only run with > > > serial console for now. > > > > > > Signed-off-by: BALATON Zoltan > > > --- > > > MAINTAINERS | 10 ++ > > > default-configs/devices/ppc-softmmu.mak | 2 + > > > hw/ppc/Kconfig | 10 ++ > > > hw/ppc/meson.build | 2 + > > > hw/ppc/pegasos2.c | 144 > > > 5 files changed, 168 insertions(+) > > > create mode 100644 hw/ppc/pegasos2.c > > > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > > index 9b2aa18e1f..a023217702 100644 > > > --- a/MAINTAINERS > > > +++ b/MAINTAINERS > > > @@ -1345,6 +1345,16 @@ F: pc-bios/canyonlands.dt[sb] > > > F: pc-bios/u-boot-sam460ex-20100605.bin > > > F: roms/u-boot-sam460ex > > > > > > +pegasos2 > > > +M: BALATON Zoltan > > > +R: David Gibson > > > > :) > > He's also listed as reviewer for the sam460ex and I think as the PPC > maintainer probably should be notified about changes that's why this is > here. I guess he can complain or submit a patch later if he wants to be > removed. Including me as reviewer is fine for now. > > > > +L: qemu-...@nongnu.org > > > +S: Maintained > > > +F: hw/ppc/pegasos2.c > > > +F: hw/pci-host/mv64361.c > > > +F: hw/pci-host/mv643xx.h > > > +F: include/hw/pci-host/mv64361.h > > > + > > > RISC-V Machines > > > --- > > > OpenTitan > > > diff --git a/default-configs/devices/ppc-softmmu.mak > > > b/default-configs/devices/ppc-softmmu.mak > > > index 61b78b844d..4535993d8d 100644 > > > --- a/default-configs/devices/ppc-softmmu.mak > > > +++ b/default-configs/devices/ppc-softmmu.mak > > > @@ -14,5 +14,7 @@ CONFIG_SAM460EX=y > > > CONFIG_MAC_OLDWORLD=y > > > CONFIG_MAC_NEWWORLD=y > > > > > > +CONFIG_PEGASOS2=y > > > + > > > # For PReP > > > CONFIG_PREP=y > > > diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig > > > index d11dc30509..98d8dd1a84 100644 > > > --- a/hw/ppc/Kconfig > > > +++ b/hw/ppc/Kconfig > > > @@ -68,6 +68,16 @@ config SAM460EX > > > select USB_OHCI > > > select FDT_PPC > > > > > > +config PEGASOS2 > > > +bool > > > +select MV64361 > > > +select VT82C686 > > > +select IDE_VIA > > > +select SMBUS_EEPROM > > > +# These should come with VT82C686 > > > +select APM > > > +select ACPI_X86 > > > + > > > config PREP > > > bool > > > imply PCI_DEVICES > > > diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build > > > index 218631c883..86d6f379d1 100644 > > > --- a/hw/ppc/meson.build > > > +++ b/hw/ppc/meson.build > > > @@ -78,5 +78,7 @@ ppc_ss.add(when: 'CONFIG_E500', if_true: files( > > > )) > > > # PowerPC 440 Xilinx ML507 reference board. > > > ppc_ss.add(when: 'CONFIG_VIRTEX', if_true: files('virtex_ml507.c')) > > > +# Pegasos2 > > > +ppc_ss.add(when: 'CONFIG_PEGASOS2', if_true: files('pegasos2.c')) > > > > > > hw_arch += {'ppc': ppc_ss} > > > diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c > > > new file mode 100644 > > > index 00..427e884fbf > > > --- /dev/null > > > +++ b/hw/ppc/pegasos2.c > > > @@ -0,0 +1,144 @@ > > > +/* > > > + * QEMU PowerPC CHRP (Genesi/bPlan Pegasos II) hardware System Emulator > > > + * > > > + * Copyright (c) 2018-2020 BALATON Zoltan > > > > 2018-2021 > > Not really. I've done this between Christmas of 2018 and 2020. This year > were only changes for upstreaming and review comments so I preserved the > dates to record when the actual code was written. Fwiw, Red Hat's internal guidelines have the opinion that the years don't matter that much and are usually out of date, so they suggest simply "Copyright Red Hat." for contributions from us. IANAL. > > > + * > > > + * This work is licensed under the GNU GPL license version 2 or later. > > > + * > > > + */ > > > + > > > +#include "qemu/osdep.h" > > > +#include "qemu-common.h" > > > +#include "qemu/units.h" > > > +#include "qapi/error.h" > > > +#include "hw/hw.h" > > > +#include "hw/ppc/ppc.h" > > > +#include "hw/sysbus.h" > > > +#include "hw/pci/pci_host.h" > > > +#include "hw/irq.h" > > > +#include "hw/pci-host/mv64361.h" > > > +#include "hw/isa/vt82c686.h" > > > +#include "hw/ide/pci.h" > > > +#include "hw/i2c/smbus_eeprom.h" > > > +#include "hw/qdev-properties.h" > > > +#include "sysemu/reset.h" > > > +#include "hw/boards.h" > > > +#include "hw/loader.h" > > >
[Bug 1917542] [NEW] qemu-img crash on M1 Mac
Public bug reported: 1. Symptom $ qemu-img create -f qcow2 disk.qcow2 10G [1] 72373 killed qemu-img create -f qcow2 disk.qcow2 10G 2. System environment CPU: Apple M1 OS: Big Sur 11.2.2 qemu: stable 5.2.0 (Binary installed by homebrew) 3. Kernel logs $ sudo log show --predicate ‘eventMessage LIKE “qemu”’ --debug ntID Dirty: 1 Event: com.apple.stability.crash {“appVersion”:"???",“exceptionType”:1,“logwritten”:1,“process”:“qemu-img”,“responsibleApp”:“iTerm2”,“timestamp”:1614666875993238} 2021-03-02 15:36:52.728210+0900 0xfb308 Default 0x0 0 0 kernel: CODE SIGNING: cs_invalid_page(0x10293): p=72373[qemu-img] final status 0x23000200, denying page sending SIGKILL 2021-03-02 15:36:52.728222+0900 0xfb308 Default 0x0 0 0 kernel: CODE SIGNING: process 72373[qemu-img]: rejecting invalid page at address 0x10293 from offset 0x0 in file “/opt/homebrew/Cellar/libssh/0.9.5_1/lib/libssh.4.8.6.dylib” (cs_mtime:1614297740.413435328 == mtime:1614297740.413435328) (signed:1 validated:1 tainted:1 nx:0 wpmapped:0 dirty:0 depth:0) 2021-03-02 15:36:52.728477+0900 0xfab09 Default 0x0 919 0 ReportCrash: Parsing corpse data for process qemu-img [pid 72373] 2021-03-02 15:36:52.884736+0900 0xfab09 Default 0x0 919 0 ReportCrash: (CrashReporterSupport) Saved crash report for qemu-img[72373] version 0 to qemu-img_2021-03-02-153652_.crash 4. Crash logs $ sudo cat /Users//Library/Logs/DiagnosticReports/qemu-img_2021-03-02-153652_.crash Process: qemu-img [72373] Path: /opt/homebrew/*/qemu-img Identifier: qemu-img Version: 0 Code Type: ARM-64 (Native) Parent Process: zsh [67484] Responsible: iTerm2 [556] User ID: 501 Date/Time: 2021-03-02 15:36:52.710 +0900 OS Version: macOS 11.2.2 (20D80) Report Version: 12 Anonymous UUID: AF87D5F0-2BED-EB72-1DC8-26F63A24DA7C Sleep/Wake UUID: 3862EA39-132E-42BD-A4BB-5A36F36607F1 Time Awake Since Boot: 89000 seconds Time Since Wake: 520 seconds System Integrity Protection: enabled Crashed Thread: 0 Exception Type: EXC_BAD_ACCESS (Code Signature Invalid) Exception Codes: 0x0032, 0x00010293 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: Namespace CODESIGNING, Code 0x2 kernel messages: VM Regions Near 0x10293: __LINKEDIT 102908000-10293 [ 160K] r–/r-- SM=COW /opt/homebrew/* → mapped file 10293-102934000 [ 16K] r–/r-x SM=PRV Object_id=fc8cc3db __TEXT 1029bc000-102a38000 [ 496K] r-x/r-x SM=COW /usr/lib/dyld Application Specific Information: dyld: launch, loading dependent libraries /opt/homebrew/opt/libssh/lib/libssh.4.dylib Thread 0 Crashed: 0 dyld 0x000102a18780 bcmp + 16 1 dyld 0x0001029d9408 ImageLoaderMachO::validateFirstPages(linkedit_data_command const*, int, unsigned char const*, unsigned long, long long, ImageLoader::LinkContext const&) + 136 2 dyld 0x0001029e03b8 ImageLoaderMachOCompressed::instantiateFromFile(char const*, int, unsigned char const*, unsigned long, unsigned long long, unsigned long long, stat const&, unsigned int, unsigned int, linkedit_data_command const*, encryption_info_command const*, ImageLoader::LinkContext const&) + 268 3 dyld 0x0001029d7ffc ImageLoaderMachO::instantiateFromFile(char const*, int, unsigned char const*, unsigned long, unsigned long long, unsigned long long, stat const&, ImageLoader::LinkContext const&) + 172 4 dyld 0x0001029c0290 dyld::loadPhase6(int, stat const&, char const*, dyld::LoadContext const&) + 668 5 dyld 0x0001029c8dd8 dyld::loadPhase5(char const*, char const*, dyld::LoadContext const&, unsigned int&, std::__1::vector >) + 1328 6 dyld 0x0001029c8824 dyld::loadPhase4(char const, char const*, dyld::LoadContext const&, unsigned int&, std::__1::vector >) + 208 7 dyld 0x0001029c8530 dyld::loadPhase3(char const, char const*, dyld::LoadContext const&, unsigned int&, std::__1::vector >) + 1100 8 dyld 0x0001029c7cf0 dyld::loadPhase1(char const, char const*, dyld::LoadContext const&, unsigned int&, std::__1::vector >) + 212 9 dyld 0x0001029bfe0c dyld::loadPhase0(char const, char const*, dyld::LoadContext const&, unsigned int&, std::__1::vector >) + 468 10 dyld 0x0001029bf9b0 dyld::load(char const, dyld::LoadContext const&, unsigned int&) + 196 11 dyld 0x0001029c977c dyld::libraryLocator(char const*, bool, char const*, ImageLoader::RPathChain const*, unsigned int&) + 56 12 dyld 0x0001029d39d4 ImageLoader::recursiveLoadLibraries(ImageLoader::LinkContext const&, bool, ImageLoader::RPathChain const&, char const*) + 344 13 dyld 0x0001029d21ac ImageLoader::link(ImageLoader::LinkContext const&, bool, bool, bool, ImageLoader::RPathChain const&, char const*) + 160 14 dyld 0x0001029c25f4 dyld::link(ImageLoader*, bool, bool, ImageLoader::RPathChain const&, unsigned int) + 328 15 dyld 0x0001029c4928 dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 6764 16 dyld 0x0001029bd258 dyldbootstrap::start(dyld3::MachOLoaded const*, int, char const**,
[PATCH 2/2] tests/acceptance: Test ast2600 machine
This tests a Debian multi-soc arm32 Linux kernel on the AST2600 based Tacoma BMC machine. There is no root file system so the test terminates when boot reaches the stage where it attempts and fails to mount something. Signed-off-by: Joel Stanley --- tests/acceptance/boot_linux_console.py | 26 ++ 1 file changed, 26 insertions(+) diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index 2f46a08fdc10..6b7d7f5df984 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -1094,6 +1094,32 @@ def do_test_arm_aspeed(self, image): # self.wait_for_console_pattern("login:") self.vm.shutdown() +def test_arm_ast2600_debian(self): +""" +:avocado: tags=arch:arm +:avocado: tags=machine:tacoma-bmc +""" +deb_url = ('http://snapshot.debian.org/archive/debian/' + '20210302T203551Z/' + 'pool/main/l/linux/' + 'linux-image-5.10.0-3-armmp_5.10.13-1_armhf.deb') +deb_hash = 'db40d32fe39255d05482bea48d72467b67d6225bb2a2a4d6f618cb8976f1e09e' +deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash, +algorithm='sha256') +kernel_path = self.extract_from_deb(deb_path, '/boot/vmlinuz-5.10.0-3-armmp') +dtb_path = self.extract_from_deb(deb_path, + '/usr/lib/linux-image-5.10.0-3-armmp/aspeed-bmc-opp-tacoma.dtb') + +self.vm.set_console() +self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path) +self.vm.launch() +self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00") +self.wait_for_console_pattern("SMP: Total of 2 processors activated") +self.wait_for_console_pattern("ftgmac100 1e67.ftgmac eth0: irq") +self.wait_for_console_pattern("VFS: Cannot open root device") +self.vm.shutdown() + def test_m68k_mcf5208evb(self): """ :avocado: tags=arch:m68k -- 2.30.1
[PATCH 0/2] tests/acceptance: Test Aspeed ARM machines
This adds tests for the Aspeed ARM SoCs. The AST2400 and AST2500 tests use OpenBMC images from that project, fetched from github releases. The AST2600 test uses a Debian arm32 kernel. Note that the ast2600 test will fail if [1] is not applied. I have tested locally and all seems good. I note that checkpatch warns about a couple of lines over 80 columns in this file. Can we agree to relax this restriction for this file, as it helps the readability of the constants such as sha hashes and URLs? [1] https://lore.kernel.org/qemu-devel/20210303010505.635621-1-j...@jms.id.au/T/#u Joel Stanley (2): tests/acceptance: Test ast2400 and ast2500 machines tests/acceptance: Test ast2600 machine tests/acceptance/boot_linux_console.py | 72 ++ 1 file changed, 72 insertions(+) -- 2.30.1
[PATCH 1/2] tests/acceptance: Test ast2400 and ast2500 machines
Test MTD images from the OpenBMC project on AST2400 and AST2500 SoCs from ASPEED, by booting Palmetto and Romulus BMC machines. The images are fetched from OpenBMC's release directory on github. Co-developed-by: Cédric Le Goater Signed-off-by: Joel Stanley --- tests/acceptance/boot_linux_console.py | 46 ++ 1 file changed, 46 insertions(+) diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index eb012867997f..2f46a08fdc10 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -1048,6 +1048,52 @@ def test_arm_vexpressa9(self): self.vm.add_args('-dtb', self.workdir + '/day16/vexpress-v2p-ca9.dtb') self.do_test_advcal_2018('16', tar_hash, 'winter.zImage') +def test_arm_ast2400_palmetto_openbmc_v2_9_0(self): +""" +:avocado: tags=arch:arm +:avocado: tags=machine:palmetto-bmc +""" + +image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' + 'obmc-phosphor-image-palmetto.static.mtd') +image_hash = ('3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d') +image_path = self.fetch_asset(image_url, asset_hash=image_hash, + algorithm='sha256') + +self.do_test_arm_aspeed(image_path) + +def test_arm_ast2500_romulus_openbmc_v2_9_0(self): +""" +:avocado: tags=arch:arm +:avocado: tags=machine:romulus-bmc +""" + +image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' + 'obmc-phosphor-image-romulus.static.mtd') +image_hash = ('820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25') +image_path = self.fetch_asset(image_url, asset_hash=image_hash, + algorithm='sha256') + +self.do_test_arm_aspeed(image_path) + +def do_test_arm_aspeed(self, image): +self.vm.set_console() +self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', + '-net', 'nic') +self.vm.launch() + +self.wait_for_console_pattern("U-Boot 2016.07") +self.wait_for_console_pattern("## Loading kernel from FIT Image at 2008") +self.wait_for_console_pattern("Starting kernel ...") +self.wait_for_console_pattern("Booting Linux on physical CPU 0x0") +self.wait_for_console_pattern( +"aspeed-smc 1e62.spi: read control register: 203b0641") +self.wait_for_console_pattern("ftgmac100 1e66.ethernet eth0: irq ") +self.wait_for_console_pattern("systemd[1]: Set hostname to") +# This often takes longer than the 90s timeout +# self.wait_for_console_pattern("login:") +self.vm.shutdown() + def test_m68k_mcf5208evb(self): """ :avocado: tags=arch:m68k -- 2.30.1
[PATCH] arm/ast2600: Fix SMP booting with -kernel
The ast2600 machines do not have PSCI firmware, so this property should have never been set. Removing this node fixes SMP booting Linux kernels that have PSCI enabled, as Linux fails to find PSCI in the device tree and falls back to the soc-specific method for enabling secondary CPUs. The comment is out of date as Qemu has supported -kernel booting since 9bb6d14081ce ("aspeed: Add boot stub for smp booting"), in v5.1. Fixes: f25c0ae1079d ("aspeed/soc: Add AST2600 support") Signed-off-by: Joel Stanley --- hw/arm/aspeed_ast2600.c | 7 --- 1 file changed, 7 deletions(-) diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index bf31ca351feb..49b00763864c 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -241,8 +241,6 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) /* CPU */ for (i = 0; i < sc->num_cpus; i++) { -object_property_set_int(OBJECT(>cpu[i]), "psci-conduit", -QEMU_PSCI_CONDUIT_SMC, _abort); if (sc->num_cpus > 1) { object_property_set_int(OBJECT(>cpu[i]), "reset-cbar", ASPEED_A7MPCORE_ADDR, _abort); @@ -253,11 +251,6 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(>cpu[i]), "cntfrq", 112500, _abort); -/* - * TODO: the secondary CPUs are started and a boot helper - * is needed when using -kernel - */ - if (!qdev_realize(DEVICE(>cpu[i]), NULL, errp)) { return; } -- 2.30.1
Re: [PATCH v2 8/8] hw/vfio/pci-quirks: Replace the word 'blacklist'
On 3/2/21 10:55 PM, Alex Williamson wrote: > On Fri, 5 Feb 2021 18:18:17 +0100 > Philippe Mathieu-Daudé wrote: > >> Follow the inclusive terminology from the "Conscious Language in your >> Open Source Projects" guidelines [*] and replace the word "blacklist" >> appropriately. >> >> [*] https://github.com/conscious-lang/conscious-lang-docs/blob/main/faq.md >> >> Reviewed-by: Alex Williamson >> Acked-by: Alex Williamson >> Reviewed-by: Daniel P. Berrangé >> Signed-off-by: Philippe Mathieu-Daudé >> --- >> hw/vfio/pci.h| 2 +- >> hw/vfio/pci-quirks.c | 14 +++--- >> hw/vfio/pci.c| 4 ++-- >> hw/vfio/trace-events | 2 +- >> 4 files changed, 11 insertions(+), 11 deletions(-) > > I thought someone might grab the whole series, but since that hasn't > happened yet, I've queued this one. Thanks, Thanks :)
Re: [PATCH] vfio: Fix vfio_listener_log_sync function name typo
On Fri, 4 Dec 2020 09:42:40 +0800 Zenghui Yu wrote: > There is an obvious typo in the function name of the .log_sync() callback. > Spell it correctly. > > Signed-off-by: Zenghui Yu > --- > hw/vfio/common.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/hw/vfio/common.c b/hw/vfio/common.c > index 6ff1daa763..d360d6f2da 100644 > --- a/hw/vfio/common.c > +++ b/hw/vfio/common.c > @@ -1118,7 +1118,7 @@ static int vfio_sync_dirty_bitmap(VFIOContainer > *container, > int128_get64(section->size), ram_addr); > } > > -static void vfio_listerner_log_sync(MemoryListener *listener, > +static void vfio_listener_log_sync(MemoryListener *listener, > MemoryRegionSection *section) > { > VFIOContainer *container = container_of(listener, VFIOContainer, > listener); > @@ -1136,7 +1136,7 @@ static void vfio_listerner_log_sync(MemoryListener > *listener, > static const MemoryListener vfio_memory_listener = { > .region_add = vfio_listener_region_add, > .region_del = vfio_listener_region_del, > -.log_sync = vfio_listerner_log_sync, > +.log_sync = vfio_listener_log_sync, > }; > > static void vfio_listener_release(VFIOContainer *container) Sorry for the delay, queued. Thanks, Alex
Re: [PATCH] target/s390x: Implement the MVPG condition-code-option bit
> Am 02.03.2021 um 22:46 schrieb Richard Henderson > : > > On 3/2/21 11:25 AM, David Hildenbrand wrote: >>> On 02.03.21 20:12, Thomas Huth wrote: >>> If the CCO bit is set, MVPG should not generate an exception >>> but report page translation faults via a CC code, so we have >>> to check the translation in this case before calling the >>> access_prepare() function. >>> >>> Signed-off-by: Thomas Huth >>> --- >>> This patch is required to get Claudio's new kvm-unit-tests patches >>> working with TCG: https://www.spinics.net/lists/kvm/msg236784.html >>> >>> target/s390x/cpu.h | 14 ++ >>> target/s390x/excp_helper.c | 14 -- >>> target/s390x/mem_helper.c | 23 ++- >>> 3 files changed, 36 insertions(+), 15 deletions(-) >>> >>> diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h >>> index 60d434d5ed..731e2c6452 100644 >>> --- a/target/s390x/cpu.h >>> +++ b/target/s390x/cpu.h >>> @@ -366,6 +366,20 @@ static inline int cpu_mmu_index(CPUS390XState *env, >>> bool ifetch) >>> #endif >>> } >>> +static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx) >>> +{ >>> +switch (mmu_idx) { >>> +case MMU_PRIMARY_IDX: >>> +return PSW_ASC_PRIMARY; >>> +case MMU_SECONDARY_IDX: >>> +return PSW_ASC_SECONDARY; >>> +case MMU_HOME_IDX: >>> +return PSW_ASC_HOME; >>> +default: >>> +abort(); >>> +} >>> +} >>> + >>> static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong >>> *pc, >>> target_ulong *cs_base, uint32_t >>> *flags) >>> { >>> diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c >>> index ce16af394b..44bff27f8f 100644 >>> --- a/target/s390x/excp_helper.c >>> +++ b/target/s390x/excp_helper.c >>> @@ -105,20 +105,6 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, >>> int size, >>> #else /* !CONFIG_USER_ONLY */ >>> -static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx) >>> -{ >>> -switch (mmu_idx) { >>> -case MMU_PRIMARY_IDX: >>> -return PSW_ASC_PRIMARY; >>> -case MMU_SECONDARY_IDX: >>> -return PSW_ASC_SECONDARY; >>> -case MMU_HOME_IDX: >>> -return PSW_ASC_HOME; >>> -default: >>> -abort(); >>> -} >>> -} >>> - >>> bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, >>> MMUAccessType access_type, int mmu_idx, >>> bool probe, uintptr_t retaddr) >>> diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c >>> index 25cfede806..c7037adf2c 100644 >>> --- a/target/s390x/mem_helper.c >>> +++ b/target/s390x/mem_helper.c >>> @@ -855,10 +855,31 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t >>> r0, uint64_t r1, uint64_t r2) >>> r1 = wrap_address(env, r1 & TARGET_PAGE_MASK); >>> r2 = wrap_address(env, r2 & TARGET_PAGE_MASK); >>> +/* >>> + * If the condition-code-option (CCO) bit is set and DAT is enabled, >>> + * we have to check for page table translation faults first: >>> + */ >>> +#ifndef CONFIG_USER_ONLY >>> +if (extract64(r0, 8, 1) && mmu_idx != MMU_REAL_IDX) { >>> +uint64_t asc = cpu_mmu_idx_to_asc(mmu_idx); >>> +uint64_t raddr, tec; >>> +int flags, exc; >>> + >>> +exc = mmu_translate(env, r2, MMU_DATA_LOAD, asc, , , >>> ); >>> +if (exc) { >>> +return 2; >>> +} >>> + >>> +exc = mmu_translate(env, r1, MMU_DATA_STORE, asc, , , >>> ); >>> +if (exc && exc != PGM_PROTECTION) { >>> +return 1; >>> +} >>> +} >>> +#endif >>> + >> This way you always need two additional translations and don't even check if >> we have something in the TLB. While this works, it's quite inefficient. >> Using probe_access_flags() we can actually lookup the tlb/fill the tlb but >> get an error instead of a fault. We could e.g., extent probe_access() to >> allow specifying whether we want a fault or not. > > I think probe_access_flags() will do all that you need; no further extension > to probe_access() required. I presume you meant access_prepare() is what you > meant to extend? I was worrying about watchpoint handling etc. as done in probe_access(). But I think what you mean is we can simply do two probe_access_flags() to catch these special pgm interrupt, followed by existing access_prepare(). That should work I guess.
Re: [PATCH v2 30/42] esp: add 4 byte PDMA read and write transfers
Le 09/02/2021 à 20:30, Mark Cave-Ayland a écrit : > The MacOS toolbox ROM performs 4 byte reads/writes when transferring data to > and from the target. Since the SCSI bus is 16-bits wide, use the memory API > to split a 4 byte access into 2 x 2 byte accesses. > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 6 -- > 1 file changed, 4 insertions(+), 2 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 7671cc398d..1d56c99527 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -1003,7 +1003,9 @@ static const MemoryRegionOps sysbus_esp_pdma_ops = { > .write = sysbus_esp_pdma_write, > .endianness = DEVICE_NATIVE_ENDIAN, > .valid.min_access_size = 1, > -.valid.max_access_size = 2, > +.valid.max_access_size = 4, > +.impl.min_access_size = 1, > +.impl.max_access_size = 2, > }; > > static const struct SCSIBusInfo esp_scsi_info = { > @@ -1048,7 +1050,7 @@ static void sysbus_esp_realize(DeviceState *dev, Error > **errp) >sysbus, "esp-regs", ESP_REGS << sysbus->it_shift); > sysbus_init_mmio(sbd, >iomem); > memory_region_init_io(>pdma, OBJECT(sysbus), > _esp_pdma_ops, > - sysbus, "esp-pdma", 2); > + sysbus, "esp-pdma", 4); > sysbus_init_mmio(sbd, >pdma); > > qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2); > Reviewed-by: Laurent Vivier
Re: [PATCH v2 29/42] esp: remove pdma_origin from ESPState
Le 09/02/2021 à 20:30, Mark Cave-Ayland a écrit : > Now that all data is transferred via the FIFO (ti_buf) there is no need to > track > the source buffer being used for the data transfer. This also eliminates the > need for a separate subsection for PDMA state migration. > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 74 +-- > include/hw/scsi/esp.h | 6 > 2 files changed, 8 insertions(+), 72 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 5dcd4cd651..7671cc398d 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -127,32 +127,14 @@ static uint32_t esp_get_stc(ESPState *s) > return dmalen; > } > > -static void set_pdma(ESPState *s, enum pdma_origin_id origin) > -{ > -s->pdma_origin = origin; > -} > - > static uint8_t esp_pdma_read(ESPState *s) > { > uint8_t val; > > -switch (s->pdma_origin) { > -case TI: > -if (s->do_cmd) { > -val = s->cmdbuf[s->cmdlen++]; > -} else { > -val = s->ti_buf[s->ti_rptr++]; > -} > -break; > -case ASYNC: > -val = s->async_buf[0]; > -if (s->async_len > 0) { > -s->async_len--; > -s->async_buf++; > -} > -break; > -default: > -g_assert_not_reached(); > +if (s->do_cmd) { > +val = s->cmdbuf[s->cmdlen++]; > +} else { > +val = s->ti_buf[s->ti_rptr++]; > } > > return val; > @@ -166,23 +148,10 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > return; > } > > -switch (s->pdma_origin) { > -case TI: > -if (s->do_cmd) { > -s->cmdbuf[s->cmdlen++] = val; > -} else { > -s->ti_buf[s->ti_wptr++] = val; > -} > -break; > -case ASYNC: > -s->async_buf[0] = val; > -if (s->async_len > 0) { > -s->async_len--; > -s->async_buf++; > -} > -break; > -default: > -g_assert_not_reached(); > +if (s->do_cmd) { > +s->cmdbuf[s->cmdlen++] = val; > +} else { > +s->ti_buf[s->ti_wptr++] = val; > } > > dmalen--; > @@ -232,7 +201,6 @@ static uint32_t get_cmd(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, buf, dmalen); > } else { > -set_pdma(s, TI); > if (esp_select(s) < 0) { > return -1; > } > @@ -411,7 +379,6 @@ static void write_response(ESPState *s) > s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; > s->rregs[ESP_RSEQ] = SEQ_CD; > } else { > -set_pdma(s, TI); > s->pdma_cb = write_response_pdma_cb; > esp_raise_drq(s); > return; > @@ -522,7 +489,6 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, >cmdbuf[s->cmdlen], len); > } else { > -set_pdma(s, TI); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > @@ -545,7 +511,6 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, s->async_buf, len); > } else { > -set_pdma(s, TI); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > @@ -562,7 +527,6 @@ static void esp_do_dma(ESPState *s) > s->async_len -= len; > s->ti_size -= len; > esp_set_tc(s, esp_get_tc(s) - len); > -set_pdma(s, TI); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > > @@ -899,24 +863,6 @@ static bool esp_mem_accepts(void *opaque, hwaddr addr, > return (size == 1) || (is_write && size == 4); > } > > -static bool esp_pdma_needed(void *opaque) > -{ > -ESPState *s = opaque; > -return s->dma_memory_read == NULL && s->dma_memory_write == NULL && > - s->dma_enabled; > -} > - > -static const VMStateDescription vmstate_esp_pdma = { > -.name = "esp/pdma", > -.version_id = 2, > -.minimum_version_id = 2, > -.needed = esp_pdma_needed, > -.fields = (VMStateField[]) { > -VMSTATE_INT32(pdma_origin, ESPState), > -VMSTATE_END_OF_LIST() > -} > -}; > - > static bool esp_is_before_version_5(void *opaque, int version_id) > { > ESPState *s = ESP(opaque); > @@ -971,10 +917,6 @@ const VMStateDescription vmstate_esp = { > VMSTATE_UINT32_TEST(mig_dma_left, ESPState, esp_is_before_version_5), > VMSTATE_END_OF_LIST() > }, > -.subsections = (const VMStateDescription * []) { > -_esp_pdma, > -NULL > -} > }; > > static void sysbus_esp_mem_write(void *opaque, hwaddr addr, > diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h > index a8d5bf8a63..6618f4e091 100644 > ---
Re: [PATCH v2 28/42] esp: use FIFO for PDMA transfers between initiator and device
Le 09/02/2021 à 20:30, Mark Cave-Ayland a écrit : > PDMA as implemented on the Quadra 800 uses DREQ to load data into the FIFO > up to a maximum of 16 bytes at a time. The MacOS toolbox ROM requires this > because it mixes FIFO and PDMA transfers whilst checking the FIFO status > and counter registers to ensure success. > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 109 ++ > 1 file changed, 75 insertions(+), 34 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index b7ab5a5592..5dcd4cd651 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -134,13 +134,8 @@ static void set_pdma(ESPState *s, enum pdma_origin_id > origin) > > static uint8_t esp_pdma_read(ESPState *s) > { > -uint32_t dmalen = esp_get_tc(s); > uint8_t val; > > -if (dmalen == 0) { > -return 0; > -} > - > switch (s->pdma_origin) { > case TI: > if (s->do_cmd) { > @@ -160,10 +155,6 @@ static uint8_t esp_pdma_read(ESPState *s) > g_assert_not_reached(); > } > > -s->ti_size--; > -dmalen--; > -esp_set_tc(s, dmalen); > - > return val; > } > > @@ -194,7 +185,6 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > g_assert_not_reached(); > } > > -s->ti_size++; > dmalen--; > esp_set_tc(s, dmalen); > } > @@ -290,6 +280,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, > uint8_t busid) > s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; > s->rregs[ESP_RSEQ] = SEQ_CD; > esp_raise_irq(s); > +esp_lower_drq(s); > } > > static void do_cmd(ESPState *s) > @@ -447,28 +438,71 @@ static void esp_dma_done(ESPState *s) > static void do_dma_pdma_cb(ESPState *s) > { > int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO); > +int len; > > if (s->do_cmd) { > s->ti_size = 0; > s->cmdlen = 0; > s->do_cmd = 0; > do_cmd(s); > +esp_lower_drq(s); > return; > } > -if (s->async_len == 0) { > -scsi_req_continue(s->current_req); > -/* > - * If there is still data to be read from the device then > - * complete the DMA operation immediately. Otherwise defer > - * until the scsi layer has completed. > - */ > -if (to_device || esp_get_tc(s) != 0 || s->ti_size == 0) { > + > +if (to_device) { > +/* Copy FIFO data to device */ > +len = MIN(s->ti_wptr, TI_BUFSZ); > +memcpy(s->async_buf, s->ti_buf, len); > +s->ti_wptr = 0; > +s->ti_rptr = 0; > +s->async_buf += len; > +s->async_len -= len; > +s->ti_size += len; > +if (s->async_len == 0) { > +scsi_req_continue(s->current_req); > return; > } > -} > > -/* Partially filled a scsi buffer. Complete immediately. */ > -esp_dma_done(s); > +if (esp_get_tc(s) == 0) { > +esp_lower_drq(s); > +esp_dma_done(s); > +} > + > +return; > +} else { > +if (s->async_len == 0) { > +if (s->current_req) { > +scsi_req_continue(s->current_req); > +} > + > +/* > + * If there is still data to be read from the device then > + * complete the DMA operation immediately. Otherwise defer > + * until the scsi layer has completed. > + */ > +if (esp_get_tc(s) != 0 || s->ti_size == 0) { > +return; > +} > +} > + > +if (esp_get_tc(s) != 0) { > +/* Copy device data to FIFO */ > +s->ti_wptr = 0; > +s->ti_rptr = 0; > +len = MIN(s->async_len, TI_BUFSZ); > +memcpy(s->ti_buf, s->async_buf, len); > +s->ti_wptr += len; > +s->async_buf += len; > +s->async_len -= len; > +s->ti_size -= len; > +esp_set_tc(s, esp_get_tc(s) - len); > +return; > +} > + > +/* Partially filled a scsi buffer. Complete immediately. */ > +esp_lower_drq(s); > +esp_dma_done(s); > +} > } > > static void esp_do_dma(ESPState *s) > @@ -511,7 +545,7 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, s->async_buf, len); > } else { > -set_pdma(s, ASYNC); > +set_pdma(s, TI); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > @@ -520,9 +554,20 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_write) { > s->dma_memory_write(s->dma_opaque, s->async_buf, len); > } else { > -set_pdma(s, ASYNC); > +/* Copy device data to FIFO */ > +len = MIN(len, TI_BUFSZ - s->ti_wptr); > +memcpy(>ti_buf[s->ti_wptr], s->async_buf, len); > +
Re: [PATCH v2 27/42] esp: fix PDMA target selection
Le 09/02/2021 à 20:30, Mark Cave-Ayland a écrit : > Currently the target selection for PDMA is done after the SCSI command has > been > delivered which is not correct. Perform target selection as part of the > initial > get_cmd() call when the command is submitted: if no target is present, don't > raise DRQ. > > If the target is present then switch to the command phase since the MacOS > toolbox > ROM checks for this before attempting to submit the SCSI command. > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 53 +-- > 1 file changed, 34 insertions(+), 19 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 6736e7142c..b7ab5a5592 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -243,6 +243,9 @@ static uint32_t get_cmd(ESPState *s) > s->dma_memory_read(s->dma_opaque, buf, dmalen); > } else { > set_pdma(s, TI); > +if (esp_select(s) < 0) { > +return -1; > +} > esp_raise_drq(s); > return 0; > } > @@ -257,7 +260,7 @@ static uint32_t get_cmd(ESPState *s) > trace_esp_get_cmd(dmalen, target); > > if (esp_select(s) < 0) { > -return 0; > +return -1; > } > return dmalen; > } > @@ -299,9 +302,6 @@ static void do_cmd(ESPState *s) > > static void satn_pdma_cb(ESPState *s) > { > -if (esp_select(s) < 0) { > -return; > -} > s->do_cmd = 0; > if (s->cmdlen) { > do_cmd(s); > @@ -310,24 +310,28 @@ static void satn_pdma_cb(ESPState *s) > > static void handle_satn(ESPState *s) > { > +int32_t cmdlen; > + > if (s->dma && !s->dma_enabled) { > s->dma_cb = handle_satn; > return; > } > s->pdma_cb = satn_pdma_cb; > -s->cmdlen = get_cmd(s); > -if (s->cmdlen) { > +cmdlen = get_cmd(s); > +if (cmdlen > 0) { > +s->cmdlen = cmdlen; > do_cmd(s); > -} else { > +} else if (cmdlen == 0) { > +s->cmdlen = 0; > s->do_cmd = 1; > +/* Target present, but no cmd yet - switch to command phase */ > +s->rregs[ESP_RSEQ] = SEQ_CD; > +s->rregs[ESP_RSTAT] = STAT_CD; > } > } > > static void s_without_satn_pdma_cb(ESPState *s) > { > -if (esp_select(s) < 0) { > -return; > -} > s->do_cmd = 0; > if (s->cmdlen) { > do_busid_cmd(s, s->cmdbuf, 0); > @@ -336,24 +340,28 @@ static void s_without_satn_pdma_cb(ESPState *s) > > static void handle_s_without_atn(ESPState *s) > { > +int32_t cmdlen; > + > if (s->dma && !s->dma_enabled) { > s->dma_cb = handle_s_without_atn; > return; > } > s->pdma_cb = s_without_satn_pdma_cb; > -s->cmdlen = get_cmd(s); > -if (s->cmdlen) { > +cmdlen = get_cmd(s); > +if (cmdlen > 0) { > +s->cmdlen = cmdlen; > do_busid_cmd(s, s->cmdbuf, 0); > -} else { > +} else if (cmdlen == 0) { > +s->cmdlen = 0; > s->do_cmd = 1; > +/* Target present, but no cmd yet - switch to command phase */ > +s->rregs[ESP_RSEQ] = SEQ_CD; > +s->rregs[ESP_RSTAT] = STAT_CD; > } > } > > static void satn_stop_pdma_cb(ESPState *s) > { > -if (esp_select(s) < 0) { > -return; > -} > s->do_cmd = 0; > if (s->cmdlen) { > trace_esp_handle_satn_stop(s->cmdlen); > @@ -367,21 +375,28 @@ static void satn_stop_pdma_cb(ESPState *s) > > static void handle_satn_stop(ESPState *s) > { > +int32_t cmdlen; > + > if (s->dma && !s->dma_enabled) { > s->dma_cb = handle_satn_stop; > return; > } > s->pdma_cb = satn_stop_pdma_cb; > -s->cmdlen = get_cmd(s); > -if (s->cmdlen) { > +cmdlen = get_cmd(s); > +if (cmdlen > 0) { > trace_esp_handle_satn_stop(s->cmdlen); > +s->cmdlen = cmdlen; > s->do_cmd = 1; > s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD; > s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; > s->rregs[ESP_RSEQ] = SEQ_CD; > esp_raise_irq(s); > -} else { > +} else if (cmdlen == 0) { > +s->cmdlen = 0; > s->do_cmd = 1; > +/* Target present, but no cmd yet - switch to command phase */ > +s->rregs[ESP_RSEQ] = SEQ_CD; > +s->rregs[ESP_RSTAT] = STAT_CD; > } > } > > Reviewed-by: Laurent Vivier
Re: [PATCH] MAINTAINERS: Cover docs/igd-assign.txt in VFIO section
On Mon, 22 Feb 2021 09:26:17 +0100 Philippe Mathieu-Daudé wrote: > ping? > > On 2/2/21 4:56 PM, Philippe Mathieu-Daudé wrote: > > Signed-off-by: Philippe Mathieu-Daudé > > --- > > MAINTAINERS | 1 + > > 1 file changed, 1 insertion(+) > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index bcd88668bcd..838d0f14a59 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -1768,6 +1768,7 @@ M: Alex Williamson > > S: Supported > > F: hw/vfio/* > > F: include/hw/vfio/ > > +F: docs/igd-assign.txt > > > > vfio-ccw > > M: Cornelia Huck > > > Queued. Thanks, Alex
Re: [PATCH v2 8/8] hw/vfio/pci-quirks: Replace the word 'blacklist'
On Fri, 5 Feb 2021 18:18:17 +0100 Philippe Mathieu-Daudé wrote: > Follow the inclusive terminology from the "Conscious Language in your > Open Source Projects" guidelines [*] and replace the word "blacklist" > appropriately. > > [*] https://github.com/conscious-lang/conscious-lang-docs/blob/main/faq.md > > Reviewed-by: Alex Williamson > Acked-by: Alex Williamson > Reviewed-by: Daniel P. Berrangé > Signed-off-by: Philippe Mathieu-Daudé > --- > hw/vfio/pci.h| 2 +- > hw/vfio/pci-quirks.c | 14 +++--- > hw/vfio/pci.c| 4 ++-- > hw/vfio/trace-events | 2 +- > 4 files changed, 11 insertions(+), 11 deletions(-) I thought someone might grab the whole series, but since that hasn't happened yet, I've queued this one. Thanks, Alex > > diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h > index 1574ef983f8..64777516d16 100644 > --- a/hw/vfio/pci.h > +++ b/hw/vfio/pci.h > @@ -197,7 +197,7 @@ void vfio_pci_write_config(PCIDevice *pdev, > uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size); > void vfio_vga_write(void *opaque, hwaddr addr, uint64_t data, unsigned size); > > -bool vfio_blacklist_opt_rom(VFIOPCIDevice *vdev); > +bool vfio_opt_rom_in_denylist(VFIOPCIDevice *vdev); > void vfio_vga_quirk_setup(VFIOPCIDevice *vdev); > void vfio_vga_quirk_exit(VFIOPCIDevice *vdev); > void vfio_vga_quirk_finalize(VFIOPCIDevice *vdev); > diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c > index fc8d63c8504..81c3e30df77 100644 > --- a/hw/vfio/pci-quirks.c > +++ b/hw/vfio/pci-quirks.c > @@ -43,19 +43,19 @@ > static const struct { > uint32_t vendor; > uint32_t device; > -} romblacklist[] = { > +} rom_denylist[] = { > { 0x14e4, 0x168e }, /* Broadcom BCM 57810 */ > }; > > -bool vfio_blacklist_opt_rom(VFIOPCIDevice *vdev) > +bool vfio_opt_rom_in_denylist(VFIOPCIDevice *vdev) > { > int i; > > -for (i = 0 ; i < ARRAY_SIZE(romblacklist); i++) { > -if (vfio_pci_is(vdev, romblacklist[i].vendor, > romblacklist[i].device)) { > -trace_vfio_quirk_rom_blacklisted(vdev->vbasedev.name, > - romblacklist[i].vendor, > - romblacklist[i].device); > +for (i = 0 ; i < ARRAY_SIZE(rom_denylist); i++) { > +if (vfio_pci_is(vdev, rom_denylist[i].vendor, > rom_denylist[i].device)) { > +trace_vfio_quirk_rom_in_denylist(vdev->vbasedev.name, > + rom_denylist[i].vendor, > + rom_denylist[i].device); > return true; > } > } > diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c > index f74be782091..759a3b1abf4 100644 > --- a/hw/vfio/pci.c > +++ b/hw/vfio/pci.c > @@ -900,7 +900,7 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev) > > if (vdev->pdev.romfile || !vdev->pdev.rom_bar) { > /* Since pci handles romfile, just print a message and return */ > -if (vfio_blacklist_opt_rom(vdev) && vdev->pdev.romfile) { > +if (vfio_opt_rom_in_denylist(vdev) && vdev->pdev.romfile) { > warn_report("Device at %s is known to cause system instability" > " issues during option rom execution", > vdev->vbasedev.name); > @@ -927,7 +927,7 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev) > return; > } > > -if (vfio_blacklist_opt_rom(vdev)) { > +if (vfio_opt_rom_in_denylist(vdev)) { > if (dev->opts && qemu_opt_get(dev->opts, "rombar")) { > warn_report("Device at %s is known to cause system instability" > " issues during option rom execution", > diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events > index c0e75f24b76..079f53acf28 100644 > --- a/hw/vfio/trace-events > +++ b/hw/vfio/trace-events > @@ -49,7 +49,7 @@ vfio_pci_emulated_sub_vendor_id(const char *name, uint16_t > val) "%s 0x%04x" > vfio_pci_emulated_sub_device_id(const char *name, uint16_t val) "%s 0x%04x" > > # pci-quirks.c > -vfio_quirk_rom_blacklisted(const char *name, uint16_t vid, uint16_t did) "%s > %04x:%04x" > +vfio_quirk_rom_in_denylist(const char *name, uint16_t vid, uint16_t did) "%s > %04x:%04x" > vfio_quirk_generic_window_address_write(const char *name, const char * > region_name, uint64_t data) "%s %s 0x%"PRIx64 > vfio_quirk_generic_window_data_read(const char *name, const char * > region_name, uint64_t data) "%s %s 0x%"PRIx64 > vfio_quirk_generic_window_data_write(const char *name, const char * > region_name, uint64_t data) "%s %s 0x%"PRIx64
Re: [PATCH v2 25/42] esp: remove CMD pdma_origin
Le 09/02/2021 à 20:30, Mark Cave-Ayland a écrit : > The cmdbuf is really just a copy of FIFO data (including extra message phase > bytes) so its pdma_origin is effectively TI. Fortunately we already know when > we are receiving a SCSI command since do_cmd == 1 which enables us to > distinguish between the two cases in esp_pdma_read()/esp_pdma_write(). > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 22 -- > include/hw/scsi/esp.h | 1 - > 2 files changed, 12 insertions(+), 11 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index bff330733f..921f79ae89 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -143,10 +143,11 @@ static uint8_t esp_pdma_read(ESPState *s) > > switch (s->pdma_origin) { > case TI: > -val = s->ti_buf[s->ti_rptr++]; > -break; > -case CMD: > -val = s->cmdbuf[s->cmdlen++]; > +if (s->do_cmd) { > +val = s->cmdbuf[s->cmdlen++]; > +} else { > +val = s->ti_buf[s->ti_rptr++]; > +} > break; > case ASYNC: > val = s->async_buf[0]; > @@ -176,10 +177,11 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > > switch (s->pdma_origin) { > case TI: > -s->ti_buf[s->ti_wptr++] = val; > -break; > -case CMD: > -s->cmdbuf[s->cmdlen++] = val; > +if (s->do_cmd) { > +s->cmdbuf[s->cmdlen++] = val; > +} else { > +s->ti_buf[s->ti_wptr++] = val; > +} > break; > case ASYNC: > s->async_buf[0] = val; > @@ -240,7 +242,7 @@ static uint32_t get_cmd(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, buf, dmalen); > } else { > -set_pdma(s, CMD); > +set_pdma(s, TI); > esp_raise_drq(s); > return 0; > } > @@ -471,7 +473,7 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, >cmdbuf[s->cmdlen], len); > } else { > -set_pdma(s, CMD); > +set_pdma(s, TI); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h > index 1e84b7bfb0..a8d5bf8a63 100644 > --- a/include/hw/scsi/esp.h > +++ b/include/hw/scsi/esp.h > @@ -17,7 +17,6 @@ typedef struct ESPState ESPState; > > enum pdma_origin_id { > TI, > -CMD, > ASYNC, > }; > > Reviewed-by: Laurent Vivier
Re: [PATCH v2 26/42] esp: rename get_cmd_cb() to esp_select()
Le 09/02/2021 à 20:30, Mark Cave-Ayland a écrit : > This better describes the purpose of the function. > > Signed-off-by: Mark Cave-Ayland > Reviewed-by: Philippe Mathieu-Daudé > --- > hw/scsi/esp.c | 10 +- > 1 file changed, 5 insertions(+), 5 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 921f79ae89..6736e7142c 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -199,7 +199,7 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > esp_set_tc(s, dmalen); > } > > -static int get_cmd_cb(ESPState *s) > +static int esp_select(ESPState *s) > { > int target; > > @@ -256,7 +256,7 @@ static uint32_t get_cmd(ESPState *s) > } > trace_esp_get_cmd(dmalen, target); > > -if (get_cmd_cb(s) < 0) { > +if (esp_select(s) < 0) { > return 0; > } > return dmalen; > @@ -299,7 +299,7 @@ static void do_cmd(ESPState *s) > > static void satn_pdma_cb(ESPState *s) > { > -if (get_cmd_cb(s) < 0) { > +if (esp_select(s) < 0) { > return; > } > s->do_cmd = 0; > @@ -325,7 +325,7 @@ static void handle_satn(ESPState *s) > > static void s_without_satn_pdma_cb(ESPState *s) > { > -if (get_cmd_cb(s) < 0) { > +if (esp_select(s) < 0) { > return; > } > s->do_cmd = 0; > @@ -351,7 +351,7 @@ static void handle_s_without_atn(ESPState *s) > > static void satn_stop_pdma_cb(ESPState *s) > { > -if (get_cmd_cb(s) < 0) { > +if (esp_select(s) < 0) { > return; > } > s->do_cmd = 0; > Reviewed-by: Laurent Vivier
Re: [PATCH v2 23/42] esp: use ti_wptr/ti_rptr to manage the current FIFO position for PDMA
Le 09/02/2021 à 20:29, Mark Cave-Ayland a écrit : > This eliminates the last user of the PDMA-specific pdma_cur variable which can > now be removed. > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 23 --- > include/hw/scsi/esp.h | 1 - > 2 files changed, 8 insertions(+), 16 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 691a2f4bdc..50503a6f53 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -127,11 +127,9 @@ static uint32_t esp_get_stc(ESPState *s) > return dmalen; > } > > -static void set_pdma(ESPState *s, enum pdma_origin_id origin, > - uint32_t index, uint32_t len) > +static void set_pdma(ESPState *s, enum pdma_origin_id origin, uint32_t len) > { > s->pdma_origin = origin; > -s->pdma_cur = index; > s->pdma_len = len; > } > > @@ -146,11 +144,10 @@ static uint8_t esp_pdma_read(ESPState *s) > > switch (s->pdma_origin) { > case TI: > -val = s->ti_buf[s->pdma_cur++]; > +val = s->ti_buf[s->ti_rptr++]; > break; > case CMD: > val = s->cmdbuf[s->cmdlen++]; > -s->pdma_cur++; > break; > case ASYNC: > val = s->async_buf[0]; > @@ -158,7 +155,6 @@ static uint8_t esp_pdma_read(ESPState *s) > s->async_len--; > s->async_buf++; > } > -s->pdma_cur++; > break; > default: > g_assert_not_reached(); > @@ -182,11 +178,10 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > > switch (s->pdma_origin) { > case TI: > -s->ti_buf[s->pdma_cur++] = val; > +s->ti_buf[s->ti_wptr++] = val; > break; > case CMD: > s->cmdbuf[s->cmdlen++] = val; > -s->pdma_cur++; > break; > case ASYNC: > s->async_buf[0] = val; > @@ -194,7 +189,6 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > s->async_len--; > s->async_buf++; > } > -s->pdma_cur++; > break; > default: > g_assert_not_reached(); > @@ -249,7 +243,7 @@ static uint32_t get_cmd(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, buf, dmalen); > } else { > -set_pdma(s, CMD, 0, dmalen); > +set_pdma(s, CMD, dmalen); > esp_raise_drq(s); > return 0; > } > @@ -412,7 +406,7 @@ static void write_response(ESPState *s) > s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; > s->rregs[ESP_RSEQ] = SEQ_CD; > } else { > -set_pdma(s, TI, 0, 2); > +set_pdma(s, TI, 2); > s->pdma_cb = write_response_pdma_cb; > esp_raise_drq(s); > return; > @@ -480,7 +474,7 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, >cmdbuf[s->cmdlen], len); > } else { > -set_pdma(s, CMD, s->cmdlen, len); > +set_pdma(s, CMD, len); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > @@ -503,7 +497,7 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, s->async_buf, len); > } else { > -set_pdma(s, ASYNC, 0, len); > +set_pdma(s, ASYNC, len); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > @@ -512,7 +506,7 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_write) { > s->dma_memory_write(s->dma_opaque, s->async_buf, len); > } else { > -set_pdma(s, ASYNC, 0, len); > +set_pdma(s, ASYNC, len); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > @@ -858,7 +852,6 @@ static const VMStateDescription vmstate_esp_pdma = { > .fields = (VMStateField[]) { > VMSTATE_INT32(pdma_origin, ESPState), > VMSTATE_UINT32(pdma_len, ESPState), > -VMSTATE_UINT32(pdma_cur, ESPState), > VMSTATE_END_OF_LIST() > } > }; > diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h > index 578d936214..5908d59a0a 100644 > --- a/include/hw/scsi/esp.h > +++ b/include/hw/scsi/esp.h > @@ -58,7 +58,6 @@ struct ESPState { > void (*dma_cb)(ESPState *s); > int pdma_origin; > uint32_t pdma_len; > -uint32_t pdma_cur; > void (*pdma_cb)(ESPState *s); > > uint8_t mig_version_id; > Reviewed-by: Laurent Vivier
Re: [PATCH v2 24/42] esp: use in-built TC to determine PDMA transfer length
Le 09/02/2021 à 20:30, Mark Cave-Ayland a écrit : > Real hardware simply counts down using the in-built TC to determine when the > the PDMA request is complete. Use the TC to determine the PDMA transfer length > which then enables us to remove the redundant pdma_len variable. > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 28 +--- > include/hw/scsi/esp.h | 1 - > 2 files changed, 13 insertions(+), 16 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 50503a6f53..bff330733f 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -127,10 +127,9 @@ static uint32_t esp_get_stc(ESPState *s) > return dmalen; > } > > -static void set_pdma(ESPState *s, enum pdma_origin_id origin, uint32_t len) > +static void set_pdma(ESPState *s, enum pdma_origin_id origin) > { > s->pdma_origin = origin; > -s->pdma_len = len; > } > > static uint8_t esp_pdma_read(ESPState *s) > @@ -138,7 +137,7 @@ static uint8_t esp_pdma_read(ESPState *s) > uint32_t dmalen = esp_get_tc(s); > uint8_t val; > > -if (dmalen == 0 || s->pdma_len == 0) { > +if (dmalen == 0) { > return 0; > } > > @@ -161,7 +160,6 @@ static uint8_t esp_pdma_read(ESPState *s) > } > > s->ti_size--; > -s->pdma_len--; > dmalen--; > esp_set_tc(s, dmalen); > > @@ -172,7 +170,7 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > { > uint32_t dmalen = esp_get_tc(s); > > -if (dmalen == 0 || s->pdma_len == 0) { > +if (dmalen == 0) { > return; > } > > @@ -195,7 +193,6 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > } > > s->ti_size++; > -s->pdma_len--; > dmalen--; > esp_set_tc(s, dmalen); > } > @@ -243,7 +240,7 @@ static uint32_t get_cmd(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, buf, dmalen); > } else { > -set_pdma(s, CMD, dmalen); > +set_pdma(s, CMD); > esp_raise_drq(s); > return 0; > } > @@ -406,7 +403,7 @@ static void write_response(ESPState *s) > s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; > s->rregs[ESP_RSEQ] = SEQ_CD; > } else { > -set_pdma(s, TI, 2); > +set_pdma(s, TI); > s->pdma_cb = write_response_pdma_cb; > esp_raise_drq(s); > return; > @@ -474,7 +471,7 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, >cmdbuf[s->cmdlen], len); > } else { > -set_pdma(s, CMD, len); > +set_pdma(s, CMD); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > @@ -497,7 +494,7 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, s->async_buf, len); > } else { > -set_pdma(s, ASYNC, len); > +set_pdma(s, ASYNC); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > @@ -506,7 +503,7 @@ static void esp_do_dma(ESPState *s) > if (s->dma_memory_write) { > s->dma_memory_write(s->dma_opaque, s->async_buf, len); > } else { > -set_pdma(s, ASYNC, len); > +set_pdma(s, ASYNC); > s->pdma_cb = do_dma_pdma_cb; > esp_raise_drq(s); > return; > @@ -851,7 +848,6 @@ static const VMStateDescription vmstate_esp_pdma = { > .needed = esp_pdma_needed, > .fields = (VMStateField[]) { > VMSTATE_INT32(pdma_origin, ESPState), > -VMSTATE_UINT32(pdma_len, ESPState), > VMSTATE_END_OF_LIST() > } > }; > @@ -950,6 +946,7 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr > addr, > { > SysBusESPState *sysbus = opaque; > ESPState *s = ESP(>esp); > +uint32_t dmalen; > > trace_esp_pdma_write(size); > > @@ -962,7 +959,8 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr > addr, > esp_pdma_write(s, val); > break; > } > -if (s->pdma_len == 0 && s->pdma_cb) { > +dmalen = esp_get_tc(s); > +if (dmalen == 0 && s->pdma_cb) { > esp_lower_drq(s); > s->pdma_cb(s); > s->pdma_cb = NULL; > @@ -979,7 +977,7 @@ static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr > addr, > > trace_esp_pdma_read(size); > > -if (dmalen == 0 || s->pdma_len == 0) { > +if (dmalen == 0) { > return 0; > } > switch (size) { > @@ -992,7 +990,7 @@ static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr > addr, > break; > } > dmalen = esp_get_tc(s); > -if (dmalen == 0 || (s->pdma_len == 0 && s->pdma_cb)) { > +if (dmalen == 0 && s->pdma_cb) { > esp_lower_drq(s); > s->pdma_cb(s); > s->pdma_cb = NULL; > diff
Re: [PATCH] target/s390x: Implement the MVPG condition-code-option bit
On 3/2/21 11:25 AM, David Hildenbrand wrote: On 02.03.21 20:12, Thomas Huth wrote: If the CCO bit is set, MVPG should not generate an exception but report page translation faults via a CC code, so we have to check the translation in this case before calling the access_prepare() function. Signed-off-by: Thomas Huth --- This patch is required to get Claudio's new kvm-unit-tests patches working with TCG: https://www.spinics.net/lists/kvm/msg236784.html target/s390x/cpu.h | 14 ++ target/s390x/excp_helper.c | 14 -- target/s390x/mem_helper.c | 23 ++- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 60d434d5ed..731e2c6452 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -366,6 +366,20 @@ static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch) #endif } +static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx) +{ + switch (mmu_idx) { + case MMU_PRIMARY_IDX: + return PSW_ASC_PRIMARY; + case MMU_SECONDARY_IDX: + return PSW_ASC_SECONDARY; + case MMU_HOME_IDX: + return PSW_ASC_HOME; + default: + abort(); + } +} + static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc, target_ulong *cs_base, uint32_t *flags) { diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index ce16af394b..44bff27f8f 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -105,20 +105,6 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, #else /* !CONFIG_USER_ONLY */ -static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx) -{ - switch (mmu_idx) { - case MMU_PRIMARY_IDX: - return PSW_ASC_PRIMARY; - case MMU_SECONDARY_IDX: - return PSW_ASC_SECONDARY; - case MMU_HOME_IDX: - return PSW_ASC_HOME; - default: - abort(); - } -} - bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 25cfede806..c7037adf2c 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -855,10 +855,31 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) r1 = wrap_address(env, r1 & TARGET_PAGE_MASK); r2 = wrap_address(env, r2 & TARGET_PAGE_MASK); + /* + * If the condition-code-option (CCO) bit is set and DAT is enabled, + * we have to check for page table translation faults first: + */ +#ifndef CONFIG_USER_ONLY + if (extract64(r0, 8, 1) && mmu_idx != MMU_REAL_IDX) { + uint64_t asc = cpu_mmu_idx_to_asc(mmu_idx); + uint64_t raddr, tec; + int flags, exc; + + exc = mmu_translate(env, r2, MMU_DATA_LOAD, asc, , , ); + if (exc) { + return 2; + } + + exc = mmu_translate(env, r1, MMU_DATA_STORE, asc, , , ); + if (exc && exc != PGM_PROTECTION) { + return 1; + } + } +#endif + This way you always need two additional translations and don't even check if we have something in the TLB. While this works, it's quite inefficient. Using probe_access_flags() we can actually lookup the tlb/fill the tlb but get an error instead of a fault. We could e.g., extent probe_access() to allow specifying whether we want a fault or not. I think probe_access_flags() will do all that you need; no further extension to probe_access() required. I presume you meant access_prepare() is what you meant to extend? r~
Re: [PATCH v2 22/42] esp: move PDMA length adjustments into esp_pdma_read()/esp_pdma_write()
Le 09/02/2021 à 20:29, Mark Cave-Ayland a écrit : > Here the updates to async_len and ti_size are moved into the corresponding > esp_pdma_read()/esp_pdma_write() function to eliminate the reference to > pdma_cur in do_dma_pdma_cb(). > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 24 ++-- > 1 file changed, 14 insertions(+), 10 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 91f65a5d9b..691a2f4bdc 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -153,12 +153,18 @@ static uint8_t esp_pdma_read(ESPState *s) > s->pdma_cur++; > break; > case ASYNC: > -val = s->async_buf[s->pdma_cur++]; > +val = s->async_buf[0]; > +if (s->async_len > 0) { > +s->async_len--; > +s->async_buf++; > +} > +s->pdma_cur++; > break; > default: > g_assert_not_reached(); > } > > +s->ti_size--; > s->pdma_len--; > dmalen--; > esp_set_tc(s, dmalen); > @@ -183,12 +189,18 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > s->pdma_cur++; > break; > case ASYNC: > -s->async_buf[s->pdma_cur++] = val; > +s->async_buf[0] = val; > +if (s->async_len > 0) { > +s->async_len--; > +s->async_buf++; > +} > +s->pdma_cur++; > break; > default: > g_assert_not_reached(); > } > > +s->ti_size++; > s->pdma_len--; > dmalen--; > esp_set_tc(s, dmalen); > @@ -427,7 +439,6 @@ static void esp_dma_done(ESPState *s) > static void do_dma_pdma_cb(ESPState *s) > { > int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO); > -int len = s->pdma_cur; > > if (s->do_cmd) { > s->ti_size = 0; > @@ -436,13 +447,6 @@ static void do_dma_pdma_cb(ESPState *s) > do_cmd(s); > return; > } > -s->async_buf += len; > -s->async_len -= len; > -if (to_device) { > -s->ti_size += len; > -} else { > -s->ti_size -= len; > -} > if (s->async_len == 0) { > scsi_req_continue(s->current_req); > /* > Reviewed-by: Laurent Vivier
[Bug 1917442] Re: [AHCI] crash when running a GNU/Hurd guest
Note: this is using the rump ahci driver. -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1917442 Title: [AHCI] crash when running a GNU/Hurd guest Status in QEMU: New Bug description: QEMU git hash = 51db2d7cf2 Running guest OS using: $ gdb --args /extra/qemu/bin/qemu-system-i386 -M q35,accel=kvm -m 4096 -net user,hostfwd=tcp::-:22 -net nic -drive id=udisk,file=/dev/sdd,format=raw,if=none -device ide- drive,drive=udisk,bootindex=1 -curses ... root@zamhurd:~# .ahcisata0 channel 5: setting WDCTL_RST failed for drive 0 Thread 1 "qemu-system-i38" received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x74f7bf00 (LWP 590666)] ahci_commit_buf (dma=0x57335870, tx_bytes=2048) at ../hw/ide/ahci.c:1462 1462tx_bytes += le32_to_cpu(ad->cur_cmd->status); (gdb) bt full #0 ahci_commit_buf (dma=0x57335870, tx_bytes=2048) at ../hw/ide/ahci.c:1462 ad = 0x57335870 #1 0x55893171 in dma_buf_commit (s=0x57335930, tx_bytes=2048) at ../hw/ide/core.c:805 #2 0x558934f8 in ide_dma_cb (opaque=0x57335930, ret=0) at ../hw/ide/core.c:887 s = 0x57335930 n = 4 sector_num = 4491160 offset = 140732794753312 stay_active = false prep_size = 0 __PRETTY_FUNCTION__ = "ide_dma_cb" #3 0x55830720 in dma_complete (dbs=0x7ffee83d5120, ret=0) at ../softmmu/dma-helpers.c:121 __PRETTY_FUNCTION__ = "dma_complete" #4 0x558307cd in dma_blk_cb (opaque=0x7ffee83d5120, ret=0) at ../softmmu/dma-helpers.c:139 dbs = 0x7ffee83d5120 cur_addr = 140732794753408 cur_len = 93825013280880 mem = 0x7ffeeccfef00 __PRETTY_FUNCTION__ = "dma_blk_cb" #5 0x55d92bce in blk_aio_complete (acb=0x7ffee847bbe0) at ../block/block-backend.c:1412 #6 0x55d92df0 in blk_aio_read_entry (opaque=0x7ffee847bbe0) at ../block/block-backend.c:1466 acb = 0x7ffee847bbe0 rwco = 0x7ffee847bc08 qiov = 0x7ffee83d5180 __PRETTY_FUNCTION__ = "blk_aio_read_entry" #7 0x55e85580 in coroutine_trampoline (i0=-398117056, i1=32766) at ../util/coroutine-ucontext.c:173 arg = {p = 0x7ffee8453740, i = {-398117056, 32766}} self = 0x7ffee8453740 co = 0x7ffee8453740 fake_stack_save = 0x0 #8 0x76544020 in __start_context () at /lib64/libc.so.6 #9 0x7ffeefdfd680 in () #10 0x in () (gdb) (gdb) l 1457 */ 1458 static void ahci_commit_buf(const IDEDMA *dma, uint32_t tx_bytes) 1459 { 1460 AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1461 1462 tx_bytes += le32_to_cpu(ad->cur_cmd->status); 1463 ad->cur_cmd->status = cpu_to_le32(tx_bytes); 1464 } 1465 1466 static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write) (gdb) p ad $1 = (AHCIDevice *) 0x57335870 (gdb) p ad->cur_cmd $2 = (AHCICmdHdr *) 0x0 (gdb) To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1917442/+subscriptions
Re: [PATCH v1 8/9] util/mmap-alloc: support RAM_NORESERVE via MAP_NORESERVE
On Tue, Mar 02, 2021 at 08:01:11PM +0100, David Hildenbrand wrote: > On 02.03.21 18:51, Peter Xu wrote: > > On Tue, Feb 09, 2021 at 02:49:38PM +0100, David Hildenbrand wrote: > > > +#define OVERCOMMIT_MEMORY_PATH "/proc/sys/vm/overcommit_memory" > > > +static bool map_noreserve_effective(int fd, bool shared) > > > +{ > > > +#if defined(__linux__) > > > +gchar *content = NULL; > > > +const char *endptr; > > > +unsigned int tmp; > > > + > > > +/* hugetlbfs behaves differently */ > > > +if (qemu_fd_getpagesize(fd) != qemu_real_host_page_size) { > > > +return true; > > > +} > > > + > > > +/* only private shared mappings are accounted (ignoring /dev/zero) */ > > > +if (fd != -1 && shared) { > > > +return true; > > > +} [1] > > > + > > > +if (g_file_get_contents(OVERCOMMIT_MEMORY_PATH, , NULL, > > > NULL) && > > > +!qemu_strtoui(content, , 0, ) && > > > +(!endptr || *endptr == '\n')) { > > > +if (tmp == 2) { > > > +error_report("Skipping reservation of swap space is not > > > supported: " > > > + " \"" OVERCOMMIT_MEMORY_PATH "\" is \"2\""); > > > +return false; > > > +} > > > +return true; > > > +} > > > +/* this interface has been around since Linux 2.6 */ > > > +error_report("Skipping reservation of swap space is not supported: " > > > + " Could not read: \"" OVERCOMMIT_MEMORY_PATH "\""); > > > +return false; > > > +#else > > > +return true; > > > +#endif > > > +} > > > > I feel like this helper wants to fail gracefully for some conditions. Could > > you elaborate one example and attach to the commit log? > > Sure. The case is "/proc/sys/vm/overcommit_memory == 2" (never overcommit) > > MAP_NORESERVE is without effect and sparse memory regions are somewhat > impossible. > > > > > I'm also wondering whether it would worth to check the global value. Even > > if > > overcommit is globally disabled, do we (as an application process) need to > > care > > about it? I think the MAP_NORESERVE would simply be silently ignored by the > > kernel and that seems to be design of it, otherwise would all apps who uses > > > MAP_NORESERVE would need to do similar things too? > > Right, I want to catch the "gets silently ignored" part, because someone > requested "reserved=off" (!default) but does not actually get what he asked > for. > > As one example, glibc manages heaps via: > > a) Creating a new heap: mmap(PROT_NONE, MAP_NORESERVE) the maximum size, > then mprotect(PROT_READ|PROT_WRITE) the initial heap size. Even if > MAP_NORESERVE is ignored, only !PROT_NONE memory ever gets committed > ("reserve swap space") in Linux. > > b) Growing the heap via mprotect(PROT_READ|PROT_WRITE) within the existing > mmap. This will commit memory in case MAP_NORESERVE got ignored. > > c) Shrinking the heap ("discard memory") via MADV_DONTNEED *unless* > "/proc/sys/vm/overcommit_memory == 2" - the only way to undo > mprotect(PROT_READ|PROT_WRITE) and to un-commit memory is by doing a > mmap(PROT_NONE, MAP_FIXED) over the problematic region. > > If you're interested, you can take a look at: > > malloc/arena.c > sysdeps/unix/sysv/linux/malloc-sysdep.h:check_may_shrink_heap() Thanks for the context. It's interesting to know libc has such special heap operations. Glibc shrinks heap to save memory for the no-over-commit case, however in our case currently we'd like to fail some users using global_overcommit=2 but reserve=off - it means even if we don't fail the user, mmap() could also fail if it's overcommitted. Even if this mmap() didn't fail, it'll fail very easily later on iiuc, right? I think it's fine to have that early failure, it just seems less helpful than what glibc was doing which shrinks active memory for real, meanwhile there seems to encode some very detailed OS information into this helper, so just less charming. Btw above [1] "fd != -1 && shared" looks weird to me. Firstly it'll bypass overcommit_memory==2 check and return true directly, is that right? I thought the global will be meaningful for all memories except hugetlbfs (in do_mmap() of Linux). Meanwhile, I don't see why file-backed share memories is so special too.. From your commit message, I'm not sure whether you wanted to return false instead, however that's still not the case IIUC, since e.g. /dev/shmem still does accounting iiuc, while MAP_NORESERVE will skip it. -- Peter Xu
[PATCH] i386: Add missing cpu feature bits in EPYC-Rome model
Found the following cpu feature bits missing from EPYC-Rome model. ibrs: Indirect Branch Restricted Speculation ssbd: Speculative Store Bypass Disable These new features will be added in EPYC-Rome-v2. The -cpu help output after the change. x86 EPYC-Rome (alias configured by machine type) x86 EPYC-Rome-v1 AMD EPYC-Rome Processor x86 EPYC-Rome-v2 AMD EPYC-Rome Processor Reported-by: Pankaj Gupta Signed-off-by: Babu Moger Signed-off-by: Pankaj Gupta --- target/i386/cpu.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 6a53446e6a..9b5a31783d 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4179,6 +4179,20 @@ static X86CPUDefinition builtin_x86_defs[] = { .xlevel = 0x801E, .model_id = "AMD EPYC-Rome Processor", .cache_info = _rome_cache_info, +.versions = (X86CPUVersionDefinition[]) { +{ .version = 1 }, +{ +.version = 2, +.props = (PropValue[]) { +{ "ibrs", "on" }, +{ "amd-ssbd", "on" }, +{ "model-id", + "AMD EPYC-Rome Processor" }, +{ /* end of list */ } +} +}, +{ /* end of list */ } +} }, { .name = "EPYC-Milan",
[PATCH v5 8/8] hw/ppc: Add emulation of Genesi/bPlan Pegasos II
Add new machine called pegasos2 emulating the Genesi/bPlan Pegasos II, a PowerPC board based on the Marvell MV64361 system controller and the VIA VT8231 integrated south bridge/superio chips. It can run Linux, AmigaOS and a wide range of MorphOS versions. Currently a firmware ROM image is needed to boot and only MorphOS has a video driver to produce graphics output. Linux could work too but distros that supported this machine don't include usual video drivers so those only run with serial console for now. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé --- MAINTAINERS | 10 ++ default-configs/devices/ppc-softmmu.mak | 2 + hw/ppc/Kconfig | 9 ++ hw/ppc/meson.build | 2 + hw/ppc/pegasos2.c | 144 5 files changed, 167 insertions(+) create mode 100644 hw/ppc/pegasos2.c diff --git a/MAINTAINERS b/MAINTAINERS index 9b2aa18e1f..a023217702 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1345,6 +1345,16 @@ F: pc-bios/canyonlands.dt[sb] F: pc-bios/u-boot-sam460ex-20100605.bin F: roms/u-boot-sam460ex +pegasos2 +M: BALATON Zoltan +R: David Gibson +L: qemu-...@nongnu.org +S: Maintained +F: hw/ppc/pegasos2.c +F: hw/pci-host/mv64361.c +F: hw/pci-host/mv643xx.h +F: include/hw/pci-host/mv64361.h + RISC-V Machines --- OpenTitan diff --git a/default-configs/devices/ppc-softmmu.mak b/default-configs/devices/ppc-softmmu.mak index 61b78b844d..4535993d8d 100644 --- a/default-configs/devices/ppc-softmmu.mak +++ b/default-configs/devices/ppc-softmmu.mak @@ -14,5 +14,7 @@ CONFIG_SAM460EX=y CONFIG_MAC_OLDWORLD=y CONFIG_MAC_NEWWORLD=y +CONFIG_PEGASOS2=y + # For PReP CONFIG_PREP=y diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index d11dc30509..e51e0e5e5a 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -68,6 +68,15 @@ config SAM460EX select USB_OHCI select FDT_PPC +config PEGASOS2 +bool +select MV64361 +select VT82C686 +select IDE_VIA +select SMBUS_EEPROM +# This should come with VT82C686 +select ACPI_X86 + config PREP bool imply PCI_DEVICES diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index 218631c883..86d6f379d1 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -78,5 +78,7 @@ ppc_ss.add(when: 'CONFIG_E500', if_true: files( )) # PowerPC 440 Xilinx ML507 reference board. ppc_ss.add(when: 'CONFIG_VIRTEX', if_true: files('virtex_ml507.c')) +# Pegasos2 +ppc_ss.add(when: 'CONFIG_PEGASOS2', if_true: files('pegasos2.c')) hw_arch += {'ppc': ppc_ss} diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c new file mode 100644 index 00..0bfd0928aa --- /dev/null +++ b/hw/ppc/pegasos2.c @@ -0,0 +1,144 @@ +/* + * QEMU PowerPC CHRP (Genesi/bPlan Pegasos II) hardware System Emulator + * + * Copyright (c) 2018-2020 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/ppc/ppc.h" +#include "hw/sysbus.h" +#include "hw/pci/pci_host.h" +#include "hw/irq.h" +#include "hw/pci-host/mv64361.h" +#include "hw/isa/vt82c686.h" +#include "hw/ide/pci.h" +#include "hw/i2c/smbus_eeprom.h" +#include "hw/qdev-properties.h" +#include "sysemu/reset.h" +#include "hw/boards.h" +#include "hw/loader.h" +#include "hw/fw-path-provider.h" +#include "elf.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "sysemu/kvm.h" +#include "kvm_ppc.h" +#include "exec/address-spaces.h" +#include "trace.h" +#include "qemu/datadir.h" +#include "sysemu/device_tree.h" + +#define PROM_FILENAME "pegasos2.rom" +#define PROM_ADDR 0xfff0 +#define PROM_SIZE 0x8 + +#define BUS_FREQ_HZ 1 + +static void pegasos2_cpu_reset(void *opaque) +{ +PowerPCCPU *cpu = opaque; + +cpu_reset(CPU(cpu)); +cpu->env.spr[SPR_HID1] = 7ULL << 28; +} + +static void pegasos2_init(MachineState *machine) +{ +PowerPCCPU *cpu = NULL; +MemoryRegion *rom = g_new(MemoryRegion, 1); +DeviceState *mv; +PCIBus *pci_bus; +PCIDevice *dev; +I2CBus *i2c_bus; +const char *fwname = machine->firmware ?: PROM_FILENAME; +char *filename; +int sz; +uint8_t *spd_data; + +/* init CPU */ +cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); +if (PPC_INPUT(>env) != PPC_FLAGS_INPUT_6xx) { +error_report("Incompatible CPU, only 6xx bus supported"); +exit(1); +} + +/* Set time-base frequency */ +cpu_ppc_tb_init(>env, BUS_FREQ_HZ / 4); +qemu_register_reset(pegasos2_cpu_reset, cpu); + +/* RAM */ +memory_region_add_subregion(get_system_memory(), 0, machine->ram); + +/* allocate and load firmware */ +filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, fwname); +if (!filename) { +error_report("Could not find firmware '%s'", fwname); +exit(1); +} +
[PATCH v5 4/8] vt82c686: Introduce abstract TYPE_VIA_ISA and base vt82c686b_isa on it
To allow reusing ISA bridge emulation for vt8231_isa move the device state of vt82c686b_isa emulation in an abstract via_isa class. Signed-off-by: BALATON Zoltan --- hw/isa/vt82c686.c| 70 ++-- include/hw/pci/pci_ids.h | 2 +- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 72234bc4d1..5137f97f37 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -609,24 +609,48 @@ static const TypeInfo vt8231_superio_info = { }; -OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BISAState, VT82C686B_ISA) +#define TYPE_VIA_ISA "via-isa" +OBJECT_DECLARE_SIMPLE_TYPE(ViaISAState, VIA_ISA) -struct VT82C686BISAState { +struct ViaISAState { PCIDevice dev; qemu_irq cpu_intr; ViaSuperIOState *via_sio; }; +static const VMStateDescription vmstate_via = { +.name = "via-isa", +.version_id = 1, +.minimum_version_id = 1, +.fields = (VMStateField[]) { +VMSTATE_PCI_DEVICE(dev, ViaISAState), +VMSTATE_END_OF_LIST() +} +}; + +static const TypeInfo via_isa_info = { +.name = TYPE_VIA_ISA, +.parent= TYPE_PCI_DEVICE, +.instance_size = sizeof(ViaISAState), +.abstract = true, +.interfaces= (InterfaceInfo[]) { +{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, +{ }, +}, +}; + static void via_isa_request_i8259_irq(void *opaque, int irq, int level) { -VT82C686BISAState *s = opaque; +ViaISAState *s = opaque; qemu_set_irq(s->cpu_intr, level); } +/* TYPE_VT82C686B_ISA */ + static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) { -VT82C686BISAState *s = VT82C686B_ISA(d); +ViaISAState *s = VIA_ISA(d); trace_via_isa_write(addr, val, len); pci_default_write_config(d, addr, val, len); @@ -636,19 +660,9 @@ static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, } } -static const VMStateDescription vmstate_via = { -.name = "vt82c686b", -.version_id = 1, -.minimum_version_id = 1, -.fields = (VMStateField[]) { -VMSTATE_PCI_DEVICE(dev, VT82C686BISAState), -VMSTATE_END_OF_LIST() -} -}; - static void vt82c686b_isa_reset(DeviceState *dev) { -VT82C686BISAState *s = VT82C686B_ISA(dev); +ViaISAState *s = VIA_ISA(dev); uint8_t *pci_conf = s->dev.config; pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x00c0); @@ -668,7 +682,7 @@ static void vt82c686b_isa_reset(DeviceState *dev) static void vt82c686b_realize(PCIDevice *d, Error **errp) { -VT82C686BISAState *s = VT82C686B_ISA(d); +ViaISAState *s = VIA_ISA(d); DeviceState *dev = DEVICE(d); ISABus *isa_bus; qemu_irq *isa_irq; @@ -692,7 +706,7 @@ static void vt82c686b_realize(PCIDevice *d, Error **errp) } } -static void via_class_init(ObjectClass *klass, void *data) +static void vt82c686b_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); @@ -700,28 +714,21 @@ static void via_class_init(ObjectClass *klass, void *data) k->realize = vt82c686b_realize; k->config_write = vt82c686b_write_config; k->vendor_id = PCI_VENDOR_ID_VIA; -k->device_id = PCI_DEVICE_ID_VIA_ISA_BRIDGE; +k->device_id = PCI_DEVICE_ID_VIA_82C686B_ISA; k->class_id = PCI_CLASS_BRIDGE_ISA; k->revision = 0x40; dc->reset = vt82c686b_isa_reset; dc->desc = "ISA bridge"; dc->vmsd = _via; -/* - * Reason: part of VIA VT82C686 southbridge, needs to be wired up, - * e.g. by mips_fuloong2e_init() - */ +/* Reason: part of VIA VT82C686 southbridge, needs to be wired up */ dc->user_creatable = false; } -static const TypeInfo via_info = { +static const TypeInfo vt82c686b_isa_info = { .name = TYPE_VT82C686B_ISA, -.parent= TYPE_PCI_DEVICE, -.instance_size = sizeof(VT82C686BISAState), -.class_init= via_class_init, -.interfaces = (InterfaceInfo[]) { -{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, -{ }, -}, +.parent= TYPE_VIA_ISA, +.instance_size = sizeof(ViaISAState), +.class_init= vt82c686b_class_init, }; @@ -733,7 +740,8 @@ static void vt82c686b_register_types(void) type_register_static(_superio_info); type_register_static(_superio_info); type_register_static(_superio_info); -type_register_static(_info); +type_register_static(_isa_info); +type_register_static(_isa_info); } type_init(vt82c686b_register_types) diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index ea28dcc850..aa3f67eaa4 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -204,7 +204,7 @@ #define PCI_VENDOR_ID_XILINX 0x10ee #define PCI_VENDOR_ID_VIA0x1106 -#define PCI_DEVICE_ID_VIA_ISA_BRIDGE 0x0686 +#define PCI_DEVICE_ID_VIA_82C686B_ISA
[PATCH v5 3/8] vt82c686: Add VT8231_SUPERIO based on VIA_SUPERIO
The VT8231 south bridge is very similar to VT82C686B but there are some differences in register addresses and functionality, e.g. the VT8231 only has one serial port. This commit adds VT8231_SUPERIO subclass based on the abstract VIA_SUPERIO class to emulate the superio part of VT8231. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 121 ++ 1 file changed, 121 insertions(+) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 9b2ffecc79..72234bc4d1 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -489,6 +489,126 @@ static const TypeInfo vt82c686b_superio_info = { }; +#define TYPE_VT8231_SUPERIO "vt8231-superio" + +static void vt8231_superio_cfg_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ +ViaSuperIOState *sc = opaque; +uint8_t idx = sc->regs[0]; + +if (addr == 0) { /* config index register */ +sc->regs[0] = data; +return; +} + +/* config data register */ +trace_via_superio_write(idx, data); +switch (idx) { +case 0x00 ... 0xdf: +case 0xe7 ... 0xef: +case 0xf0 ... 0xf1: +case 0xf5: +case 0xf8: +case 0xfd: +/* ignore write to read only registers */ +return; +case 0xf2: /* Function select */ +{ +data &= 0x17; +if (data & BIT(2)) { /* Serial port enable */ +ISADevice *dev = sc->superio.serial[0]; +if (!memory_region_is_mapped(sc->serial_io[0])) { +memory_region_add_subregion(isa_address_space_io(dev), +dev->ioport_id, sc->serial_io[0]); +} +} else { +MemoryRegion *io = isa_address_space_io(sc->superio.serial[0]); +if (memory_region_is_mapped(sc->serial_io[0])) { +memory_region_del_subregion(io, sc->serial_io[0]); +} +} +break; +} +case 0xf4: /* Serial port io base address */ +{ +data &= 0xfe; +sc->superio.serial[0]->ioport_id = data << 2; +if (memory_region_is_mapped(sc->serial_io[0])) { +memory_region_set_address(sc->serial_io[0], data << 2); +} +break; +} +default: +qemu_log_mask(LOG_UNIMP, + "via_superio_cfg: unimplemented register 0x%x\n", idx); +break; +} +sc->regs[idx] = data; +} + +static const MemoryRegionOps vt8231_superio_cfg_ops = { +.read = via_superio_cfg_read, +.write = vt8231_superio_cfg_write, +.endianness = DEVICE_NATIVE_ENDIAN, +.impl = { +.min_access_size = 1, +.max_access_size = 1, +}, +}; + +static void vt8231_superio_reset(DeviceState *dev) +{ +ViaSuperIOState *s = VIA_SUPERIO(dev); + +memset(s->regs, 0, sizeof(s->regs)); +/* Device ID */ +s->regs[0xf0] = 0x3c; +/* Device revision */ +s->regs[0xf1] = 0x01; +/* Function select - all disabled */ +vt8231_superio_cfg_write(s, 0, 0xf2, 1); +vt8231_superio_cfg_write(s, 1, 0x03, 1); +/* Serial port base addr */ +vt8231_superio_cfg_write(s, 0, 0xf4, 1); +vt8231_superio_cfg_write(s, 1, 0xfe, 1); +/* Parallel port base addr */ +vt8231_superio_cfg_write(s, 0, 0xf6, 1); +vt8231_superio_cfg_write(s, 1, 0xde, 1); +/* Floppy ctrl base addr */ +vt8231_superio_cfg_write(s, 0, 0xf7, 1); +vt8231_superio_cfg_write(s, 1, 0xfc, 1); + +vt8231_superio_cfg_write(s, 0, 0, 1); +} + +static void vt8231_superio_init(Object *obj) +{ +VIA_SUPERIO(obj)->io_ops = _superio_cfg_ops; +} + +static void vt8231_superio_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +ISASuperIOClass *sc = ISA_SUPERIO_CLASS(klass); + +dc->reset = vt8231_superio_reset; +sc->serial.count = 1; +sc->parallel.count = 1; +sc->ide.count = 0; /* emulated by via-ide */ +sc->floppy.count = 1; +} + +static const TypeInfo vt8231_superio_info = { +.name = TYPE_VT8231_SUPERIO, +.parent= TYPE_VIA_SUPERIO, +.instance_size = sizeof(ViaSuperIOState), +.instance_init = vt8231_superio_init, +.class_size= sizeof(ISASuperIOClass), +.class_init= vt8231_superio_class_init, +}; + + OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BISAState, VT82C686B_ISA) struct VT82C686BISAState { @@ -612,6 +732,7 @@ static void vt82c686b_register_types(void) type_register_static(_pm_info); type_register_static(_superio_info); type_register_static(_superio_info); +type_register_static(_superio_info); type_register_static(_info); } -- 2.21.3
[PATCH v5 6/8] hw/isa/Kconfig: Add missing dependency VIA VT82C686 -> APM
From: Philippe Mathieu-Daudé TYPE_VIA_PM calls apm_init() in via_pm_realize(), so requires APM to be selected. Reported-by: BALATON Zoltan Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: BALATON Zoltan --- hw/isa/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig index c7f07854f7..9c026d0c51 100644 --- a/hw/isa/Kconfig +++ b/hw/isa/Kconfig @@ -47,6 +47,7 @@ config VT82C686 select ACPI_SMBUS select SERIAL_ISA select FDC +select APM config SMC37C669 bool -- 2.21.3
Re: [PATCH v3 3/3] vfio: Avoid disabling and enabling vectors repeatedly in VFIO migration
MST/Marcel, Do you have an Ack or objection to exporting msix_masked() as below? Thanks, Alex On Tue, 23 Feb 2021 10:22:25 +0800 Shenming Lu wrote: > In VFIO migration resume phase and some guest startups, there are > already unmasked vectors in the vector table when calling > vfio_msix_enable(). So in order to avoid inefficiently disabling > and enabling vectors repeatedly, let's allocate all needed vectors > first and then enable these unmasked vectors one by one without > disabling. > > Signed-off-by: Shenming Lu > --- > hw/pci/msix.c | 2 +- > hw/vfio/pci.c | 20 +--- > include/hw/pci/msix.h | 1 + > 3 files changed, 19 insertions(+), 4 deletions(-) > > diff --git a/hw/pci/msix.c b/hw/pci/msix.c > index ae9331cd0b..e057958fcd 100644 > --- a/hw/pci/msix.c > +++ b/hw/pci/msix.c > @@ -131,7 +131,7 @@ static void msix_handle_mask_update(PCIDevice *dev, int > vector, bool was_masked) > } > } > > -static bool msix_masked(PCIDevice *dev) > +bool msix_masked(PCIDevice *dev) > { > return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & > MSIX_MASKALL_MASK; > } > diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c > index f74be78209..088fd41926 100644 > --- a/hw/vfio/pci.c > +++ b/hw/vfio/pci.c > @@ -569,6 +569,9 @@ static void vfio_msix_vector_release(PCIDevice *pdev, > unsigned int nr) > > static void vfio_msix_enable(VFIOPCIDevice *vdev) > { > +PCIDevice *pdev = >pdev; > +unsigned int nr, max_vec = 0; > + > vfio_disable_interrupts(vdev); > > vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->msix->entries); > @@ -587,11 +590,22 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev) > * triggering to userspace, then immediately release the vector, leaving > * the physical device with no vectors enabled, but MSI-X enabled, just > * like the guest view. > + * If there are already unmasked vectors (in migration resume phase and > + * some guest startups) which will be enabled soon, we can allocate all > + * of them here to avoid inefficiently disabling and enabling vectors > + * repeatedly later. > */ > -vfio_msix_vector_do_use(>pdev, 0, NULL, NULL); > -vfio_msix_vector_release(>pdev, 0); > +if (!msix_masked(pdev)) { > +for (nr = 0; nr < msix_nr_vectors_allocated(pdev); nr++) { > +if (!msix_is_masked(pdev, nr)) { > +max_vec = nr; > +} > +} > +} > +vfio_msix_vector_do_use(pdev, max_vec, NULL, NULL); > +vfio_msix_vector_release(pdev, max_vec); > > -if (msix_set_vector_notifiers(>pdev, vfio_msix_vector_use, > +if (msix_set_vector_notifiers(pdev, vfio_msix_vector_use, >vfio_msix_vector_release, NULL)) { > error_report("vfio: msix_set_vector_notifiers failed"); > } > diff --git a/include/hw/pci/msix.h b/include/hw/pci/msix.h > index 4c4a60c739..b3cd88e262 100644 > --- a/include/hw/pci/msix.h > +++ b/include/hw/pci/msix.h > @@ -28,6 +28,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f); > > int msix_enabled(PCIDevice *dev); > int msix_present(PCIDevice *dev); > +bool msix_masked(PCIDevice *dev); > > bool msix_is_masked(PCIDevice *dev, unsigned vector); > void msix_set_pending(PCIDevice *dev, unsigned vector);
[PATCH v5 7/8] hw/pci-host: Add emulation of Marvell MV64361 PPC system controller
The Marvell Discovery II aka. MV64361 is a PowerPC system controller chip that is used on the pegasos2 PPC board. This adds emulation of it that models the device enough to boot guests on this board. The mv643xx.h header with register definitions is taken from Linux 4.15.10 only fixing white space errors, removing not needed parts and changing formatting for QEMU coding style. Signed-off-by: BALATON Zoltan --- hw/pci-host/Kconfig | 4 + hw/pci-host/meson.build | 2 + hw/pci-host/mv64361.c | 966 ++ hw/pci-host/mv643xx.h | 918 hw/pci-host/trace-events | 6 + include/hw/pci-host/mv64361.h | 8 + include/hw/pci/pci_ids.h | 1 + 7 files changed, 1905 insertions(+) create mode 100644 hw/pci-host/mv64361.c create mode 100644 hw/pci-host/mv643xx.h create mode 100644 include/hw/pci-host/mv64361.h diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index 8b8c763c28..4a8615b2d0 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -68,3 +68,7 @@ config PCI_POWERNV config REMOTE_PCIHOST bool + +config MV64361 +bool +select PCI diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index 1847c69905..3f9e716cfa 100644 --- a/hw/pci-host/meson.build +++ b/hw/pci-host/meson.build @@ -18,6 +18,8 @@ pci_ss.add(when: 'CONFIG_GRACKLE_PCI', if_true: files('grackle.c')) pci_ss.add(when: 'CONFIG_UNIN_PCI', if_true: files('uninorth.c')) # PowerPC E500 boards pci_ss.add(when: 'CONFIG_PPCE500_PCI', if_true: files('ppce500.c')) +# Pegasos2 +pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c')) # ARM devices pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c')) diff --git a/hw/pci-host/mv64361.c b/hw/pci-host/mv64361.c new file mode 100644 index 00..d71402f8b5 --- /dev/null +++ b/hw/pci-host/mv64361.c @@ -0,0 +1,966 @@ +/* + * Marvell Discovery II MV64361 System Controller for + * QEMU PowerPC CHRP (Genesi/bPlan Pegasos II) hardware System Emulator + * + * Copyright (c) 2018-2020 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "hw/irq.h" +#include "hw/intc/i8259.h" +#include "hw/qdev-properties.h" +#include "exec/address-spaces.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "trace.h" +#include "hw/pci-host/mv64361.h" +#include "mv643xx.h" + +#define TYPE_MV64361_PCI_BRIDGE "mv64361-pcibridge" + +static void mv64361_pcibridge_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + +k->vendor_id = PCI_VENDOR_ID_MARVELL; +k->device_id = PCI_DEVICE_ID_MARVELL_MV6436X; +k->class_id = PCI_CLASS_BRIDGE_HOST; +/* + * PCI-facing part of the host bridge, + * not usable without the host-facing part + */ +dc->user_creatable = false; +} + +static const TypeInfo mv64361_pcibridge_info = { +.name = TYPE_MV64361_PCI_BRIDGE, +.parent= TYPE_PCI_DEVICE, +.instance_size = sizeof(PCIDevice), +.class_init= mv64361_pcibridge_class_init, +.interfaces = (InterfaceInfo[]) { +{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, +{ }, +}, +}; + + +#define TYPE_MV64361_PCI "mv64361-pcihost" +OBJECT_DECLARE_SIMPLE_TYPE(MV64361PCIState, MV64361_PCI) + +struct MV64361PCIState { +PCIHostState parent_obj; + +uint8_t index; +MemoryRegion io; +MemoryRegion mem; +qemu_irq irq[PCI_NUM_PINS]; + +uint32_t io_base; +uint32_t io_size; +uint32_t mem_base[4]; +uint32_t mem_size[4]; +uint64_t remap[5]; +}; + +static int mv64361_pcihost_map_irq(PCIDevice *pci_dev, int n) +{ +return (n + PCI_SLOT(pci_dev->devfn)) % PCI_NUM_PINS; +} + +static void mv64361_pcihost_set_irq(void *opaque, int n, int level) +{ +MV64361PCIState *s = opaque; +qemu_set_irq(s->irq[n], level); +} + +static void mv64361_pcihost_realize(DeviceState *dev, Error **errp) +{ +MV64361PCIState *s = MV64361_PCI(dev); +PCIHostState *h = PCI_HOST_BRIDGE(dev); +char *name; + +name = g_strdup_printf("pci%d-io", s->index); +memory_region_init(>io, OBJECT(dev), name, 0x1); +g_free(name); +name = g_strdup_printf("pci%d-mem", s->index); +memory_region_init(>mem, OBJECT(dev), name, 1ULL << 32); +g_free(name); +name = g_strdup_printf("pci.%d", s->index); +h->bus = pci_register_root_bus(dev, name, mv64361_pcihost_set_irq, + mv64361_pcihost_map_irq, dev, + >mem, >io, 0, 4, TYPE_PCI_BUS); +g_free(name); +pci_create_simple(h->bus, 0, TYPE_MV64361_PCI_BRIDGE); +} + +static Property mv64361_pcihost_props[] = { +
[PATCH v5 5/8] vt82c686: Add emulation of VT8231 south bridge
Add emulation of VT8231 south bridge ISA part based on the similar VT82C686B but implemented in a separate subclass that holds the differences while reusing parts that can be shared. Signed-off-by: BALATON Zoltan --- hw/isa/vt82c686.c | 84 +++ include/hw/isa/vt82c686.h | 1 + include/hw/pci/pci_ids.h | 1 + 3 files changed, 86 insertions(+) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 5137f97f37..e0f2f2a5ce 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -8,6 +8,9 @@ * * Contributions after 2012-01-13 are licensed under the terms of the * GNU GPL, version 2 or (at your option) any later version. + * + * VT8231 south bridge support and general clean up to allow it + * Copyright (c) 2018-2020 BALATON Zoltan */ #include "qemu/osdep.h" @@ -731,6 +734,86 @@ static const TypeInfo vt82c686b_isa_info = { .class_init= vt82c686b_class_init, }; +/* TYPE_VT8231_ISA */ + +static void vt8231_write_config(PCIDevice *d, uint32_t addr, +uint32_t val, int len) +{ +ViaISAState *s = VIA_ISA(d); + +trace_via_isa_write(addr, val, len); +pci_default_write_config(d, addr, val, len); +if (addr == 0x50) { +/* BIT(2): enable or disable superio config io ports */ +via_superio_io_enable(s->via_sio, val & BIT(2)); +} +} + +static void vt8231_isa_reset(DeviceState *dev) +{ +ViaISAState *s = VIA_ISA(dev); +uint8_t *pci_conf = s->dev.config; + +pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x00c0); +pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL); +pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM); + +pci_conf[0x58] = 0x40; /* Miscellaneous Control 0 */ +pci_conf[0x67] = 0x08; /* Fast IR Config */ +pci_conf[0x6b] = 0x01; /* Fast IR I/O Base */ +} + +static void vt8231_realize(PCIDevice *d, Error **errp) +{ +ViaISAState *s = VIA_ISA(d); +DeviceState *dev = DEVICE(d); +ISABus *isa_bus; +qemu_irq *isa_irq; +int i; + +qdev_init_gpio_out(dev, >cpu_intr, 1); +isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1); +isa_bus = isa_bus_new(dev, get_system_memory(), pci_address_space_io(d), + _fatal); +isa_bus_irqs(isa_bus, i8259_init(isa_bus, *isa_irq)); +i8254_pit_init(isa_bus, 0x40, 0, NULL); +i8257_dma_init(isa_bus, 0); +s->via_sio = VIA_SUPERIO(isa_create_simple(isa_bus, TYPE_VT8231_SUPERIO)); +mc146818_rtc_init(isa_bus, 2000, NULL); + +for (i = 0; i < PCI_CONFIG_HEADER_SIZE; i++) { +if (i < PCI_COMMAND || i >= PCI_REVISION_ID) { +d->wmask[i] = 0; +} +} +} + +static void vt8231_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + +k->realize = vt8231_realize; +k->config_write = vt8231_write_config; +k->vendor_id = PCI_VENDOR_ID_VIA; +k->device_id = PCI_DEVICE_ID_VIA_8231_ISA; +k->class_id = PCI_CLASS_BRIDGE_ISA; +k->revision = 0x10; +dc->reset = vt8231_isa_reset; +dc->desc = "ISA bridge"; +dc->vmsd = _via; +/* Reason: part of VIA VT8231 southbridge, needs to be wired up */ +dc->user_creatable = false; +} + +static const TypeInfo vt8231_isa_info = { +.name = TYPE_VT8231_ISA, +.parent= TYPE_VIA_ISA, +.instance_size = sizeof(ViaISAState), +.class_init= vt8231_class_init, +}; + static void vt82c686b_register_types(void) { @@ -742,6 +825,7 @@ static void vt82c686b_register_types(void) type_register_static(_superio_info); type_register_static(_isa_info); type_register_static(_isa_info); +type_register_static(_isa_info); } type_init(vt82c686b_register_types) diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index 0692b9a527..0f01aaa471 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -3,6 +3,7 @@ #define TYPE_VT82C686B_ISA "vt82c686b-isa" #define TYPE_VT82C686B_PM "vt82c686b-pm" +#define TYPE_VT8231_ISA "vt8231-isa" #define TYPE_VT8231_PM "vt8231-pm" #define TYPE_VIA_AC97 "via-ac97" #define TYPE_VIA_MC97 "via-mc97" diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index aa3f67eaa4..ac0c23ebc7 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -210,6 +210,7 @@ #define PCI_DEVICE_ID_VIA_82C686B_PM 0x3057 #define PCI_DEVICE_ID_VIA_AC97 0x3058 #define PCI_DEVICE_ID_VIA_MC97 0x3068 +#define PCI_DEVICE_ID_VIA_8231_ISA 0x8231 #define PCI_DEVICE_ID_VIA_8231_PM0x8235 #define PCI_VENDOR_ID_MARVELL0x11ab -- 2.21.3
[PATCH v5 2/8] vt82c686: QOM-ify superio related functionality
Collect superio functionality and its controlling config registers handling in an abstract VIA_SUPERIO class that is a subclass of ISA_SUPERIO and put vt82c686b specific parts in a subclass of this abstract class. Signed-off-by: BALATON Zoltan --- hw/isa/vt82c686.c | 240 -- include/hw/isa/vt82c686.h | 1 - 2 files changed, 150 insertions(+), 91 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index a3353ec5db..9b2ffecc79 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -249,12 +249,21 @@ static const TypeInfo vt8231_pm_info = { }; -typedef struct SuperIOConfig { +#define TYPE_VIA_SUPERIO "via-superio" +OBJECT_DECLARE_SIMPLE_TYPE(ViaSuperIOState, VIA_SUPERIO) + +struct ViaSuperIOState { +ISASuperIODevice superio; uint8_t regs[0x100]; +const MemoryRegionOps *io_ops; MemoryRegion io; -ISASuperIODevice *superio; MemoryRegion *serial_io[SUPERIO_MAX_SERIAL_PORTS]; -} SuperIOConfig; +}; + +static inline void via_superio_io_enable(ViaSuperIOState *s, bool enable) +{ +memory_region_set_enabled(>io, enable); +} static MemoryRegion *find_subregion(ISADevice *d, MemoryRegion *parent, int offs) @@ -270,10 +279,76 @@ static MemoryRegion *find_subregion(ISADevice *d, MemoryRegion *parent, return mr; } -static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, - unsigned size) +static void via_superio_realize(DeviceState *d, Error **errp) +{ +ViaSuperIOState *s = VIA_SUPERIO(d); +ISASuperIOClass *ic = ISA_SUPERIO_GET_CLASS(s); +int i; + +assert(s->io_ops); +ic->parent_realize(d, errp); +if (*errp) { +return; +} +/* Grab io regions of serial devices so we can control them */ +for (i = 0; i < ic->serial.count; i++) { +ISADevice *sd = s->superio.serial[i]; +MemoryRegion *io = isa_address_space_io(sd); +MemoryRegion *mr = find_subregion(sd, io, sd->ioport_id); +if (!mr) { +error_setg(errp, "Could not get io region for serial %d", i); +return; +} +s->serial_io[i] = mr; +} + +memory_region_init_io(>io, OBJECT(d), s->io_ops, s, "via-superio", 2); +memory_region_set_enabled(>io, false); +/* The floppy also uses 0x3f0 and 0x3f1 but this seems to work anyway */ +memory_region_add_subregion(isa_address_space_io(ISA_DEVICE(s)), 0x3f0, +>io); +} + +static uint64_t via_superio_cfg_read(void *opaque, hwaddr addr, unsigned size) +{ +ViaSuperIOState *sc = opaque; +uint8_t idx = sc->regs[0]; +uint8_t val = sc->regs[idx]; + +if (addr == 0) { +return idx; +} +if (addr == 1 && idx == 0) { +val = 0; /* reading reg 0 where we store index value */ +} +trace_via_superio_read(idx, val); +return val; +} + +static void via_superio_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +ISASuperIOClass *sc = ISA_SUPERIO_CLASS(klass); + +sc->parent_realize = dc->realize; +dc->realize = via_superio_realize; +} + +static const TypeInfo via_superio_info = { +.name = TYPE_VIA_SUPERIO, +.parent= TYPE_ISA_SUPERIO, +.instance_size = sizeof(ViaSuperIOState), +.class_size= sizeof(ISASuperIOClass), +.class_init= via_superio_class_init, +.abstract = true, +}; + +#define TYPE_VT82C686B_SUPERIO "vt82c686b-superio" + +static void vt82c686b_superio_cfg_write(void *opaque, hwaddr addr, +uint64_t data, unsigned size) { -SuperIOConfig *sc = opaque; +ViaSuperIOState *sc = opaque; uint8_t idx = sc->regs[0]; if (addr == 0) { /* config index register */ @@ -295,29 +370,29 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, case 0xfd ... 0xff: /* ignore write to read only registers */ return; -case 0xe2: +case 0xe2: /* Function select */ { data &= 0x1f; if (data & BIT(2)) { /* Serial port 1 enable */ -ISADevice *dev = sc->superio->serial[0]; +ISADevice *dev = sc->superio.serial[0]; if (!memory_region_is_mapped(sc->serial_io[0])) { memory_region_add_subregion(isa_address_space_io(dev), dev->ioport_id, sc->serial_io[0]); } } else { -MemoryRegion *io = isa_address_space_io(sc->superio->serial[0]); +MemoryRegion *io = isa_address_space_io(sc->superio.serial[0]); if (memory_region_is_mapped(sc->serial_io[0])) { memory_region_del_subregion(io, sc->serial_io[0]); } } if (data & BIT(3)) { /* Serial port 2 enable */ -ISADevice *dev = sc->superio->serial[1]; +ISADevice *dev = sc->superio.serial[1];
[PATCH v5 1/8] vt82c686: Implement control of serial port io ranges via config regs
In VIA super south bridge the io ranges of superio components (parallel and serial ports and FDC) can be controlled by superio config registers to set their base address and enable/disable them. This is not easy to implement in QEMU because ISA emulation is only designed to set io base address once on creating the device and io ranges are registered at creation and cannot easily be disabled or moved later. In this patch we hack around that but only for serial ports because those have a single io range at port base that's relatively easy to handle and it's what guests actually use and set address different than the default. We do not attempt to handle controlling the parallel and FDC regions because those have multiple io ranges so handling them would be messy and guests either don't change their deafult or don't care. We could even get away with disabling and not emulating them, but since they are already there, this patch leaves them mapped at their default address just in case this could be useful for a guest in the future. Signed-off-by: BALATON Zoltan --- hw/isa/vt82c686.c | 84 +-- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 05d084f698..a3353ec5db 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -252,8 +252,24 @@ static const TypeInfo vt8231_pm_info = { typedef struct SuperIOConfig { uint8_t regs[0x100]; MemoryRegion io; +ISASuperIODevice *superio; +MemoryRegion *serial_io[SUPERIO_MAX_SERIAL_PORTS]; } SuperIOConfig; +static MemoryRegion *find_subregion(ISADevice *d, MemoryRegion *parent, +int offs) +{ +MemoryRegion *subregion, *mr = NULL; + +QTAILQ_FOREACH(subregion, >subregions, subregions_link) { +if (subregion->addr == offs) { +mr = subregion; +break; +} +} +return mr; +} + static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { @@ -279,7 +295,53 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, case 0xfd ... 0xff: /* ignore write to read only registers */ return; -/* case 0xe6 ... 0xe8: Should set base port of parallel and serial */ +case 0xe2: +{ +data &= 0x1f; +if (data & BIT(2)) { /* Serial port 1 enable */ +ISADevice *dev = sc->superio->serial[0]; +if (!memory_region_is_mapped(sc->serial_io[0])) { +memory_region_add_subregion(isa_address_space_io(dev), +dev->ioport_id, sc->serial_io[0]); +} +} else { +MemoryRegion *io = isa_address_space_io(sc->superio->serial[0]); +if (memory_region_is_mapped(sc->serial_io[0])) { +memory_region_del_subregion(io, sc->serial_io[0]); +} +} +if (data & BIT(3)) { /* Serial port 2 enable */ +ISADevice *dev = sc->superio->serial[1]; +if (!memory_region_is_mapped(sc->serial_io[1])) { +memory_region_add_subregion(isa_address_space_io(dev), +dev->ioport_id, sc->serial_io[1]); +} +} else { +MemoryRegion *io = isa_address_space_io(sc->superio->serial[1]); +if (memory_region_is_mapped(sc->serial_io[1])) { +memory_region_del_subregion(io, sc->serial_io[1]); +} +} +break; +} +case 0xe7: /* Serial port 1 io base address */ +{ +data &= 0xfe; +sc->superio->serial[0]->ioport_id = data << 2; +if (memory_region_is_mapped(sc->serial_io[0])) { +memory_region_set_address(sc->serial_io[0], data << 2); +} +break; +} +case 0xe8: /* Serial port 2 io base address */ +{ +data &= 0xfe; +sc->superio->serial[1]->ioport_id = data << 2; +if (memory_region_is_mapped(sc->serial_io[1])) { +memory_region_set_address(sc->serial_io[1], data << 2); +} +break; +} default: qemu_log_mask(LOG_UNIMP, "via_superio_cfg: unimplemented register 0x%x\n", idx); @@ -385,6 +447,7 @@ static void vt82c686b_realize(PCIDevice *d, Error **errp) DeviceState *dev = DEVICE(d); ISABus *isa_bus; qemu_irq *isa_irq; +ISASuperIOClass *ic; int i; qdev_init_gpio_out(dev, >cpu_intr, 1); @@ -394,7 +457,9 @@ static void vt82c686b_realize(PCIDevice *d, Error **errp) isa_bus_irqs(isa_bus, i8259_init(isa_bus, *isa_irq)); i8254_pit_init(isa_bus, 0x40, 0, NULL); i8257_dma_init(isa_bus, 0); -isa_create_simple(isa_bus, TYPE_VT82C686B_SUPERIO); +s->superio_cfg.superio = ISA_SUPERIO(isa_create_simple(isa_bus, + TYPE_VT82C686B_SUPERIO)); +ic =
[PATCH v5 0/8] Pegasos2 emulation
Hello, This is adding a new PPC board called pegasos2. More info on it can be found at: https://osdn.net/projects/qmiga/wiki/SubprojectPegasos2 Currently it needs a firmware ROM image that I cannot include due to original copyright holder (bPlan) did not release it under a free licence but I have plans to write a replacement in the future. With the original board firmware it can boot MorphOS now as: qemu-system-ppc -M pegasos2 -cdrom morphos.iso -device ati-vga,romfile="" -serial stdio then enter "boot cd boot.img" at the firmware "ok" prompt as described in the MorphOS.readme. To boot Linux use same command line with e.g. -cdrom debian-8.11.0-powerpc-netinst.iso then enter "boot cd install/pegasos" The last patch adds the actual board code after previous patches adding VT8231 and MV64361 system controller chip emulation. Regards, BALATON Zoltan v5: Changes for review comments from David and Philippe V4: Rename pegasos2_reset to pegasos2_cpu_reset Add new files to MAINTAINERS BALATON Zoltan (7): vt82c686: Implement control of serial port io ranges via config regs vt82c686: QOM-ify superio related functionality vt82c686: Add VT8231_SUPERIO based on VIA_SUPERIO vt82c686: Introduce abstract TYPE_VIA_ISA and base vt82c686b_isa on it vt82c686: Add emulation of VT8231 south bridge hw/pci-host: Add emulation of Marvell MV64361 PPC system controller hw/ppc: Add emulation of Genesi/bPlan Pegasos II Philippe Mathieu-Daudé (1): hw/isa/Kconfig: Add missing dependency VIA VT82C686 -> APM MAINTAINERS | 10 + default-configs/devices/ppc-softmmu.mak | 2 + hw/isa/Kconfig | 1 + hw/isa/vt82c686.c | 515 +++-- hw/pci-host/Kconfig | 4 + hw/pci-host/meson.build | 2 + hw/pci-host/mv64361.c | 966 hw/pci-host/mv643xx.h | 918 ++ hw/pci-host/trace-events| 6 + hw/ppc/Kconfig | 9 + hw/ppc/meson.build | 2 + hw/ppc/pegasos2.c | 144 include/hw/isa/vt82c686.h | 2 +- include/hw/pci-host/mv64361.h | 8 + include/hw/pci/pci_ids.h| 4 +- 15 files changed, 2510 insertions(+), 83 deletions(-) create mode 100644 hw/pci-host/mv64361.c create mode 100644 hw/pci-host/mv643xx.h create mode 100644 hw/ppc/pegasos2.c create mode 100644 include/hw/pci-host/mv64361.h -- 2.21.3
Re: [PATCH] meson: add tests option
Hello, Le 02/03/2021 à 12:08, Paolo Bonzini a écrit : > On 02/03/21 11:22, Thomas Huth wrote: >> On 26/02/2021 23.07, Romain Naour wrote: >>> tests/fp/fp-bench.c use fenv.h that is not always provided >>> by the libc (uClibc). >> >> For such problem it might be better to check for the availability of the >> header and then to only disable the single test that depends on it if the >> header is not available. You're right, I thought about adding a header check but I noticed that was no option to disable all tests. Buildroot try to avoid as much as possible building tests program. >> >> Anyway, a switch to disable the tests completely could still be handy in some >> cases, so FWIW: It can save some build time: qemu build with tests disabled real3m27,310s user19m56,887s sys 2m1,738s qemu build with tests enabled real4m0,638s user23m34,963s sys 2m32,944s >> >> Acked-by: Thomas Huth > > I disagree, without a use case the right thing to do is to check for fenv.h. > It's as easy as this: Is it ok if I take your patch to disable fp tests when fenv.h is missing and resend my patch with an updated commit log to disable all tests to save some build time? Best regards, Romain > > diff --git a/tests/meson.build b/tests/meson.build > index 0c939f89f7..3b9b2f0483 100644 > --- a/tests/meson.build > +++ b/tests/meson.build > @@ -281,7 +281,7 @@ test('decodetree', sh, > workdir: meson.current_source_dir() / 'decode', > suite: 'decodetree') > > -if 'CONFIG_TCG' in config_all > +if 'CONFIG_TCG' in config_all and cc.has_header('fenv.h') > subdir('fp') > endif > > Thanks, > > Paolo >
Re: [RFC PATCH 00/26] Confidential guest live migration
Patchew URL: https://patchew.org/QEMU/20210302204822.81901-1-dovmu...@linux.vnet.ibm.com/ Hi, This series seems to have some coding style problems. See output below for more information: Type: series Message-id: 20210302204822.81901-1-dovmu...@linux.vnet.ibm.com Subject: [RFC PATCH 00/26] Confidential guest live migration === TEST SCRIPT BEGIN === #!/bin/bash git rev-parse base > /dev/null || exit 0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram ./scripts/checkpatch.pl --mailback base.. === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 From https://github.com/patchew-project/qemu - [tag update] patchew/20210302175524.1290840-1-berra...@redhat.com -> patchew/20210302175524.1290840-1-berra...@redhat.com * [new tag] patchew/20210302204822.81901-1-dovmu...@linux.vnet.ibm.com -> patchew/20210302204822.81901-1-dovmu...@linux.vnet.ibm.com Switched to a new branch 'test' f283a35 docs: Add confidential guest live migration documentation 08f3c3b target/i386: SEV: Allow migration unless there are no aux vcpus 99d1efb migration: Add start-migrate-incoming QMP command 6ca0894 target/i386: Re-sync kvm-clock after confidential guest migration 47e02a0 hw/isa/lpc_ich9: Allow updating an already-running VM af25d7b migration: Call migration handler cleanup routines 48db1fb migration: When starting target, don't sync auxiliary vcpus 5eb9336 migration: Don't sync vcpus when migrating confidential guests af9b2fa migration: Stop non-aux vcpus before copying the last pages 2789368 migration: Stop VM after loading confidential RAM 4692252 migration: Load confidential guest RAM using migration helper e041f58 migration: Save confidential guest RAM using migration helper 328a888 migration: Introduce gpa_inside_migration_helper_shared_area b71be10 migration: Add helpers to load confidential RAM 32bdb2e migration: Add helpers to save confidential RAM 8d2fccb softmmu: Add pause_all_vcpus_except_aux ed10484 softmmu: Add cpu_synchronize_without_aux_post_init e68df04 softmmu: Don't sync aux vcpus in pre_loadvm 17bfe19 hw/i386: Set CPUState.aux=true for auxiliary vcpus 808eb76 cpu: Add boolean aux field to CPUState 34d94b2 hw/acpi: Don't include auxiliary vcpus in ACPI tables 2e9bc24 hw/i386: Mark auxiliary vcpus in possible_cpus 3d07b10 hw/boards: Add aux flag to CPUArchId 0e07c01 machine: Add auxcpus=N suboption to -smp 49124f3 kvm: add support to sync the page encryption state bitmap 47f202b linux-headers: Add definitions of KVM page encryption bitmap ioctls === OUTPUT BEGIN === 1/26 Checking commit 47f202b0bc8c (linux-headers: Add definitions of KVM page encryption bitmap ioctls) 2/26 Checking commit 49124f3bf03f (kvm: add support to sync the page encryption state bitmap) ERROR: use qemu_real_host_page_size instead of getpagesize() #51: FILE: accel/kvm/kvm-all.c:615: +ram_addr_t pages = int128_get64(section->size) / getpagesize(); ERROR: use qemu_real_host_page_size instead of getpagesize() #171: FILE: include/exec/ram_addr.h:398: +unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE; WARNING: line over 80 characters #197: FILE: include/exec/ram_addr.h:424: +qatomic_xchg([DIRTY_MEMORY_ENCRYPTED][idx][offset], temp); total: 2 errors, 1 warnings, 340 lines checked Patch 2/26 has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. 3/26 Checking commit 0e07c0168e00 (machine: Add auxcpus=N suboption to -smp) 4/26 Checking commit 3d07b103b36f (hw/boards: Add aux flag to CPUArchId) 5/26 Checking commit 2e9bc24b9064 (hw/i386: Mark auxiliary vcpus in possible_cpus) 6/26 Checking commit 34d94b2baa07 (hw/acpi: Don't include auxiliary vcpus in ACPI tables) 7/26 Checking commit 808eb7693543 (cpu: Add boolean aux field to CPUState) 8/26 Checking commit 17bfe1902081 (hw/i386: Set CPUState.aux=true for auxiliary vcpus) WARNING: line over 80 characters #26: FILE: hw/i386/x86.c:104: +void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, bool aux, Error **errp) WARNING: line over 80 characters #58: FILE: include/hw/i386/x86.h:88: +void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, bool aux, Error **errp); total: 0 errors, 2 warnings, 34 lines checked Patch 8/26 has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. 9/26 Checking commit e68df046c12e (softmmu: Don't sync aux vcpus in pre_loadvm) 10/26 Checking commit ed104842e25d (softmmu: Add cpu_synchronize_without_aux_post_init) 11/26 Checking commit 8d2fccbd9cf9 (softmmu: Add pause_all_vcpus_except_aux) WARNING: Block comments use a leading /* on a separate line #88: FILE: softmmu/cpus.c:614: +/* We need to drop the replay_lock so any vCPU threads woken up total: 0 errors, 1 warnings, 78 lines checked Patch 11/26 has style problems, please review. If any
Re: [PATCH v2 18/42] esp: accumulate SCSI commands for PDMA transfers in cmdbuf instead of pdma_buf
Le 09/02/2021 à 20:29, Mark Cave-Ayland a écrit : > ESP SCSI commands are already accumulated in cmdbuf and so there is no need to > keep a separate pdma_buf buffer. Accumulate SCSI commands for PDMA transfers > in > cmdbuf instead of pdma_buf so update cmdlen accordingly and change pdma_origin > for PDMA transfers to CMD which allows the PDMA origin to be removed. > > This commit also removes a stray memcpy() from get_cmd() which is a no-op > because > cmdlen is always zero at the start of a command. > > Notionally the removal of pdma_buf from vmstate_esp_pdma also breaks migration > compatibility for the PDMA subsection until its complete removal by the end of > the series. > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 56 +++ > include/hw/scsi/esp.h | 2 -- > 2 files changed, 25 insertions(+), 33 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 7134c0aff4..b846f022fb 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -139,8 +139,6 @@ static void set_pdma(ESPState *s, enum pdma_origin_id > origin, > static uint8_t *get_pdma_buf(ESPState *s) > { > switch (s->pdma_origin) { > -case PDMA: > -return s->pdma_buf; > case TI: > return s->ti_buf; > case CMD: > @@ -161,14 +159,12 @@ static uint8_t esp_pdma_read(ESPState *s) > } > > switch (s->pdma_origin) { > -case PDMA: > -val = s->pdma_buf[s->pdma_cur++]; > -break; > case TI: > val = s->ti_buf[s->pdma_cur++]; > break; > case CMD: > -val = s->cmdbuf[s->pdma_cur++]; > +val = s->cmdbuf[s->cmdlen++]; > +s->pdma_cur++; > break; > case ASYNC: > val = s->async_buf[s->pdma_cur++]; > @@ -193,14 +189,12 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > } > > switch (s->pdma_origin) { > -case PDMA: > -s->pdma_buf[s->pdma_cur++] = val; > -break; > case TI: > s->ti_buf[s->pdma_cur++] = val; > break; > case CMD: > -s->cmdbuf[s->pdma_cur++] = val; > +s->cmdbuf[s->cmdlen++] = val; > +s->pdma_cur++; > break; > case ASYNC: > s->async_buf[s->pdma_cur++] = val; > @@ -256,8 +250,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, > uint8_t buflen) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, buf, dmalen); > } else { > -memcpy(s->pdma_buf, buf, dmalen); > -set_pdma(s, PDMA, 0, dmalen); > +set_pdma(s, CMD, 0, dmalen); > esp_raise_drq(s); > return 0; > } > @@ -316,24 +309,24 @@ static void satn_pdma_cb(ESPState *s) > if (get_cmd_cb(s) < 0) { > return; > } > -if (s->pdma_cur != s->pdma_start) { > -do_cmd(s, get_pdma_buf(s) + s->pdma_start); > +s->do_cmd = 0; > +if (s->cmdlen) { > +do_cmd(s, s->cmdbuf); > } > } > > static void handle_satn(ESPState *s) > { > -uint8_t buf[32]; > -int len; > - > if (s->dma && !s->dma_enabled) { > s->dma_cb = handle_satn; > return; > } > s->pdma_cb = satn_pdma_cb; > -len = get_cmd(s, buf, sizeof(buf)); > -if (len) { > -do_cmd(s, buf); > +s->cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf)); > +if (s->cmdlen) { > +do_cmd(s, s->cmdbuf); > +} else { > +s->do_cmd = 1; > } > } > > @@ -342,24 +335,24 @@ static void s_without_satn_pdma_cb(ESPState *s) > if (get_cmd_cb(s) < 0) { > return; > } > -if (s->pdma_cur != s->pdma_start) { > +s->do_cmd = 0; > +if (s->cmdlen) { > do_busid_cmd(s, get_pdma_buf(s) + s->pdma_start, 0); > } > } > > static void handle_s_without_atn(ESPState *s) > { > -uint8_t buf[32]; > -int len; > - > if (s->dma && !s->dma_enabled) { > s->dma_cb = handle_s_without_atn; > return; > } > s->pdma_cb = s_without_satn_pdma_cb; > -len = get_cmd(s, buf, sizeof(buf)); > -if (len) { > -do_busid_cmd(s, buf, 0); > +s->cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf)); > +if (s->cmdlen) { > +do_busid_cmd(s, s->cmdbuf, 0); > +} else { > +s->do_cmd = 1; > } > } > > @@ -368,7 +361,7 @@ static void satn_stop_pdma_cb(ESPState *s) > if (get_cmd_cb(s) < 0) { > return; > } > -s->cmdlen = s->pdma_cur - s->pdma_start; > +s->do_cmd = 0; > if (s->cmdlen) { > trace_esp_handle_satn_stop(s->cmdlen); > s->do_cmd = 1; > @@ -394,6 +387,8 @@ static void handle_satn_stop(ESPState *s) > s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; > s->rregs[ESP_RSEQ] = SEQ_CD; > esp_raise_irq(s); > +} else { > +s->do_cmd = 1; > } > } > > @@ -865,11 +860,10 @@ static bool esp_pdma_needed(void *opaque) > > static const VMStateDescription
Re: [PATCH 1/3] qapi, audio: add query-audiodev command
On 3/2/21 6:55 PM, Daniel P. Berrangé wrote: > Way back in QEMU 4.0, the -audiodev command line option was introduced > for configuring audio backends. This CLI option does not use QemuOpts > so it is not visible for introspection in 'query-command-line-options', > instead using the QAPI Audiodev type. Unfortunately there is also no > QMP command that uses the Audiodev type, so it is not introspectable > with 'query-qmp-schema' either. > > This introduces a 'query-audiodev' command that simply reflects back > the list of configured -audiodev command line options. This in turn > makes Audiodev introspectable via 'query-qmp-schema'. > > Signed-off-by: Daniel P. Berrangé > --- > audio/audio.c | 19 +++ > qapi/audio.json | 13 + > 2 files changed, 32 insertions(+) > + > +## > +# @query-audiodevs: > +# > +# Returns information about audiodev configuration > +# > +# Returns: array of @Audiodev > +# > +# Since: 6.0 > +# > +## > +{ 'command': 'query-audiodevs', > + 'returns': ['Audiodev'] } > Can we use 'query-audiodev-backends' similarly to 'query-chardev-backends'?
Re: [PATCH v2 21/42] esp: remove redundant pdma_start from ESPState
Le 09/02/2021 à 20:29, Mark Cave-Ayland a écrit : > Now that PDMA SCSI commands are accumulated in cmdbuf in the same way as > normal > commands, the existing logic for locating the start of the SCSI command in > cmdbuf via cmdlen can be used. This enables the PDMA-specific pdma_start and > also get_pdma_buf() to be removed. > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 19 ++- > include/hw/scsi/esp.h | 1 - > 2 files changed, 2 insertions(+), 18 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 7055520a26..91f65a5d9b 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -131,24 +131,10 @@ static void set_pdma(ESPState *s, enum pdma_origin_id > origin, > uint32_t index, uint32_t len) > { > s->pdma_origin = origin; > -s->pdma_start = index; > s->pdma_cur = index; > s->pdma_len = len; > } > > -static uint8_t *get_pdma_buf(ESPState *s) > -{ > -switch (s->pdma_origin) { > -case TI: > -return s->ti_buf; > -case CMD: > -return s->cmdbuf; > -case ASYNC: > -return s->async_buf; > -} > -return NULL; > -} > - > static uint8_t esp_pdma_read(ESPState *s) > { > uint32_t dmalen = esp_get_tc(s); > @@ -339,7 +325,7 @@ static void s_without_satn_pdma_cb(ESPState *s) > } > s->do_cmd = 0; > if (s->cmdlen) { > -do_busid_cmd(s, get_pdma_buf(s) + s->pdma_start, 0); > +do_busid_cmd(s, s->cmdbuf, 0); > } > } > > @@ -441,7 +427,7 @@ static void esp_dma_done(ESPState *s) > static void do_dma_pdma_cb(ESPState *s) > { > int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO); > -int len = s->pdma_cur - s->pdma_start; > +int len = s->pdma_cur; > > if (s->do_cmd) { > s->ti_size = 0; > @@ -868,7 +854,6 @@ static const VMStateDescription vmstate_esp_pdma = { > .fields = (VMStateField[]) { > VMSTATE_INT32(pdma_origin, ESPState), > VMSTATE_UINT32(pdma_len, ESPState), > -VMSTATE_UINT32(pdma_start, ESPState), > VMSTATE_UINT32(pdma_cur, ESPState), > VMSTATE_END_OF_LIST() > } > diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h > index c323d43f70..578d936214 100644 > --- a/include/hw/scsi/esp.h > +++ b/include/hw/scsi/esp.h > @@ -58,7 +58,6 @@ struct ESPState { > void (*dma_cb)(ESPState *s); > int pdma_origin; > uint32_t pdma_len; > -uint32_t pdma_start; > uint32_t pdma_cur; > void (*pdma_cb)(ESPState *s); > > Reviewed-by: Laurent Vivier
Re: [PATCH v2 18/42] esp: accumulate SCSI commands for PDMA transfers in cmdbuf instead of pdma_buf
Le 02/03/2021 à 20:29, Mark Cave-Ayland a écrit : > On 02/03/2021 17:59, Laurent Vivier wrote: > >> Le 02/03/2021 à 18:34, Mark Cave-Ayland a écrit : >>> On 02/03/2021 17:02, Laurent Vivier wrote: >>> Le 09/02/2021 à 20:29, Mark Cave-Ayland a écrit : > ESP SCSI commands are already accumulated in cmdbuf and so there is no > need to > keep a separate pdma_buf buffer. Accumulate SCSI commands for PDMA > transfers in > cmdbuf instead of pdma_buf so update cmdlen accordingly and change > pdma_origin > for PDMA transfers to CMD which allows the PDMA origin to be removed. > > This commit also removes a stray memcpy() from get_cmd() which is a no-op > because > cmdlen is always zero at the start of a command. > > Notionally the removal of pdma_buf from vmstate_esp_pdma also breaks > migration > compatibility for the PDMA subsection until its complete removal by the > end of > the series. > > Signed-off-by: Mark Cave-Ayland > --- > hw/scsi/esp.c | 56 +++ > include/hw/scsi/esp.h | 2 -- > 2 files changed, 25 insertions(+), 33 deletions(-) > > diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c > index 7134c0aff4..b846f022fb 100644 > --- a/hw/scsi/esp.c > +++ b/hw/scsi/esp.c > @@ -139,8 +139,6 @@ static void set_pdma(ESPState *s, enum pdma_origin_id > origin, > static uint8_t *get_pdma_buf(ESPState *s) > { > switch (s->pdma_origin) { > - case PDMA: > - return s->pdma_buf; > case TI: > return s->ti_buf; > case CMD: > @@ -161,14 +159,12 @@ static uint8_t esp_pdma_read(ESPState *s) > } > switch (s->pdma_origin) { > - case PDMA: > - val = s->pdma_buf[s->pdma_cur++]; > - break; > case TI: > val = s->ti_buf[s->pdma_cur++]; > break; > case CMD: > - val = s->cmdbuf[s->pdma_cur++]; > + val = s->cmdbuf[s->cmdlen++]; > + s->pdma_cur++; > break; > case ASYNC: > val = s->async_buf[s->pdma_cur++]; > @@ -193,14 +189,12 @@ static void esp_pdma_write(ESPState *s, uint8_t val) > } > switch (s->pdma_origin) { > - case PDMA: > - s->pdma_buf[s->pdma_cur++] = val; > - break; > case TI: > s->ti_buf[s->pdma_cur++] = val; > break; > case CMD: > - s->cmdbuf[s->pdma_cur++] = val; > + s->cmdbuf[s->cmdlen++] = val; > + s->pdma_cur++; > break; > case ASYNC: > s->async_buf[s->pdma_cur++] = val; > @@ -256,8 +250,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, > uint8_t buflen) > if (s->dma_memory_read) { > s->dma_memory_read(s->dma_opaque, buf, dmalen); > } else { > - memcpy(s->pdma_buf, buf, dmalen); > - set_pdma(s, PDMA, 0, dmalen); > + set_pdma(s, CMD, 0, dmalen); > esp_raise_drq(s); > return 0; > } > @@ -316,24 +309,24 @@ static void satn_pdma_cb(ESPState *s) > if (get_cmd_cb(s) < 0) { > return; > } > - if (s->pdma_cur != s->pdma_start) { > - do_cmd(s, get_pdma_buf(s) + s->pdma_start); > + s->do_cmd = 0; > + if (s->cmdlen) { > + do_cmd(s, s->cmdbuf); I don't understant how you can remove the pdma_start: normally it is here to keep track of the position in the pDMA if the migration is occuraing while a pDMA transfer. >>> >>> Hi Laurent, >>> >>> I was going to follow up on your reviews later this evening, however this >>> one caught my eye: as per >>> the cover letter, this patchset is a migration break for the q800 machine. >>> As there are likely more >>> incompatible changes for the q800 machine coming up soon, it didn't seem >>> worth the effort (and >>> indeed I don't think it's possible to recreate the new internal state with >>> 100% accuracy from the >>> old state). >>> >>> Migration for ESP devices that don't use PDMA is still supported, and I've >>> tested this during >>> development with qemu-system-sparc. >>> >> >> I don't mean we can't migrate from a previous version to the new one, I mean >> the migration between >> two machines of the current version is not possible anymore as we don't keep >> track of the position >> of the pDMA index inside the buffer. >> >> With a DMA, the migration cannot happen in the middle of the DMA, while with >> pDMA it can (as it's a >> processor loop). >> >> The whole purpose of get_pdma() and set_pdma() was for the migration. >> >>
Re: Plugin Address Translations Inconsistent/Incorrect?
Aaron Lindsay writes: > On Mar 02 16:06, Alex Bennée wrote: >> >> Aaron Lindsay writes: >> >> > On Feb 23 15:53, Aaron Lindsay wrote: >> >> On Feb 22 15:48, Aaron Lindsay wrote: >> >> > On Feb 22 19:30, Alex Bennée wrote: >> >> > > Aaron Lindsay writes: >> >> > > That said I think we could add an additional helper to translate a >> >> > > hwaddr to a global address space address. I'm open to suggestions of >> >> > > the >> >> > > best way to structure this. >> >> > >> >> > Haven't put a ton of thought into it, but what about something like this >> >> > (untested): >> >> > >> >> > uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr >> >> > *haddr) >> >> > { >> >> > #ifdef CONFIG_SOFTMMU >> >> > if (haddr) { >> >> > if (!haddr->is_io) { >> >> > RAMBlock *block; >> >> > ram_addr_t offset; >> >> > >> >> > block = qemu_ram_block_from_host((void *) >> >> > haddr->v.ram.hostaddr, false, ); >> >> > if (!block) { >> >> > error_report("Bad ram pointer %"PRIx64"", >> >> > haddr->v.ram.hostaddr); >> >> > abort(); >> >> > } >> >> > >> >> > return block->offset + offset + block->mr->addr; >> >> > } else { >> >> > MemoryRegionSection *mrs = haddr->v.io.section; >> >> > return haddr->v.io.offset + mrs->mr->addr; >> >> > } >> >> > } >> >> > #endif >> >> > return 0; >> >> > } >> >> >> >> This appears to successfully return correct physical addresses for RAM >> >> at least, though I've not tested it thoroughly for MMIO yet. >> >> >> >> If it ends up being desirable based on the discussion elsewhere on this >> >> thread I am willing to perform more complete testing, turn this into a >> >> patch, and submit it. >> > >> > Ping - Is this something worth me pursuing? >> >> Yes please. > > Okay, I'll work on it. Is your thinking that this would this be a > separate call as shown above, or a replacement of the existing > qemu_plugin_hwaddr_device_offset function? And, if a replacement, should > we keep the name similar to retain compatibility, or make a clean break? > > It seemed like Peter may have been saying the device offset shouldn't be > exposed at all (leading me to consider full replacement), but I also > don't see a definitive resolution of that conversation. I think a full replacement and an increment of the minimum API version. That way people will at least query why the plugin failed to load and hopefully will read the release notes ;-) > > -Aaron -- Alex Bennée
Re: [PATCH 1/3] qapi, audio: add query-audiodev command
On 3/2/21 10:10 PM, Philippe Mathieu-Daudé wrote: > On 3/2/21 6:55 PM, Daniel P. Berrangé wrote: >> Way back in QEMU 4.0, the -audiodev command line option was introduced >> for configuring audio backends. This CLI option does not use QemuOpts >> so it is not visible for introspection in 'query-command-line-options', >> instead using the QAPI Audiodev type. Unfortunately there is also no >> QMP command that uses the Audiodev type, so it is not introspectable >> with 'query-qmp-schema' either. >> >> This introduces a 'query-audiodev' command that simply reflects back >> the list of configured -audiodev command line options. This in turn >> makes Audiodev introspectable via 'query-qmp-schema'. >> >> Signed-off-by: Daniel P. Berrangé >> --- >> audio/audio.c | 19 +++ >> qapi/audio.json | 13 + >> 2 files changed, 32 insertions(+) > >> + >> +## >> +# @query-audiodevs: >> +# >> +# Returns information about audiodev configuration >> +# >> +# Returns: array of @Audiodev Also with chardev we return ChardevBackendInfo. I'm not sure if this is because I'm custom to read it, but it seems clearer. Can we return a AudiodevBackendInfo type? >> +# >> +# Since: 6.0 >> +# >> +## >> +{ 'command': 'query-audiodevs', >> + 'returns': ['Audiodev'] } >> > > Can we use 'query-audiodev-backends' similarly to > 'query-chardev-backends'? >
Re: [PATCH v4 5/6] hw/pci-host: Add emulation of Marvell MV64361 PPC system controller
On Tue, 2 Mar 2021, Philippe Mathieu-Daudé wrote: On 2/25/21 8:47 PM, BALATON Zoltan wrote: The Marvell Discovery II aka. MV64361 is a PowerPC system controller chip that is used on the pegasos2 PPC board. This adds emulation of it that models the device enough to boot guests on this board. The mv643xx.h header with register definitions is taken from Linux 4.15.10 only fixing end of line white space errors and removing not needed parts, it's otherwise keeps Linux formatting. Signed-off-by: BALATON Zoltan --- hw/pci-host/Kconfig | 3 + hw/pci-host/meson.build | 2 + hw/pci-host/mv64361.c | 966 ++ hw/pci-host/mv643xx.h | 919 Maybe name this one mv643xx_regs.h? This comes originally from Linux where it had this name so to make it simpler to find where it comes from I've kept the name for now. If we ever change the contents beyond just formatting it could be renamed too. Regards, BALATON Zoltan hw/pci-host/trace-events | 6 + include/hw/pci-host/mv64361.h | 8 + include/hw/pci/pci_ids.h | 1 + 7 files changed, 1905 insertions(+) create mode 100644 hw/pci-host/mv64361.c create mode 100644 hw/pci-host/mv643xx.h create mode 100644 include/hw/pci-host/mv64361.h diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index 8b8c763c28..65a983d6fd 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -68,3 +68,6 @@ config PCI_POWERNV config REMOTE_PCIHOST bool + +config MV64361 +bool Missing: select PCI
[RFC PATCH 10/26] softmmu: Add cpu_synchronize_without_aux_post_init
This will be used during migration on the target. Signed-off-by: Dov Murik --- include/sysemu/cpus.h | 1 + softmmu/cpus.c| 11 +++ 2 files changed, 12 insertions(+) diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index 868f1192de..dc24e38254 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -46,6 +46,7 @@ bool cpus_are_resettable(void); void cpu_synchronize_all_states(void); void cpu_synchronize_all_post_reset(void); void cpu_synchronize_all_post_init(void); +void cpu_synchronize_without_aux_post_init(void); void cpu_synchronize_all_pre_loadvm(void); #ifndef CONFIG_USER_ONLY diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 878cf2a421..68fa4639a7 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -157,6 +157,17 @@ void cpu_synchronize_all_post_init(void) } } +void cpu_synchronize_without_aux_post_init(void) +{ +CPUState *cpu; + +CPU_FOREACH(cpu) { +if (!cpu->aux) { +cpu_synchronize_post_init(cpu); +} +} +} + void cpu_synchronize_all_pre_loadvm(void) { CPUState *cpu; -- 2.20.1
Re: [PATCH 3/3] qapi: provide a friendly string representation of QAPI classes
On 3/2/21 6:55 PM, Daniel P. Berrangé wrote: > If printing a QAPI schema object for debugging we get the classname and > a hex value for the instance. With this change we instead get the > classname and the human friendly name of the QAPI type instance. > > Signed-off-by: Daniel P. Berrangé > --- > scripts/qapi/schema.py | 3 +++ > 1 file changed, 3 insertions(+) Reviewed-by: Philippe Mathieu-Daudé
[RFC PATCH 20/26] migration: When starting target, don't sync auxiliary vcpus
If auxiliary vcpus are defined, they are used for running the migration helper inside the guest. We want to keep them running and not sync their state. This behaves exactly like cpu_synchronize_all_post_init() when there are no auxiliary vcpus. Signed-off-by: Dov Murik --- migration/savevm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/savevm.c b/migration/savevm.c index c5252612c3..c6af1f7bba 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2754,7 +2754,7 @@ int qemu_loadvm_state(QEMUFile *f) } qemu_loadvm_state_cleanup(); -cpu_synchronize_all_post_init(); +cpu_synchronize_without_aux_post_init(); return ret; } -- 2.20.1
Re: [PATCH v2 0/2] gitlab-ci.yml: Add jobs to test CFI
On 3/2/2021 11:40 AM, Daniel P. Berrangé wrote: The CFI protection is something I'd say is relevant to virtualization use cases, not to emulation use cases https://qemu-project.gitlab.io/qemu/system/security.html IOW, the targets that are important to test are the ones where KVM is available. So that's s390x, ppc, x86, mips, and arm. I think we can probably ignore mips as that's fairly niche. We can also reasonably limit ourselves to only test the 64-bit variants of the target, on the basis that 32-bit is increasingly legacy/niche too. So that gives us ppc64le, x86_64, aarch64 and s390x as the targets we should get CI coverage for CFI. Thanks Daniel, I'll start working on a V3 that only contains those 4 targets, probably in two sets of build/check/acceptance to maintain the jobs below the hour mark. These would still be x86 binaries that are not testing KVM, however, because of the capabilities of the shared gitlab runners. I see that there's some work from Cleber Rosa to allow running custom jobs on aarch64 and s390x systems. I think that, when the infrastructure is ready, having a KVM-based CFI test there would help a lot in terms of coverage for those architectures.
Re: [PATCH] vfio-ccw: Do not read region ret_code after write
On 3/2/21 1:14 PM, Cornelia Huck wrote: On Mon, 1 Mar 2021 20:51:43 +0100 Eric Farman wrote: A pwrite() call returns the number of bytes written (or -1 on error), and vfio-ccw compares this number with the size of the region to determine if an error had occurred or not. If they are equal, the code reads the ret_code field from the region. However, while the kernel sets the ret_code field as necessary, the region and thus this field is not "written back" to the user. So the value can only be what it was initialized to, which is zero. Not harming anything, but it's a puzzle. Let's avoid the confusion and just set the return code to zero for this case. Yes, ret_code seems to be pretty much useless for us: we don't even look at it when we read the region for interrupt handling. Thankfully, we don't seem to really need it, as we can rely on errno. (Probably worth double checking that this is indeed the case.) I didn't see any scenario on either the kernel or qemu side that made me worried. I don't suppose we need to handle a hypothetical broken kernel that returns the wrong size with errno==0? Well, that would be silly of it. :) But, since I'm in here, sure I can add in some suspenders. Thanks, Eric Suggested-by: Matthew Rosato Signed-off-by: Eric Farman --- hw/vfio/ccw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index bc78a0ad76..bfd5fd07a5 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -106,7 +106,7 @@ again: error_report("vfio-ccw: write I/O region failed with errno=%d", errno); ret = -errno; } else { -ret = region->ret_code; +ret = 0; } switch (ret) { case 0: @@ -194,7 +194,7 @@ again: error_report("vfio-ccw: write cmd region failed with errno=%d", errno); ret = -errno; } else { -ret = region->ret_code; +ret = 0; } switch (ret) { case 0: @@ -234,7 +234,7 @@ again: error_report("vfio-ccw: write cmd region failed with errno=%d", errno); ret = -errno; } else { -ret = region->ret_code; +ret = 0; } switch (ret) { case 0:
Re: [PATCH v1 7/9] memory: introduce RAM_NORESERVE and wire it up in qemu_ram_mmap()
On 02.03.21 21:54, Peter Xu wrote: On Tue, Mar 02, 2021 at 08:02:34PM +0100, David Hildenbrand wrote: @@ -174,12 +175,18 @@ void *qemu_ram_mmap(int fd, size_t align, bool readonly, bool shared, -bool is_pmem) +bool is_pmem, +bool noreserve) Maybe at some point we should use flags too here to cover all bools. Right. I guess the main point was to not reuse RAM_XXX. Should I introduce RAM_MMAP_XXX ? Maybe we can directly use MAP_*? Since I see qemu_ram_mmap() should only exist I think the issue is that there is for example no flag that corresponds to "is_pmem" - and the fallback logic in our mmap code to make "is_pmem" still work is a little bit more involved. In addition, "readonly" translates to PROT_READ ... with CONFIG_POSIX. However indeed I see no sign to extend more bools in the near future either, so maybe also fine to keep it as is, as 4 bools still looks okay - your call. :) Well, I had the same idea when I added yet another bool :) But I guess we won't be adding a lot of additional flags in the near future. (MAP_POPULATE? ;) fortunately we use a different approach to populate memory) I'll think about it, not sure yet if this is worth proper flags. Thanks! -- Thanks, David / dhildenb
[RFC PATCH 15/26] migration: Save confidential guest RAM using migration helper
When saving RAM pages of a confidential guest, check whether a page is encrypted. If it is, ask the in-guest migration helper to encrypt the page for transmission. This relies on ability to track the encryption status of each page according to guest's reports, and thus requires the relevant patches in the guest OS and OVMF and the host KVM and QEMU. This is all encapsulated in is_page_encrypted; the implementation can be modified according to the underlying implementation of page encryption status tracking (bitmap / KVM shared regions list / user-side list) Signed-off-by: Dov Murik --- migration/ram.c | 91 + 1 file changed, 91 insertions(+) diff --git a/migration/ram.c b/migration/ram.c index 997f90cc5b..8e55ed49fd 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -53,10 +53,13 @@ #include "block.h" #include "sysemu/sysemu.h" #include "sysemu/cpu-throttle.h" +#include "sysemu/kvm.h" #include "savevm.h" #include "qemu/iov.h" #include "multifd.h" #include "sysemu/runstate.h" +#include "hw/boards.h" +#include "confidential-ram.h" #if defined(__linux__) #include "qemu/userfaultfd.h" @@ -81,6 +84,7 @@ #define RAM_SAVE_FLAG_XBZRLE 0x40 /* 0x80 is reserved in migration.h start with 0x100 next */ #define RAM_SAVE_FLAG_COMPRESS_PAGE0x100 +#define RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE0x200 static inline bool memcrypt_enabled(void) { @@ -94,6 +98,13 @@ static inline bool is_zero_range(uint8_t *p, uint64_t size) return buffer_is_zero(p, size); } +static inline bool confidential_guest(void) +{ +MachineState *ms = MACHINE(qdev_get_machine()); + +return ms->cgs; +} + XBZRLECacheStats xbzrle_counters; /* struct contains XBZRLE cache and a static page @@ -660,6 +671,23 @@ static void mig_throttle_guest_down(uint64_t bytes_dirty_period, } } +/** + * is_page_encrypted: check if the page is encrypted + * + * Returns a bool indicating whether the page is encrypted. + */ +static bool is_page_encrypted(RAMState *rs, RAMBlock *block, unsigned long page) +{ +/* ROM devices contain unencrypted data */ +if (memory_region_is_romd(block->mr) || +memory_region_is_rom(block->mr) || +!memory_region_is_ram(block->mr)) { +return false; +} + +return test_bit(page, block->encbmap); +} + /** * xbzrle_cache_zero_page: insert a zero page in the XBZRLE cache * @@ -1928,6 +1956,45 @@ static bool save_compress_page(RAMState *rs, RAMBlock *block, ram_addr_t offset) return false; } +/** + * ram_save_encrypted_page - send the given encrypted page to the stream + * + * Return the number of pages written (=1). + */ +static int ram_save_encrypted_page(RAMState *rs, PageSearchStatus *pss, + bool last_stage) +{ +int ret; +uint8_t *p; +RAMBlock *block = pss->block; +ram_addr_t offset = pss->page << TARGET_PAGE_BITS; +ram_addr_t gpa; +uint64_t bytes_sent; + +p = block->host + offset; + +/* Find the GPA of the page */ +if (!kvm_physical_memory_addr_from_host(kvm_state, p, )) { +error_report("%s failed to get gpa for offset %" PRIu64 " block %s", + __func__, offset, memory_region_name(block->mr)); +return -1; +} + +ram_counters.transferred += +save_page_header(rs, rs->f, block, +offset | RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE); + +ret = cgs_mh_save_encrypted_page(rs->f, gpa, TARGET_PAGE_SIZE, _sent); +if (ret) { +return -1; +} + +ram_counters.transferred += bytes_sent; +ram_counters.normal++; + +return 1; +} + /** * ram_save_target_page: save one target page * @@ -1948,6 +2015,26 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss, return res; } +/* + * If memory encryption is enabled then skip saving the data pages used by + * the migration handler. + */ +if (confidential_guest() && +gpa_inside_migration_helper_shared_area(offset)) { +return 0; +} + +/* + * If memory encryption is enabled then use memory encryption APIs + * to write the outgoing buffer to the wire. The encryption APIs + * will take care of accessing the guest memory and re-encrypt it + * for the transport purposes. + */ +if (confidential_guest() && +is_page_encrypted(rs, pss->block, pss->page)) { +return ram_save_encrypted_page(rs, pss, last_stage); +} + if (save_compress_page(rs, block, offset)) { return 1; } @@ -2776,6 +2863,10 @@ static int ram_save_setup(QEMUFile *f, void *opaque) return -1; } +if (confidential_guest()) { +cgs_mh_init(); +} + /* migration has already setup the bitmap, reuse it. */ if (!migration_in_colo_state()) { if (ram_init_all(rsp) != 0) { -- 2.20.1
[RFC PATCH 05/26] hw/i386: Mark auxiliary vcpus in possible_cpus
Mark the last aux_cpus vcpus in the machine state's possible_cpus as auxiliary. Signed-off-by: Dov Murik --- hw/i386/x86.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 6329f90ef9..be23fad650 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -448,6 +448,7 @@ const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms) { X86MachineState *x86ms = X86_MACHINE(ms); unsigned int max_cpus = ms->smp.max_cpus; +unsigned int aux_cpus_start_at = max_cpus - ms->smp.aux_cpus; X86CPUTopoInfo topo_info; int i; @@ -475,6 +476,7 @@ const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms) x86_cpu_apic_id_from_index(x86ms, i); x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id, _info, _ids); +ms->possible_cpus->cpus[i].aux = i >= aux_cpus_start_at; ms->possible_cpus->cpus[i].props.has_socket_id = true; ms->possible_cpus->cpus[i].props.socket_id = topo_ids.pkg_id; if (x86ms->smp_dies > 1) { -- 2.20.1
[RFC PATCH 08/26] hw/i386: Set CPUState.aux=true for auxiliary vcpus
On x86 machines, when initializing the CPUState structs, set the aux flag to true for auxiliary vcpus. Signed-off-by: Dov Murik --- include/hw/i386/x86.h | 2 +- hw/i386/x86.c | 8 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index 56080bd1fb..f9ec6af9b7 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -85,7 +85,7 @@ void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms); uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms, unsigned int cpu_index); -void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp); +void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, bool aux, Error **errp); void x86_cpus_init(X86MachineState *pcms, int default_cpu_version); CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index); diff --git a/hw/i386/x86.c b/hw/i386/x86.c index be23fad650..bc17b53180 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -101,13 +101,16 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms, } -void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp) +void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, bool aux, Error **errp) { Object *cpu = object_new(MACHINE(x86ms)->cpu_type); if (!object_property_set_uint(cpu, "apic-id", apic_id, errp)) { goto out; } +if (!object_property_set_bool(cpu, "aux", aux, errp)) { +goto out; +} qdev_realize(DEVICE(cpu), NULL, errp); out: @@ -135,7 +138,8 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) ms->smp.max_cpus - 1) + 1; possible_cpus = mc->possible_cpu_arch_ids(ms); for (i = 0; i < ms->smp.cpus; i++) { -x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, _fatal); +x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, +possible_cpus->cpus[i].aux, _fatal); } } -- 2.20.1
Re: [PATCH v1 7/9] memory: introduce RAM_NORESERVE and wire it up in qemu_ram_mmap()
On Tue, Mar 02, 2021 at 08:02:34PM +0100, David Hildenbrand wrote: > > > @@ -174,12 +175,18 @@ void *qemu_ram_mmap(int fd, > > > size_t align, > > > bool readonly, > > > bool shared, > > > -bool is_pmem) > > > +bool is_pmem, > > > +bool noreserve) > > > > Maybe at some point we should use flags too here to cover all bools. > > > > Right. I guess the main point was to not reuse RAM_XXX. > > Should I introduce RAM_MMAP_XXX ? Maybe we can directly use MAP_*? Since I see qemu_ram_mmap() should only exist with CONFIG_POSIX. However indeed I see no sign to extend more bools in the near future either, so maybe also fine to keep it as is, as 4 bools still looks okay - your call. :) -- Peter Xu
[RFC PATCH 26/26] docs: Add confidential guest live migration documentation
The new page is linked from the main index, otherwise sphinx complains that "document isn't included in any toctree"; I assume there would be a better place for it in the documentation tree. Signed-off-by: Dov Murik --- docs/confidential-guest-live-migration.rst | 142 + docs/confidential-guest-support.txt| 5 + docs/index.rst | 1 + 3 files changed, 148 insertions(+) create mode 100644 docs/confidential-guest-live-migration.rst diff --git a/docs/confidential-guest-live-migration.rst b/docs/confidential-guest-live-migration.rst new file mode 100644 index 00..dc59df8f9c --- /dev/null +++ b/docs/confidential-guest-live-migration.rst @@ -0,0 +1,142 @@ += +Confidential Guest Live Migration += + +When migrating regular QEMU guests, QEMU reads the guest's RAM and sends it +over to the migration target host, where QEMU there writes it into the target +guest's RAM and starts the VM. This mechanism doesn't work when the guest +memory is encrypted or QEMU is prevented from reading it in another way. + +In order to support live migration in such scenarios, QEMU relies on an +in-guest migration helper which can securely extract RAM content from the +guest in order to send it to the target. The migration helper is implemented as +part of the VM's firmware in OVMF. + + +Migration flow +== + +Source VM +- + +The source VM is started with an extra auxiliary vcpu which is not listed in the +ACPI tables. OVMF uses this vcpu and starts a dedicated migration helper on it; +the migration helper simply waits for commands from QEMU. When migration starts +using the ``migrate`` command, QEMU starts saving the state of the different +devices. When it reaches saving RAM pages, it'll check for each page whether it +is encrypted or not; for encrypted pages, it'll send a command to the migration +helper to extract the given page. The migration helper receives this command, +reads the page content, encrypts it with a transport key, and returns the +newly-encrypted page to QEMU. QEMU saves those pages to the outgoing migration +stream using a new page flag ``RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE``. + +When QEMU reaches the last stage of RAM migration, it stops the source VM to +avoid dirtying the last pages of RAM. However, the auxiliary vcpu must be kept +running so the migration helper can still extract pages from the guest memory. + +Target VM +- + +Usually QEMU migration target VMs are started with the ``-incoming`` +command-line option which starts the VM paused. However, in order to migrate +confidential guests we must have the migration helper running inside the guest; +in such a case, we start the target with a special ``-fw_cfg`` value that tells +OVMF to enter a CPU dead loop on all vcpus except the auxiliary vcpu, which runs +the migration helper. After this short "boot" completes, QEMU can switch to the +"migration incoming" mode; we do that with the new ``start-migrate-incoming`` +QMP command that makes the target VM listen for incoming migration connections. + +QEMU will load the state of VM devices as it arrives from the incoming migration +stream. When it encounters a RAM page with the +``RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE`` flag, it will send its +transport-encrypted content and guest physical address to the migration helper. +The migration helper running inside the guest will decrypt the page using the +transport key and place the content in memory (again, that memory page is not +accessible to host due to the confidential guest properties; for example, in SEV +it is hardware-encrypted with a VM-specific key). + + +Usage += + +In order to start the source and target VMs with auxiliary CPUs, the auxcpus= +option must be passed to ``-smp`` . For example:: + +# ${QEMU} -smp 5,auxcpus=1 ... + +This command starts a VM with 5 vcpus of which 4 are main vcpus (available for +the guest OS) and 1 is auxliary vcpu. + +Moreover, in both the source and target we need to instruct OVMF to start the +migration helper running in the auxiliary vcpu. This is achieved using the +following command-line option:: + +# ${QEMU} -fw_cfg name=opt/ovmf/PcdSevIsMigrationHelper,string=0 ... + +In the target VM we need to add another ``-fw_cfg`` entry to instruct OVMF to +start only the migration helepr, which will wait for incoming pages (the target +cannot be started with ``-incoming`` because that option completely pauses the +VM, not allowing the migration helper to run). Because the migration helper must +be running when the incoming RAM pages are received, starting the target VM with +the ``-incoming`` option doesn't work (with that option, the VM doesn't start +executing). Instead, start the target VM without ``-incoming`` but with the +following option:: + +# ${QEMU} -fw_cfg name=opt/ovmf/PcdSevIsMigrationTarget,string=1 ... + +After the VM
[RFC PATCH 21/26] migration: Call migration handler cleanup routines
From: Tobin Feldman-Fitzthum Signed-off-by: Tobin Feldman-Fitzthum Signed-off-by: Dov Murik --- migration/ram.c | 8 1 file changed, 8 insertions(+) diff --git a/migration/ram.c b/migration/ram.c index 82a1d13f5f..ce551c1d2f 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -3054,6 +3054,10 @@ static int ram_save_complete(QEMUFile *f, void *opaque) ram_control_after_iterate(f, RAM_CONTROL_FINISH); } +if (confidential_guest()) { +cgs_mh_cleanup(); +} + if (ret >= 0) { multifd_send_sync_main(rs->f); qemu_put_be64(f, RAM_SAVE_FLAG_EOS); @@ -3549,6 +3553,10 @@ static int ram_load_cleanup(void *opaque) rb->receivedmap = NULL; } +if (confidential_guest()) { +cgs_mh_cleanup(); +} + return 0; } -- 2.20.1
[RFC PATCH 18/26] migration: Stop non-aux vcpus before copying the last pages
From: Tobin Feldman-Fitzthum Co-Author: Dov Murik Signed-off-by: Dov Murik Signed-off-by: Tobin Feldman-Fitzthum --- migration/migration.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index a5ddf43559..7ec25bd006 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -24,6 +24,7 @@ #include "sysemu/runstate.h" #include "sysemu/sysemu.h" #include "sysemu/cpu-throttle.h" +#include "sysemu/cpus.h" #include "rdma.h" #include "ram.h" #include "migration/global_state.h" @@ -3156,14 +3157,14 @@ static void migration_completion(MigrationState *s) qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL); s->vm_was_running = runstate_is_running(); ret = global_state_store(); +pause_all_vcpus_except_aux(); +qemu_mutex_unlock_iothread(); if (!ret) { bool inactivate = !migrate_colo_enabled(); -ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); -if (ret >= 0) { -ret = migration_maybe_pause(s, _active_state, -MIGRATION_STATUS_DEVICE); -} +ret = migration_maybe_pause(s, _active_state, +MIGRATION_STATUS_DEVICE); + if (ret >= 0) { qemu_file_set_rate_limit(s->to_dst_file, INT64_MAX); ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false, @@ -3173,7 +3174,7 @@ static void migration_completion(MigrationState *s) s->block_inactive = true; } } -qemu_mutex_unlock_iothread(); +runstate_set(RUN_STATE_FINISH_MIGRATE); if (ret < 0) { goto fail; -- 2.20.1
[RFC PATCH 17/26] migration: Stop VM after loading confidential RAM
Register a dummy device state (EndOfConfidentialRAMState) with high priority so it is the first device which is loaded in the target. The post_load handler of this device stops the VM, which makes things easier when loading devices' states which expect the VM not to be running at the same time. Signed-off-by: Dov Murik --- migration/confidential-ram.h | 2 ++ migration/confidential-ram.c | 31 +++ softmmu/runstate.c | 1 + target/i386/sev.c| 2 ++ 4 files changed, 36 insertions(+) diff --git a/migration/confidential-ram.h b/migration/confidential-ram.h index 9a1027bdaf..2822c5ee3d 100644 --- a/migration/confidential-ram.h +++ b/migration/confidential-ram.h @@ -18,4 +18,6 @@ int cgs_mh_save_encrypted_page(QEMUFile *f, ram_addr_t src_gpa, uint32_t size, int cgs_mh_load_encrypted_page(QEMUFile *f, ram_addr_t dest_gpa); +void register_end_of_confidential_ram(void); + #endif diff --git a/migration/confidential-ram.c b/migration/confidential-ram.c index 0b821af774..982cf9b874 100644 --- a/migration/confidential-ram.c +++ b/migration/confidential-ram.c @@ -8,6 +8,8 @@ #include "io/channel.h" #include "qapi/error.h" #include "exec/memory.h" +#include "migration/vmstate.h" +#include "sysemu/runstate.h" #include "trace.h" #include "confidential-ram.h" @@ -225,3 +227,32 @@ int cgs_mh_load_encrypted_page(QEMUFile *f, ram_addr_t dest_gpa) } return ret; } + +typedef struct { +bool dummy; +} EndOfConfidentialRAMState; + +static EndOfConfidentialRAMState end_of_confidential_ram_state = { .dummy = false }; + +static int end_of_confidential_ram_post_load(void *opaque, int version_id) +{ +vm_stop(RUN_STATE_INMIGRATE); +return 0; +} + +static const VMStateDescription vmstate_end_of_confidential_ram = { +.name = "end-of-confidential-ram", +.priority = MIG_PRI_GICV3, /* TODO define new (higher) priority level */ +.version_id = 1, +.post_load = end_of_confidential_ram_post_load, +.fields = (VMStateField[]) { +VMSTATE_BOOL(dummy, EndOfConfidentialRAMState), +VMSTATE_END_OF_LIST() +}, +}; + +void register_end_of_confidential_ram(void) +{ +vmstate_register(NULL, 0, _end_of_confidential_ram, + _of_confidential_ram_state); +} diff --git a/softmmu/runstate.c b/softmmu/runstate.c index 2874417b61..193413246d 100644 --- a/softmmu/runstate.c +++ b/softmmu/runstate.c @@ -131,6 +131,7 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR }, { RUN_STATE_RUNNING, RUN_STATE_IO_ERROR }, { RUN_STATE_RUNNING, RUN_STATE_PAUSED }, +{ RUN_STATE_RUNNING, RUN_STATE_INMIGRATE }, { RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM }, { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM }, diff --git a/target/i386/sev.c b/target/i386/sev.c index 0f414df02f..da2d0cc699 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -33,6 +33,7 @@ #include "exec/address-spaces.h" #include "monitor/monitor.h" #include "exec/confidential-guest-support.h" +#include "migration/confidential-ram.h" #include "hw/i386/pc.h" #define TYPE_SEV_GUEST "sev-guest" @@ -1011,6 +1012,7 @@ static void sev_register_types(void) { type_register_static(_guest_info); +register_end_of_confidential_ram(); } type_init(sev_register_types); -- 2.20.1
[RFC PATCH 00/26] Confidential guest live migration
This is an RFC series for fast migration of confidential guests using an in-guest migration helper that lives in OVMF. QEMU VM live migration needs to read source VM's RAM and write it in the target VM; this mechanism doesn't work when the guest memory is encrypted or QEMU is prevented from reading it in another way. In order to support live migration in such scenarios, we introduce an in-guest migration helper which can securely extract RAM content from the guest in order to send it to the target. The migration helper is implemented as part of the VM's firmware in OVMF. We've implemented and tested this on AMD SEV, but expect most of the processes can be used with other technologies that prevent direct access of hypervisor to the guest's memory. Specifically, we don't use SEV's PSP migration commands (SEV_SEND_START, SEV_RECEIVE_START, etc) at all. Corresponding RFC patches for OVMF have been posted by my colleague Tobin Feldman-Fitzthum on edk2-devel. Those include the crux of the migration helper: a mailbox protocol over a shared memory page which allows communication between QEMU and the migration helper. In the source VM this is used to read a page and encrypt it for transport; in the target it is used to decrypt the incoming page and storing the content in the correct address in the guest memory. All encryption and decryption operations occur inside the trusted context in the VM, and therefore the VM's memory plaintext content is never accessible to the hosts participating in the migration. In order to allow OVMF to run the migration helper in parallel to the guest OS, we introduce the notion of auxiliary vcpus, which are usable for OVMF but are hidden from the guest OS. These might have other future uses for in-guest operations/agents. In the target VM we need the migration handler running to receive incoming RAM pages; to achieve that, we boot the VM into OVMF with a special fw_cfg value that causes OVMF to not boot the guest OS; we then allow QEMU to receive an incoming migration by issuing a new start-migrate-incoming QMP command. The confidential RAM migration requires checking whether a given guest RAM page is encrypted or not. This is currently achieved using AMD's patches which track the encryption status of guest pages in KVM, using hypercalls from OVMF and guest Linux to report changes of such status. The QEMU side of these patches is included as the first two patches in this series. The concrete implementation of this page encryption tracking is currently in flux in the KVM mailing list, but the underlying implementation doesn't affect our confidential RAM migration as long as it can check whether a given guest address is encrypted. List of patches in this series: 1-2: reposting AMD encrypted page bitmap support. 3-11: introduce the notion of auxiliary vcpus. 12-21: introduce the migration specifics. 22-23: fix devices issues when loading state into a live VM 24: introduce the start-migrate-incoming QMP command to switch the target into accepting the incoming migration. 25: remove SEV migration blocker 26: add documentation Brijesh Singh (1): kvm: add support to sync the page encryption state bitmap Dov Murik (21): linux-headers: Add definitions of KVM page encryption bitmap ioctls machine: Add auxcpus=N suboption to -smp hw/boards: Add aux flag to CPUArchId hw/i386: Mark auxiliary vcpus in possible_cpus cpu: Add boolean aux field to CPUState hw/i386: Set CPUState.aux=true for auxiliary vcpus softmmu: Don't sync aux vcpus in pre_loadvm softmmu: Add cpu_synchronize_without_aux_post_init migration: Add helpers to save confidential RAM migration: Add helpers to load confidential RAM migration: Introduce gpa_inside_migration_helper_shared_area migration: Save confidential guest RAM using migration helper migration: Load confidential guest RAM using migration helper migration: Stop VM after loading confidential RAM migration: Don't sync vcpus when migrating confidential guests migration: When starting target, don't sync auxiliary vcpus hw/isa/lpc_ich9: Allow updating an already-running VM target/i386: Re-sync kvm-clock after confidential guest migration migration: Add start-migrate-incoming QMP command target/i386: SEV: Allow migration unless there are no aux vcpus docs: Add confidential guest live migration documentation Tobin Feldman-Fitzthum (4): hw/acpi: Don't include auxiliary vcpus in ACPI tables softmmu: Add pause_all_vcpus_except_aux migration: Stop non-aux vcpus before copying the last pages migration: Call migration handler cleanup routines docs/confidential-guest-live-migration.rst | 142 docs/confidential-guest-support.txt| 5 + docs/index.rst | 1 + qapi/migration.json| 26 +++ include/exec/ram_addr.h| 197 include/exec/ramblock.h| 3 + include/exec/ramlist.h
[RFC PATCH 22/26] hw/isa/lpc_ich9: Allow updating an already-running VM
The post_load function crashed when we were loading the device state in to an already-running guest. This was because an existing memory region as not deleted in ich9_lpc_rcba_update. Signed-off-by: Dov Murik --- hw/isa/lpc_ich9.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index d3145bf014..1fc1af3491 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -529,9 +529,10 @@ ich9_lpc_pmcon_update(ICH9LPCState *lpc) static int ich9_lpc_post_load(void *opaque, int version_id) { ICH9LPCState *lpc = opaque; +uint32_t rcba_old = pci_get_long(lpc->d.config + ICH9_LPC_RCBA); ich9_lpc_pmbase_sci_update(lpc); -ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RCBA_EN */); +ich9_lpc_rcba_update(lpc, rcba_old); ich9_lpc_pmcon_update(lpc); return 0; } -- 2.20.1
[RFC PATCH 13/26] migration: Add helpers to load confidential RAM
QEMU cannot write directly to the memory of memory-encrypted guests; this breaks normal RAM-load in the migration target. Instead, QEMU asks a migration helper running on an auxiliary vcpu in the guest to restore encrypted pages as they were received from the source to a specific GPA. The migration helper running inside the guest can safely decrypt the pages arrived from the source and load them into their proper location in the guest's memory. Loading pages uses the same shared (unencrypted) pages which both QEMU and the guest can read from and write to. Signed-off-by: Dov Murik --- migration/confidential-ram.h | 2 ++ migration/confidential-ram.c | 37 migration/trace-events | 1 + 3 files changed, 40 insertions(+) diff --git a/migration/confidential-ram.h b/migration/confidential-ram.h index 0d49718d31..ebe4073bce 100644 --- a/migration/confidential-ram.h +++ b/migration/confidential-ram.h @@ -14,4 +14,6 @@ void cgs_mh_cleanup(void); int cgs_mh_save_encrypted_page(QEMUFile *f, ram_addr_t src_gpa, uint32_t size, uint64_t *bytes_sent); +int cgs_mh_load_encrypted_page(QEMUFile *f, ram_addr_t dest_gpa); + #endif diff --git a/migration/confidential-ram.c b/migration/confidential-ram.c index 65a588e7f6..fe317ee74b 100644 --- a/migration/confidential-ram.c +++ b/migration/confidential-ram.c @@ -182,3 +182,40 @@ int cgs_mh_save_encrypted_page(QEMUFile *f, ram_addr_t src_gpa, uint32_t size, return ret; } + +int cgs_mh_load_encrypted_page(QEMUFile *f, ram_addr_t dest_gpa) +{ +int ret = 1; +uint32_t page_hdr_len, enc_page_len; + +init_cgs_mig_helper_if_needed(); + +assert((dest_gpa & TARGET_PAGE_MASK) == dest_gpa); + +/* Read page header */ +page_hdr_len = qemu_get_be32(f); +if (page_hdr_len > 1024) { +error_report("confidential-ram: page header is too large (%d bytes) " + "when loading gpa %" PRIu64, page_hdr_len, dest_gpa); +return -EINVAL; +} +cmhs.io_page_hdr->len = page_hdr_len; +qemu_get_buffer(f, cmhs.io_page_hdr->data, page_hdr_len); + +/* Read encrypted page */ +enc_page_len = qemu_get_be32(f); +if (enc_page_len != TARGET_PAGE_SIZE) { +error_report("confidential-ram: encrypted page is too large (%d bytes) " + "when loading gpa %" PRIu64, enc_page_len, dest_gpa); +return -EINVAL; +} +qemu_get_buffer(f, cmhs.io_page, enc_page_len); + +trace_encrypted_ram_load_page(page_hdr_len, enc_page_len, dest_gpa); +ret = send_command_to_cgs_mig_helper(CGS_MIG_HELPER_CMD_DECRYPT, dest_gpa); +if (ret) { +error_report("confidential-ram: failed loading page at dest_gpa " + "%" PRIu64 ": ret=%d", dest_gpa, ret); +} +return ret; +} diff --git a/migration/trace-events b/migration/trace-events index 929de4ca98..ef31cf78cb 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -345,4 +345,5 @@ migration_pagecache_init(int64_t max_num_items) "Setting cache buckets to %" PRI migration_pagecache_insert(void) "Error allocating page" # confidential-ram.c +encrypted_ram_load_page(uint32_t hdr_len, uint32_t trans_len, uint64_t gpa) "hdr_len: %u, trans_len: %u, gpa: 0x%" PRIx64 encrypted_ram_save_page(uint32_t size, uint64_t gpa) "size: %u, gpa: 0x%" PRIx64 -- 2.20.1
[RFC PATCH 14/26] migration: Introduce gpa_inside_migration_helper_shared_area
The gpa_inside_migration_helper_shared_area will be used to skip migrating RAM pages that are used by the migration helper at the target. Signed-off-by: Dov Murik --- migration/confidential-ram.h | 2 ++ migration/confidential-ram.c | 6 ++ 2 files changed, 8 insertions(+) diff --git a/migration/confidential-ram.h b/migration/confidential-ram.h index ebe4073bce..9a1027bdaf 100644 --- a/migration/confidential-ram.h +++ b/migration/confidential-ram.h @@ -8,6 +8,8 @@ #include "exec/cpu-common.h" #include "qemu-file.h" +bool gpa_inside_migration_helper_shared_area(ram_addr_t gpa); + void cgs_mh_init(void); void cgs_mh_cleanup(void); diff --git a/migration/confidential-ram.c b/migration/confidential-ram.c index fe317ee74b..0b821af774 100644 --- a/migration/confidential-ram.c +++ b/migration/confidential-ram.c @@ -68,6 +68,12 @@ static CGSMigHelperState cmhs = {0}; #define MH_SHARED_CMD_PARAMS_ADDR0x82 #define MH_SHARED_IO_PAGE_HDR_ADDR (MH_SHARED_CMD_PARAMS_ADDR + 0x800) #define MH_SHARED_IO_PAGE_ADDR (MH_SHARED_CMD_PARAMS_ADDR + 0x1000) +#define MH_SHARED_LAST_BYTE (MH_SHARED_CMD_PARAMS_ADDR + 0x1fff) + +bool gpa_inside_migration_helper_shared_area(ram_addr_t gpa) +{ +return gpa >= MH_SHARED_CMD_PARAMS_ADDR && gpa <= MH_SHARED_LAST_BYTE; +} void cgs_mh_init(void) { -- 2.20.1
[RFC PATCH 24/26] migration: Add start-migrate-incoming QMP command
This command forces a running VM into a migrate-incoming state. When using guest-assisted migration (for confidential guests), the target must be started so that its auxiliary vcpu is running the migration helper; after it is ready we can start receiving the incoming migration connection. Signed-off-by: Dov Murik --- qapi/migration.json | 26 ++ migration/migration.c | 5 + 2 files changed, 31 insertions(+) diff --git a/qapi/migration.json b/qapi/migration.json index 6e5943fbb4..c7361e0038 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -1569,6 +1569,32 @@ ## { 'command': 'migrate-incoming', 'data': {'uri': 'str' } } +## +# @start-migrate-incoming: +# +# Force start an incoming migration even in a running VM. This is used by the +# target VM in guest-assisted migration of a confidential guest. +# +# @uri: The Uniform Resource Identifier identifying the source or +# address to listen on +# +# Returns: nothing on success +# +# Since: 6.0 +# +# Notes: +# +# The uri format is the same as the -incoming command-line option. +# +# Example: +# +# -> { "execute": "start-migrate-incoming", +# "arguments": { "uri": "tcp::4446" } } +# <- { "return": {} } +# +## +{ 'command': 'start-migrate-incoming', 'data': {'uri': 'str' } } + ## # @xen-save-devices-state: # diff --git a/migration/migration.c b/migration/migration.c index 7ec25bd006..4729b89bef 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2098,6 +2098,11 @@ void qmp_migrate_incoming(const char *uri, Error **errp) once = false; } +void qmp_start_migrate_incoming(const char *uri, Error **errp) +{ +qemu_start_incoming_migration(uri, errp); +} + void qmp_migrate_recover(const char *uri, Error **errp) { MigrationIncomingState *mis = migration_incoming_get_current(); -- 2.20.1
[RFC PATCH 23/26] target/i386: Re-sync kvm-clock after confidential guest migration
If confidential guest support is active, set TSC to 0 on the target when loading the CPU state. This causes the guest OS to re-sync with kvm-clock. Without this change, the guest clocks after migration are stuck (don't advance), except the *_COARSE clocks which advance normally. Signed-off-by: Dov Murik --- target/i386/machine.c | 9 + 1 file changed, 9 insertions(+) diff --git a/target/i386/machine.c b/target/i386/machine.c index 3768a753af..36c52ec02e 100644 --- a/target/i386/machine.c +++ b/target/i386/machine.c @@ -297,8 +297,17 @@ static int cpu_post_load(void *opaque, int version_id) X86CPU *cpu = opaque; CPUState *cs = CPU(cpu); CPUX86State *env = >env; +MachineState *ms = MACHINE(qdev_get_machine()); int i; +/* + * When loading the state of a confidential guest, set TSC to zero at allow + * the guest OS to re-sync with kvmclock. + */ +if (ms->cgs) { +env->tsc = 0; +} + if (env->tsc_khz && env->user_tsc_khz && env->tsc_khz != env->user_tsc_khz) { error_report("Mismatch between user-specified TSC frequency and " -- 2.20.1