PING: [PATCH v3 0/6] Misc fixes for throttle
Hi Kevin, Hanna, Patch 1 -> patch 5 of this series are already reviewed by Alberto(these affects throttle framework only), the patch 6 affects qemu block layer, would you please review this(in the further step, merge this series if this is acceptable)? On 7/13/23 14:41, zhenwei pi wrote: v2 -> v3: - patch 1 -> patch 5 are already reviewed by Alberto - append patch 6: throttle: use enum ThrottleType instead of bool is_write v1 -> v2: - rename 'ThrottleTimerType' to 'ThrottleType' - add assertion to throttle_schedule_timer v1: - introduce enum ThrottleTimerType instead of timers[0], timer[1]... - support read-only and write-only for throttle - adapt related test codes - cryptodev uses a write-only throttle timer Zhenwei Pi (6): throttle: introduce enum ThrottleType test-throttle: use enum ThrottleType throttle: support read-only and write-only test-throttle: test read only and write only cryptodev: use NULL throttle timer cb for read direction throttle: use enum ThrottleType instead of bool is_write backends/cryptodev.c| 12 +++--- block/throttle-groups.c | 6 ++- fsdev/qemu-fsdev-throttle.c | 8 ++-- include/qemu/throttle.h | 15 +--- tests/unit/test-throttle.c | 76 ++--- util/throttle.c | 64 +++ 6 files changed, 136 insertions(+), 45 deletions(-) -- zhenwei pi
[PATCH v6 2/3] hw/ufs: Support for Query Transfer Requests
This commit makes the UFS device support query and nop out transfer requests. The next patch would be support for UFS logical unit and scsi command transfer request. Signed-off-by: Jeuk Kim --- hw/ufs/trace-events | 1 + hw/ufs/ufs.c| 980 +++- hw/ufs/ufs.h| 46 +++ 3 files changed, 1025 insertions(+), 2 deletions(-) diff --git a/hw/ufs/trace-events b/hw/ufs/trace-events index d1badcad10..665e1a942b 100644 --- a/hw/ufs/trace-events +++ b/hw/ufs/trace-events @@ -18,6 +18,7 @@ ufs_err_dma_read_req_upiu(uint32_t slot, uint64_t addr) "failed to read req upiu ufs_err_dma_read_prdt(uint32_t slot, uint64_t addr) "failed to read prdt. UTRLDBR slot %"PRIu32", prdt addr %"PRIu64"" ufs_err_dma_write_utrd(uint32_t slot, uint64_t addr) "failed to write utrd. UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64"" ufs_err_dma_write_rsp_upiu(uint32_t slot, uint64_t addr) "failed to write rsp upiu. UTRLDBR slot %"PRIu32", response upiu addr %"PRIu64"" +ufs_err_utrl_slot_error(uint32_t slot) "UTRLDBR slot %"PRIu32" is in error" ufs_err_utrl_slot_busy(uint32_t slot) "UTRLDBR slot %"PRIu32" is busy" ufs_err_unsupport_register_offset(uint32_t offset) "Register offset 0x%"PRIx32" is not yet supported" ufs_err_invalid_register_offset(uint32_t offset) "Register offset 0x%"PRIx32" is invalid" diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index 101082a8a3..cd33af2cde 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -15,10 +15,221 @@ #include "ufs.h" /* The QEMU-UFS device follows spec version 3.1 */ -#define UFS_SPEC_VER 0x0310 +#define UFS_SPEC_VER 0x0310 #define UFS_MAX_NUTRS 32 #define UFS_MAX_NUTMRS 8 +static MemTxResult ufs_addr_read(UfsHc *u, hwaddr addr, void *buf, int size) +{ +hwaddr hi = addr + size - 1; + +if (hi < addr) { +return MEMTX_DECODE_ERROR; +} + +if (!FIELD_EX32(u->reg.cap, CAP, 64AS) && (hi >> 32)) { +return MEMTX_DECODE_ERROR; +} + +return pci_dma_read(PCI_DEVICE(u), addr, buf, size); +} + +static MemTxResult ufs_addr_write(UfsHc *u, hwaddr addr, const void *buf, + int size) +{ +hwaddr hi = addr + size - 1; +if (hi < addr) { +return MEMTX_DECODE_ERROR; +} + +if (!FIELD_EX32(u->reg.cap, CAP, 64AS) && (hi >> 32)) { +return MEMTX_DECODE_ERROR; +} + +return pci_dma_write(PCI_DEVICE(u), addr, buf, size); +} + +static void ufs_complete_req(UfsRequest *req, UfsReqResult req_result); + +static inline hwaddr ufs_get_utrd_addr(UfsHc *u, uint32_t slot) +{ +hwaddr utrl_base_addr = (((hwaddr)u->reg.utrlbau) << 32) + u->reg.utrlba; +hwaddr utrd_addr = utrl_base_addr + slot * sizeof(UtpTransferReqDesc); + +return utrd_addr; +} + +static inline hwaddr ufs_get_req_upiu_base_addr(const UtpTransferReqDesc *utrd) +{ +uint32_t cmd_desc_base_addr_lo = +le32_to_cpu(utrd->command_desc_base_addr_lo); +uint32_t cmd_desc_base_addr_hi = +le32_to_cpu(utrd->command_desc_base_addr_hi); + +return (((hwaddr)cmd_desc_base_addr_hi) << 32) + cmd_desc_base_addr_lo; +} + +static inline hwaddr ufs_get_rsp_upiu_base_addr(const UtpTransferReqDesc *utrd) +{ +hwaddr req_upiu_base_addr = ufs_get_req_upiu_base_addr(utrd); +uint32_t rsp_upiu_byte_off = +le16_to_cpu(utrd->response_upiu_offset) * sizeof(uint32_t); +return req_upiu_base_addr + rsp_upiu_byte_off; +} + +static MemTxResult ufs_dma_read_utrd(UfsRequest *req) +{ +UfsHc *u = req->hc; +hwaddr utrd_addr = ufs_get_utrd_addr(u, req->slot); +MemTxResult ret; + +ret = ufs_addr_read(u, utrd_addr, &req->utrd, sizeof(req->utrd)); +if (ret) { +trace_ufs_err_dma_read_utrd(req->slot, utrd_addr); +} +return ret; +} + +static MemTxResult ufs_dma_read_req_upiu(UfsRequest *req) +{ +UfsHc *u = req->hc; +hwaddr req_upiu_base_addr = ufs_get_req_upiu_base_addr(&req->utrd); +UtpUpiuReq *req_upiu = &req->req_upiu; +uint32_t copy_size; +uint16_t data_segment_length; +MemTxResult ret; + +/* + * To know the size of the req_upiu, we need to read the + * data_segment_length in the header first. + */ +ret = ufs_addr_read(u, req_upiu_base_addr, &req_upiu->header, +sizeof(UtpUpiuHeader)); +if (ret) { +trace_ufs_err_dma_read_req_upiu(req->slot, req_upiu_base_addr); +return ret; +} +data_segment_length = be16_to_cpu(req_upiu->header.data_segment_length); + +copy_size = sizeof(UtpUpiuHeader) + UFS_TRANSACTION_SPECIFIC_FIELD_SIZE + +data_segment_length; + +ret = ufs_addr_read(u, req_upiu_base_addr, &req->req_upiu, copy_size); +if (ret) { +trace_ufs_err_dma_read_req_upiu(req->slot, req_upiu_base_addr); +} +return ret; +} + +static MemTxResult ufs_dma_read_prdt(UfsRequest *req) +{ +UfsHc *u = req->hc; +uint16_t prdt_len = le16_to_cpu(req->utrd.prd_table_length); +uint16_t prdt_byte_off = +le16_t
[PATCH v6 0/3] hw/ufs: Add Universal Flash Storage (UFS) support
Since v5: - Fix to print an error message instead of a segmentation fault when no drive property is specified for a ufs-lu device Since v4: Addressed review comment from Stefan Hajnoczi. The fixes are as follows. - Keep u->reg fields in host endian (Removed little-endian helper functions from MemoryRegionOps) - Remove unnecessary NULL checks for g_new and g_malloc0 - Replace DEFINE_PROP_DRIVE_IOTHREAD -> DEFINE_PROP_DRIVE In case you were wondering, ufs and ufs-lu have been tested for the following behaviours. 1. Checked ufs device recognition in Windows10 environment 2. Verified ufs device recognition in Ubuntu 22.04 environment 3. Verified io behaviour via fio in Ubuntu 22.04 environment 4. Verified query request via ufs-tools in Ubuntu 22.04 environment Since v3: - Replace softmmu_ss -> system_ss in meson Since v2: Addressed review comment from Stefan Hajnoczi. The main fixes are as follows. - Use of SPDX licence identifiers - fixed endianness error - removed memory leak - fixed DMA error handling logic Since v1: - use macros of "hw/registerfields.h" (Addressed Philippe's review comments) This patch series adds support for a new PCI-based UFS device. The UFS pci device id (PCI_DEVICE_ID_REDHAT_UFS) is not registered in the Linux kernel yet, so it does not work right away, but I confirmed that it works with Linux when the UFS pci device id is registered. I have also verified that it works with Windows 10. Jeuk Kim (3): hw/ufs: Initial commit for emulated Universal-Flash-Storage hw/ufs: Support for Query Transfer Requests hw/ufs: Support for UFS logical unit MAINTAINERS |6 + docs/specs/pci-ids.rst |2 + hw/Kconfig |1 + hw/meson.build |1 + hw/ufs/Kconfig |4 + hw/ufs/lu.c | 1439 hw/ufs/meson.build |1 + hw/ufs/trace-events | 58 ++ hw/ufs/trace.h |1 + hw/ufs/ufs.c | 1494 ++ hw/ufs/ufs.h | 131 include/block/ufs.h | 1048 ++ include/hw/pci/pci.h |1 + include/hw/pci/pci_ids.h |1 + include/scsi/constants.h |1 + meson.build |1 + 16 files changed, 4190 insertions(+) create mode 100644 hw/ufs/Kconfig create mode 100644 hw/ufs/lu.c create mode 100644 hw/ufs/meson.build create mode 100644 hw/ufs/trace-events create mode 100644 hw/ufs/trace.h create mode 100644 hw/ufs/ufs.c create mode 100644 hw/ufs/ufs.h create mode 100644 include/block/ufs.h -- 2.34.1
[PATCH v6 1/3] hw/ufs: Initial commit for emulated Universal-Flash-Storage
Universal Flash Storage (UFS) is a high-performance mass storage device with a serial interface. It is primarily used as a high-performance data storage device for embedded applications. This commit contains code for UFS device to be recognized as a UFS PCI device. Patches to handle UFS logical unit and Transfer Request will follow. Signed-off-by: Jeuk Kim --- MAINTAINERS |6 + docs/specs/pci-ids.rst |2 + hw/Kconfig |1 + hw/meson.build |1 + hw/ufs/Kconfig |4 + hw/ufs/meson.build |1 + hw/ufs/trace-events | 32 ++ hw/ufs/trace.h |1 + hw/ufs/ufs.c | 278 ++ hw/ufs/ufs.h | 42 ++ include/block/ufs.h | 1048 ++ include/hw/pci/pci.h |1 + include/hw/pci/pci_ids.h |1 + meson.build |1 + 14 files changed, 1419 insertions(+) create mode 100644 hw/ufs/Kconfig create mode 100644 hw/ufs/meson.build create mode 100644 hw/ufs/trace-events create mode 100644 hw/ufs/trace.h create mode 100644 hw/ufs/ufs.c create mode 100644 hw/ufs/ufs.h create mode 100644 include/block/ufs.h diff --git a/MAINTAINERS b/MAINTAINERS index 12e59b6b27..0c8a955b42 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2256,6 +2256,12 @@ F: tests/qtest/nvme-test.c F: docs/system/devices/nvme.rst T: git git://git.infradead.org/qemu-nvme.git nvme-next +ufs +M: Jeuk Kim +S: Supported +F: hw/ufs/* +F: include/block/ufs.h + megasas M: Hannes Reinecke L: qemu-block@nongnu.org diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst index e302bea484..d6707fa069 100644 --- a/docs/specs/pci-ids.rst +++ b/docs/specs/pci-ids.rst @@ -92,6 +92,8 @@ PCI devices (other than virtio): PCI PVPanic device (``-device pvpanic-pci``) 1b36:0012 PCI ACPI ERST device (``-device acpi-erst``) +1b36:0013 + PCI UFS device (``-device ufs``) All these devices are documented in :doc:`index`. diff --git a/hw/Kconfig b/hw/Kconfig index ba62ff6417..9ca7b38c31 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -38,6 +38,7 @@ source smbios/Kconfig source ssi/Kconfig source timer/Kconfig source tpm/Kconfig +source ufs/Kconfig source usb/Kconfig source virtio/Kconfig source vfio/Kconfig diff --git a/hw/meson.build b/hw/meson.build index c7ac7d3d75..f01fac4617 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -37,6 +37,7 @@ subdir('smbios') subdir('ssi') subdir('timer') subdir('tpm') +subdir('ufs') subdir('usb') subdir('vfio') subdir('virtio') diff --git a/hw/ufs/Kconfig b/hw/ufs/Kconfig new file mode 100644 index 00..b7b3392e85 --- /dev/null +++ b/hw/ufs/Kconfig @@ -0,0 +1,4 @@ +config UFS_PCI +bool +default y if PCI_DEVICES +depends on PCI diff --git a/hw/ufs/meson.build b/hw/ufs/meson.build new file mode 100644 index 00..eb5164bde9 --- /dev/null +++ b/hw/ufs/meson.build @@ -0,0 +1 @@ +system_ss.add(when: 'CONFIG_UFS_PCI', if_true: files('ufs.c')) diff --git a/hw/ufs/trace-events b/hw/ufs/trace-events new file mode 100644 index 00..d1badcad10 --- /dev/null +++ b/hw/ufs/trace-events @@ -0,0 +1,32 @@ +# ufs.c +ufs_irq_raise(void) "INTx" +ufs_irq_lower(void) "INTx" +ufs_mmio_read(uint64_t addr, uint64_t data, unsigned size) "addr 0x%"PRIx64" data 0x%"PRIx64" size %d" +ufs_mmio_write(uint64_t addr, uint64_t data, unsigned size) "addr 0x%"PRIx64" data 0x%"PRIx64" size %d" +ufs_process_db(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_process_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_complete_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_sendback_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_exec_nop_cmd(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_exec_scsi_cmd(uint32_t slot, uint8_t lun, uint8_t opcode) "slot %"PRIu32", lun 0x%"PRIx8", opcode 0x%"PRIx8"" +ufs_exec_query_cmd(uint32_t slot, uint8_t opcode) "slot %"PRIu32", opcode 0x%"PRIx8"" +ufs_process_uiccmd(uint32_t uiccmd, uint32_t ucmdarg1, uint32_t ucmdarg2, uint32_t ucmdarg3) "uiccmd 0x%"PRIx32", ucmdarg1 0x%"PRIx32", ucmdarg2 0x%"PRIx32", ucmdarg3 0x%"PRIx32"" + +# error condition +ufs_err_dma_read_utrd(uint32_t slot, uint64_t addr) "failed to read utrd. UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64"" +ufs_err_dma_read_req_upiu(uint32_t slot, uint64_t addr) "failed to read req upiu. UTRLDBR slot %"PRIu32", request upiu addr %"PRIu64"" +ufs_err_dma_read_prdt(uint32_t slot, uint64_t addr) "failed to read prdt. UTRLDBR slot %"PRIu32", prdt addr %"PRIu64"" +ufs_err_dma_write_utrd(uint32_t slot, uint64_t addr) "failed to write utrd. UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64"" +ufs_err_dma_write_rsp_upiu(uint32_t slot, uint64_t addr) "failed to write rsp upiu. UTRLDBR slot %"PRIu32", response upiu addr %"PRIu64"" +ufs_err_utrl_slot_busy(uint32_t slot) "UTRLDBR slot %"PRIu32" is busy" +ufs_err_unsupport_register_offset(uint32_t offset) "Register offset 0x%"PRIx32" is not yet supported" +ufs_err_invalid_register_offset(uint32_t o
[PATCH v6 3/3] hw/ufs: Support for UFS logical unit
This commit adds support for ufs logical unit. The LU handles processing for the SCSI command, unit descriptor query request. This commit enables the UFS device to process IO requests. Signed-off-by: Jeuk Kim --- hw/ufs/lu.c | 1439 ++ hw/ufs/meson.build |2 +- hw/ufs/trace-events | 25 + hw/ufs/ufs.c | 252 ++- hw/ufs/ufs.h | 43 ++ include/scsi/constants.h |1 + 6 files changed, 1755 insertions(+), 7 deletions(-) create mode 100644 hw/ufs/lu.c diff --git a/hw/ufs/lu.c b/hw/ufs/lu.c new file mode 100644 index 00..6f6d301bc7 --- /dev/null +++ b/hw/ufs/lu.c @@ -0,0 +1,1439 @@ +/* + * QEMU UFS Logical Unit + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved. + * + * Written by Jeuk Kim + * + * This code is licensed under the GNU GPL v2 or later. + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "qemu/memalign.h" +#include "hw/scsi/scsi.h" +#include "scsi/constants.h" +#include "sysemu/block-backend.h" +#include "qemu/cutils.h" +#include "trace.h" +#include "ufs.h" + +/* + * The code below handling SCSI commands is copied from hw/scsi/scsi-disk.c, + * with minor adjustments to make it work for UFS. + */ + +#define SCSI_DMA_BUF_SIZE (128 * KiB) +#define SCSI_MAX_INQUIRY_LEN 256 +#define SCSI_INQUIRY_DATA_SIZE 36 +#define SCSI_MAX_MODE_LEN 256 + +typedef struct UfsSCSIReq { +SCSIRequest req; +/* Both sector and sector_count are in terms of BDRV_SECTOR_SIZE bytes. */ +uint64_t sector; +uint32_t sector_count; +uint32_t buflen; +bool started; +bool need_fua_emulation; +struct iovec iov; +QEMUIOVector qiov; +BlockAcctCookie acct; +} UfsSCSIReq; + +static void ufs_scsi_free_request(SCSIRequest *req) +{ +UfsSCSIReq *r = DO_UPCAST(UfsSCSIReq, req, req); + +qemu_vfree(r->iov.iov_base); +} + +static void scsi_check_condition(UfsSCSIReq *r, SCSISense sense) +{ +trace_ufs_scsi_check_condition(r->req.tag, sense.key, sense.asc, + sense.ascq); +scsi_req_build_sense(&r->req, sense); +scsi_req_complete(&r->req, CHECK_CONDITION); +} + +static int ufs_scsi_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf, + uint32_t outbuf_len) +{ +UfsHc *u = UFS(req->bus->qbus.parent); +UfsLu *lu = DO_UPCAST(UfsLu, qdev, req->dev); +uint8_t page_code = req->cmd.buf[2]; +int start, buflen = 0; + +if (outbuf_len < SCSI_INQUIRY_DATA_SIZE) { +return -1; +} + +outbuf[buflen++] = lu->qdev.type & 0x1f; +outbuf[buflen++] = page_code; +outbuf[buflen++] = 0x00; +outbuf[buflen++] = 0x00; +start = buflen; + +switch (page_code) { +case 0x00: /* Supported page codes, mandatory */ +{ +trace_ufs_scsi_emulate_vpd_page_00(req->cmd.xfer); +outbuf[buflen++] = 0x00; /* list of supported pages (this page) */ +if (u->params.serial) { +outbuf[buflen++] = 0x80; /* unit serial number */ +} +outbuf[buflen++] = 0x87; /* mode page policy */ +break; +} +case 0x80: /* Device serial number, optional */ +{ +int l; + +if (!u->params.serial) { +trace_ufs_scsi_emulate_vpd_page_80_not_supported(); +return -1; +} + +l = strlen(u->params.serial); +if (l > SCSI_INQUIRY_DATA_SIZE) { +l = SCSI_INQUIRY_DATA_SIZE; +} + +trace_ufs_scsi_emulate_vpd_page_80(req->cmd.xfer); +memcpy(outbuf + buflen, u->params.serial, l); +buflen += l; +break; +} +case 0x87: /* Mode Page Policy, mandatory */ +{ +trace_ufs_scsi_emulate_vpd_page_87(req->cmd.xfer); +outbuf[buflen++] = 0x3f; /* apply to all mode pages and subpages */ +outbuf[buflen++] = 0xff; +outbuf[buflen++] = 0; /* shared */ +outbuf[buflen++] = 0; +break; +} +default: +return -1; +} +/* done with EVPD */ +assert(buflen - start <= 255); +outbuf[start - 1] = buflen - start; +return buflen; +} + +static int ufs_scsi_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf, +uint32_t outbuf_len) +{ +int buflen = 0; + +if (outbuf_len < SCSI_INQUIRY_DATA_SIZE) { +return -1; +} + +if (req->cmd.buf[1] & 0x1) { +/* Vital product data */ +return ufs_scsi_emulate_vpd_page(req, outbuf, outbuf_len); +} + +/* Standard INQUIRY data */ +if (req->cmd.buf[2] != 0) { +return -1; +} + +/* PAGE CODE == 0 */ +buflen = req->cmd.xfer; +if (buflen > SCSI_MAX_INQUIRY_LEN) { +buflen = SCSI_MAX_INQUIRY_LEN; +} + +if (is_wlun(req->lun)) { +outbuf[0] = TYPE_WLUN; +} else { +outbuf[0] = 0; +} +outbuf[1] = 0; + +strpadcpy((char *)&outbuf[16], 16, "QEMU UFS", ' '); +strpa
Re: [PATCH v5 0/3] hw/ufs: Add Universal Flash Storage (UFS) support
On 7/21/2023 3:49 AM, Stefan Hajnoczi wrote: Hi, I'm ready to merge this but encountered a bug when testing: $ qemu-system-x86_64 --device ufs --device ufs-lu Segmentation fault (core dumped) Please ensure there is an error message like with SCSI disks: $ qemu-system-x86_64 --device virtio-scsi-pci --device scsi-hd qemu-system-x86_64: --device scsi-hd: drive property not set Thanks, Stefan Thanks for letting me know. I'll fix it right away and send the patch again. Thanks, Jeuk
Re: [PATCH v5 0/3] hw/ufs: Add Universal Flash Storage (UFS) support
Hi, I'm ready to merge this but encountered a bug when testing: $ qemu-system-x86_64 --device ufs --device ufs-lu Segmentation fault (core dumped) Please ensure there is an error message like with SCSI disks: $ qemu-system-x86_64 --device virtio-scsi-pci --device scsi-hd qemu-system-x86_64: --device scsi-hd: drive property not set Thanks, Stefan signature.asc Description: PGP signature
Re: [PATCH] block: Be more verbose in create fallback
On Thu, Jul 20, 2023 at 04:00:24PM +0200, Hanna Czenczek wrote: > For image creation code, we have central fallback code for protocols > that do not support creating new images (like NBD or iscsi). So for > them, you can only specify existing paths/exports that are overwritten > to make clean new images. In such a case, if the given path cannot be > opened (assuming a pre-existing image there), we print an error message > that tries to describe what is going on: That with this protocol, you > cannot create new images, but only overwrite existing ones; and the > given path could not be opened as a pre-existing image. > > However, the current message is confusing, because it does not say that > the protocol in question does not support creating new images, but > instead that "image creation" is unsupported. This can be interpreted > to mean that `qemu-img create` will not work in principle, which is not > true. Be more verbose for clarity. > > Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2217204 > Signed-off-by: Hanna Czenczek > --- > block.c | 6 -- > 1 file changed, 4 insertions(+), 2 deletions(-) Definitely more vebose, but I don't see that as a bad thing. Reviewed-by: Eric Blake > > diff --git a/block.c b/block.c > index a307c151a8..f530dd9c02 100644 > --- a/block.c > +++ b/block.c > @@ -661,8 +661,10 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver > *drv, > blk = blk_co_new_open(filename, NULL, options, >BDRV_O_RDWR | BDRV_O_RESIZE, errp); > if (!blk) { > -error_prepend(errp, "Protocol driver '%s' does not support image " > - "creation, and opening the image failed: ", > +error_prepend(errp, "Protocol driver '%s' does not support creating " > + "new images, so an existing image must be selected as " > + "the target; however, opening the given target as an " > + "existing image failed: ", >drv->format_name); > return -EINVAL; > } > -- > 2.41.0 > > -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
Re: [PATCH] hw/nvme: use stl/ldl pci dma api
On 7/20/23 11:42, Klaus Jensen wrote: From: Klaus Jensen Use the stl/ldl pci dma api for writing/reading doorbells. This removes the explicit endian conversions. Signed-off-by: Klaus Jensen Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater on big and little endian hosts, Thanks, C. --- hw/nvme/ctrl.c | 42 +- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index dadc2dc7da10..f2e5a2fa737b 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1468,20 +1468,16 @@ static inline void nvme_blk_write(BlockBackend *blk, int64_t offset, static void nvme_update_cq_eventidx(const NvmeCQueue *cq) { -uint32_t v = cpu_to_le32(cq->head); - trace_pci_nvme_update_cq_eventidx(cq->cqid, cq->head); -pci_dma_write(PCI_DEVICE(cq->ctrl), cq->ei_addr, &v, sizeof(v)); +stl_le_pci_dma(PCI_DEVICE(cq->ctrl), cq->ei_addr, cq->head, + MEMTXATTRS_UNSPECIFIED); } static void nvme_update_cq_head(NvmeCQueue *cq) { -uint32_t v; - -pci_dma_read(PCI_DEVICE(cq->ctrl), cq->db_addr, &v, sizeof(v)); - -cq->head = le32_to_cpu(v); +ldl_le_pci_dma(PCI_DEVICE(cq->ctrl), cq->db_addr, &cq->head, + MEMTXATTRS_UNSPECIFIED); trace_pci_nvme_update_cq_head(cq->cqid, cq->head); } @@ -6801,7 +6797,6 @@ static uint16_t nvme_dbbuf_config(NvmeCtrl *n, const NvmeRequest *req) PCIDevice *pci = PCI_DEVICE(n); uint64_t dbs_addr = le64_to_cpu(req->cmd.dptr.prp1); uint64_t eis_addr = le64_to_cpu(req->cmd.dptr.prp2); -uint32_t v; int i; /* Address should be page aligned */ @@ -6819,8 +6814,6 @@ static uint16_t nvme_dbbuf_config(NvmeCtrl *n, const NvmeRequest *req) NvmeCQueue *cq = n->cq[i]; if (sq) { -v = cpu_to_le32(sq->tail); - /* * CAP.DSTRD is 0, so offset of ith sq db_addr is (i<<3) * nvme_process_db() uses this hard-coded way to calculate @@ -6828,7 +6821,7 @@ static uint16_t nvme_dbbuf_config(NvmeCtrl *n, const NvmeRequest *req) */ sq->db_addr = dbs_addr + (i << 3); sq->ei_addr = eis_addr + (i << 3); -pci_dma_write(pci, sq->db_addr, &v, sizeof(sq->tail)); +stl_le_pci_dma(pci, sq->db_addr, sq->tail, MEMTXATTRS_UNSPECIFIED); if (n->params.ioeventfd && sq->sqid != 0) { if (!nvme_init_sq_ioeventfd(sq)) { @@ -6838,12 +6831,10 @@ static uint16_t nvme_dbbuf_config(NvmeCtrl *n, const NvmeRequest *req) } if (cq) { -v = cpu_to_le32(cq->head); - /* CAP.DSTRD is 0, so offset of ith cq db_addr is (i<<3)+(1<<2) */ cq->db_addr = dbs_addr + (i << 3) + (1 << 2); cq->ei_addr = eis_addr + (i << 3) + (1 << 2); -pci_dma_write(pci, cq->db_addr, &v, sizeof(cq->head)); +stl_le_pci_dma(pci, cq->db_addr, cq->head, MEMTXATTRS_UNSPECIFIED); if (n->params.ioeventfd && cq->cqid != 0) { if (!nvme_init_cq_ioeventfd(cq)) { @@ -6974,20 +6965,16 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeRequest *req) static void nvme_update_sq_eventidx(const NvmeSQueue *sq) { -uint32_t v = cpu_to_le32(sq->tail); - trace_pci_nvme_update_sq_eventidx(sq->sqid, sq->tail); -pci_dma_write(PCI_DEVICE(sq->ctrl), sq->ei_addr, &v, sizeof(v)); +stl_le_pci_dma(PCI_DEVICE(sq->ctrl), sq->ei_addr, sq->tail, + MEMTXATTRS_UNSPECIFIED); } static void nvme_update_sq_tail(NvmeSQueue *sq) { -uint32_t v; - -pci_dma_read(PCI_DEVICE(sq->ctrl), sq->db_addr, &v, sizeof(v)); - -sq->tail = le32_to_cpu(v); +ldl_le_pci_dma(PCI_DEVICE(sq->ctrl), sq->db_addr, &sq->tail, + MEMTXATTRS_UNSPECIFIED); trace_pci_nvme_update_sq_tail(sq->sqid, sq->tail); } @@ -7592,7 +7579,7 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size) static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) { PCIDevice *pci = PCI_DEVICE(n); -uint32_t qid, v; +uint32_t qid; if (unlikely(addr & ((1 << 2) - 1))) { NVME_GUEST_ERR(pci_nvme_ub_db_wr_misaligned, @@ -7659,8 +7646,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) start_sqs = nvme_cq_full(cq) ? 1 : 0; cq->head = new_head; if (!qid && n->dbbuf_enabled) { -v = cpu_to_le32(cq->head); -pci_dma_write(pci, cq->db_addr, &v, sizeof(cq->head)); +stl_le_pci_dma(pci, cq->db_addr, cq->head, MEMTXATTRS_UNSPECIFIED); } if (start_sqs) { NvmeSQueue *sq; @@ -7720,8 +7706,6 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) sq->tail = new_tail; if (!qid && n->dbbuf_enabled) { -v = cpu_to_le32(sq->tail); -
Re: [PATCH 2/4] python/console_socket: accept existing FD in initializer
On Thu, Jul 20, 2023 at 10:01 AM Daniel P. Berrangé wrote: > > On Thu, Jul 20, 2023 at 09:04:46AM -0400, John Snow wrote: > > Useful if we want to use ConsoleSocket() for a socket created by > > socketpair(). > > > > Signed-off-by: John Snow > > --- > > python/qemu/machine/console_socket.py | 11 +++ > > 1 file changed, 7 insertions(+), 4 deletions(-) > > > > diff --git a/python/qemu/machine/console_socket.py > > b/python/qemu/machine/console_socket.py > > index 4e28ba9bb2..42bfa12411 100644 > > --- a/python/qemu/machine/console_socket.py > > +++ b/python/qemu/machine/console_socket.py > > @@ -17,7 +17,7 @@ > > import socket > > import threading > > import time > > -from typing import Deque, Optional > > +from typing import Deque, Optional, Union > > > > > > class ConsoleSocket(socket.socket): > > @@ -30,13 +30,16 @@ class ConsoleSocket(socket.socket): > > Optionally a file path can be passed in and we will also > > dump the characters to this file for debugging purposes. > > """ > > -def __init__(self, address: str, file: Optional[str] = None, > > +def __init__(self, address: Union[str, int], file: Optional[str] = > > None, > > drain: bool = False): > > IMHO calling the pre-opened FD an "address" is pushing the > interpretation a bit. > You're right. > It also makes the behaviour non-obvious from a caller. Seeing a > caller, you have to work backwards to find out what type it has, > to figure out the semantics of the method call. > > IOW, I'd prefer to see > >address: Optional[str], sock_fd: Optional[int] > > and then just do a check > >if (address is not None and sock_fd is not None) or > (address is None and sock_fd is None): > raise Exception("either 'address' or 'sock_fd' is required") > > thus when you see > >ConsoleSocket(sock_fd=xxx) > > it is now obvious it has different behaviour to > >ConsoleSocket(address=yyy) > Yeah, that's just a little harder to type - in the sense that it appears as though you could omit either argument by just observing the signature. One thing I like about "one mandatory argument that takes many forms" is that it's obvious you need to give it *something* from the signature. You're right that the name is now very silly, though. The "obvious it has different behavior" is a good argument, I'll change it. --js > > > self._recv_timeout_sec = 300.0 > > self._sleep_time = 0.5 > > self._buffer: Deque[int] = deque() > > -socket.socket.__init__(self, socket.AF_UNIX, socket.SOCK_STREAM) > > -self.connect(address) > > +if isinstance(address, str): > > +socket.socket.__init__(self, socket.AF_UNIX, > > socket.SOCK_STREAM) > > +self.connect(address) > > +else: > > +socket.socket.__init__(self, fileno=address) > > self._logfile = None > > if file: > > # pylint: disable=consider-using-with > > -- > > 2.41.0 > > > > With regards, > Daniel > -- > |: https://berrange.com -o-https://www.flickr.com/photos/dberrange :| > |: https://libvirt.org -o-https://fstop138.berrange.com :| > |: https://entangle-photo.org-o-https://www.instagram.com/dberrange :| >
Re: [PATCH 4/4] python/machine: remove unused console socket configuration arguments
On Thu, Jul 20, 2023 at 10:05 AM Daniel P. Berrangé wrote: > > On Thu, Jul 20, 2023 at 09:04:48AM -0400, John Snow wrote: > > By using a socketpair for the console, we don't need the sock_dir > > argument for the base class anymore, remove it. > > > > The qtest subclass still uses the argument for the qtest socket for now. > > > > Signed-off-by: John Snow > > --- > > python/qemu/machine/machine.py | 18 -- > > python/qemu/machine/qtest.py | 6 +++--- > > tests/qemu-iotests/tests/copy-before-write | 3 +-- > > 3 files changed, 4 insertions(+), 23 deletions(-) > > A couple of callers to be updated to remove 'sock_dir=': > > $ git grep 'sock_dir=' tests > tests/avocado/acpi-bits.py: sock_dir=sock_dir, > qmp_timer=qmp_timer) > tests/avocado/avocado_qemu/__init__.py: > sock_dir=self._sd.name, log_dir=self.logdir) > tests/qemu-iotests/iotests.py: sock_dir=sock_dir, > qmp_timer=timer) > tests/qemu-iotests/tests/copy-before-write: > sock_dir=iotests.sock_dir) > > presume the avocado_qemu/__init__.py one is what caused the > failure Peter reported. > Yep, missed a spot, sorry :( I tested avocado after patch 3 but not here. While I'm at it, though, I am testing the same treatment for the qtest extension and just removing sock_dir from *everything*, since we don't need that workaround anymore if we aren't creating named sockets. ...And if I get rid of *that*, I can get rid of some other temp directory management stuff too. > > > > diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py > > index ef9b2dc02e..350aa8bb26 100644 > > --- a/python/qemu/machine/machine.py > > +++ b/python/qemu/machine/machine.py > > @@ -127,7 +127,6 @@ def __init__(self, > > name: Optional[str] = None, > > base_temp_dir: str = "/var/tmp", > > monitor_address: Optional[SocketAddrT] = None, > > - sock_dir: Optional[str] = None, > > drain_console: bool = False, > > console_log: Optional[str] = None, > > log_dir: Optional[str] = None, > > @@ -141,7 +140,6 @@ def __init__(self, > > @param name: prefix for socket and log file names (default: > > qemu-PID) > > @param base_temp_dir: default location where temp files are created > > @param monitor_address: address for QMP monitor > > -@param sock_dir: where to create socket (defaults to base_temp_dir) > > @param drain_console: (optional) True to drain console socket to > > buffer > > @param console_log: (optional) path to console log file > > @param log_dir: where to create and keep log files > > @@ -163,7 +161,6 @@ def __init__(self, > > Tuple[socket.socket, socket.socket]] = None > > self._temp_dir: Optional[str] = None > > self._base_temp_dir = base_temp_dir > > -self._sock_dir = sock_dir > > self._log_dir = log_dir > > > > self._monitor_address = monitor_address > > @@ -189,9 +186,6 @@ def __init__(self, > > self._console_index = 0 > > self._console_set = False > > self._console_device_type: Optional[str] = None > > -self._console_address = os.path.join( > > -self.sock_dir, f"{self._name}.con" > > -) > > self._console_socket: Optional[socket.socket] = None > > self._remove_files: List[str] = [] > > self._user_killed = False > > @@ -334,9 +328,6 @@ def args(self) -> List[str]: > > return self._args > > > > def _pre_launch(self) -> None: > > -if self._console_set: > > -self._remove_files.append(self._console_address) > > - > > if self._qmp_set: > > if self._monitor_address is None: > > self._sock_pair = socket.socketpair() > > @@ -900,15 +891,6 @@ def temp_dir(self) -> str: > >dir=self._base_temp_dir) > > return self._temp_dir > > > > -@property > > -def sock_dir(self) -> str: > > -""" > > -Returns the directory used for sockfiles by this machine. > > -""" > > -if self._sock_dir: > > -return self._sock_dir > > -return self.temp_dir > > - > > @property > > def log_dir(self) -> str: > > """ > > diff --git a/python/qemu/machine/qtest.py b/python/qemu/machine/qtest.py > > index 1c46138bd0..22f8045ef6 100644 > > --- a/python/qemu/machine/qtest.py > > +++ b/python/qemu/machine/qtest.py > > @@ -115,8 +115,8 @@ def __init__(self, > > wrapper: Sequence[str] = (), > > name: Optional[str] = None, > > base_temp_dir: str = "/var/tmp", > > - sock_dir: Optional[str] = None, > > - qmp_timer: Optional[float] = None): > > +
Re: [PATCH 4/4] python/machine: remove unused console socket configuration arguments
On Thu, Jul 20, 2023 at 09:04:48AM -0400, John Snow wrote: > By using a socketpair for the console, we don't need the sock_dir > argument for the base class anymore, remove it. > > The qtest subclass still uses the argument for the qtest socket for now. > > Signed-off-by: John Snow > --- > python/qemu/machine/machine.py | 18 -- > python/qemu/machine/qtest.py | 6 +++--- > tests/qemu-iotests/tests/copy-before-write | 3 +-- > 3 files changed, 4 insertions(+), 23 deletions(-) A couple of callers to be updated to remove 'sock_dir=': $ git grep 'sock_dir=' tests tests/avocado/acpi-bits.py: sock_dir=sock_dir, qmp_timer=qmp_timer) tests/avocado/avocado_qemu/__init__.py: sock_dir=self._sd.name, log_dir=self.logdir) tests/qemu-iotests/iotests.py: sock_dir=sock_dir, qmp_timer=timer) tests/qemu-iotests/tests/copy-before-write: sock_dir=iotests.sock_dir) presume the avocado_qemu/__init__.py one is what caused the failure Peter reported. > > diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py > index ef9b2dc02e..350aa8bb26 100644 > --- a/python/qemu/machine/machine.py > +++ b/python/qemu/machine/machine.py > @@ -127,7 +127,6 @@ def __init__(self, > name: Optional[str] = None, > base_temp_dir: str = "/var/tmp", > monitor_address: Optional[SocketAddrT] = None, > - sock_dir: Optional[str] = None, > drain_console: bool = False, > console_log: Optional[str] = None, > log_dir: Optional[str] = None, > @@ -141,7 +140,6 @@ def __init__(self, > @param name: prefix for socket and log file names (default: qemu-PID) > @param base_temp_dir: default location where temp files are created > @param monitor_address: address for QMP monitor > -@param sock_dir: where to create socket (defaults to base_temp_dir) > @param drain_console: (optional) True to drain console socket to > buffer > @param console_log: (optional) path to console log file > @param log_dir: where to create and keep log files > @@ -163,7 +161,6 @@ def __init__(self, > Tuple[socket.socket, socket.socket]] = None > self._temp_dir: Optional[str] = None > self._base_temp_dir = base_temp_dir > -self._sock_dir = sock_dir > self._log_dir = log_dir > > self._monitor_address = monitor_address > @@ -189,9 +186,6 @@ def __init__(self, > self._console_index = 0 > self._console_set = False > self._console_device_type: Optional[str] = None > -self._console_address = os.path.join( > -self.sock_dir, f"{self._name}.con" > -) > self._console_socket: Optional[socket.socket] = None > self._remove_files: List[str] = [] > self._user_killed = False > @@ -334,9 +328,6 @@ def args(self) -> List[str]: > return self._args > > def _pre_launch(self) -> None: > -if self._console_set: > -self._remove_files.append(self._console_address) > - > if self._qmp_set: > if self._monitor_address is None: > self._sock_pair = socket.socketpair() > @@ -900,15 +891,6 @@ def temp_dir(self) -> str: >dir=self._base_temp_dir) > return self._temp_dir > > -@property > -def sock_dir(self) -> str: > -""" > -Returns the directory used for sockfiles by this machine. > -""" > -if self._sock_dir: > -return self._sock_dir > -return self.temp_dir > - > @property > def log_dir(self) -> str: > """ > diff --git a/python/qemu/machine/qtest.py b/python/qemu/machine/qtest.py > index 1c46138bd0..22f8045ef6 100644 > --- a/python/qemu/machine/qtest.py > +++ b/python/qemu/machine/qtest.py > @@ -115,8 +115,8 @@ def __init__(self, > wrapper: Sequence[str] = (), > name: Optional[str] = None, > base_temp_dir: str = "/var/tmp", > - sock_dir: Optional[str] = None, > - qmp_timer: Optional[float] = None): > + qmp_timer: Optional[float] = None, > + sock_dir: Optional[str] = None): > # pylint: disable=too-many-arguments > > if name is None: > @@ -125,7 +125,7 @@ def __init__(self, > sock_dir = base_temp_dir > super().__init__(binary, args, wrapper=wrapper, name=name, > base_temp_dir=base_temp_dir, > - sock_dir=sock_dir, qmp_timer=qmp_timer) > + qmp_timer=qmp_timer) > self._qtest: Optional[QEMUQtestProtocol] = None > self._qtest_path = os.path.join(sock_dir, name + "-qtest.sock") > > diff
Re: [PATCH 3/4] python/machine: use socketpair() for console connections
On Thu, Jul 20, 2023 at 09:04:47AM -0400, John Snow wrote: > Create a socketpair for the console output. This should help eliminate > race conditions around console text early in the boot process that might > otherwise have been dropped on the floor before being able to connect to > QEMU under "server,nowait". > > Signed-off-by: John Snow > --- > python/qemu/machine/machine.py | 17 ++--- > 1 file changed, 14 insertions(+), 3 deletions(-) Reviewed-by: Daniel P. Berrangé With regards, Daniel -- |: https://berrange.com -o-https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o-https://fstop138.berrange.com :| |: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|
Re: [PATCH 2/4] python/console_socket: accept existing FD in initializer
On Thu, Jul 20, 2023 at 09:04:46AM -0400, John Snow wrote: > Useful if we want to use ConsoleSocket() for a socket created by > socketpair(). > > Signed-off-by: John Snow > --- > python/qemu/machine/console_socket.py | 11 +++ > 1 file changed, 7 insertions(+), 4 deletions(-) > > diff --git a/python/qemu/machine/console_socket.py > b/python/qemu/machine/console_socket.py > index 4e28ba9bb2..42bfa12411 100644 > --- a/python/qemu/machine/console_socket.py > +++ b/python/qemu/machine/console_socket.py > @@ -17,7 +17,7 @@ > import socket > import threading > import time > -from typing import Deque, Optional > +from typing import Deque, Optional, Union > > > class ConsoleSocket(socket.socket): > @@ -30,13 +30,16 @@ class ConsoleSocket(socket.socket): > Optionally a file path can be passed in and we will also > dump the characters to this file for debugging purposes. > """ > -def __init__(self, address: str, file: Optional[str] = None, > +def __init__(self, address: Union[str, int], file: Optional[str] = None, > drain: bool = False): IMHO calling the pre-opened FD an "address" is pushing the interpretation a bit. It also makes the behaviour non-obvious from a caller. Seeing a caller, you have to work backwards to find out what type it has, to figure out the semantics of the method call. IOW, I'd prefer to see address: Optional[str], sock_fd: Optional[int] and then just do a check if (address is not None and sock_fd is not None) or (address is None and sock_fd is None): raise Exception("either 'address' or 'sock_fd' is required") thus when you see ConsoleSocket(sock_fd=xxx) it is now obvious it has different behaviour to ConsoleSocket(address=yyy) > self._recv_timeout_sec = 300.0 > self._sleep_time = 0.5 > self._buffer: Deque[int] = deque() > -socket.socket.__init__(self, socket.AF_UNIX, socket.SOCK_STREAM) > -self.connect(address) > +if isinstance(address, str): > +socket.socket.__init__(self, socket.AF_UNIX, socket.SOCK_STREAM) > +self.connect(address) > +else: > +socket.socket.__init__(self, fileno=address) > self._logfile = None > if file: > # pylint: disable=consider-using-with > -- > 2.41.0 > With regards, Daniel -- |: https://berrange.com -o-https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o-https://fstop138.berrange.com :| |: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|
[PATCH] block: Be more verbose in create fallback
For image creation code, we have central fallback code for protocols that do not support creating new images (like NBD or iscsi). So for them, you can only specify existing paths/exports that are overwritten to make clean new images. In such a case, if the given path cannot be opened (assuming a pre-existing image there), we print an error message that tries to describe what is going on: That with this protocol, you cannot create new images, but only overwrite existing ones; and the given path could not be opened as a pre-existing image. However, the current message is confusing, because it does not say that the protocol in question does not support creating new images, but instead that "image creation" is unsupported. This can be interpreted to mean that `qemu-img create` will not work in principle, which is not true. Be more verbose for clarity. Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2217204 Signed-off-by: Hanna Czenczek --- block.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index a307c151a8..f530dd9c02 100644 --- a/block.c +++ b/block.c @@ -661,8 +661,10 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv, blk = blk_co_new_open(filename, NULL, options, BDRV_O_RDWR | BDRV_O_RESIZE, errp); if (!blk) { -error_prepend(errp, "Protocol driver '%s' does not support image " - "creation, and opening the image failed: ", +error_prepend(errp, "Protocol driver '%s' does not support creating " + "new images, so an existing image must be selected as " + "the target; however, opening the given target as an " + "existing image failed: ", drv->format_name); return -EINVAL; } -- 2.41.0
Re: [PATCH 1/4] python/machine: move socket setup out of _base_args property
On Thu, Jul 20, 2023 at 09:04:45AM -0400, John Snow wrote: > This property isn't meant to do much else besides return a list of > strings, so move this setup back out into _pre_launch(). > > Signed-off-by: John Snow > --- > python/qemu/machine/machine.py | 5 ++--- > 1 file changed, 2 insertions(+), 3 deletions(-) Reviewed-by: Daniel P. Berrangé With regards, Daniel -- |: https://berrange.com -o-https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o-https://fstop138.berrange.com :| |: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|
Re: [PATCH 0/4] python/machine: use socketpair() for console socket
On Thu, 20 Jul 2023 at 14:04, John Snow wrote: > > Like we did for the QMP socket, use socketpair() for the console socket > so that hopefully there isn't a race condition during early boot where > data might get dropped on the floor. > > "lightly tested"; passes local tests and gitlab CI. Doesn't seem to make > anything worse. I tried this on the s390 linux box and the test failed because of a python exception: __init__() got an unexpected keyword argument 'sock_dir' $ QEMU_TEST_FLAKY_TESTS=1 ./build/aarch64/tests/venv/bin/avocado run ./build/aarch64/tests/avocado/machine_aarch64_sbsaref.py:Aarch64SbsarefMachine.test_sbsaref_edk2_firmware JOB ID : 8392ba37b5a825ed75278f85f686364d181c01d3 JOB LOG: /home/linux1/avocado/job-results/job-2023-07-20T13.41-8392ba3/job.log (1/1) ./build/aarch64/tests/avocado/machine_aarch64_sbsaref.py:Aarch64SbsarefMachine.test_sbsaref_edk2_firmware: ERROR: __init__() got an unexpected keyword argument 'sock_dir' (3.64 s) RESULTS: PASS 0 | ERROR 1 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0 JOB TIME : 6.92 s Backtrace etc from in the job.log: 2023-07-20 13:41:49,125 stacktrace L0041 ERROR| Reproduced traceback from: /home/linux1/qemu/build/aarch64/tests/venv/lib/python3.8/site-package s/avocado/core/test.py:770 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| Traceback (most recent call last): 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| File "/home/linux1/qemu/build/aarch64/tests/venv/lib/python3.8/site-packages/avocado/core/decorators.py", line 90, in wrapper 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| return function(obj, *args, **kwargs) 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| File "/home/linux1/qemu/build/aarch64/tests/avocado/machine_aarch64_sbsaref.py", line 84, in test_sbsaref_edk2_firmware 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| self.fetch_firmware() 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| File "/home/linux1/qemu/build/aarch64/tests/avocado/machine_aarch64_sbsaref.py", line 66, in fetch_firmware 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| self.vm.set_console() 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| File "/home/linux1/qemu/build/aarch64/tests/avocado/avocado_qemu/__init__.py", line 348, in vm 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| return self.get_vm(name='default') 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| File "/home/linux1/qemu/build/aarch64/tests/avocado/avocado_qemu/__init__.py", line 354, in get_vm 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| self._vms[name] = self._new_vm(name, *args) 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| File "/home/linux1/qemu/build/aarch64/tests/avocado/avocado_qemu/__init__.py", line 324, in _new_vm 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir, 2023-07-20 13:41:49,147 stacktrace L0045 ERROR| TypeError: __init__() got an unexpected keyword argument 'sock_dir' 2023-07-20 13:41:49,147 stacktrace L0046 ERROR| 2023-07-20 13:41:49,147 test L0775 DEBUG| Local variables: 2023-07-20 13:41:49,160 test L0778 DEBUG| -> obj : 1-./build/aarch64/tests/avocado/machine_aarch64_sbsaref.py:Aarch64SbsarefMachine.test_sbsaref_edk2_firmware 2023-07-20 13:41:49,160 test L0778 DEBUG| -> args : () 2023-07-20 13:41:49,160 test L0778 DEBUG| -> kwargs : {} 2023-07-20 13:41:49,160 test L0778 DEBUG| -> condition : 1 2023-07-20 13:41:49,160 test L0778 DEBUG| -> function : 2023-07-20 13:41:49,160 test L0778 DEBUG| -> message : Test is not reliable 2023-07-20 13:41:49,160 test L0778 DEBUG| -> negate : True thanks -- PMM
Re: [PATCH] hw/nvme: use stl/ldl pci dma api
On 20/7/23 11:42, Klaus Jensen wrote: From: Klaus Jensen Use the stl/ldl pci dma api for writing/reading doorbells. This removes the explicit endian conversions. Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 42 +- 1 file changed, 13 insertions(+), 29 deletions(-) Reviewed-by: Philippe Mathieu-Daudé
[PATCH 1/4] python/machine: move socket setup out of _base_args property
This property isn't meant to do much else besides return a list of strings, so move this setup back out into _pre_launch(). Signed-off-by: John Snow --- python/qemu/machine/machine.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index c16a0b6fed..8be0f684fe 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -300,9 +300,7 @@ def _base_args(self) -> List[str]: if self._qmp_set: if self._sock_pair: -fd = self._sock_pair[0].fileno() -os.set_inheritable(fd, True) -moncdev = f"socket,id=mon,fd={fd}" +moncdev = f"socket,id=mon,fd={self._sock_pair[0].fileno()}" elif isinstance(self._monitor_address, tuple): moncdev = "socket,id=mon,host={},port={}".format( *self._monitor_address @@ -339,6 +337,7 @@ def _pre_launch(self) -> None: if self._qmp_set: if self._monitor_address is None: self._sock_pair = socket.socketpair() +os.set_inheritable(self._sock_pair[0].fileno(), True) sock = self._sock_pair[1] if isinstance(self._monitor_address, str): self._remove_files.append(self._monitor_address) -- 2.41.0
[PATCH 3/4] python/machine: use socketpair() for console connections
Create a socketpair for the console output. This should help eliminate race conditions around console text early in the boot process that might otherwise have been dropped on the floor before being able to connect to QEMU under "server,nowait". Signed-off-by: John Snow --- python/qemu/machine/machine.py | 17 ++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index 8be0f684fe..ef9b2dc02e 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -159,6 +159,8 @@ def __init__(self, self._name = name or f"{id(self):x}" self._sock_pair: Optional[Tuple[socket.socket, socket.socket]] = None +self._cons_sock_pair: Optional[ +Tuple[socket.socket, socket.socket]] = None self._temp_dir: Optional[str] = None self._base_temp_dir = base_temp_dir self._sock_dir = sock_dir @@ -315,8 +317,9 @@ def _base_args(self) -> List[str]: for _ in range(self._console_index): args.extend(['-serial', 'null']) if self._console_set: -chardev = ('socket,id=console,path=%s,server=on,wait=off' % - self._console_address) +assert self._cons_sock_pair is not None +fd = self._cons_sock_pair[0].fileno() +chardev = f"socket,id=console,fd={fd}" args.extend(['-chardev', chardev]) if self._console_device_type is None: args.extend(['-serial', 'chardev:console']) @@ -351,6 +354,10 @@ def _pre_launch(self) -> None: nickname=self._name ) +if self._console_set: +self._cons_sock_pair = socket.socketpair() +os.set_inheritable(self._cons_sock_pair[0].fileno(), True) + # NOTE: Make sure any opened resources are *definitely* freed in # _post_shutdown()! # pylint: disable=consider-using-with @@ -873,8 +880,12 @@ def console_socket(self) -> socket.socket: Returns a socket connected to the console """ if self._console_socket is None: +if not self._console_set: +raise QEMUMachineError( +"Attempt to access console socket with no connection") +assert self._cons_sock_pair is not None self._console_socket = console_socket.ConsoleSocket( -self._console_address, +self._cons_sock_pair[1].fileno(), file=self._console_log_path, drain=self._drain_console) return self._console_socket -- 2.41.0
[PATCH 2/4] python/console_socket: accept existing FD in initializer
Useful if we want to use ConsoleSocket() for a socket created by socketpair(). Signed-off-by: John Snow --- python/qemu/machine/console_socket.py | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/python/qemu/machine/console_socket.py b/python/qemu/machine/console_socket.py index 4e28ba9bb2..42bfa12411 100644 --- a/python/qemu/machine/console_socket.py +++ b/python/qemu/machine/console_socket.py @@ -17,7 +17,7 @@ import socket import threading import time -from typing import Deque, Optional +from typing import Deque, Optional, Union class ConsoleSocket(socket.socket): @@ -30,13 +30,16 @@ class ConsoleSocket(socket.socket): Optionally a file path can be passed in and we will also dump the characters to this file for debugging purposes. """ -def __init__(self, address: str, file: Optional[str] = None, +def __init__(self, address: Union[str, int], file: Optional[str] = None, drain: bool = False): self._recv_timeout_sec = 300.0 self._sleep_time = 0.5 self._buffer: Deque[int] = deque() -socket.socket.__init__(self, socket.AF_UNIX, socket.SOCK_STREAM) -self.connect(address) +if isinstance(address, str): +socket.socket.__init__(self, socket.AF_UNIX, socket.SOCK_STREAM) +self.connect(address) +else: +socket.socket.__init__(self, fileno=address) self._logfile = None if file: # pylint: disable=consider-using-with -- 2.41.0
[PATCH 4/4] python/machine: remove unused console socket configuration arguments
By using a socketpair for the console, we don't need the sock_dir argument for the base class anymore, remove it. The qtest subclass still uses the argument for the qtest socket for now. Signed-off-by: John Snow --- python/qemu/machine/machine.py | 18 -- python/qemu/machine/qtest.py | 6 +++--- tests/qemu-iotests/tests/copy-before-write | 3 +-- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index ef9b2dc02e..350aa8bb26 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -127,7 +127,6 @@ def __init__(self, name: Optional[str] = None, base_temp_dir: str = "/var/tmp", monitor_address: Optional[SocketAddrT] = None, - sock_dir: Optional[str] = None, drain_console: bool = False, console_log: Optional[str] = None, log_dir: Optional[str] = None, @@ -141,7 +140,6 @@ def __init__(self, @param name: prefix for socket and log file names (default: qemu-PID) @param base_temp_dir: default location where temp files are created @param monitor_address: address for QMP monitor -@param sock_dir: where to create socket (defaults to base_temp_dir) @param drain_console: (optional) True to drain console socket to buffer @param console_log: (optional) path to console log file @param log_dir: where to create and keep log files @@ -163,7 +161,6 @@ def __init__(self, Tuple[socket.socket, socket.socket]] = None self._temp_dir: Optional[str] = None self._base_temp_dir = base_temp_dir -self._sock_dir = sock_dir self._log_dir = log_dir self._monitor_address = monitor_address @@ -189,9 +186,6 @@ def __init__(self, self._console_index = 0 self._console_set = False self._console_device_type: Optional[str] = None -self._console_address = os.path.join( -self.sock_dir, f"{self._name}.con" -) self._console_socket: Optional[socket.socket] = None self._remove_files: List[str] = [] self._user_killed = False @@ -334,9 +328,6 @@ def args(self) -> List[str]: return self._args def _pre_launch(self) -> None: -if self._console_set: -self._remove_files.append(self._console_address) - if self._qmp_set: if self._monitor_address is None: self._sock_pair = socket.socketpair() @@ -900,15 +891,6 @@ def temp_dir(self) -> str: dir=self._base_temp_dir) return self._temp_dir -@property -def sock_dir(self) -> str: -""" -Returns the directory used for sockfiles by this machine. -""" -if self._sock_dir: -return self._sock_dir -return self.temp_dir - @property def log_dir(self) -> str: """ diff --git a/python/qemu/machine/qtest.py b/python/qemu/machine/qtest.py index 1c46138bd0..22f8045ef6 100644 --- a/python/qemu/machine/qtest.py +++ b/python/qemu/machine/qtest.py @@ -115,8 +115,8 @@ def __init__(self, wrapper: Sequence[str] = (), name: Optional[str] = None, base_temp_dir: str = "/var/tmp", - sock_dir: Optional[str] = None, - qmp_timer: Optional[float] = None): + qmp_timer: Optional[float] = None, + sock_dir: Optional[str] = None): # pylint: disable=too-many-arguments if name is None: @@ -125,7 +125,7 @@ def __init__(self, sock_dir = base_temp_dir super().__init__(binary, args, wrapper=wrapper, name=name, base_temp_dir=base_temp_dir, - sock_dir=sock_dir, qmp_timer=qmp_timer) + qmp_timer=qmp_timer) self._qtest: Optional[QEMUQtestProtocol] = None self._qtest_path = os.path.join(sock_dir, name + "-qtest.sock") diff --git a/tests/qemu-iotests/tests/copy-before-write b/tests/qemu-iotests/tests/copy-before-write index 2ffe092b31..d3987db942 100755 --- a/tests/qemu-iotests/tests/copy-before-write +++ b/tests/qemu-iotests/tests/copy-before-write @@ -44,8 +44,7 @@ class TestCbwError(iotests.QMPTestCase): opts = ['-nodefaults', '-display', 'none', '-machine', 'none'] self.vm = QEMUMachine(iotests.qemu_prog, opts, - base_temp_dir=iotests.test_dir, - sock_dir=iotests.sock_dir) + base_temp_dir=iotests.test_dir) self.vm.launch() def do_cbw_error(self, on_cbw_error): -- 2.41.0
[PATCH 0/4] python/machine: use socketpair() for console socket
Like we did for the QMP socket, use socketpair() for the console socket so that hopefully there isn't a race condition during early boot where data might get dropped on the floor. "lightly tested"; passes local tests and gitlab CI. Doesn't seem to make anything worse. John Snow (4): python/machine: move socket setup out of _base_args property python/console_socket: accept existing FD in initializer python/machine: use socketpair() for console connections python/machine: remove unused console socket configuration arguments python/qemu/machine/console_socket.py | 11 +++--- python/qemu/machine/machine.py | 40 +- python/qemu/machine/qtest.py | 6 ++-- tests/qemu-iotests/tests/copy-before-write | 3 +- 4 files changed, 27 insertions(+), 33 deletions(-) -- 2.41.0
Re: [PATCH] hw/nvme: use stl/ldl pci dma api
On 20/07/2023 11.42, Klaus Jensen wrote: From: Klaus Jensen Use the stl/ldl pci dma api for writing/reading doorbells. This removes the explicit endian conversions. Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 42 +- 1 file changed, 13 insertions(+), 29 deletions(-) Reviewed-by: Thomas Huth
[PATCH] hw/nvme: use stl/ldl pci dma api
From: Klaus Jensen Use the stl/ldl pci dma api for writing/reading doorbells. This removes the explicit endian conversions. Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 42 +- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index dadc2dc7da10..f2e5a2fa737b 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1468,20 +1468,16 @@ static inline void nvme_blk_write(BlockBackend *blk, int64_t offset, static void nvme_update_cq_eventidx(const NvmeCQueue *cq) { -uint32_t v = cpu_to_le32(cq->head); - trace_pci_nvme_update_cq_eventidx(cq->cqid, cq->head); -pci_dma_write(PCI_DEVICE(cq->ctrl), cq->ei_addr, &v, sizeof(v)); +stl_le_pci_dma(PCI_DEVICE(cq->ctrl), cq->ei_addr, cq->head, + MEMTXATTRS_UNSPECIFIED); } static void nvme_update_cq_head(NvmeCQueue *cq) { -uint32_t v; - -pci_dma_read(PCI_DEVICE(cq->ctrl), cq->db_addr, &v, sizeof(v)); - -cq->head = le32_to_cpu(v); +ldl_le_pci_dma(PCI_DEVICE(cq->ctrl), cq->db_addr, &cq->head, + MEMTXATTRS_UNSPECIFIED); trace_pci_nvme_update_cq_head(cq->cqid, cq->head); } @@ -6801,7 +6797,6 @@ static uint16_t nvme_dbbuf_config(NvmeCtrl *n, const NvmeRequest *req) PCIDevice *pci = PCI_DEVICE(n); uint64_t dbs_addr = le64_to_cpu(req->cmd.dptr.prp1); uint64_t eis_addr = le64_to_cpu(req->cmd.dptr.prp2); -uint32_t v; int i; /* Address should be page aligned */ @@ -6819,8 +6814,6 @@ static uint16_t nvme_dbbuf_config(NvmeCtrl *n, const NvmeRequest *req) NvmeCQueue *cq = n->cq[i]; if (sq) { -v = cpu_to_le32(sq->tail); - /* * CAP.DSTRD is 0, so offset of ith sq db_addr is (i<<3) * nvme_process_db() uses this hard-coded way to calculate @@ -6828,7 +6821,7 @@ static uint16_t nvme_dbbuf_config(NvmeCtrl *n, const NvmeRequest *req) */ sq->db_addr = dbs_addr + (i << 3); sq->ei_addr = eis_addr + (i << 3); -pci_dma_write(pci, sq->db_addr, &v, sizeof(sq->tail)); +stl_le_pci_dma(pci, sq->db_addr, sq->tail, MEMTXATTRS_UNSPECIFIED); if (n->params.ioeventfd && sq->sqid != 0) { if (!nvme_init_sq_ioeventfd(sq)) { @@ -6838,12 +6831,10 @@ static uint16_t nvme_dbbuf_config(NvmeCtrl *n, const NvmeRequest *req) } if (cq) { -v = cpu_to_le32(cq->head); - /* CAP.DSTRD is 0, so offset of ith cq db_addr is (i<<3)+(1<<2) */ cq->db_addr = dbs_addr + (i << 3) + (1 << 2); cq->ei_addr = eis_addr + (i << 3) + (1 << 2); -pci_dma_write(pci, cq->db_addr, &v, sizeof(cq->head)); +stl_le_pci_dma(pci, cq->db_addr, cq->head, MEMTXATTRS_UNSPECIFIED); if (n->params.ioeventfd && cq->cqid != 0) { if (!nvme_init_cq_ioeventfd(cq)) { @@ -6974,20 +6965,16 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeRequest *req) static void nvme_update_sq_eventidx(const NvmeSQueue *sq) { -uint32_t v = cpu_to_le32(sq->tail); - trace_pci_nvme_update_sq_eventidx(sq->sqid, sq->tail); -pci_dma_write(PCI_DEVICE(sq->ctrl), sq->ei_addr, &v, sizeof(v)); +stl_le_pci_dma(PCI_DEVICE(sq->ctrl), sq->ei_addr, sq->tail, + MEMTXATTRS_UNSPECIFIED); } static void nvme_update_sq_tail(NvmeSQueue *sq) { -uint32_t v; - -pci_dma_read(PCI_DEVICE(sq->ctrl), sq->db_addr, &v, sizeof(v)); - -sq->tail = le32_to_cpu(v); +ldl_le_pci_dma(PCI_DEVICE(sq->ctrl), sq->db_addr, &sq->tail, + MEMTXATTRS_UNSPECIFIED); trace_pci_nvme_update_sq_tail(sq->sqid, sq->tail); } @@ -7592,7 +7579,7 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size) static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) { PCIDevice *pci = PCI_DEVICE(n); -uint32_t qid, v; +uint32_t qid; if (unlikely(addr & ((1 << 2) - 1))) { NVME_GUEST_ERR(pci_nvme_ub_db_wr_misaligned, @@ -7659,8 +7646,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) start_sqs = nvme_cq_full(cq) ? 1 : 0; cq->head = new_head; if (!qid && n->dbbuf_enabled) { -v = cpu_to_le32(cq->head); -pci_dma_write(pci, cq->db_addr, &v, sizeof(cq->head)); +stl_le_pci_dma(pci, cq->db_addr, cq->head, MEMTXATTRS_UNSPECIFIED); } if (start_sqs) { NvmeSQueue *sq; @@ -7720,8 +7706,6 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) sq->tail = new_tail; if (!qid && n->dbbuf_enabled) { -v = cpu_to_le32(sq->tail); - /* * The spec states "the host shall also update the controller's * corresponding doorbell property to match the value of that entry @@ -7735,7 +7719,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr
Re: [PULL 1/1] hw/nvme: fix endianness issue for shadow doorbells
On Jul 20 09:51, Peter Maydell wrote: > On Thu, 20 Jul 2023 at 09:49, Klaus Jensen wrote: > > > > On Jul 20 09:43, Peter Maydell wrote: > > > On Wed, 19 Jul 2023 at 21:13, Michael Tokarev wrote: > > > > > > > > 19.07.2023 10:36, Klaus Jensen wrote: > > > > pu(req->cmd.dptr.prp2); > > > > > +uint32_t v; > > > > > > > > > if (sq) { > > > > > +v = cpu_to_le32(sq->tail); > > > > > > > > > -pci_dma_write(pci, sq->db_addr, &sq->tail, > > > > > sizeof(sq->tail)); > > > > > +pci_dma_write(pci, sq->db_addr, &v, sizeof(sq->tail)); > > > > > > > > This and similar cases hurts my eyes. > > > > > > > > Why we pass address of v here, but use sizeof(sq->tail) ? > > > > > > > > Yes, I know both in theory should be of the same size, but heck, > > > > this is puzzling at best, and confusing in a regular case. > > > > > > > > Dunno how it slipped in the review, it instantly catched my eye > > > > in a row of applied patches.. > > > > > > > > Also, why v is computed a few lines before it is used, with > > > > some expressions between the assignment and usage? > > > > > > > > How about the following patch: > > > > > > If you're going to change this, better to take the approach > > > Philippe suggested in review of using stl_le_pci_dma(). > > > > > > https://lore.kernel.org/qemu-devel/376e5e45-a3e7-0029-603a-b7ad9673f...@linaro.org/ > > > > > > > Yup, that was my plan for next. But the original patch was already > > verified on hardware and mutiple testes, so wanted to go with that for > > the "fix". > > > > But yes, I will refactor into the much nicer stl/ldl api. > > FWIW, I don't think this bug fix was so urgent that we > needed to go with a quick fix and a followup -- we're > not yet that close to 8.1 release. > Alright, noted ;) I will spin this into the other fix I have under review. signature.asc Description: PGP signature
Re: [PULL 1/1] hw/nvme: fix endianness issue for shadow doorbells
On Thu, 20 Jul 2023 at 09:49, Klaus Jensen wrote: > > On Jul 20 09:43, Peter Maydell wrote: > > On Wed, 19 Jul 2023 at 21:13, Michael Tokarev wrote: > > > > > > 19.07.2023 10:36, Klaus Jensen wrote: > > > pu(req->cmd.dptr.prp2); > > > > +uint32_t v; > > > > > > > if (sq) { > > > > +v = cpu_to_le32(sq->tail); > > > > > > > -pci_dma_write(pci, sq->db_addr, &sq->tail, > > > > sizeof(sq->tail)); > > > > +pci_dma_write(pci, sq->db_addr, &v, sizeof(sq->tail)); > > > > > > This and similar cases hurts my eyes. > > > > > > Why we pass address of v here, but use sizeof(sq->tail) ? > > > > > > Yes, I know both in theory should be of the same size, but heck, > > > this is puzzling at best, and confusing in a regular case. > > > > > > Dunno how it slipped in the review, it instantly catched my eye > > > in a row of applied patches.. > > > > > > Also, why v is computed a few lines before it is used, with > > > some expressions between the assignment and usage? > > > > > > How about the following patch: > > > > If you're going to change this, better to take the approach > > Philippe suggested in review of using stl_le_pci_dma(). > > > > https://lore.kernel.org/qemu-devel/376e5e45-a3e7-0029-603a-b7ad9673f...@linaro.org/ > > > > Yup, that was my plan for next. But the original patch was already > verified on hardware and mutiple testes, so wanted to go with that for > the "fix". > > But yes, I will refactor into the much nicer stl/ldl api. FWIW, I don't think this bug fix was so urgent that we needed to go with a quick fix and a followup -- we're not yet that close to 8.1 release. thanks -- PMM
Re: [PULL 1/1] hw/nvme: fix endianness issue for shadow doorbells
On Jul 20 09:43, Peter Maydell wrote: > On Wed, 19 Jul 2023 at 21:13, Michael Tokarev wrote: > > > > 19.07.2023 10:36, Klaus Jensen wrote: > > pu(req->cmd.dptr.prp2); > > > +uint32_t v; > > > > > if (sq) { > > > +v = cpu_to_le32(sq->tail); > > > > > -pci_dma_write(pci, sq->db_addr, &sq->tail, sizeof(sq->tail)); > > > +pci_dma_write(pci, sq->db_addr, &v, sizeof(sq->tail)); > > > > This and similar cases hurts my eyes. > > > > Why we pass address of v here, but use sizeof(sq->tail) ? > > > > Yes, I know both in theory should be of the same size, but heck, > > this is puzzling at best, and confusing in a regular case. > > > > Dunno how it slipped in the review, it instantly catched my eye > > in a row of applied patches.. > > > > Also, why v is computed a few lines before it is used, with > > some expressions between the assignment and usage? > > > > How about the following patch: > > If you're going to change this, better to take the approach > Philippe suggested in review of using stl_le_pci_dma(). > > https://lore.kernel.org/qemu-devel/376e5e45-a3e7-0029-603a-b7ad9673f...@linaro.org/ > Yup, that was my plan for next. But the original patch was already verified on hardware and mutiple testes, so wanted to go with that for the "fix". But yes, I will refactor into the much nicer stl/ldl api. signature.asc Description: PGP signature
Re: [PULL 1/1] hw/nvme: fix endianness issue for shadow doorbells
On Wed, 19 Jul 2023 at 21:13, Michael Tokarev wrote: > > 19.07.2023 10:36, Klaus Jensen wrote: > pu(req->cmd.dptr.prp2); > > +uint32_t v; > > > if (sq) { > > +v = cpu_to_le32(sq->tail); > > > -pci_dma_write(pci, sq->db_addr, &sq->tail, sizeof(sq->tail)); > > +pci_dma_write(pci, sq->db_addr, &v, sizeof(sq->tail)); > > This and similar cases hurts my eyes. > > Why we pass address of v here, but use sizeof(sq->tail) ? > > Yes, I know both in theory should be of the same size, but heck, > this is puzzling at best, and confusing in a regular case. > > Dunno how it slipped in the review, it instantly catched my eye > in a row of applied patches.. > > Also, why v is computed a few lines before it is used, with > some expressions between the assignment and usage? > > How about the following patch: If you're going to change this, better to take the approach Philippe suggested in review of using stl_le_pci_dma(). https://lore.kernel.org/qemu-devel/376e5e45-a3e7-0029-603a-b7ad9673f...@linaro.org/ thanks -- PMM