From 4ce1e15fbc7266a108a7c77a3962644b3935346e Mon Sep 17 00:00:00 2001 From: Christophe de Dinechin Date: Fri, 28 Feb 2020 16:00:59 +0100 Subject: scsi/qemu-pr-helper: Fix out-of-bounds access to trnptid_list[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compile error reported by gcc 10.0.1: scsi/qemu-pr-helper.c: In function ‘multipath_pr_out’: scsi/qemu-pr-helper.c:523:32: error: array subscript is outside array bounds of ‘struct transportid *[0]’ [-Werror=array-bounds] 523 | paramp.trnptid_list[paramp.num_transportid++] = id; | ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from scsi/qemu-pr-helper.c:36: /usr/include/mpath_persist.h:168:22: note: while referencing ‘trnptid_list’ 168 | struct transportid *trnptid_list[]; | ^~~~~~~~~~~~ scsi/qemu-pr-helper.c:424:35: note: defined here ‘paramp’ 424 | struct prout_param_descriptor paramp; | ^~~~~~ This highlights an actual implementation issue in function multipath_pr_out. The variable paramp is declared with type `struct prout_param_descriptor`, which is a struct terminated by an empty array in mpath_persist.h: struct transportid *trnptid_list[]; That empty array was filled with code that looked like that: trnptid_list[paramp.descr.num_transportid++] = id; This is an actual out-of-bounds access. The fix is to malloc `paramp`. Signed-off-by: Christophe de Dinechin Signed-off-by: Paolo Bonzini --- scsi/qemu-pr-helper.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c index 0659cee..181ed4a 100644 --- a/scsi/qemu-pr-helper.c +++ b/scsi/qemu-pr-helper.c @@ -421,10 +421,13 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense, int rq_servact = cdb[1]; int rq_scope = cdb[2] >> 4; int rq_type = cdb[2] & 0xf; - struct prout_param_descriptor paramp; + g_autofree struct prout_param_descriptor *paramp = NULL; char transportids[PR_HELPER_DATA_SIZE]; int r; + paramp = g_malloc0(sizeof(struct prout_param_descriptor) + + sizeof(struct transportid *) * MPATH_MX_TIDS); + if (sz < PR_OUT_FIXED_PARAM_SIZE) { /* Illegal request, Parameter list length error. This isn't fatal; * we have read the data, send an error without closing the socket. @@ -454,10 +457,9 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense, * used by libmpathpersist (which, of course, will immediately * do the opposite). */ - memset(¶mp, 0, sizeof(paramp)); - memcpy(¶mp.key, ¶m[0], 8); - memcpy(¶mp.sa_key, ¶m[8], 8); - paramp.sa_flags = param[20]; + memcpy(¶mp->key, ¶m[0], 8); + memcpy(¶mp->sa_key, ¶m[8], 8); + paramp->sa_flags = param[20]; if (sz > PR_OUT_FIXED_PARAM_SIZE) { size_t transportid_len; int i, j; @@ -520,12 +522,13 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense, return CHECK_CONDITION; } - paramp.trnptid_list[paramp.num_transportid++] = id; + assert(paramp->num_transportid < MPATH_MX_TIDS); + paramp->trnptid_list[paramp->num_transportid++] = id; } } r = mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type, - ¶mp, noisy, verbose); + paramp, noisy, verbose); return mpath_reconstruct_sense(fd, r, sense); } #endif -- cgit v1.1 From 770275ed0c0ab05677472efcf184b1a02ab14d07 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Tue, 3 Mar 2020 02:52:47 -0800 Subject: optionrom/pvh: scan entire RSDP Area Right now the PVH option rom scans for the RSDP from 0xE0000 to 0xE1FFF. This is probobly a typo, it should scan from 0xE0000 to 0xFFFFF. This is actually an issue on some QEMU versions/machines. For example, when I run QEMU the RSDP is placed at 0xf5ad0 which will not be picked up by the current implementation. This bug still allows a Linux guest to boot (in most configurations) as the kernel will just scan for the RSDP if one isn't provided. Signed-off-by: Joe Richey Reviewed-by: Stefano Garzarella Fixes: 2785dc7b17 ("optionrom: add new PVH option rom") Signed-off-by: Paolo Bonzini --- pc-bios/optionrom/pvh_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/optionrom/pvh_main.c b/pc-bios/optionrom/pvh_main.c index a015e1b..28e79d7 100644 --- a/pc-bios/optionrom/pvh_main.c +++ b/pc-bios/optionrom/pvh_main.c @@ -29,7 +29,7 @@ asm (".code32"); /* this code will be executed in protected mode */ #define RSDP_SIGNATURE 0x2052545020445352LL /* "RSD PTR " */ #define RSDP_AREA_ADDR 0x000E0000 -#define RSDP_AREA_SIZE 2048 +#define RSDP_AREA_SIZE 0x00020000 #define EBDA_BASE_ADDR 0x0000040E #define EBDA_SIZE 1024 -- cgit v1.1 From f7795e4096d8bd1c767c5ddb450fa859ff20490e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 4 Mar 2020 16:38:15 +0100 Subject: misc: Replace zero-length arrays with flexible array member (automatic) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description copied from Linux kernel commit from Gustavo A. R. Silva (see [3]): --v-- description start --v-- The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member [1], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being unadvertenly introduced [2] to the Linux codebase from now on. --^-- description end --^-- Do the similar housekeeping in the QEMU codebase (which uses C99 since commit 7be41675f7cb). All these instances of code were found with the help of the following Coccinelle script: @@ identifier s, m, a; type t, T; @@ struct s { ... t m; - T a[0]; + T a[]; }; @@ identifier s, m, a; type t, T; @@ struct s { ... t m; - T a[0]; + T a[]; } QEMU_PACKED; [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=76497732932f [3] https://git.kernel.org/pub/scm/linux/kernel/git/gustavoars/linux.git/commit/?id=17642a2fbd2c1 Inspired-by: Gustavo A. R. Silva Reviewed-by: David Hildenbrand Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- block/linux-aio.c | 2 +- bsd-user/qemu.h | 2 +- contrib/libvhost-user/libvhost-user.h | 2 +- hw/acpi/nvdimm.c | 6 +++--- hw/dma/soc_dma.c | 2 +- hw/i386/x86.c | 2 +- hw/m68k/bootinfo.h | 2 +- hw/misc/omap_l4.c | 2 +- hw/nvram/eeprom93xx.c | 2 +- hw/rdma/vmw/pvrdma_qp_ops.c | 4 ++-- hw/usb/dev-network.c | 2 +- hw/usb/dev-smartcard-reader.c | 4 ++-- hw/virtio/virtio.c | 4 ++-- hw/xen/xen_pt.h | 2 +- include/hw/acpi/acpi-defs.h | 12 ++++++------ include/hw/arm/smmu-common.h | 2 +- include/hw/i386/intel_iommu.h | 3 ++- include/hw/virtio/virtio-iommu.h | 2 +- include/sysemu/cryptodev.h | 2 +- include/tcg/tcg.h | 2 +- net/queue.c | 2 +- pc-bios/s390-ccw/bootmap.h | 2 +- pc-bios/s390-ccw/sclp.h | 2 +- tests/qtest/libqos/ahci.h | 2 +- 24 files changed, 35 insertions(+), 34 deletions(-) diff --git a/block/linux-aio.c b/block/linux-aio.c index 91204a2..3c0527c 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -121,7 +121,7 @@ struct aio_ring { unsigned incompat_features; unsigned header_length; /* size of aio_ring */ - struct io_event io_events[0]; + struct io_event io_events[]; }; /** diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index 09e8aed..f8bb1e5 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -95,7 +95,7 @@ typedef struct TaskState { struct sigqueue *first_free; /* first free siginfo queue entry */ int signal_pending; /* non zero if a signal may be pending */ - uint8_t stack[0]; + uint8_t stack[]; } __attribute__((aligned(16))) TaskState; void init_task_state(TaskState *ts); diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index 6fc8000..f30394f 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -286,7 +286,7 @@ typedef struct VuVirtqInflight { uint16_t used_idx; /* Used to track the state of each descriptor in descriptor table */ - VuDescStateSplit desc[0]; + VuDescStateSplit desc[]; } VuVirtqInflight; typedef struct VuVirtqInflightDesc { diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 5219dd0..eb6a37b 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -485,7 +485,7 @@ struct NvdimmFuncGetLabelDataOut { /* the size of buffer filled by QEMU. */ uint32_t len; uint32_t func_ret_status; /* return status code. */ - uint8_t out_buf[0]; /* the data got via Get Namesapce Label function. */ + uint8_t out_buf[]; /* the data got via Get Namesapce Label function. */ } QEMU_PACKED; typedef struct NvdimmFuncGetLabelDataOut NvdimmFuncGetLabelDataOut; QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataOut) > NVDIMM_DSM_MEMORY_SIZE); @@ -493,7 +493,7 @@ QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataOut) > NVDIMM_DSM_MEMORY_SIZE); struct NvdimmFuncSetLabelDataIn { uint32_t offset; /* the offset in the namespace label data area. */ uint32_t length; /* the size of data is to be written via the function. */ - uint8_t in_buf[0]; /* the data written to label data area. */ + uint8_t in_buf[]; /* the data written to label data area. */ } QEMU_PACKED; typedef struct NvdimmFuncSetLabelDataIn NvdimmFuncSetLabelDataIn; QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncSetLabelDataIn) + @@ -510,7 +510,7 @@ struct NvdimmFuncReadFITOut { /* the size of buffer filled by QEMU. */ uint32_t len; uint32_t func_ret_status; /* return status code. */ - uint8_t fit[0]; /* the FIT data. */ + uint8_t fit[]; /* the FIT data. */ } QEMU_PACKED; typedef struct NvdimmFuncReadFITOut NvdimmFuncReadFITOut; QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncReadFITOut) > NVDIMM_DSM_MEMORY_SIZE); diff --git a/hw/dma/soc_dma.c b/hw/dma/soc_dma.c index c3e4158..3a43005 100644 --- a/hw/dma/soc_dma.c +++ b/hw/dma/soc_dma.c @@ -80,7 +80,7 @@ struct dma_s { } *memmap; int memmap_size; - struct soc_dma_ch_s ch[0]; + struct soc_dma_ch_s ch[]; }; static void soc_dma_ch_schedule(struct soc_dma_ch_s *ch, int delay_bytes) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 7f38e6b..0824652 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -328,7 +328,7 @@ struct setup_data { uint64_t next; uint32_t type; uint32_t len; - uint8_t data[0]; + uint8_t data[]; } __attribute__((packed)); diff --git a/hw/m68k/bootinfo.h b/hw/m68k/bootinfo.h index 5f8ded2..c954270 100644 --- a/hw/m68k/bootinfo.h +++ b/hw/m68k/bootinfo.h @@ -14,7 +14,7 @@ struct bi_record { uint16_t tag; /* tag ID */ uint16_t size; /* size of record */ - uint32_t data[0]; /* data */ + uint32_t data[]; /* data */ }; /* machine independent tags */ diff --git a/hw/misc/omap_l4.c b/hw/misc/omap_l4.c index 61b6df5..54aeaec 100644 --- a/hw/misc/omap_l4.c +++ b/hw/misc/omap_l4.c @@ -24,7 +24,7 @@ struct omap_l4_s { MemoryRegion *address_space; hwaddr base; int ta_num; - struct omap_target_agent_s ta[0]; + struct omap_target_agent_s ta[]; }; struct omap_l4_s *omap_l4_init(MemoryRegion *address_space, diff --git a/hw/nvram/eeprom93xx.c b/hw/nvram/eeprom93xx.c index 07f0954..ca6f591 100644 --- a/hw/nvram/eeprom93xx.c +++ b/hw/nvram/eeprom93xx.c @@ -86,7 +86,7 @@ struct _eeprom_t { uint8_t addrbits; uint16_t size; uint16_t data; - uint16_t contents[0]; + uint16_t contents[]; }; /* Code for saving and restoring of EEPROM state. */ diff --git a/hw/rdma/vmw/pvrdma_qp_ops.c b/hw/rdma/vmw/pvrdma_qp_ops.c index bd6db85..8050287 100644 --- a/hw/rdma/vmw/pvrdma_qp_ops.c +++ b/hw/rdma/vmw/pvrdma_qp_ops.c @@ -34,13 +34,13 @@ typedef struct CompHandlerCtx { /* Send Queue WQE */ typedef struct PvrdmaSqWqe { struct pvrdma_sq_wqe_hdr hdr; - struct pvrdma_sge sge[0]; + struct pvrdma_sge sge[]; } PvrdmaSqWqe; /* Recv Queue WQE */ typedef struct PvrdmaRqWqe { struct pvrdma_rq_wqe_hdr hdr; - struct pvrdma_sge sge[0]; + struct pvrdma_sge sge[]; } PvrdmaRqWqe; /* diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 9a78ad9..6210427 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -626,7 +626,7 @@ static const uint32_t oid_supported_list[] = struct rndis_response { QTAILQ_ENTRY(rndis_response) entries; uint32_t length; - uint8_t buf[0]; + uint8_t buf[]; }; typedef struct USBNetState { diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 02693a2..ef72738 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -227,7 +227,7 @@ typedef struct QEMU_PACKED CCID_Parameter { typedef struct QEMU_PACKED CCID_DataBlock { CCID_BULK_IN b; uint8_t bChainParameter; - uint8_t abData[0]; + uint8_t abData[]; } CCID_DataBlock; /* 6.1.4 PC_to_RDR_XfrBlock */ @@ -235,7 +235,7 @@ typedef struct QEMU_PACKED CCID_XferBlock { CCID_Header hdr; uint8_t bBWI; /* Block Waiting Timeout */ uint16_t wLevelParameter; /* XXX currently unused */ - uint8_t abData[0]; + uint8_t abData[]; } CCID_XferBlock; typedef struct QEMU_PACKED CCID_IccPowerOn { diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index b2d415e..b6c8ef5 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -54,7 +54,7 @@ typedef struct VRingAvail { uint16_t flags; uint16_t idx; - uint16_t ring[0]; + uint16_t ring[]; } VRingAvail; typedef struct VRingUsedElem @@ -67,7 +67,7 @@ typedef struct VRingUsed { uint16_t flags; uint16_t idx; - VRingUsedElem ring[0]; + VRingUsedElem ring[]; } VRingUsed; typedef struct VRingMemoryRegionCaches { diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h index 9167bba..179775d 100644 --- a/hw/xen/xen_pt.h +++ b/hw/xen/xen_pt.h @@ -203,7 +203,7 @@ typedef struct XenPTMSIX { uint64_t mmio_base_addr; MemoryRegion mmio; void *phys_iomem_base; - XenPTMSIXEntry msix_entry[0]; + XenPTMSIXEntry msix_entry[]; } XenPTMSIX; struct XenPCIPassthroughState { diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 57a3f58..19f7ba7 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -518,7 +518,7 @@ struct AcpiDmarDeviceScope { struct { uint8_t device; uint8_t function; - } path[0]; + } path[]; } QEMU_PACKED; typedef struct AcpiDmarDeviceScope AcpiDmarDeviceScope; @@ -530,7 +530,7 @@ struct AcpiDmarHardwareUnit { uint8_t reserved; uint16_t pci_segment; /* The PCI Segment associated with this unit */ uint64_t address; /* Base address of remapping hardware register-set */ - AcpiDmarDeviceScope scope[0]; + AcpiDmarDeviceScope scope[]; } QEMU_PACKED; typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit; @@ -541,7 +541,7 @@ struct AcpiDmarRootPortATS { uint8_t flags; uint8_t reserved; uint16_t pci_segment; - AcpiDmarDeviceScope scope[0]; + AcpiDmarDeviceScope scope[]; } QEMU_PACKED; typedef struct AcpiDmarRootPortATS AcpiDmarRootPortATS; @@ -604,7 +604,7 @@ typedef struct AcpiIortMemoryAccess AcpiIortMemoryAccess; struct AcpiIortItsGroup { ACPI_IORT_NODE_HEADER_DEF uint32_t its_count; - uint32_t identifiers[0]; + uint32_t identifiers[]; } QEMU_PACKED; typedef struct AcpiIortItsGroup AcpiIortItsGroup; @@ -621,7 +621,7 @@ struct AcpiIortSmmu3 { uint32_t pri_gsiv; uint32_t gerr_gsiv; uint32_t sync_gsiv; - AcpiIortIdMapping id_mapping_array[0]; + AcpiIortIdMapping id_mapping_array[]; } QEMU_PACKED; typedef struct AcpiIortSmmu3 AcpiIortSmmu3; @@ -630,7 +630,7 @@ struct AcpiIortRC { AcpiIortMemoryAccess memory_properties; uint32_t ats_attribute; uint32_t pci_segment_number; - AcpiIortIdMapping id_mapping_array[0]; + AcpiIortIdMapping id_mapping_array[]; } QEMU_PACKED; typedef struct AcpiIortRC AcpiIortRC; diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 1f37844..ca4a4b1 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -85,7 +85,7 @@ typedef struct SMMUDevice { typedef struct SMMUPciBus { PCIBus *bus; - SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */ + SMMUDevice *pbdev[]; /* Parent array is sparse, so dynamically alloc */ } SMMUPciBus; typedef struct SMMUIOTLBKey { diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index a1c4afc..3870052 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -114,7 +114,8 @@ struct VTDAddressSpace { struct VTDBus { PCIBus* bus; /* A reference to the bus to provide translation for */ - VTDAddressSpace *dev_as[0]; /* A table of VTDAddressSpace objects indexed by devfn */ + /* A table of VTDAddressSpace objects indexed by devfn */ + VTDAddressSpace *dev_as[]; }; struct VTDIOTLBEntry { diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h index 6f67f10..e653004 100644 --- a/include/hw/virtio/virtio-iommu.h +++ b/include/hw/virtio/virtio-iommu.h @@ -41,7 +41,7 @@ typedef struct IOMMUDevice { typedef struct IOMMUPciBus { PCIBus *bus; - IOMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */ + IOMMUDevice *pbdev[]; /* Parent array is sparse, so dynamically alloc */ } IOMMUPciBus; typedef struct VirtIOIOMMU { diff --git a/include/sysemu/cryptodev.h b/include/sysemu/cryptodev.h index a9afb7e..35eab06 100644 --- a/include/sysemu/cryptodev.h +++ b/include/sysemu/cryptodev.h @@ -143,7 +143,7 @@ typedef struct CryptoDevBackendSymOpInfo { uint8_t *dst; uint8_t *aad_data; uint8_t *digest_result; - uint8_t data[0]; + uint8_t data[]; } CryptoDevBackendSymOpInfo; typedef struct CryptoDevBackendClass { diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 54e5446..c48bd76 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -267,7 +267,7 @@ struct TCGLabel { typedef struct TCGPool { struct TCGPool *next; int size; - uint8_t data[0] __attribute__ ((aligned)); + uint8_t data[] __attribute__ ((aligned)); } TCGPool; #define TCG_POOL_CHUNK_SIZE 32768 diff --git a/net/queue.c b/net/queue.c index 61276ca..0164727 100644 --- a/net/queue.c +++ b/net/queue.c @@ -46,7 +46,7 @@ struct NetPacket { unsigned flags; int size; NetPacketSent *sent_cb; - uint8_t data[0]; + uint8_t data[]; }; struct NetQueue { diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h index 94f53a5..12a0166 100644 --- a/pc-bios/s390-ccw/bootmap.h +++ b/pc-bios/s390-ccw/bootmap.h @@ -136,7 +136,7 @@ typedef struct BootMapScriptHeader { typedef struct BootMapScript { BootMapScriptHeader header; - BootMapScriptEntry entry[0]; + BootMapScriptEntry entry[]; } __attribute__ ((packed)) BootMapScript; /* diff --git a/pc-bios/s390-ccw/sclp.h b/pc-bios/s390-ccw/sclp.h index 8450161..64b53ca 100644 --- a/pc-bios/s390-ccw/sclp.h +++ b/pc-bios/s390-ccw/sclp.h @@ -95,7 +95,7 @@ typedef struct EventBufferHeader { typedef struct WriteEventData { SCCBHeader h; EventBufferHeader ebh; - char data[0]; + char data[]; } __attribute__((packed)) WriteEventData; typedef struct ReadEventData { diff --git a/tests/qtest/libqos/ahci.h b/tests/qtest/libqos/ahci.h index f05b3e5..44ab110 100644 --- a/tests/qtest/libqos/ahci.h +++ b/tests/qtest/libqos/ahci.h @@ -351,7 +351,7 @@ typedef struct AHCIQState { typedef struct FIS { uint8_t fis_type; uint8_t flags; - char data[0]; + char data[]; } __attribute__((__packed__)) FIS; /** -- cgit v1.1 From 880a7817c1a82a93d3f83dfb25dce1f0db629c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 4 Mar 2020 16:38:16 +0100 Subject: misc: Replace zero-length arrays with flexible array member (manual) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description copied from Linux kernel commit from Gustavo A. R. Silva (see [3]): --v-- description start --v-- The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member [1], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being unadvertenly introduced [2] to the Linux codebase from now on. --^-- description end --^-- Do the similar housekeeping in the QEMU codebase (which uses C99 since commit 7be41675f7cb). All these instances of code were found with the help of the following command (then manual analysis, without modifying structures only having a single flexible array member, such QEDTable in block/qed.h): git grep -F '[0];' [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=76497732932f [3] https://git.kernel.org/pub/scm/linux/kernel/git/gustavoars/linux.git/commit/?id=17642a2fbd2c1 Inspired-by: Gustavo A. R. Silva Reviewed-by: David Hildenbrand Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- block/vmdk.c | 2 +- docs/interop/vhost-user.rst | 4 ++-- hw/char/sclpconsole-lm.c | 2 +- hw/char/sclpconsole.c | 2 +- hw/s390x/virtio-ccw.c | 2 +- include/hw/acpi/acpi-defs.h | 4 ++-- include/hw/boards.h | 2 +- include/hw/s390x/event-facility.h | 2 +- include/hw/s390x/sclp.h | 8 ++++---- target/s390x/ioinst.c | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 20e909d..8466051 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -187,7 +187,7 @@ typedef struct VmdkMetaData { typedef struct VmdkGrainMarker { uint64_t lba; uint32_t size; - uint8_t data[0]; + uint8_t data[]; } QEMU_PACKED VmdkGrainMarker; enum { diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst index 4016523..3b1b660 100644 --- a/docs/interop/vhost-user.rst +++ b/docs/interop/vhost-user.rst @@ -568,7 +568,7 @@ For split virtqueue, queue region can be implemented as: uint16_t used_idx; /* Used to track the state of each descriptor in descriptor table */ - DescStateSplit desc[0]; + DescStateSplit desc[]; } QueueRegionSplit; To track inflight I/O, the queue region should be processed as follows: @@ -690,7 +690,7 @@ For packed virtqueue, queue region can be implemented as: uint8_t padding[7]; /* Used to track the state of each descriptor fetched from descriptor ring */ - DescStatePacked desc[0]; + DescStatePacked desc[]; } QueueRegionPacked; To track inflight I/O, the queue region should be processed as follows: diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index c420dc0..2b5f37b 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -31,7 +31,7 @@ typedef struct OprtnsCommand { EventBufferHeader header; MDMSU message_unit; - char data[0]; + char data[]; } QEMU_PACKED OprtnsCommand; /* max size for line-mode data in 4K SCCB page */ diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index 1fa124d..5c76649 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -25,7 +25,7 @@ typedef struct ASCIIConsoleData { EventBufferHeader ebh; - char data[0]; + char data[]; } QEMU_PACKED ASCIIConsoleData; /* max size for ASCII data in 4K SCCB page */ diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 50cf95b..64f928f 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -193,7 +193,7 @@ typedef struct VirtioThinintInfo { typedef struct VirtioRevInfo { uint16_t revision; uint16_t length; - uint8_t data[0]; + uint8_t data[]; } QEMU_PACKED VirtioRevInfo; /* Specify where the virtqueues for the subchannel are in guest memory. */ diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 19f7ba7..c13327f 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -152,7 +152,7 @@ typedef struct AcpiSerialPortConsoleRedirection */ struct AcpiRsdtDescriptorRev1 { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - uint32_t table_offset_entry[0]; /* Array of pointers to other */ + uint32_t table_offset_entry[]; /* Array of pointers to other */ /* ACPI tables */ } QEMU_PACKED; typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1; @@ -162,7 +162,7 @@ typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1; */ struct AcpiXsdtDescriptorRev2 { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - uint64_t table_offset_entry[0]; /* Array of pointers to other */ + uint64_t table_offset_entry[]; /* Array of pointers to other */ /* ACPI tables */ } QEMU_PACKED; typedef struct AcpiXsdtDescriptorRev2 AcpiXsdtDescriptorRev2; diff --git a/include/hw/boards.h b/include/hw/boards.h index 9bc42df..c96120d 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -71,7 +71,7 @@ typedef struct CPUArchId { */ typedef struct { int len; - CPUArchId cpus[0]; + CPUArchId cpus[]; } CPUArchIdList; /** diff --git a/include/hw/s390x/event-facility.h b/include/hw/s390x/event-facility.h index bdc32a3..700a610 100644 --- a/include/hw/s390x/event-facility.h +++ b/include/hw/s390x/event-facility.h @@ -122,7 +122,7 @@ typedef struct MDBO { typedef struct MDB { MdbHeader header; - MDBO mdbo[0]; + MDBO mdbo[]; } QEMU_PACKED MDB; typedef struct SclpMsg { diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h index c54413b..cd7b243 100644 --- a/include/hw/s390x/sclp.h +++ b/include/hw/s390x/sclp.h @@ -132,7 +132,7 @@ typedef struct ReadInfo { uint16_t highest_cpu; uint8_t _reserved5[124 - 122]; /* 122-123 */ uint32_t hmfai; - struct CPUEntry entries[0]; + struct CPUEntry entries[]; } QEMU_PACKED ReadInfo; typedef struct ReadCpuInfo { @@ -142,7 +142,7 @@ typedef struct ReadCpuInfo { uint16_t nr_standby; /* 12-13 */ uint16_t offset_standby; /* 14-15 */ uint8_t reserved0[24-16]; /* 16-23 */ - struct CPUEntry entries[0]; + struct CPUEntry entries[]; } QEMU_PACKED ReadCpuInfo; typedef struct ReadStorageElementInfo { @@ -151,7 +151,7 @@ typedef struct ReadStorageElementInfo { uint16_t assigned; uint16_t standby; uint8_t _reserved0[16 - 14]; /* 14-15 */ - uint32_t entries[0]; + uint32_t entries[]; } QEMU_PACKED ReadStorageElementInfo; typedef struct AttachStorageElement { @@ -159,7 +159,7 @@ typedef struct AttachStorageElement { uint8_t _reserved0[10 - 8]; /* 8-9 */ uint16_t assigned; uint8_t _reserved1[16 - 12]; /* 12-15 */ - uint32_t entries[0]; + uint32_t entries[]; } QEMU_PACKED AttachStorageElement; typedef struct AssignStorage { diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c index c437a1d..0e840cc 100644 --- a/target/s390x/ioinst.c +++ b/target/s390x/ioinst.c @@ -347,7 +347,7 @@ typedef struct ChscResp { uint16_t len; uint16_t code; uint32_t param; - char data[0]; + char data[]; } QEMU_PACKED ChscResp; #define CHSC_MIN_RESP_LEN 0x0008 -- cgit v1.1 From 6b8cd447efdad1d8bb637904e5077900d063e05d Mon Sep 17 00:00:00 2001 From: Robert Hoo Date: Sat, 29 Feb 2020 20:34:34 +0800 Subject: configure: add configure option avx512f_opt If it is enabled, config-host.mak will have CONFIG_AVX512F_OPT defined. AVX512F instruction set is available since Intel Skylake, and can be enabled in compiling with -mavx512f. More info: https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf Signed-off-by: Robert Hoo Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- configure | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/configure b/configure index eb49bb6..1a82683 100755 --- a/configure +++ b/configure @@ -1421,6 +1421,11 @@ for opt do ;; --enable-avx2) avx2_opt="yes" ;; + --disable-avx512f) avx512f_opt="no" + ;; + --enable-avx512f) avx512f_opt="yes" + ;; + --enable-glusterfs) glusterfs="yes" ;; --disable-virtio-blk-data-plane|--enable-virtio-blk-data-plane) @@ -1857,6 +1862,7 @@ disabled with --disable-FEATURE, default is enabled if available: tcmalloc tcmalloc support jemalloc jemalloc support avx2 AVX2 optimization support + avx512f AVX512F optimization support replication replication support opengl opengl support virglrenderer virgl rendering support @@ -5574,6 +5580,36 @@ EOF fi fi +########################################## +# avx512f optimization requirement check +# +# There is no point enabling this if cpuid.h is not usable, +# since we won't be able to select the new routines. +# by default, it is turned off. +# if user explicitly want to enable it, check environment + +if test "$cpuid_h" = "yes" && test "$avx512f_opt" = "yes"; then + cat > $TMPC << EOF +#pragma GCC push_options +#pragma GCC target("avx512f") +#include +#include +static int bar(void *a) { + __m512i x = *(__m512i *)a; + return _mm512_test_epi64_mask(x, x); +} +int main(int argc, char *argv[]) +{ + return bar(argv[0]); +} +EOF + if ! compile_object "" ; then + avx512f_opt="no" + fi +else + avx512f_opt="no" +fi + ######################################## # check if __[u]int128_t is usable. @@ -6717,6 +6753,7 @@ echo "libxml2 $libxml2" echo "tcmalloc support $tcmalloc" echo "jemalloc support $jemalloc" echo "avx2 optimization $avx2_opt" +echo "avx512f optimization $avx512f_opt" echo "replication support $replication" echo "VxHS block device $vxhs" echo "bochs support $bochs" @@ -7268,6 +7305,10 @@ if test "$avx2_opt" = "yes" ; then echo "CONFIG_AVX2_OPT=y" >> $config_host_mak fi +if test "$avx512f_opt" = "yes" ; then + echo "CONFIG_AVX512F_OPT=y" >> $config_host_mak +fi + if test "$lzo" = "yes" ; then echo "CONFIG_LZO=y" >> $config_host_mak fi -- cgit v1.1 From 27f08ea1c7abf04125f6f9f23b8ba2f8c20e95b6 Mon Sep 17 00:00:00 2001 From: Robert Hoo Date: Sat, 29 Feb 2020 20:34:35 +0800 Subject: util: add util function buffer_zero_avx512() And intialize buffer_is_zero() with it, when Intel AVX512F is available on host. This function utilizes Intel AVX512 fundamental instructions which is faster than its implementation with AVX2 (in my unit test, with 4K buffer, on CascadeLake SP, ~36% faster, buffer_zero_avx512() V.S. buffer_zero_avx2()). Signed-off-by: Robert Hoo Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- include/qemu/cpuid.h | 3 +++ util/bufferiszero.c | 71 ++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/include/qemu/cpuid.h b/include/qemu/cpuid.h index 6930170..09fc245 100644 --- a/include/qemu/cpuid.h +++ b/include/qemu/cpuid.h @@ -45,6 +45,9 @@ #ifndef bit_AVX2 #define bit_AVX2 (1 << 5) #endif +#ifndef bit_AVX512F +#define bit_AVX512F (1 << 16) +#endif #ifndef bit_BMI2 #define bit_BMI2 (1 << 8) #endif diff --git a/util/bufferiszero.c b/util/bufferiszero.c index bfb2605..6639035 100644 --- a/util/bufferiszero.c +++ b/util/bufferiszero.c @@ -63,11 +63,11 @@ buffer_zero_int(const void *buf, size_t len) } } -#if defined(CONFIG_AVX2_OPT) || defined(__SSE2__) +#if defined(CONFIG_AVX512F_OPT) || defined(CONFIG_AVX2_OPT) || defined(__SSE2__) /* Do not use push_options pragmas unnecessarily, because clang * does not support them. */ -#ifdef CONFIG_AVX2_OPT +#if defined(CONFIG_AVX512F_OPT) || defined(CONFIG_AVX2_OPT) #pragma GCC push_options #pragma GCC target("sse2") #endif @@ -104,7 +104,7 @@ buffer_zero_sse2(const void *buf, size_t len) return _mm_movemask_epi8(_mm_cmpeq_epi8(t, zero)) == 0xFFFF; } -#ifdef CONFIG_AVX2_OPT +#if defined(CONFIG_AVX512F_OPT) || defined(CONFIG_AVX2_OPT) #pragma GCC pop_options #endif @@ -187,18 +187,54 @@ buffer_zero_avx2(const void *buf, size_t len) #pragma GCC pop_options #endif /* CONFIG_AVX2_OPT */ +#ifdef CONFIG_AVX512F_OPT +#pragma GCC push_options +#pragma GCC target("avx512f") +#include + +static bool +buffer_zero_avx512(const void *buf, size_t len) +{ + /* Begin with an unaligned head of 64 bytes. */ + __m512i t = _mm512_loadu_si512(buf); + __m512i *p = (__m512i *)(((uintptr_t)buf + 5 * 64) & -64); + __m512i *e = (__m512i *)(((uintptr_t)buf + len) & -64); + + /* Loop over 64-byte aligned blocks of 256. */ + while (p <= e) { + __builtin_prefetch(p); + if (unlikely(_mm512_test_epi64_mask(t, t))) { + return false; + } + t = p[-4] | p[-3] | p[-2] | p[-1]; + p += 4; + } + + t |= _mm512_loadu_si512(buf + len - 4 * 64); + t |= _mm512_loadu_si512(buf + len - 3 * 64); + t |= _mm512_loadu_si512(buf + len - 2 * 64); + t |= _mm512_loadu_si512(buf + len - 1 * 64); + + return !_mm512_test_epi64_mask(t, t); + +} +#pragma GCC pop_options +#endif + + /* Note that for test_buffer_is_zero_next_accel, the most preferred * ISA must have the least significant bit. */ -#define CACHE_AVX2 1 -#define CACHE_SSE4 2 -#define CACHE_SSE2 4 +#define CACHE_AVX512F 1 +#define CACHE_AVX2 2 +#define CACHE_SSE4 4 +#define CACHE_SSE2 8 /* Make sure that these variables are appropriately initialized when * SSE2 is enabled on the compiler command-line, but the compiler is * too old to support CONFIG_AVX2_OPT. */ -#ifdef CONFIG_AVX2_OPT +#if defined(CONFIG_AVX512F_OPT) || defined(CONFIG_AVX2_OPT) # define INIT_CACHE 0 # define INIT_ACCEL buffer_zero_int #else @@ -211,6 +247,7 @@ buffer_zero_avx2(const void *buf, size_t len) static unsigned cpuid_cache = INIT_CACHE; static bool (*buffer_accel)(const void *, size_t) = INIT_ACCEL; +static int length_to_accel = 64; static void init_accel(unsigned cache) { @@ -226,10 +263,16 @@ static void init_accel(unsigned cache) fn = buffer_zero_avx2; } #endif +#ifdef CONFIG_AVX512F_OPT + if (cache & CACHE_AVX512F) { + fn = buffer_zero_avx512; + length_to_accel = 256; + } +#endif buffer_accel = fn; } -#ifdef CONFIG_AVX2_OPT +#if defined(CONFIG_AVX512F_OPT) || defined(CONFIG_AVX2_OPT) #include "qemu/cpuid.h" static void __attribute__((constructor)) init_cpuid_cache(void) @@ -252,9 +295,17 @@ static void __attribute__((constructor)) init_cpuid_cache(void) int bv; __asm("xgetbv" : "=a"(bv), "=d"(d) : "c"(0)); __cpuid_count(7, 0, a, b, c, d); - if ((bv & 6) == 6 && (b & bit_AVX2)) { + if ((bv & 0x6) == 0x6 && (b & bit_AVX2)) { cache |= CACHE_AVX2; } + /* 0xe6: + * XCR0[7:5] = 111b (OPMASK state, upper 256-bit of ZMM0-ZMM15 + * and ZMM16-ZMM31 state are enabled by OS) + * XCR0[2:1] = 11b (XMM state and YMM state are enabled by OS) + */ + if ((bv & 0xe6) == 0xe6 && (b & bit_AVX512F)) { + cache |= CACHE_AVX512F; + } } } cpuid_cache = cache; @@ -277,7 +328,7 @@ bool test_buffer_is_zero_next_accel(void) static bool select_accel_fn(const void *buf, size_t len) { - if (likely(len >= 64)) { + if (likely(len >= length_to_accel)) { return buffer_accel(buf, len); } return buffer_zero_int(buf, len); -- cgit v1.1 From 6785e767017a3fcc39e245b7bca2c383b8bf39ef Mon Sep 17 00:00:00 2001 From: Sunil Muthuswamy Date: Wed, 26 Feb 2020 20:54:39 +0000 Subject: WHPX: TSC get and set should be dependent on VM state Currently, TSC is set as part of the VM runtime state. Setting TSC at runtime is heavy and additionally can have side effects on the guest, which are not very resilient to variances in the TSC. This patch uses the VM state to determine whether to set TSC or not. Some minor enhancements for getting TSC values as well that considers the VM state. Additionally, while setting the TSC, the partition is suspended to reduce the variance in the TSC value across vCPUs. Signed-off-by: Sunil Muthuswamy Message-Id: Signed-off-by: Paolo Bonzini --- include/sysemu/whpx.h | 7 +++ target/i386/whp-dispatch.h | 9 ++++ target/i386/whpx-all.c | 103 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 110 insertions(+), 9 deletions(-) diff --git a/include/sysemu/whpx.h b/include/sysemu/whpx.h index 4794e8e..a84b49e 100644 --- a/include/sysemu/whpx.h +++ b/include/sysemu/whpx.h @@ -35,4 +35,11 @@ int whpx_enabled(void); #endif /* CONFIG_WHPX */ +/* state subset only touched by the VCPU itself during runtime */ +#define WHPX_SET_RUNTIME_STATE 1 +/* state subset modified during VCPU reset */ +#define WHPX_SET_RESET_STATE 2 +/* full state set, modified during initialization or on vmload */ +#define WHPX_SET_FULL_STATE 3 + #endif /* QEMU_WHPX_H */ diff --git a/target/i386/whp-dispatch.h b/target/i386/whp-dispatch.h index 87d049c..e4695c3 100644 --- a/target/i386/whp-dispatch.h +++ b/target/i386/whp-dispatch.h @@ -23,6 +23,12 @@ X(HRESULT, WHvGetVirtualProcessorRegisters, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, const WHV_REGISTER_NAME* RegisterNames, UINT32 RegisterCount, WHV_REGISTER_VALUE* RegisterValues)) \ X(HRESULT, WHvSetVirtualProcessorRegisters, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, const WHV_REGISTER_NAME* RegisterNames, UINT32 RegisterCount, const WHV_REGISTER_VALUE* RegisterValues)) \ +/* + * These are supplemental functions that may not be present + * on all versions and are not critical for basic functionality. + */ +#define LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(X) \ + X(HRESULT, WHvSuspendPartitionTime, (WHV_PARTITION_HANDLE Partition)) \ #define LIST_WINHVEMULATION_FUNCTIONS(X) \ X(HRESULT, WHvEmulatorCreateEmulator, (const WHV_EMULATOR_CALLBACKS* Callbacks, WHV_EMULATOR_HANDLE* Emulator)) \ @@ -40,10 +46,12 @@ /* Define function typedef */ LIST_WINHVPLATFORM_FUNCTIONS(WHP_DEFINE_TYPE) LIST_WINHVEMULATION_FUNCTIONS(WHP_DEFINE_TYPE) +LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_DEFINE_TYPE) struct WHPDispatch { LIST_WINHVPLATFORM_FUNCTIONS(WHP_DECLARE_MEMBER) LIST_WINHVEMULATION_FUNCTIONS(WHP_DECLARE_MEMBER) + LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_DECLARE_MEMBER) }; extern struct WHPDispatch whp_dispatch; @@ -53,6 +61,7 @@ bool init_whp_dispatch(void); typedef enum WHPFunctionList { WINHV_PLATFORM_FNS_DEFAULT, WINHV_EMULATION_FNS_DEFAULT, + WINHV_PLATFORM_FNS_SUPPLEMENTAL } WHPFunctionList; #endif /* WHP_DISPATCH_H */ diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index 683d49d..b947eb1 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -114,7 +114,6 @@ static const WHV_REGISTER_NAME whpx_register_names[] = { WHvX64RegisterXmmControlStatus, /* X64 MSRs */ - WHvX64RegisterTsc, WHvX64RegisterEfer, #ifdef TARGET_X86_64 WHvX64RegisterKernelGsBase, @@ -215,7 +214,44 @@ static SegmentCache whpx_seg_h2q(const WHV_X64_SEGMENT_REGISTER *hs) return qs; } -static void whpx_set_registers(CPUState *cpu) +static int whpx_set_tsc(CPUState *cpu) +{ + struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr); + WHV_REGISTER_NAME tsc_reg = WHvX64RegisterTsc; + WHV_REGISTER_VALUE tsc_val; + HRESULT hr; + struct whpx_state *whpx = &whpx_global; + + /* + * Suspend the partition prior to setting the TSC to reduce the variance + * in TSC across vCPUs. When the first vCPU runs post suspend, the + * partition is automatically resumed. + */ + if (whp_dispatch.WHvSuspendPartitionTime) { + + /* + * Unable to suspend partition while setting TSC is not a fatal + * error. It just increases the likelihood of TSC variance between + * vCPUs and some guest OS are able to handle that just fine. + */ + hr = whp_dispatch.WHvSuspendPartitionTime(whpx->partition); + if (FAILED(hr)) { + warn_report("WHPX: Failed to suspend partition, hr=%08lx", hr); + } + } + + tsc_val.Reg64 = env->tsc; + hr = whp_dispatch.WHvSetVirtualProcessorRegisters( + whpx->partition, cpu->cpu_index, &tsc_reg, 1, &tsc_val); + if (FAILED(hr)) { + error_report("WHPX: Failed to set TSC, hr=%08lx", hr); + return -1; + } + + return 0; +} + +static void whpx_set_registers(CPUState *cpu, int level) { struct whpx_state *whpx = &whpx_global; struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu); @@ -230,6 +266,14 @@ static void whpx_set_registers(CPUState *cpu) assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + /* + * Following MSRs have side effects on the guest or are too heavy for + * runtime. Limit them to full state update. + */ + if (level >= WHPX_SET_RESET_STATE) { + whpx_set_tsc(cpu); + } + memset(&vcxt, 0, sizeof(struct whpx_register_set)); v86 = (env->eflags & VM_MASK); @@ -330,8 +374,6 @@ static void whpx_set_registers(CPUState *cpu) idx += 1; /* MSRs */ - assert(whpx_register_names[idx] == WHvX64RegisterTsc); - vcxt.values[idx++].Reg64 = env->tsc; assert(whpx_register_names[idx] == WHvX64RegisterEfer); vcxt.values[idx++].Reg64 = env->efer; #ifdef TARGET_X86_64 @@ -379,6 +421,25 @@ static void whpx_set_registers(CPUState *cpu) return; } +static int whpx_get_tsc(CPUState *cpu) +{ + struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr); + WHV_REGISTER_NAME tsc_reg = WHvX64RegisterTsc; + WHV_REGISTER_VALUE tsc_val; + HRESULT hr; + struct whpx_state *whpx = &whpx_global; + + hr = whp_dispatch.WHvGetVirtualProcessorRegisters( + whpx->partition, cpu->cpu_index, &tsc_reg, 1, &tsc_val); + if (FAILED(hr)) { + error_report("WHPX: Failed to get TSC, hr=%08lx", hr); + return -1; + } + + env->tsc = tsc_val.Reg64; + return 0; +} + static void whpx_get_registers(CPUState *cpu) { struct whpx_state *whpx = &whpx_global; @@ -394,6 +455,11 @@ static void whpx_get_registers(CPUState *cpu) assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + if (!env->tsc_valid) { + whpx_get_tsc(cpu); + env->tsc_valid = !runstate_is_running(); + } + hr = whp_dispatch.WHvGetVirtualProcessorRegisters( whpx->partition, cpu->cpu_index, whpx_register_names, @@ -492,8 +558,6 @@ static void whpx_get_registers(CPUState *cpu) idx += 1; /* MSRs */ - assert(whpx_register_names[idx] == WHvX64RegisterTsc); - env->tsc = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterEfer); env->efer = vcxt.values[idx++].Reg64; #ifdef TARGET_X86_64 @@ -896,7 +960,7 @@ static int whpx_vcpu_run(CPUState *cpu) do { if (cpu->vcpu_dirty) { - whpx_set_registers(cpu); + whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE); cpu->vcpu_dirty = false; } @@ -1074,14 +1138,14 @@ static void do_whpx_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) static void do_whpx_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) { - whpx_set_registers(cpu); + whpx_set_registers(cpu, WHPX_SET_RESET_STATE); cpu->vcpu_dirty = false; } static void do_whpx_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) { - whpx_set_registers(cpu); + whpx_set_registers(cpu, WHPX_SET_FULL_STATE); cpu->vcpu_dirty = false; } @@ -1123,6 +1187,15 @@ void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu) static Error *whpx_migration_blocker; +static void whpx_cpu_update_state(void *opaque, int running, RunState state) +{ + CPUX86State *env = opaque; + + if (running) { + env->tsc_valid = false; + } +} + int whpx_init_vcpu(CPUState *cpu) { HRESULT hr; @@ -1178,6 +1251,7 @@ int whpx_init_vcpu(CPUState *cpu) cpu->vcpu_dirty = true; cpu->hax_vcpu = (struct hax_vcpu_state *)vcpu; + qemu_add_vm_change_state_handler(whpx_cpu_update_state, cpu->env_ptr); return 0; } @@ -1367,6 +1441,10 @@ static bool load_whp_dispatch_fns(HMODULE *handle, #define WINHV_PLATFORM_DLL "WinHvPlatform.dll" #define WINHV_EMULATION_DLL "WinHvEmulation.dll" + #define WHP_LOAD_FIELD_OPTIONAL(return_type, function_name, signature) \ + whp_dispatch.function_name = \ + (function_name ## _t)GetProcAddress(hLib, #function_name); \ + #define WHP_LOAD_FIELD(return_type, function_name, signature) \ whp_dispatch.function_name = \ (function_name ## _t)GetProcAddress(hLib, #function_name); \ @@ -1394,6 +1472,11 @@ static bool load_whp_dispatch_fns(HMODULE *handle, WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib) LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD) break; + + case WINHV_PLATFORM_FNS_SUPPLEMENTAL: + WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib) + LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_LOAD_FIELD_OPTIONAL) + break; } *handle = hLib; @@ -1554,6 +1637,8 @@ bool init_whp_dispatch(void) goto error; } + assert(load_whp_dispatch_fns(&hWinHvPlatform, + WINHV_PLATFORM_FNS_SUPPLEMENTAL)); whp_dispatch_initialized = true; return true; -- cgit v1.1 From dadf3011c85d5cb165e3cc4434df187ed3d294dd Mon Sep 17 00:00:00 2001 From: Sunil Muthuswamy Date: Thu, 27 Feb 2020 21:01:04 +0000 Subject: WHPX: Use QEMU values for trapped CPUID Currently, WHPX is using some default values for the trapped CPUID functions. These were not in sync with the QEMU values because the CPUID values were never set with WHPX during VCPU initialization. Additionally, at the moment, WHPX doesn't support setting CPUID values in the hypervisor at runtime (i.e. after the partition has been setup). That is needed to be able to set the CPUID values in the hypervisor during VCPU init. Until that support comes, use the QEMU values for the trapped CPUIDs. Signed-off-by: Sunil Muthuswamy Message-Id: Signed-off-by: Paolo Bonzini --- target/i386/whpx-all.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index b947eb1..cb863b7 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -1044,38 +1044,32 @@ static int whpx_vcpu_run(CPUState *cpu) WHV_REGISTER_VALUE reg_values[5]; WHV_REGISTER_NAME reg_names[5]; UINT32 reg_count = 5; - UINT64 rip, rax, rcx, rdx, rbx; + UINT64 cpuid_fn, rip = 0, rax = 0, rcx = 0, rdx = 0, rbx = 0; + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; memset(reg_values, 0, sizeof(reg_values)); rip = vcpu->exit_ctx.VpContext.Rip + vcpu->exit_ctx.VpContext.InstructionLength; - switch (vcpu->exit_ctx.CpuidAccess.Rax) { - case 1: - rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax; - /* Advertise that we are running on a hypervisor */ - rcx = - vcpu->exit_ctx.CpuidAccess.DefaultResultRcx | - CPUID_EXT_HYPERVISOR; - - rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx; - rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx; - break; + cpuid_fn = vcpu->exit_ctx.CpuidAccess.Rax; + + /* + * Ideally, these should be supplied to the hypervisor during VCPU + * initialization and it should be able to satisfy this request. + * But, currently, WHPX doesn't support setting CPUID values in the + * hypervisor once the partition has been setup, which is too late + * since VCPUs are realized later. For now, use the values from + * QEMU to satisfy these requests, until WHPX adds support for + * being able to set these values in the hypervisor at runtime. + */ + cpu_x86_cpuid(env, cpuid_fn, 0, (UINT32 *)&rax, (UINT32 *)&rbx, + (UINT32 *)&rcx, (UINT32 *)&rdx); + switch (cpuid_fn) { case 0x80000001: - rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax; /* Remove any support of OSVW */ - rcx = - vcpu->exit_ctx.CpuidAccess.DefaultResultRcx & - ~CPUID_EXT3_OSVW; - - rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx; - rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx; + rcx &= ~CPUID_EXT3_OSVW; break; - default: - rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax; - rcx = vcpu->exit_ctx.CpuidAccess.DefaultResultRcx; - rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx; - rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx; } reg_names[0] = WHvX64RegisterRip; -- cgit v1.1 From 6c94b95274b7a602243f8ab5a9c3e54d4f5acc6b Mon Sep 17 00:00:00 2001 From: Colin Xu Date: Fri, 28 Feb 2020 09:20:46 +0800 Subject: MAINTAINERS: Add entry for Guest X86 HAXM CPUs HAXM covers below files: include/sysemu/hax.h target/i386/hax-* V2: Add HAXM github page for wiki and issue tracking. Cc: Wenchao Wang Cc: Hang Yuan Reviewed-by: Hang Yuan Signed-off-by: Colin Xu Message-Id: <20200228012046.6629-1-colin.xu@intel.com> Signed-off-by: Paolo Bonzini --- MAINTAINERS | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 32867bc..a88bc28 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -436,6 +436,17 @@ F: include/hw/block/dataplane/xen* F: include/hw/xen/ F: include/sysemu/xen-mapcache.h +Guest CPU Cores (HAXM) +--------------------- +X86 HAXM CPUs +M: Wenchao Wang +M: Colin Xu +L: haxm-team@intel.com +W: https://github.com/intel/haxm/issues +S: Maintained +F: include/sysemu/hax.h +F: target/i386/hax-* + Hosts ----- LINUX -- cgit v1.1 From 3c507c26ecda8f072c80338592d7894543448fe4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 10 Mar 2020 18:42:11 +0100 Subject: hw/i386/intel_iommu: Fix out-of-bounds access on guest IRT vtd_irte_get failed to check the index against the configured table size, causing an out-of-bounds access on guest memory and potentially misinterpreting the result. Signed-off-by: Jan Kiszka Message-Id: <4b15b728-bdfe-3bbe-3a5c-ca3baeef3c5c@siemens.com> Signed-off-by: Paolo Bonzini --- hw/i386/intel_iommu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 204b684..df7ad25 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -3094,6 +3094,12 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index, uint16_t mask, source_id; uint8_t bus, bus_max, bus_min; + if (index >= iommu->intr_size) { + error_report_once("%s: index too large: ind=0x%x", + __func__, index); + return -VTD_FR_IR_INDEX_OVER; + } + addr = iommu->intr_root + index * sizeof(*entry); if (dma_memory_read(&address_space_memory, addr, entry, sizeof(*entry))) { -- cgit v1.1 From 78b3f67acdf0f646d35ebdf98b9e91fb04ab9a07 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 10 Mar 2020 18:58:30 +0100 Subject: oslib-posix: initialize mutex and condition variable The mutex and condition variable were never initialized, causing -mem-prealloc to abort with an assertion failure. Fixes: 037fb5eb3941c80a2b7c36a843e47207ddb004d4 Reported-by: Marc Hartmayer Cc: bauerchen Signed-off-by: Paolo Bonzini --- util/oslib-posix.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 897e8f3..4dd6d7d 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -466,10 +466,17 @@ static inline int get_memset_num_threads(int smp_cpus) static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, int smp_cpus) { + static gsize initialized = 0; size_t numpages_per_thread, leftover; char *addr = area; int i = 0; + if (g_once_init_enter(&initialized)) { + qemu_mutex_init(&page_mutex); + qemu_cond_init(&page_cond); + g_once_init_leave(&initialized, 1); + } + memset_thread_failed = false; threads_created_flag = false; memset_num_threads = get_memset_num_threads(smp_cpus); -- cgit v1.1 From 5b42bc5ce9ab4a3171819feea5042931817211fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 11 Mar 2020 17:09:23 +0100 Subject: build-sys: do not make qemu-ga link with pixman MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit d52c454aadcdae74506f315ebf8b58bb79a05573 ("contrib: add vhost-user-gpu"), qemu-ga is linking with pixman. This is because the Make-based build-system use a global namespace for variables, and we rely on "main.o-libs" for different linking targets. Note: this kind of variable clashing is hard to fix or prevent currently. meson should help, as declarations have a linear dependency and doesn't rely so much on variables and clever tricks. Note2: we have a lot of main.c (or other duplicated names!) in tree. Imho, it would be annoying and a bad workaroud to rename all those to avoid conflicts like I did here. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1811670 Signed-off-by: Marc-André Lureau Message-Id: <20200311160923.882474-1-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- contrib/vhost-user-gpu/Makefile.objs | 6 +- contrib/vhost-user-gpu/main.c | 1191 ------------------------------- contrib/vhost-user-gpu/vhost-user-gpu.c | 1191 +++++++++++++++++++++++++++++++ 3 files changed, 1194 insertions(+), 1194 deletions(-) delete mode 100644 contrib/vhost-user-gpu/main.c create mode 100644 contrib/vhost-user-gpu/vhost-user-gpu.c diff --git a/contrib/vhost-user-gpu/Makefile.objs b/contrib/vhost-user-gpu/Makefile.objs index 6170c91..0929609 100644 --- a/contrib/vhost-user-gpu/Makefile.objs +++ b/contrib/vhost-user-gpu/Makefile.objs @@ -1,7 +1,7 @@ -vhost-user-gpu-obj-y = main.o virgl.o vugbm.o +vhost-user-gpu-obj-y = vhost-user-gpu.o virgl.o vugbm.o -main.o-cflags := $(PIXMAN_CFLAGS) $(GBM_CFLAGS) -main.o-libs := $(PIXMAN_LIBS) +vhost-user-gpu.o-cflags := $(PIXMAN_CFLAGS) $(GBM_CFLAGS) +vhost-user-gpu.o-libs := $(PIXMAN_LIBS) virgl.o-cflags := $(VIRGL_CFLAGS) $(GBM_CFLAGS) virgl.o-libs := $(VIRGL_LIBS) diff --git a/contrib/vhost-user-gpu/main.c b/contrib/vhost-user-gpu/main.c deleted file mode 100644 index b45d201..0000000 --- a/contrib/vhost-user-gpu/main.c +++ /dev/null @@ -1,1191 +0,0 @@ -/* - * Virtio vhost-user GPU Device - * - * Copyright Red Hat, Inc. 2013-2018 - * - * Authors: - * Dave Airlie - * Gerd Hoffmann - * Marc-André Lureau - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ -#include "qemu/osdep.h" -#include "qemu/drm.h" -#include "qapi/error.h" -#include "qemu/sockets.h" - -#include -#include - -#include "vugpu.h" -#include "hw/virtio/virtio-gpu-bswap.h" -#include "hw/virtio/virtio-gpu-pixman.h" -#include "virgl.h" -#include "vugbm.h" - -enum { - VHOST_USER_GPU_MAX_QUEUES = 2, -}; - -struct virtio_gpu_simple_resource { - uint32_t resource_id; - uint32_t width; - uint32_t height; - uint32_t format; - struct iovec *iov; - unsigned int iov_cnt; - uint32_t scanout_bitmask; - pixman_image_t *image; - struct vugbm_buffer buffer; - QTAILQ_ENTRY(virtio_gpu_simple_resource) next; -}; - -static gboolean opt_print_caps; -static int opt_fdnum = -1; -static char *opt_socket_path; -static char *opt_render_node; -static gboolean opt_virgl; - -static void vg_handle_ctrl(VuDev *dev, int qidx); - -static const char * -vg_cmd_to_string(int cmd) -{ -#define CMD(cmd) [cmd] = #cmd - static const char *vg_cmd_str[] = { - CMD(VIRTIO_GPU_UNDEFINED), - - /* 2d commands */ - CMD(VIRTIO_GPU_CMD_GET_DISPLAY_INFO), - CMD(VIRTIO_GPU_CMD_RESOURCE_CREATE_2D), - CMD(VIRTIO_GPU_CMD_RESOURCE_UNREF), - CMD(VIRTIO_GPU_CMD_SET_SCANOUT), - CMD(VIRTIO_GPU_CMD_RESOURCE_FLUSH), - CMD(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D), - CMD(VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING), - CMD(VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING), - CMD(VIRTIO_GPU_CMD_GET_CAPSET_INFO), - CMD(VIRTIO_GPU_CMD_GET_CAPSET), - - /* 3d commands */ - CMD(VIRTIO_GPU_CMD_CTX_CREATE), - CMD(VIRTIO_GPU_CMD_CTX_DESTROY), - CMD(VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE), - CMD(VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE), - CMD(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D), - CMD(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D), - CMD(VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D), - CMD(VIRTIO_GPU_CMD_SUBMIT_3D), - - /* cursor commands */ - CMD(VIRTIO_GPU_CMD_UPDATE_CURSOR), - CMD(VIRTIO_GPU_CMD_MOVE_CURSOR), - }; -#undef REQ - - if (cmd >= 0 && cmd < G_N_ELEMENTS(vg_cmd_str)) { - return vg_cmd_str[cmd]; - } else { - return "unknown"; - } -} - -static int -vg_sock_fd_read(int sock, void *buf, ssize_t buflen) -{ - int ret; - - do { - ret = read(sock, buf, buflen); - } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); - - g_warn_if_fail(ret == buflen); - return ret; -} - -static void -vg_sock_fd_close(VuGpu *g) -{ - if (g->sock_fd >= 0) { - close(g->sock_fd); - g->sock_fd = -1; - } -} - -static gboolean -source_wait_cb(gint fd, GIOCondition condition, gpointer user_data) -{ - VuGpu *g = user_data; - - if (!vg_recv_msg(g, VHOST_USER_GPU_DMABUF_UPDATE, 0, NULL)) { - return G_SOURCE_CONTINUE; - } - - /* resume */ - g->wait_ok = 0; - vg_handle_ctrl(&g->dev.parent, 0); - - return G_SOURCE_REMOVE; -} - -void -vg_wait_ok(VuGpu *g) -{ - assert(g->wait_ok == 0); - g->wait_ok = g_unix_fd_add(g->sock_fd, G_IO_IN | G_IO_HUP, - source_wait_cb, g); -} - -static int -vg_sock_fd_write(int sock, const void *buf, ssize_t buflen, int fd) -{ - ssize_t ret; - struct iovec iov = { - .iov_base = (void *)buf, - .iov_len = buflen, - }; - struct msghdr msg = { - .msg_iov = &iov, - .msg_iovlen = 1, - }; - union { - struct cmsghdr cmsghdr; - char control[CMSG_SPACE(sizeof(int))]; - } cmsgu; - struct cmsghdr *cmsg; - - if (fd != -1) { - msg.msg_control = cmsgu.control; - msg.msg_controllen = sizeof(cmsgu.control); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - - *((int *)CMSG_DATA(cmsg)) = fd; - } - - do { - ret = sendmsg(sock, &msg, 0); - } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - - g_warn_if_fail(ret == buflen); - return ret; -} - -void -vg_send_msg(VuGpu *vg, const VhostUserGpuMsg *msg, int fd) -{ - if (vg_sock_fd_write(vg->sock_fd, msg, - VHOST_USER_GPU_HDR_SIZE + msg->size, fd) < 0) { - vg_sock_fd_close(vg); - } -} - -bool -vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size, - gpointer payload) -{ - uint32_t req, flags, size; - - if (vg_sock_fd_read(g->sock_fd, &req, sizeof(req)) < 0 || - vg_sock_fd_read(g->sock_fd, &flags, sizeof(flags)) < 0 || - vg_sock_fd_read(g->sock_fd, &size, sizeof(size)) < 0) { - goto err; - } - - g_return_val_if_fail(req == expect_req, false); - g_return_val_if_fail(flags & VHOST_USER_GPU_MSG_FLAG_REPLY, false); - g_return_val_if_fail(size == expect_size, false); - - if (size && vg_sock_fd_read(g->sock_fd, payload, size) != size) { - goto err; - } - - return true; - -err: - vg_sock_fd_close(g); - return false; -} - -static struct virtio_gpu_simple_resource * -virtio_gpu_find_resource(VuGpu *g, uint32_t resource_id) -{ - struct virtio_gpu_simple_resource *res; - - QTAILQ_FOREACH(res, &g->reslist, next) { - if (res->resource_id == resource_id) { - return res; - } - } - return NULL; -} - -void -vg_ctrl_response(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd, - struct virtio_gpu_ctrl_hdr *resp, - size_t resp_len) -{ - size_t s; - - if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE) { - resp->flags |= VIRTIO_GPU_FLAG_FENCE; - resp->fence_id = cmd->cmd_hdr.fence_id; - resp->ctx_id = cmd->cmd_hdr.ctx_id; - } - virtio_gpu_ctrl_hdr_bswap(resp); - s = iov_from_buf(cmd->elem.in_sg, cmd->elem.in_num, 0, resp, resp_len); - if (s != resp_len) { - g_critical("%s: response size incorrect %zu vs %zu", - __func__, s, resp_len); - } - vu_queue_push(&g->dev.parent, cmd->vq, &cmd->elem, s); - vu_queue_notify(&g->dev.parent, cmd->vq); - cmd->finished = true; -} - -void -vg_ctrl_response_nodata(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd, - enum virtio_gpu_ctrl_type type) -{ - struct virtio_gpu_ctrl_hdr resp = { - .type = type, - }; - - vg_ctrl_response(g, cmd, &resp, sizeof(resp)); -} - -void -vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_resp_display_info dpy_info = { {} }; - VhostUserGpuMsg msg = { - .request = VHOST_USER_GPU_GET_DISPLAY_INFO, - .size = 0, - }; - - assert(vg->wait_ok == 0); - - vg_send_msg(vg, &msg, -1); - if (!vg_recv_msg(vg, msg.request, sizeof(dpy_info), &dpy_info)) { - return; - } - - vg_ctrl_response(vg, cmd, &dpy_info.hdr, sizeof(dpy_info)); -} - -static void -vg_resource_create_2d(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd) -{ - pixman_format_code_t pformat; - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_create_2d c2d; - - VUGPU_FILL_CMD(c2d); - virtio_gpu_bswap_32(&c2d, sizeof(c2d)); - - if (c2d.resource_id == 0) { - g_critical("%s: resource id 0 is not allowed", __func__); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - res = virtio_gpu_find_resource(g, c2d.resource_id); - if (res) { - g_critical("%s: resource already exists %d", __func__, c2d.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - res = g_new0(struct virtio_gpu_simple_resource, 1); - res->width = c2d.width; - res->height = c2d.height; - res->format = c2d.format; - res->resource_id = c2d.resource_id; - - pformat = virtio_gpu_get_pixman_format(c2d.format); - if (!pformat) { - g_critical("%s: host couldn't handle guest format %d", - __func__, c2d.format); - g_free(res); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; - return; - } - vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height); - res->image = pixman_image_create_bits(pformat, - c2d.width, - c2d.height, - (uint32_t *)res->buffer.mmap, - res->buffer.stride); - if (!res->image) { - g_critical("%s: resource creation failed %d %d %d", - __func__, c2d.resource_id, c2d.width, c2d.height); - g_free(res); - cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY; - return; - } - - QTAILQ_INSERT_HEAD(&g->reslist, res, next); -} - -static void -vg_disable_scanout(VuGpu *g, int scanout_id) -{ - struct virtio_gpu_scanout *scanout = &g->scanout[scanout_id]; - struct virtio_gpu_simple_resource *res; - - if (scanout->resource_id == 0) { - return; - } - - res = virtio_gpu_find_resource(g, scanout->resource_id); - if (res) { - res->scanout_bitmask &= ~(1 << scanout_id); - } - - scanout->width = 0; - scanout->height = 0; - - if (g->sock_fd >= 0) { - VhostUserGpuMsg msg = { - .request = VHOST_USER_GPU_SCANOUT, - .size = sizeof(VhostUserGpuScanout), - .payload.scanout.scanout_id = scanout_id, - }; - vg_send_msg(g, &msg, -1); - } -} - -static void -vg_resource_destroy(VuGpu *g, - struct virtio_gpu_simple_resource *res) -{ - int i; - - if (res->scanout_bitmask) { - for (i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) { - if (res->scanout_bitmask & (1 << i)) { - vg_disable_scanout(g, i); - } - } - } - - vugbm_buffer_destroy(&res->buffer); - pixman_image_unref(res->image); - QTAILQ_REMOVE(&g->reslist, res, next); - g_free(res); -} - -static void -vg_resource_unref(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_unref unref; - - VUGPU_FILL_CMD(unref); - virtio_gpu_bswap_32(&unref, sizeof(unref)); - - res = virtio_gpu_find_resource(g, unref.resource_id); - if (!res) { - g_critical("%s: illegal resource specified %d", - __func__, unref.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - vg_resource_destroy(g, res); -} - -int -vg_create_mapping_iov(VuGpu *g, - struct virtio_gpu_resource_attach_backing *ab, - struct virtio_gpu_ctrl_command *cmd, - struct iovec **iov) -{ - struct virtio_gpu_mem_entry *ents; - size_t esize, s; - int i; - - if (ab->nr_entries > 16384) { - g_critical("%s: nr_entries is too big (%d > 16384)", - __func__, ab->nr_entries); - return -1; - } - - esize = sizeof(*ents) * ab->nr_entries; - ents = g_malloc(esize); - s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, - sizeof(*ab), ents, esize); - if (s != esize) { - g_critical("%s: command data size incorrect %zu vs %zu", - __func__, s, esize); - g_free(ents); - return -1; - } - - *iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries); - for (i = 0; i < ab->nr_entries; i++) { - uint64_t len = ents[i].length; - (*iov)[i].iov_len = ents[i].length; - (*iov)[i].iov_base = vu_gpa_to_va(&g->dev.parent, &len, ents[i].addr); - if (!(*iov)[i].iov_base || len != ents[i].length) { - g_critical("%s: resource %d element %d", - __func__, ab->resource_id, i); - g_free(*iov); - g_free(ents); - *iov = NULL; - return -1; - } - } - g_free(ents); - return 0; -} - -static void -vg_resource_attach_backing(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_attach_backing ab; - int ret; - - VUGPU_FILL_CMD(ab); - virtio_gpu_bswap_32(&ab, sizeof(ab)); - - res = virtio_gpu_find_resource(g, ab.resource_id); - if (!res) { - g_critical("%s: illegal resource specified %d", - __func__, ab.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - ret = vg_create_mapping_iov(g, &ab, cmd, &res->iov); - if (ret != 0) { - cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; - return; - } - - res->iov_cnt = ab.nr_entries; -} - -static void -vg_resource_detach_backing(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_detach_backing detach; - - VUGPU_FILL_CMD(detach); - virtio_gpu_bswap_32(&detach, sizeof(detach)); - - res = virtio_gpu_find_resource(g, detach.resource_id); - if (!res || !res->iov) { - g_critical("%s: illegal resource specified %d", - __func__, detach.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - g_free(res->iov); - res->iov = NULL; - res->iov_cnt = 0; -} - -static void -vg_transfer_to_host_2d(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - int h; - uint32_t src_offset, dst_offset, stride; - int bpp; - pixman_format_code_t format; - struct virtio_gpu_transfer_to_host_2d t2d; - - VUGPU_FILL_CMD(t2d); - virtio_gpu_t2d_bswap(&t2d); - - res = virtio_gpu_find_resource(g, t2d.resource_id); - if (!res || !res->iov) { - g_critical("%s: illegal resource specified %d", - __func__, t2d.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - if (t2d.r.x > res->width || - t2d.r.y > res->height || - t2d.r.width > res->width || - t2d.r.height > res->height || - t2d.r.x + t2d.r.width > res->width || - t2d.r.y + t2d.r.height > res->height) { - g_critical("%s: transfer bounds outside resource" - " bounds for resource %d: %d %d %d %d vs %d %d", - __func__, t2d.resource_id, t2d.r.x, t2d.r.y, - t2d.r.width, t2d.r.height, res->width, res->height); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; - return; - } - - format = pixman_image_get_format(res->image); - bpp = (PIXMAN_FORMAT_BPP(format) + 7) / 8; - stride = pixman_image_get_stride(res->image); - - if (t2d.offset || t2d.r.x || t2d.r.y || - t2d.r.width != pixman_image_get_width(res->image)) { - void *img_data = pixman_image_get_data(res->image); - for (h = 0; h < t2d.r.height; h++) { - src_offset = t2d.offset + stride * h; - dst_offset = (t2d.r.y + h) * stride + (t2d.r.x * bpp); - - iov_to_buf(res->iov, res->iov_cnt, src_offset, - img_data - + dst_offset, t2d.r.width * bpp); - } - } else { - iov_to_buf(res->iov, res->iov_cnt, 0, - pixman_image_get_data(res->image), - pixman_image_get_stride(res->image) - * pixman_image_get_height(res->image)); - } -} - -static void -vg_set_scanout(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res, *ores; - struct virtio_gpu_scanout *scanout; - struct virtio_gpu_set_scanout ss; - int fd; - - VUGPU_FILL_CMD(ss); - virtio_gpu_bswap_32(&ss, sizeof(ss)); - - if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUTS) { - g_critical("%s: illegal scanout id specified %d", - __func__, ss.scanout_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID; - return; - } - - if (ss.resource_id == 0) { - vg_disable_scanout(g, ss.scanout_id); - return; - } - - /* create a surface for this scanout */ - res = virtio_gpu_find_resource(g, ss.resource_id); - if (!res) { - g_critical("%s: illegal resource specified %d", - __func__, ss.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - if (ss.r.x > res->width || - ss.r.y > res->height || - ss.r.width > res->width || - ss.r.height > res->height || - ss.r.x + ss.r.width > res->width || - ss.r.y + ss.r.height > res->height) { - g_critical("%s: illegal scanout %d bounds for" - " resource %d, (%d,%d)+%d,%d vs %d %d", - __func__, ss.scanout_id, ss.resource_id, ss.r.x, ss.r.y, - ss.r.width, ss.r.height, res->width, res->height); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; - return; - } - - scanout = &g->scanout[ss.scanout_id]; - - ores = virtio_gpu_find_resource(g, scanout->resource_id); - if (ores) { - ores->scanout_bitmask &= ~(1 << ss.scanout_id); - } - - res->scanout_bitmask |= (1 << ss.scanout_id); - scanout->resource_id = ss.resource_id; - scanout->x = ss.r.x; - scanout->y = ss.r.y; - scanout->width = ss.r.width; - scanout->height = ss.r.height; - - struct vugbm_buffer *buffer = &res->buffer; - - if (vugbm_buffer_can_get_dmabuf_fd(buffer)) { - VhostUserGpuMsg msg = { - .request = VHOST_USER_GPU_DMABUF_SCANOUT, - .size = sizeof(VhostUserGpuDMABUFScanout), - .payload.dmabuf_scanout = (VhostUserGpuDMABUFScanout) { - .scanout_id = ss.scanout_id, - .x = ss.r.x, - .y = ss.r.y, - .width = ss.r.width, - .height = ss.r.height, - .fd_width = buffer->width, - .fd_height = buffer->height, - .fd_stride = buffer->stride, - .fd_drm_fourcc = buffer->format - } - }; - - if (vugbm_buffer_get_dmabuf_fd(buffer, &fd)) { - vg_send_msg(g, &msg, fd); - close(fd); - } - } else { - VhostUserGpuMsg msg = { - .request = VHOST_USER_GPU_SCANOUT, - .size = sizeof(VhostUserGpuScanout), - .payload.scanout = (VhostUserGpuScanout) { - .scanout_id = ss.scanout_id, - .width = scanout->width, - .height = scanout->height - } - }; - vg_send_msg(g, &msg, -1); - } -} - -static void -vg_resource_flush(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd) -{ - struct virtio_gpu_simple_resource *res; - struct virtio_gpu_resource_flush rf; - pixman_region16_t flush_region; - int i; - - VUGPU_FILL_CMD(rf); - virtio_gpu_bswap_32(&rf, sizeof(rf)); - - res = virtio_gpu_find_resource(g, rf.resource_id); - if (!res) { - g_critical("%s: illegal resource specified %d\n", - __func__, rf.resource_id); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; - return; - } - - if (rf.r.x > res->width || - rf.r.y > res->height || - rf.r.width > res->width || - rf.r.height > res->height || - rf.r.x + rf.r.width > res->width || - rf.r.y + rf.r.height > res->height) { - g_critical("%s: flush bounds outside resource" - " bounds for resource %d: %d %d %d %d vs %d %d\n", - __func__, rf.resource_id, rf.r.x, rf.r.y, - rf.r.width, rf.r.height, res->width, res->height); - cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; - return; - } - - pixman_region_init_rect(&flush_region, - rf.r.x, rf.r.y, rf.r.width, rf.r.height); - for (i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) { - struct virtio_gpu_scanout *scanout; - pixman_region16_t region, finalregion; - pixman_box16_t *extents; - - if (!(res->scanout_bitmask & (1 << i))) { - continue; - } - scanout = &g->scanout[i]; - - pixman_region_init(&finalregion); - pixman_region_init_rect(®ion, scanout->x, scanout->y, - scanout->width, scanout->height); - - pixman_region_intersect(&finalregion, &flush_region, ®ion); - - extents = pixman_region_extents(&finalregion); - size_t width = extents->x2 - extents->x1; - size_t height = extents->y2 - extents->y1; - - if (vugbm_buffer_can_get_dmabuf_fd(&res->buffer)) { - VhostUserGpuMsg vmsg = { - .request = VHOST_USER_GPU_DMABUF_UPDATE, - .size = sizeof(VhostUserGpuUpdate), - .payload.update = (VhostUserGpuUpdate) { - .scanout_id = i, - .x = extents->x1, - .y = extents->y1, - .width = width, - .height = height, - } - }; - vg_send_msg(g, &vmsg, -1); - vg_wait_ok(g); - } else { - size_t bpp = - PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) / 8; - size_t size = width * height * bpp; - - void *p = g_malloc(VHOST_USER_GPU_HDR_SIZE + - sizeof(VhostUserGpuUpdate) + size); - VhostUserGpuMsg *msg = p; - msg->request = VHOST_USER_GPU_UPDATE; - msg->size = sizeof(VhostUserGpuUpdate) + size; - msg->payload.update = (VhostUserGpuUpdate) { - .scanout_id = i, - .x = extents->x1, - .y = extents->y1, - .width = width, - .height = height, - }; - pixman_image_t *i = - pixman_image_create_bits(pixman_image_get_format(res->image), - msg->payload.update.width, - msg->payload.update.height, - p + offsetof(VhostUserGpuMsg, - payload.update.data), - width * bpp); - pixman_image_composite(PIXMAN_OP_SRC, - res->image, NULL, i, - extents->x1, extents->y1, - 0, 0, 0, 0, - width, height); - pixman_image_unref(i); - vg_send_msg(g, msg, -1); - g_free(msg); - } - pixman_region_fini(®ion); - pixman_region_fini(&finalregion); - } - pixman_region_fini(&flush_region); -} - -static void -vg_process_cmd(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd) -{ - switch (cmd->cmd_hdr.type) { - case VIRTIO_GPU_CMD_GET_DISPLAY_INFO: - vg_get_display_info(vg, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: - vg_resource_create_2d(vg, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_UNREF: - vg_resource_unref(vg, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_FLUSH: - vg_resource_flush(vg, cmd); - break; - case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: - vg_transfer_to_host_2d(vg, cmd); - break; - case VIRTIO_GPU_CMD_SET_SCANOUT: - vg_set_scanout(vg, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING: - vg_resource_attach_backing(vg, cmd); - break; - case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING: - vg_resource_detach_backing(vg, cmd); - break; - /* case VIRTIO_GPU_CMD_GET_EDID: */ - /* break */ - default: - g_warning("TODO handle ctrl %x\n", cmd->cmd_hdr.type); - cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; - break; - } - if (!cmd->finished) { - vg_ctrl_response_nodata(vg, cmd, cmd->error ? cmd->error : - VIRTIO_GPU_RESP_OK_NODATA); - } -} - -static void -vg_handle_ctrl(VuDev *dev, int qidx) -{ - VuGpu *vg = container_of(dev, VuGpu, dev.parent); - VuVirtq *vq = vu_get_queue(dev, qidx); - struct virtio_gpu_ctrl_command *cmd = NULL; - size_t len; - - for (;;) { - if (vg->wait_ok != 0) { - return; - } - - cmd = vu_queue_pop(dev, vq, sizeof(struct virtio_gpu_ctrl_command)); - if (!cmd) { - break; - } - cmd->vq = vq; - cmd->error = 0; - cmd->finished = false; - - len = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, - 0, &cmd->cmd_hdr, sizeof(cmd->cmd_hdr)); - if (len != sizeof(cmd->cmd_hdr)) { - g_warning("%s: command size incorrect %zu vs %zu\n", - __func__, len, sizeof(cmd->cmd_hdr)); - } - - virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr); - g_debug("%d %s\n", cmd->cmd_hdr.type, - vg_cmd_to_string(cmd->cmd_hdr.type)); - - if (vg->virgl) { - vg_virgl_process_cmd(vg, cmd); - } else { - vg_process_cmd(vg, cmd); - } - - if (!cmd->finished) { - QTAILQ_INSERT_TAIL(&vg->fenceq, cmd, next); - vg->inflight++; - } else { - g_free(cmd); - } - } -} - -static void -update_cursor_data_simple(VuGpu *g, uint32_t resource_id, gpointer data) -{ - struct virtio_gpu_simple_resource *res; - - res = virtio_gpu_find_resource(g, resource_id); - g_return_if_fail(res != NULL); - g_return_if_fail(pixman_image_get_width(res->image) == 64); - g_return_if_fail(pixman_image_get_height(res->image) == 64); - g_return_if_fail( - PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) == 32); - - memcpy(data, pixman_image_get_data(res->image), 64 * 64 * sizeof(uint32_t)); -} - -static void -vg_process_cursor_cmd(VuGpu *g, struct virtio_gpu_update_cursor *cursor) -{ - bool move = cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR; - - g_debug("%s move:%d\n", G_STRFUNC, move); - - if (move) { - VhostUserGpuMsg msg = { - .request = cursor->resource_id ? - VHOST_USER_GPU_CURSOR_POS : VHOST_USER_GPU_CURSOR_POS_HIDE, - .size = sizeof(VhostUserGpuCursorPos), - .payload.cursor_pos = { - .scanout_id = cursor->pos.scanout_id, - .x = cursor->pos.x, - .y = cursor->pos.y, - } - }; - vg_send_msg(g, &msg, -1); - } else { - VhostUserGpuMsg msg = { - .request = VHOST_USER_GPU_CURSOR_UPDATE, - .size = sizeof(VhostUserGpuCursorUpdate), - .payload.cursor_update = { - .pos = { - .scanout_id = cursor->pos.scanout_id, - .x = cursor->pos.x, - .y = cursor->pos.y, - }, - .hot_x = cursor->hot_x, - .hot_y = cursor->hot_y, - } - }; - if (g->virgl) { - vg_virgl_update_cursor_data(g, cursor->resource_id, - msg.payload.cursor_update.data); - } else { - update_cursor_data_simple(g, cursor->resource_id, - msg.payload.cursor_update.data); - } - vg_send_msg(g, &msg, -1); - } -} - -static void -vg_handle_cursor(VuDev *dev, int qidx) -{ - VuGpu *g = container_of(dev, VuGpu, dev.parent); - VuVirtq *vq = vu_get_queue(dev, qidx); - VuVirtqElement *elem; - size_t len; - struct virtio_gpu_update_cursor cursor; - - for (;;) { - elem = vu_queue_pop(dev, vq, sizeof(VuVirtqElement)); - if (!elem) { - break; - } - g_debug("cursor out:%d in:%d\n", elem->out_num, elem->in_num); - - len = iov_to_buf(elem->out_sg, elem->out_num, - 0, &cursor, sizeof(cursor)); - if (len != sizeof(cursor)) { - g_warning("%s: cursor size incorrect %zu vs %zu\n", - __func__, len, sizeof(cursor)); - } else { - virtio_gpu_bswap_32(&cursor, sizeof(cursor)); - vg_process_cursor_cmd(g, &cursor); - } - vu_queue_push(dev, vq, elem, 0); - vu_queue_notify(dev, vq); - g_free(elem); - } -} - -static void -vg_panic(VuDev *dev, const char *msg) -{ - g_critical("%s\n", msg); - exit(1); -} - -static void -vg_queue_set_started(VuDev *dev, int qidx, bool started) -{ - VuVirtq *vq = vu_get_queue(dev, qidx); - - g_debug("queue started %d:%d\n", qidx, started); - - switch (qidx) { - case 0: - vu_set_queue_handler(dev, vq, started ? vg_handle_ctrl : NULL); - break; - case 1: - vu_set_queue_handler(dev, vq, started ? vg_handle_cursor : NULL); - break; - default: - break; - } -} - -static void -set_gpu_protocol_features(VuGpu *g) -{ - uint64_t u64; - VhostUserGpuMsg msg = { - .request = VHOST_USER_GPU_GET_PROTOCOL_FEATURES - }; - - assert(g->wait_ok == 0); - vg_send_msg(g, &msg, -1); - if (!vg_recv_msg(g, msg.request, sizeof(u64), &u64)) { - return; - } - - msg = (VhostUserGpuMsg) { - .request = VHOST_USER_GPU_SET_PROTOCOL_FEATURES, - .size = sizeof(uint64_t), - .payload.u64 = 0 - }; - vg_send_msg(g, &msg, -1); -} - -static int -vg_process_msg(VuDev *dev, VhostUserMsg *msg, int *do_reply) -{ - VuGpu *g = container_of(dev, VuGpu, dev.parent); - - switch (msg->request) { - case VHOST_USER_GPU_SET_SOCKET: { - g_return_val_if_fail(msg->fd_num == 1, 1); - g_return_val_if_fail(g->sock_fd == -1, 1); - g->sock_fd = msg->fds[0]; - set_gpu_protocol_features(g); - return 1; - } - default: - return 0; - } - - return 0; -} - -static uint64_t -vg_get_features(VuDev *dev) -{ - uint64_t features = 0; - - if (opt_virgl) { - features |= 1 << VIRTIO_GPU_F_VIRGL; - } - - return features; -} - -static void -vg_set_features(VuDev *dev, uint64_t features) -{ - VuGpu *g = container_of(dev, VuGpu, dev.parent); - bool virgl = features & (1 << VIRTIO_GPU_F_VIRGL); - - if (virgl && !g->virgl_inited) { - if (!vg_virgl_init(g)) { - vg_panic(dev, "Failed to initialize virgl"); - } - g->virgl_inited = true; - } - - g->virgl = virgl; -} - -static int -vg_get_config(VuDev *dev, uint8_t *config, uint32_t len) -{ - VuGpu *g = container_of(dev, VuGpu, dev.parent); - - g_return_val_if_fail(len <= sizeof(struct virtio_gpu_config), -1); - - if (opt_virgl) { - g->virtio_config.num_capsets = vg_virgl_get_num_capsets(); - } - - memcpy(config, &g->virtio_config, len); - - return 0; -} - -static int -vg_set_config(VuDev *dev, const uint8_t *data, - uint32_t offset, uint32_t size, - uint32_t flags) -{ - VuGpu *g = container_of(dev, VuGpu, dev.parent); - struct virtio_gpu_config *config = (struct virtio_gpu_config *)data; - - if (config->events_clear) { - g->virtio_config.events_read &= ~config->events_clear; - } - - return 0; -} - -static const VuDevIface vuiface = { - .set_features = vg_set_features, - .get_features = vg_get_features, - .queue_set_started = vg_queue_set_started, - .process_msg = vg_process_msg, - .get_config = vg_get_config, - .set_config = vg_set_config, -}; - -static void -vg_destroy(VuGpu *g) -{ - struct virtio_gpu_simple_resource *res, *tmp; - - vug_deinit(&g->dev); - - vg_sock_fd_close(g); - - QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) { - vg_resource_destroy(g, res); - } - - vugbm_device_destroy(&g->gdev); -} - -static GOptionEntry entries[] = { - { "print-capabilities", 'c', 0, G_OPTION_ARG_NONE, &opt_print_caps, - "Print capabilities", NULL }, - { "fd", 'f', 0, G_OPTION_ARG_INT, &opt_fdnum, - "Use inherited fd socket", "FDNUM" }, - { "socket-path", 's', 0, G_OPTION_ARG_FILENAME, &opt_socket_path, - "Use UNIX socket path", "PATH" }, - { "render-node", 'r', 0, G_OPTION_ARG_FILENAME, &opt_render_node, - "Specify DRM render node", "PATH" }, - { "virgl", 'v', 0, G_OPTION_ARG_NONE, &opt_virgl, - "Turn virgl rendering on", NULL }, - { NULL, } -}; - -int -main(int argc, char *argv[]) -{ - GOptionContext *context; - GError *error = NULL; - GMainLoop *loop = NULL; - int fd; - VuGpu g = { .sock_fd = -1, .drm_rnode_fd = -1 }; - - QTAILQ_INIT(&g.reslist); - QTAILQ_INIT(&g.fenceq); - - context = g_option_context_new("QEMU vhost-user-gpu"); - g_option_context_add_main_entries(context, entries, NULL); - if (!g_option_context_parse(context, &argc, &argv, &error)) { - g_printerr("Option parsing failed: %s\n", error->message); - exit(EXIT_FAILURE); - } - g_option_context_free(context); - - if (opt_print_caps) { - g_print("{\n"); - g_print(" \"type\": \"gpu\",\n"); - g_print(" \"features\": [\n"); - g_print(" \"render-node\",\n"); - g_print(" \"virgl\"\n"); - g_print(" ]\n"); - g_print("}\n"); - exit(EXIT_SUCCESS); - } - - g.drm_rnode_fd = qemu_drm_rendernode_open(opt_render_node); - if (opt_render_node && g.drm_rnode_fd == -1) { - g_printerr("Failed to open DRM rendernode.\n"); - exit(EXIT_FAILURE); - } - - if (g.drm_rnode_fd >= 0) { - if (!vugbm_device_init(&g.gdev, g.drm_rnode_fd)) { - g_warning("Failed to init DRM device, using fallback path"); - } - } - - if ((!!opt_socket_path + (opt_fdnum != -1)) != 1) { - g_printerr("Please specify either --fd or --socket-path\n"); - exit(EXIT_FAILURE); - } - - if (opt_socket_path) { - int lsock = unix_listen(opt_socket_path, &error_fatal); - if (lsock < 0) { - g_printerr("Failed to listen on %s.\n", opt_socket_path); - exit(EXIT_FAILURE); - } - fd = accept(lsock, NULL, NULL); - close(lsock); - } else { - fd = opt_fdnum; - } - if (fd == -1) { - g_printerr("Invalid vhost-user socket.\n"); - exit(EXIT_FAILURE); - } - - if (!vug_init(&g.dev, VHOST_USER_GPU_MAX_QUEUES, fd, vg_panic, &vuiface)) { - g_printerr("Failed to initialize libvhost-user-glib.\n"); - exit(EXIT_FAILURE); - } - - loop = g_main_loop_new(NULL, FALSE); - g_main_loop_run(loop); - g_main_loop_unref(loop); - - vg_destroy(&g); - if (g.drm_rnode_fd >= 0) { - close(g.drm_rnode_fd); - } - - return 0; -} diff --git a/contrib/vhost-user-gpu/vhost-user-gpu.c b/contrib/vhost-user-gpu/vhost-user-gpu.c new file mode 100644 index 0000000..b45d201 --- /dev/null +++ b/contrib/vhost-user-gpu/vhost-user-gpu.c @@ -0,0 +1,1191 @@ +/* + * Virtio vhost-user GPU Device + * + * Copyright Red Hat, Inc. 2013-2018 + * + * Authors: + * Dave Airlie + * Gerd Hoffmann + * Marc-André Lureau + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu/drm.h" +#include "qapi/error.h" +#include "qemu/sockets.h" + +#include +#include + +#include "vugpu.h" +#include "hw/virtio/virtio-gpu-bswap.h" +#include "hw/virtio/virtio-gpu-pixman.h" +#include "virgl.h" +#include "vugbm.h" + +enum { + VHOST_USER_GPU_MAX_QUEUES = 2, +}; + +struct virtio_gpu_simple_resource { + uint32_t resource_id; + uint32_t width; + uint32_t height; + uint32_t format; + struct iovec *iov; + unsigned int iov_cnt; + uint32_t scanout_bitmask; + pixman_image_t *image; + struct vugbm_buffer buffer; + QTAILQ_ENTRY(virtio_gpu_simple_resource) next; +}; + +static gboolean opt_print_caps; +static int opt_fdnum = -1; +static char *opt_socket_path; +static char *opt_render_node; +static gboolean opt_virgl; + +static void vg_handle_ctrl(VuDev *dev, int qidx); + +static const char * +vg_cmd_to_string(int cmd) +{ +#define CMD(cmd) [cmd] = #cmd + static const char *vg_cmd_str[] = { + CMD(VIRTIO_GPU_UNDEFINED), + + /* 2d commands */ + CMD(VIRTIO_GPU_CMD_GET_DISPLAY_INFO), + CMD(VIRTIO_GPU_CMD_RESOURCE_CREATE_2D), + CMD(VIRTIO_GPU_CMD_RESOURCE_UNREF), + CMD(VIRTIO_GPU_CMD_SET_SCANOUT), + CMD(VIRTIO_GPU_CMD_RESOURCE_FLUSH), + CMD(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D), + CMD(VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING), + CMD(VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING), + CMD(VIRTIO_GPU_CMD_GET_CAPSET_INFO), + CMD(VIRTIO_GPU_CMD_GET_CAPSET), + + /* 3d commands */ + CMD(VIRTIO_GPU_CMD_CTX_CREATE), + CMD(VIRTIO_GPU_CMD_CTX_DESTROY), + CMD(VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE), + CMD(VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE), + CMD(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D), + CMD(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D), + CMD(VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D), + CMD(VIRTIO_GPU_CMD_SUBMIT_3D), + + /* cursor commands */ + CMD(VIRTIO_GPU_CMD_UPDATE_CURSOR), + CMD(VIRTIO_GPU_CMD_MOVE_CURSOR), + }; +#undef REQ + + if (cmd >= 0 && cmd < G_N_ELEMENTS(vg_cmd_str)) { + return vg_cmd_str[cmd]; + } else { + return "unknown"; + } +} + +static int +vg_sock_fd_read(int sock, void *buf, ssize_t buflen) +{ + int ret; + + do { + ret = read(sock, buf, buflen); + } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); + + g_warn_if_fail(ret == buflen); + return ret; +} + +static void +vg_sock_fd_close(VuGpu *g) +{ + if (g->sock_fd >= 0) { + close(g->sock_fd); + g->sock_fd = -1; + } +} + +static gboolean +source_wait_cb(gint fd, GIOCondition condition, gpointer user_data) +{ + VuGpu *g = user_data; + + if (!vg_recv_msg(g, VHOST_USER_GPU_DMABUF_UPDATE, 0, NULL)) { + return G_SOURCE_CONTINUE; + } + + /* resume */ + g->wait_ok = 0; + vg_handle_ctrl(&g->dev.parent, 0); + + return G_SOURCE_REMOVE; +} + +void +vg_wait_ok(VuGpu *g) +{ + assert(g->wait_ok == 0); + g->wait_ok = g_unix_fd_add(g->sock_fd, G_IO_IN | G_IO_HUP, + source_wait_cb, g); +} + +static int +vg_sock_fd_write(int sock, const void *buf, ssize_t buflen, int fd) +{ + ssize_t ret; + struct iovec iov = { + .iov_base = (void *)buf, + .iov_len = buflen, + }; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + }; + union { + struct cmsghdr cmsghdr; + char control[CMSG_SPACE(sizeof(int))]; + } cmsgu; + struct cmsghdr *cmsg; + + if (fd != -1) { + msg.msg_control = cmsgu.control; + msg.msg_controllen = sizeof(cmsgu.control); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + + *((int *)CMSG_DATA(cmsg)) = fd; + } + + do { + ret = sendmsg(sock, &msg, 0); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + g_warn_if_fail(ret == buflen); + return ret; +} + +void +vg_send_msg(VuGpu *vg, const VhostUserGpuMsg *msg, int fd) +{ + if (vg_sock_fd_write(vg->sock_fd, msg, + VHOST_USER_GPU_HDR_SIZE + msg->size, fd) < 0) { + vg_sock_fd_close(vg); + } +} + +bool +vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size, + gpointer payload) +{ + uint32_t req, flags, size; + + if (vg_sock_fd_read(g->sock_fd, &req, sizeof(req)) < 0 || + vg_sock_fd_read(g->sock_fd, &flags, sizeof(flags)) < 0 || + vg_sock_fd_read(g->sock_fd, &size, sizeof(size)) < 0) { + goto err; + } + + g_return_val_if_fail(req == expect_req, false); + g_return_val_if_fail(flags & VHOST_USER_GPU_MSG_FLAG_REPLY, false); + g_return_val_if_fail(size == expect_size, false); + + if (size && vg_sock_fd_read(g->sock_fd, payload, size) != size) { + goto err; + } + + return true; + +err: + vg_sock_fd_close(g); + return false; +} + +static struct virtio_gpu_simple_resource * +virtio_gpu_find_resource(VuGpu *g, uint32_t resource_id) +{ + struct virtio_gpu_simple_resource *res; + + QTAILQ_FOREACH(res, &g->reslist, next) { + if (res->resource_id == resource_id) { + return res; + } + } + return NULL; +} + +void +vg_ctrl_response(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd, + struct virtio_gpu_ctrl_hdr *resp, + size_t resp_len) +{ + size_t s; + + if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE) { + resp->flags |= VIRTIO_GPU_FLAG_FENCE; + resp->fence_id = cmd->cmd_hdr.fence_id; + resp->ctx_id = cmd->cmd_hdr.ctx_id; + } + virtio_gpu_ctrl_hdr_bswap(resp); + s = iov_from_buf(cmd->elem.in_sg, cmd->elem.in_num, 0, resp, resp_len); + if (s != resp_len) { + g_critical("%s: response size incorrect %zu vs %zu", + __func__, s, resp_len); + } + vu_queue_push(&g->dev.parent, cmd->vq, &cmd->elem, s); + vu_queue_notify(&g->dev.parent, cmd->vq); + cmd->finished = true; +} + +void +vg_ctrl_response_nodata(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd, + enum virtio_gpu_ctrl_type type) +{ + struct virtio_gpu_ctrl_hdr resp = { + .type = type, + }; + + vg_ctrl_response(g, cmd, &resp, sizeof(resp)); +} + +void +vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_resp_display_info dpy_info = { {} }; + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_GET_DISPLAY_INFO, + .size = 0, + }; + + assert(vg->wait_ok == 0); + + vg_send_msg(vg, &msg, -1); + if (!vg_recv_msg(vg, msg.request, sizeof(dpy_info), &dpy_info)) { + return; + } + + vg_ctrl_response(vg, cmd, &dpy_info.hdr, sizeof(dpy_info)); +} + +static void +vg_resource_create_2d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + pixman_format_code_t pformat; + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_create_2d c2d; + + VUGPU_FILL_CMD(c2d); + virtio_gpu_bswap_32(&c2d, sizeof(c2d)); + + if (c2d.resource_id == 0) { + g_critical("%s: resource id 0 is not allowed", __func__); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + res = virtio_gpu_find_resource(g, c2d.resource_id); + if (res) { + g_critical("%s: resource already exists %d", __func__, c2d.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + res = g_new0(struct virtio_gpu_simple_resource, 1); + res->width = c2d.width; + res->height = c2d.height; + res->format = c2d.format; + res->resource_id = c2d.resource_id; + + pformat = virtio_gpu_get_pixman_format(c2d.format); + if (!pformat) { + g_critical("%s: host couldn't handle guest format %d", + __func__, c2d.format); + g_free(res); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } + vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height); + res->image = pixman_image_create_bits(pformat, + c2d.width, + c2d.height, + (uint32_t *)res->buffer.mmap, + res->buffer.stride); + if (!res->image) { + g_critical("%s: resource creation failed %d %d %d", + __func__, c2d.resource_id, c2d.width, c2d.height); + g_free(res); + cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY; + return; + } + + QTAILQ_INSERT_HEAD(&g->reslist, res, next); +} + +static void +vg_disable_scanout(VuGpu *g, int scanout_id) +{ + struct virtio_gpu_scanout *scanout = &g->scanout[scanout_id]; + struct virtio_gpu_simple_resource *res; + + if (scanout->resource_id == 0) { + return; + } + + res = virtio_gpu_find_resource(g, scanout->resource_id); + if (res) { + res->scanout_bitmask &= ~(1 << scanout_id); + } + + scanout->width = 0; + scanout->height = 0; + + if (g->sock_fd >= 0) { + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_SCANOUT, + .size = sizeof(VhostUserGpuScanout), + .payload.scanout.scanout_id = scanout_id, + }; + vg_send_msg(g, &msg, -1); + } +} + +static void +vg_resource_destroy(VuGpu *g, + struct virtio_gpu_simple_resource *res) +{ + int i; + + if (res->scanout_bitmask) { + for (i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) { + if (res->scanout_bitmask & (1 << i)) { + vg_disable_scanout(g, i); + } + } + } + + vugbm_buffer_destroy(&res->buffer); + pixman_image_unref(res->image); + QTAILQ_REMOVE(&g->reslist, res, next); + g_free(res); +} + +static void +vg_resource_unref(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_unref unref; + + VUGPU_FILL_CMD(unref); + virtio_gpu_bswap_32(&unref, sizeof(unref)); + + res = virtio_gpu_find_resource(g, unref.resource_id); + if (!res) { + g_critical("%s: illegal resource specified %d", + __func__, unref.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + vg_resource_destroy(g, res); +} + +int +vg_create_mapping_iov(VuGpu *g, + struct virtio_gpu_resource_attach_backing *ab, + struct virtio_gpu_ctrl_command *cmd, + struct iovec **iov) +{ + struct virtio_gpu_mem_entry *ents; + size_t esize, s; + int i; + + if (ab->nr_entries > 16384) { + g_critical("%s: nr_entries is too big (%d > 16384)", + __func__, ab->nr_entries); + return -1; + } + + esize = sizeof(*ents) * ab->nr_entries; + ents = g_malloc(esize); + s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, + sizeof(*ab), ents, esize); + if (s != esize) { + g_critical("%s: command data size incorrect %zu vs %zu", + __func__, s, esize); + g_free(ents); + return -1; + } + + *iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries); + for (i = 0; i < ab->nr_entries; i++) { + uint64_t len = ents[i].length; + (*iov)[i].iov_len = ents[i].length; + (*iov)[i].iov_base = vu_gpa_to_va(&g->dev.parent, &len, ents[i].addr); + if (!(*iov)[i].iov_base || len != ents[i].length) { + g_critical("%s: resource %d element %d", + __func__, ab->resource_id, i); + g_free(*iov); + g_free(ents); + *iov = NULL; + return -1; + } + } + g_free(ents); + return 0; +} + +static void +vg_resource_attach_backing(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_attach_backing ab; + int ret; + + VUGPU_FILL_CMD(ab); + virtio_gpu_bswap_32(&ab, sizeof(ab)); + + res = virtio_gpu_find_resource(g, ab.resource_id); + if (!res) { + g_critical("%s: illegal resource specified %d", + __func__, ab.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + ret = vg_create_mapping_iov(g, &ab, cmd, &res->iov); + if (ret != 0) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; + } + + res->iov_cnt = ab.nr_entries; +} + +static void +vg_resource_detach_backing(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_detach_backing detach; + + VUGPU_FILL_CMD(detach); + virtio_gpu_bswap_32(&detach, sizeof(detach)); + + res = virtio_gpu_find_resource(g, detach.resource_id); + if (!res || !res->iov) { + g_critical("%s: illegal resource specified %d", + __func__, detach.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + g_free(res->iov); + res->iov = NULL; + res->iov_cnt = 0; +} + +static void +vg_transfer_to_host_2d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + int h; + uint32_t src_offset, dst_offset, stride; + int bpp; + pixman_format_code_t format; + struct virtio_gpu_transfer_to_host_2d t2d; + + VUGPU_FILL_CMD(t2d); + virtio_gpu_t2d_bswap(&t2d); + + res = virtio_gpu_find_resource(g, t2d.resource_id); + if (!res || !res->iov) { + g_critical("%s: illegal resource specified %d", + __func__, t2d.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + if (t2d.r.x > res->width || + t2d.r.y > res->height || + t2d.r.width > res->width || + t2d.r.height > res->height || + t2d.r.x + t2d.r.width > res->width || + t2d.r.y + t2d.r.height > res->height) { + g_critical("%s: transfer bounds outside resource" + " bounds for resource %d: %d %d %d %d vs %d %d", + __func__, t2d.resource_id, t2d.r.x, t2d.r.y, + t2d.r.width, t2d.r.height, res->width, res->height); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } + + format = pixman_image_get_format(res->image); + bpp = (PIXMAN_FORMAT_BPP(format) + 7) / 8; + stride = pixman_image_get_stride(res->image); + + if (t2d.offset || t2d.r.x || t2d.r.y || + t2d.r.width != pixman_image_get_width(res->image)) { + void *img_data = pixman_image_get_data(res->image); + for (h = 0; h < t2d.r.height; h++) { + src_offset = t2d.offset + stride * h; + dst_offset = (t2d.r.y + h) * stride + (t2d.r.x * bpp); + + iov_to_buf(res->iov, res->iov_cnt, src_offset, + img_data + + dst_offset, t2d.r.width * bpp); + } + } else { + iov_to_buf(res->iov, res->iov_cnt, 0, + pixman_image_get_data(res->image), + pixman_image_get_stride(res->image) + * pixman_image_get_height(res->image)); + } +} + +static void +vg_set_scanout(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res, *ores; + struct virtio_gpu_scanout *scanout; + struct virtio_gpu_set_scanout ss; + int fd; + + VUGPU_FILL_CMD(ss); + virtio_gpu_bswap_32(&ss, sizeof(ss)); + + if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUTS) { + g_critical("%s: illegal scanout id specified %d", + __func__, ss.scanout_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID; + return; + } + + if (ss.resource_id == 0) { + vg_disable_scanout(g, ss.scanout_id); + return; + } + + /* create a surface for this scanout */ + res = virtio_gpu_find_resource(g, ss.resource_id); + if (!res) { + g_critical("%s: illegal resource specified %d", + __func__, ss.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + if (ss.r.x > res->width || + ss.r.y > res->height || + ss.r.width > res->width || + ss.r.height > res->height || + ss.r.x + ss.r.width > res->width || + ss.r.y + ss.r.height > res->height) { + g_critical("%s: illegal scanout %d bounds for" + " resource %d, (%d,%d)+%d,%d vs %d %d", + __func__, ss.scanout_id, ss.resource_id, ss.r.x, ss.r.y, + ss.r.width, ss.r.height, res->width, res->height); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } + + scanout = &g->scanout[ss.scanout_id]; + + ores = virtio_gpu_find_resource(g, scanout->resource_id); + if (ores) { + ores->scanout_bitmask &= ~(1 << ss.scanout_id); + } + + res->scanout_bitmask |= (1 << ss.scanout_id); + scanout->resource_id = ss.resource_id; + scanout->x = ss.r.x; + scanout->y = ss.r.y; + scanout->width = ss.r.width; + scanout->height = ss.r.height; + + struct vugbm_buffer *buffer = &res->buffer; + + if (vugbm_buffer_can_get_dmabuf_fd(buffer)) { + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_DMABUF_SCANOUT, + .size = sizeof(VhostUserGpuDMABUFScanout), + .payload.dmabuf_scanout = (VhostUserGpuDMABUFScanout) { + .scanout_id = ss.scanout_id, + .x = ss.r.x, + .y = ss.r.y, + .width = ss.r.width, + .height = ss.r.height, + .fd_width = buffer->width, + .fd_height = buffer->height, + .fd_stride = buffer->stride, + .fd_drm_fourcc = buffer->format + } + }; + + if (vugbm_buffer_get_dmabuf_fd(buffer, &fd)) { + vg_send_msg(g, &msg, fd); + close(fd); + } + } else { + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_SCANOUT, + .size = sizeof(VhostUserGpuScanout), + .payload.scanout = (VhostUserGpuScanout) { + .scanout_id = ss.scanout_id, + .width = scanout->width, + .height = scanout->height + } + }; + vg_send_msg(g, &msg, -1); + } +} + +static void +vg_resource_flush(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_flush rf; + pixman_region16_t flush_region; + int i; + + VUGPU_FILL_CMD(rf); + virtio_gpu_bswap_32(&rf, sizeof(rf)); + + res = virtio_gpu_find_resource(g, rf.resource_id); + if (!res) { + g_critical("%s: illegal resource specified %d\n", + __func__, rf.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + if (rf.r.x > res->width || + rf.r.y > res->height || + rf.r.width > res->width || + rf.r.height > res->height || + rf.r.x + rf.r.width > res->width || + rf.r.y + rf.r.height > res->height) { + g_critical("%s: flush bounds outside resource" + " bounds for resource %d: %d %d %d %d vs %d %d\n", + __func__, rf.resource_id, rf.r.x, rf.r.y, + rf.r.width, rf.r.height, res->width, res->height); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } + + pixman_region_init_rect(&flush_region, + rf.r.x, rf.r.y, rf.r.width, rf.r.height); + for (i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) { + struct virtio_gpu_scanout *scanout; + pixman_region16_t region, finalregion; + pixman_box16_t *extents; + + if (!(res->scanout_bitmask & (1 << i))) { + continue; + } + scanout = &g->scanout[i]; + + pixman_region_init(&finalregion); + pixman_region_init_rect(®ion, scanout->x, scanout->y, + scanout->width, scanout->height); + + pixman_region_intersect(&finalregion, &flush_region, ®ion); + + extents = pixman_region_extents(&finalregion); + size_t width = extents->x2 - extents->x1; + size_t height = extents->y2 - extents->y1; + + if (vugbm_buffer_can_get_dmabuf_fd(&res->buffer)) { + VhostUserGpuMsg vmsg = { + .request = VHOST_USER_GPU_DMABUF_UPDATE, + .size = sizeof(VhostUserGpuUpdate), + .payload.update = (VhostUserGpuUpdate) { + .scanout_id = i, + .x = extents->x1, + .y = extents->y1, + .width = width, + .height = height, + } + }; + vg_send_msg(g, &vmsg, -1); + vg_wait_ok(g); + } else { + size_t bpp = + PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) / 8; + size_t size = width * height * bpp; + + void *p = g_malloc(VHOST_USER_GPU_HDR_SIZE + + sizeof(VhostUserGpuUpdate) + size); + VhostUserGpuMsg *msg = p; + msg->request = VHOST_USER_GPU_UPDATE; + msg->size = sizeof(VhostUserGpuUpdate) + size; + msg->payload.update = (VhostUserGpuUpdate) { + .scanout_id = i, + .x = extents->x1, + .y = extents->y1, + .width = width, + .height = height, + }; + pixman_image_t *i = + pixman_image_create_bits(pixman_image_get_format(res->image), + msg->payload.update.width, + msg->payload.update.height, + p + offsetof(VhostUserGpuMsg, + payload.update.data), + width * bpp); + pixman_image_composite(PIXMAN_OP_SRC, + res->image, NULL, i, + extents->x1, extents->y1, + 0, 0, 0, 0, + width, height); + pixman_image_unref(i); + vg_send_msg(g, msg, -1); + g_free(msg); + } + pixman_region_fini(®ion); + pixman_region_fini(&finalregion); + } + pixman_region_fini(&flush_region); +} + +static void +vg_process_cmd(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd) +{ + switch (cmd->cmd_hdr.type) { + case VIRTIO_GPU_CMD_GET_DISPLAY_INFO: + vg_get_display_info(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: + vg_resource_create_2d(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_UNREF: + vg_resource_unref(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_FLUSH: + vg_resource_flush(vg, cmd); + break; + case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: + vg_transfer_to_host_2d(vg, cmd); + break; + case VIRTIO_GPU_CMD_SET_SCANOUT: + vg_set_scanout(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING: + vg_resource_attach_backing(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING: + vg_resource_detach_backing(vg, cmd); + break; + /* case VIRTIO_GPU_CMD_GET_EDID: */ + /* break */ + default: + g_warning("TODO handle ctrl %x\n", cmd->cmd_hdr.type); + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + break; + } + if (!cmd->finished) { + vg_ctrl_response_nodata(vg, cmd, cmd->error ? cmd->error : + VIRTIO_GPU_RESP_OK_NODATA); + } +} + +static void +vg_handle_ctrl(VuDev *dev, int qidx) +{ + VuGpu *vg = container_of(dev, VuGpu, dev.parent); + VuVirtq *vq = vu_get_queue(dev, qidx); + struct virtio_gpu_ctrl_command *cmd = NULL; + size_t len; + + for (;;) { + if (vg->wait_ok != 0) { + return; + } + + cmd = vu_queue_pop(dev, vq, sizeof(struct virtio_gpu_ctrl_command)); + if (!cmd) { + break; + } + cmd->vq = vq; + cmd->error = 0; + cmd->finished = false; + + len = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, + 0, &cmd->cmd_hdr, sizeof(cmd->cmd_hdr)); + if (len != sizeof(cmd->cmd_hdr)) { + g_warning("%s: command size incorrect %zu vs %zu\n", + __func__, len, sizeof(cmd->cmd_hdr)); + } + + virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr); + g_debug("%d %s\n", cmd->cmd_hdr.type, + vg_cmd_to_string(cmd->cmd_hdr.type)); + + if (vg->virgl) { + vg_virgl_process_cmd(vg, cmd); + } else { + vg_process_cmd(vg, cmd); + } + + if (!cmd->finished) { + QTAILQ_INSERT_TAIL(&vg->fenceq, cmd, next); + vg->inflight++; + } else { + g_free(cmd); + } + } +} + +static void +update_cursor_data_simple(VuGpu *g, uint32_t resource_id, gpointer data) +{ + struct virtio_gpu_simple_resource *res; + + res = virtio_gpu_find_resource(g, resource_id); + g_return_if_fail(res != NULL); + g_return_if_fail(pixman_image_get_width(res->image) == 64); + g_return_if_fail(pixman_image_get_height(res->image) == 64); + g_return_if_fail( + PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) == 32); + + memcpy(data, pixman_image_get_data(res->image), 64 * 64 * sizeof(uint32_t)); +} + +static void +vg_process_cursor_cmd(VuGpu *g, struct virtio_gpu_update_cursor *cursor) +{ + bool move = cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR; + + g_debug("%s move:%d\n", G_STRFUNC, move); + + if (move) { + VhostUserGpuMsg msg = { + .request = cursor->resource_id ? + VHOST_USER_GPU_CURSOR_POS : VHOST_USER_GPU_CURSOR_POS_HIDE, + .size = sizeof(VhostUserGpuCursorPos), + .payload.cursor_pos = { + .scanout_id = cursor->pos.scanout_id, + .x = cursor->pos.x, + .y = cursor->pos.y, + } + }; + vg_send_msg(g, &msg, -1); + } else { + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_CURSOR_UPDATE, + .size = sizeof(VhostUserGpuCursorUpdate), + .payload.cursor_update = { + .pos = { + .scanout_id = cursor->pos.scanout_id, + .x = cursor->pos.x, + .y = cursor->pos.y, + }, + .hot_x = cursor->hot_x, + .hot_y = cursor->hot_y, + } + }; + if (g->virgl) { + vg_virgl_update_cursor_data(g, cursor->resource_id, + msg.payload.cursor_update.data); + } else { + update_cursor_data_simple(g, cursor->resource_id, + msg.payload.cursor_update.data); + } + vg_send_msg(g, &msg, -1); + } +} + +static void +vg_handle_cursor(VuDev *dev, int qidx) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + VuVirtq *vq = vu_get_queue(dev, qidx); + VuVirtqElement *elem; + size_t len; + struct virtio_gpu_update_cursor cursor; + + for (;;) { + elem = vu_queue_pop(dev, vq, sizeof(VuVirtqElement)); + if (!elem) { + break; + } + g_debug("cursor out:%d in:%d\n", elem->out_num, elem->in_num); + + len = iov_to_buf(elem->out_sg, elem->out_num, + 0, &cursor, sizeof(cursor)); + if (len != sizeof(cursor)) { + g_warning("%s: cursor size incorrect %zu vs %zu\n", + __func__, len, sizeof(cursor)); + } else { + virtio_gpu_bswap_32(&cursor, sizeof(cursor)); + vg_process_cursor_cmd(g, &cursor); + } + vu_queue_push(dev, vq, elem, 0); + vu_queue_notify(dev, vq); + g_free(elem); + } +} + +static void +vg_panic(VuDev *dev, const char *msg) +{ + g_critical("%s\n", msg); + exit(1); +} + +static void +vg_queue_set_started(VuDev *dev, int qidx, bool started) +{ + VuVirtq *vq = vu_get_queue(dev, qidx); + + g_debug("queue started %d:%d\n", qidx, started); + + switch (qidx) { + case 0: + vu_set_queue_handler(dev, vq, started ? vg_handle_ctrl : NULL); + break; + case 1: + vu_set_queue_handler(dev, vq, started ? vg_handle_cursor : NULL); + break; + default: + break; + } +} + +static void +set_gpu_protocol_features(VuGpu *g) +{ + uint64_t u64; + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_GET_PROTOCOL_FEATURES + }; + + assert(g->wait_ok == 0); + vg_send_msg(g, &msg, -1); + if (!vg_recv_msg(g, msg.request, sizeof(u64), &u64)) { + return; + } + + msg = (VhostUserGpuMsg) { + .request = VHOST_USER_GPU_SET_PROTOCOL_FEATURES, + .size = sizeof(uint64_t), + .payload.u64 = 0 + }; + vg_send_msg(g, &msg, -1); +} + +static int +vg_process_msg(VuDev *dev, VhostUserMsg *msg, int *do_reply) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + + switch (msg->request) { + case VHOST_USER_GPU_SET_SOCKET: { + g_return_val_if_fail(msg->fd_num == 1, 1); + g_return_val_if_fail(g->sock_fd == -1, 1); + g->sock_fd = msg->fds[0]; + set_gpu_protocol_features(g); + return 1; + } + default: + return 0; + } + + return 0; +} + +static uint64_t +vg_get_features(VuDev *dev) +{ + uint64_t features = 0; + + if (opt_virgl) { + features |= 1 << VIRTIO_GPU_F_VIRGL; + } + + return features; +} + +static void +vg_set_features(VuDev *dev, uint64_t features) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + bool virgl = features & (1 << VIRTIO_GPU_F_VIRGL); + + if (virgl && !g->virgl_inited) { + if (!vg_virgl_init(g)) { + vg_panic(dev, "Failed to initialize virgl"); + } + g->virgl_inited = true; + } + + g->virgl = virgl; +} + +static int +vg_get_config(VuDev *dev, uint8_t *config, uint32_t len) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + + g_return_val_if_fail(len <= sizeof(struct virtio_gpu_config), -1); + + if (opt_virgl) { + g->virtio_config.num_capsets = vg_virgl_get_num_capsets(); + } + + memcpy(config, &g->virtio_config, len); + + return 0; +} + +static int +vg_set_config(VuDev *dev, const uint8_t *data, + uint32_t offset, uint32_t size, + uint32_t flags) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + struct virtio_gpu_config *config = (struct virtio_gpu_config *)data; + + if (config->events_clear) { + g->virtio_config.events_read &= ~config->events_clear; + } + + return 0; +} + +static const VuDevIface vuiface = { + .set_features = vg_set_features, + .get_features = vg_get_features, + .queue_set_started = vg_queue_set_started, + .process_msg = vg_process_msg, + .get_config = vg_get_config, + .set_config = vg_set_config, +}; + +static void +vg_destroy(VuGpu *g) +{ + struct virtio_gpu_simple_resource *res, *tmp; + + vug_deinit(&g->dev); + + vg_sock_fd_close(g); + + QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) { + vg_resource_destroy(g, res); + } + + vugbm_device_destroy(&g->gdev); +} + +static GOptionEntry entries[] = { + { "print-capabilities", 'c', 0, G_OPTION_ARG_NONE, &opt_print_caps, + "Print capabilities", NULL }, + { "fd", 'f', 0, G_OPTION_ARG_INT, &opt_fdnum, + "Use inherited fd socket", "FDNUM" }, + { "socket-path", 's', 0, G_OPTION_ARG_FILENAME, &opt_socket_path, + "Use UNIX socket path", "PATH" }, + { "render-node", 'r', 0, G_OPTION_ARG_FILENAME, &opt_render_node, + "Specify DRM render node", "PATH" }, + { "virgl", 'v', 0, G_OPTION_ARG_NONE, &opt_virgl, + "Turn virgl rendering on", NULL }, + { NULL, } +}; + +int +main(int argc, char *argv[]) +{ + GOptionContext *context; + GError *error = NULL; + GMainLoop *loop = NULL; + int fd; + VuGpu g = { .sock_fd = -1, .drm_rnode_fd = -1 }; + + QTAILQ_INIT(&g.reslist); + QTAILQ_INIT(&g.fenceq); + + context = g_option_context_new("QEMU vhost-user-gpu"); + g_option_context_add_main_entries(context, entries, NULL); + if (!g_option_context_parse(context, &argc, &argv, &error)) { + g_printerr("Option parsing failed: %s\n", error->message); + exit(EXIT_FAILURE); + } + g_option_context_free(context); + + if (opt_print_caps) { + g_print("{\n"); + g_print(" \"type\": \"gpu\",\n"); + g_print(" \"features\": [\n"); + g_print(" \"render-node\",\n"); + g_print(" \"virgl\"\n"); + g_print(" ]\n"); + g_print("}\n"); + exit(EXIT_SUCCESS); + } + + g.drm_rnode_fd = qemu_drm_rendernode_open(opt_render_node); + if (opt_render_node && g.drm_rnode_fd == -1) { + g_printerr("Failed to open DRM rendernode.\n"); + exit(EXIT_FAILURE); + } + + if (g.drm_rnode_fd >= 0) { + if (!vugbm_device_init(&g.gdev, g.drm_rnode_fd)) { + g_warning("Failed to init DRM device, using fallback path"); + } + } + + if ((!!opt_socket_path + (opt_fdnum != -1)) != 1) { + g_printerr("Please specify either --fd or --socket-path\n"); + exit(EXIT_FAILURE); + } + + if (opt_socket_path) { + int lsock = unix_listen(opt_socket_path, &error_fatal); + if (lsock < 0) { + g_printerr("Failed to listen on %s.\n", opt_socket_path); + exit(EXIT_FAILURE); + } + fd = accept(lsock, NULL, NULL); + close(lsock); + } else { + fd = opt_fdnum; + } + if (fd == -1) { + g_printerr("Invalid vhost-user socket.\n"); + exit(EXIT_FAILURE); + } + + if (!vug_init(&g.dev, VHOST_USER_GPU_MAX_QUEUES, fd, vg_panic, &vuiface)) { + g_printerr("Failed to initialize libvhost-user-glib.\n"); + exit(EXIT_FAILURE); + } + + loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(loop); + g_main_loop_unref(loop); + + vg_destroy(&g); + if (g.drm_rnode_fd >= 0) { + close(g.drm_rnode_fd); + } + + return 0; +} -- cgit v1.1 From bd83c861c0628a64997b7bd95c3bcc2e916baf2e Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Tue, 10 Mar 2020 15:58:06 +0100 Subject: modules: load modules from versioned /var/run dir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On upgrades the old .so files usually are replaced. But on the other hand since a qemu process represents a guest instance it is usually kept around. That makes late addition of dynamic features e.g. 'hot-attach of a ceph disk' fail by trying to load a new version of e.f. block-rbd.so into an old still running qemu binary. This adds a fallback to also load modules from a versioned directory in the temporary /var/run path. That way qemu is providing a way for packaging to store modules of an upgraded qemu package as needed until the next reboot. An example how that can then be used in packaging can be seen in: https://git.launchpad.net/~paelzer/ubuntu/+source/qemu/log/?h=bug-1847361-miss-old-so-on-upgrade-UBUNTU Fixes: https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1847361 Signed-off-by: Christian Ehrhardt Reviewed-by: Daniel P. Berrangé Message-Id: <20200310145806.18335-2-christian.ehrhardt@canonical.com> Signed-off-by: Paolo Bonzini --- configure | 15 +++++++++++++++ util/module.c | 14 ++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/configure b/configure index 1a82683..a7f2c3e 100755 --- a/configure +++ b/configure @@ -405,6 +405,7 @@ EXESUF="" DSOSUF=".so" LDFLAGS_SHARED="-shared" modules="no" +module_upgrades="no" prefix="/usr/local" mandir="\${prefix}/share/man" datadir="\${prefix}/share" @@ -1032,6 +1033,10 @@ for opt do --disable-modules) modules="no" ;; + --disable-module-upgrades) module_upgrades="no" + ;; + --enable-module-upgrades) module_upgrades="yes" + ;; --cpu=*) ;; --target-list=*) target_list="$optarg" @@ -1791,6 +1796,7 @@ disabled with --disable-FEATURE, default is enabled if available: guest-agent-msi build guest agent Windows MSI installation package pie Position Independent Executables modules modules support (non-Windows) + module-upgrades try to load modules from alternate paths for upgrades debug-tcg TCG debugging (default is disabled) debug-info debugging information sparse sparse checker @@ -2055,6 +2061,11 @@ if test "$modules" = "yes" && test "$mingw32" = "yes" ; then error_exit "Modules are not available for Windows" fi +# module_upgrades is only reasonable if modules are enabled +if test "$modules" = "no" && test "$module_upgrades" = "yes" ; then + error_exit "Can't enable module-upgrades as Modules are not enabled" +fi + # Static linking is not possible with modules or PIE if test "$static" = "yes" ; then if test "$modules" = "yes" ; then @@ -6626,6 +6637,7 @@ if test "$slirp" != "no" ; then echo "smbd $smbd" fi echo "module support $modules" +echo "alt path mod load $module_upgrades" echo "host CPU $cpu" echo "host big endian $bigendian" echo "target list $target_list" @@ -6980,6 +6992,9 @@ if test "$modules" = "yes"; then echo "CONFIG_STAMP=_$( (echo $qemu_version; echo $pkgversion; cat $0) | $shacmd - | cut -f1 -d\ )" >> $config_host_mak echo "CONFIG_MODULES=y" >> $config_host_mak fi +if test "$module_upgrades" = "yes"; then + echo "CONFIG_MODULE_UPGRADES=y" >> $config_host_mak +fi if test "$have_x11" = "yes" && test "$need_x11" = "yes"; then echo "CONFIG_X11=y" >> $config_host_mak echo "X11_CFLAGS=$x11_cflags" >> $config_host_mak diff --git a/util/module.c b/util/module.c index 236a7bb..5f78968 100644 --- a/util/module.c +++ b/util/module.c @@ -19,6 +19,9 @@ #endif #include "qemu/queue.h" #include "qemu/module.h" +#ifdef CONFIG_MODULE_UPGRADES +#include "qemu-version.h" +#endif typedef struct ModuleEntry { @@ -170,6 +173,9 @@ bool module_load_one(const char *prefix, const char *lib_name) #ifdef CONFIG_MODULES char *fname = NULL; char *exec_dir; +#ifdef CONFIG_MODULE_UPGRADES + char *version_dir; +#endif const char *search_dir; char *dirs[4]; char *module_name; @@ -201,6 +207,14 @@ bool module_load_one(const char *prefix, const char *lib_name) dirs[n_dirs++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR); dirs[n_dirs++] = g_strdup_printf("%s/..", exec_dir ? : ""); dirs[n_dirs++] = g_strdup_printf("%s", exec_dir ? : ""); + +#ifdef CONFIG_MODULE_UPGRADES + version_dir = g_strcanon(g_strdup(QEMU_PKGVERSION), + G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "+-.~", + '_'); + dirs[n_dirs++] = g_strdup_printf("/var/run/qemu/%s", version_dir); +#endif + assert(n_dirs <= ARRAY_SIZE(dirs)); g_free(exec_dir); -- cgit v1.1 From bd702ffc506b62623bb5c246f7b706be098038b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 9 Mar 2020 13:24:53 +0100 Subject: configure: Fix building with SASL on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Simple Authentication and Security Layer (SASL) library re-defines the struct iovec on Win32 [*]. QEMU also re-defines it in "qemu/osdep.h". The two definitions then clash on a MinGW build. We can avoid the SASL definition by defining STRUCT_IOVEC_DEFINED. Since QEMU already defines 'struct iovec' if it is missing, add the definition to vnc_sasl_cflags to avoid SASL re-defining it. [*] https://github.com/cyrusimap/cyrus-sasl/blob/cyrus-sasl-2.1.27/include/sasl.h#L187 Cc: Alexey Pavlov Cc: Biswapriyo Nath Reported-by: Youry Metlitsky Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20200309122454.22551-2-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- configure | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure b/configure index a7f2c3e..44a70cf 100755 --- a/configure +++ b/configure @@ -3367,7 +3367,9 @@ if test "$vnc" = "yes" && test "$vnc_sasl" != "no" ; then int main(void) { sasl_server_init(NULL, "qemu"); return 0; } EOF # Assuming Cyrus-SASL installed in /usr prefix - vnc_sasl_cflags="" + # QEMU defines struct iovec in "qemu/osdep.h", + # we don't want libsasl to redefine it in . + vnc_sasl_cflags="-DSTRUCT_IOVEC_DEFINED" vnc_sasl_libs="-lsasl2" if compile_prog "$vnc_sasl_cflags" "$vnc_sasl_libs" ; then vnc_sasl=yes -- cgit v1.1 From a4aad716cbda2ea480ba294cfc7690bef3927f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 9 Mar 2020 13:24:54 +0100 Subject: tests/docker: Install SASL library to extend code coverage on amd64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Install the SASL library to build the VNC SASL auth protocol code. Reviewed-by: Daniel P. Berrangé Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20200309122454.22551-3-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- tests/docker/dockerfiles/debian-amd64.docker | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/docker/dockerfiles/debian-amd64.docker b/tests/docker/dockerfiles/debian-amd64.docker index 3b860af..0456fc7 100644 --- a/tests/docker/dockerfiles/debian-amd64.docker +++ b/tests/docker/dockerfiles/debian-amd64.docker @@ -17,6 +17,7 @@ RUN apt update && \ libbz2-dev \ liblzo2-dev \ librdmacm-dev \ + libsasl2-dev \ libsnappy-dev \ libvte-dev -- cgit v1.1 From 25aa6b3718b6bc936b24045e8f8ba98b47170320 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Tue, 18 Feb 2020 03:19:10 -0700 Subject: memory: Fix start offset for bitmap log_clear hook Currently only the final page offset is being passed to the `log_clear` hook via `memory_region_clear_dirty_bitmap` after it is used as an iterator in `cpu_physical_memory_test_and_clear_dirty`. This patch corrects the start address and size of the region. Signed-off-by: Matt Borgerson Reviewed-by: Peter Xu Signed-off-by: Paolo Bonzini --- exec.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/exec.c b/exec.c index 0cc500d..de9d949 100644 --- a/exec.c +++ b/exec.c @@ -1315,7 +1315,7 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, unsigned client) { DirtyMemoryBlocks *blocks; - unsigned long end, page; + unsigned long end, page, start_page; bool dirty = false; RAMBlock *ramblock; uint64_t mr_offset, mr_size; @@ -1325,7 +1325,8 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, } end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; - page = start >> TARGET_PAGE_BITS; + start_page = start >> TARGET_PAGE_BITS; + page = start_page; WITH_RCU_READ_LOCK_GUARD() { blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); @@ -1345,8 +1346,8 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, page += num; } - mr_offset = (ram_addr_t)(page << TARGET_PAGE_BITS) - ramblock->offset; - mr_size = (end - page) << TARGET_PAGE_BITS; + mr_offset = (ram_addr_t)(start_page << TARGET_PAGE_BITS) - ramblock->offset; + mr_size = (end - start_page) << TARGET_PAGE_BITS; memory_region_clear_dirty_bitmap(ramblock->mr, mr_offset, mr_size); } -- cgit v1.1 From 836e1b3813c522a9e46f70a10d427f70ff590d77 Mon Sep 17 00:00:00 2001 From: Felipe Franciosi Date: Tue, 4 Feb 2020 13:15:58 +0000 Subject: qom/object: enable setter for uint types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Traditionally, the uint-specific property helpers only offer getters. When adding object (or class) uint types, one must therefore use the generic property helper if a setter is needed (and probably duplicate some code writing their own getters/setters). This enhances the uint-specific property helper APIs by adding a bitwise-or'd 'flags' field and modifying all clients of that API to set this paramater to OBJ_PROP_FLAG_READ. This maintains the current behaviour whilst allowing others to also set OBJ_PROP_FLAG_WRITE (or use the more convenient OBJ_PROP_FLAG_READWRITE) in the future (which will automatically install a setter). Other flags may be added later. Signed-off-by: Felipe Franciosi Reviewed-by: Marc-André Lureau Signed-off-by: Paolo Bonzini --- hw/acpi/ich9.c | 4 +- hw/acpi/pcihp.c | 7 +- hw/acpi/piix4.c | 12 +-- hw/isa/lpc_ich9.c | 4 +- hw/ppc/spapr_drc.c | 3 +- include/qom/object.h | 48 ++++++++++-- qom/object.c | 212 +++++++++++++++++++++++++++++++++++++++++++++------ ui/console.c | 4 +- 8 files changed, 246 insertions(+), 48 deletions(-) diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 4e74284..67fe05a 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -454,12 +454,12 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp) pm->s4_val = 2; object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, - &pm->pm_io_base, errp); + &pm->pm_io_base, OBJ_PROP_FLAG_READ, errp); object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32", ich9_pm_get_gpe0_blk, NULL, NULL, pm, NULL); object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN, - &gpe0_len, errp); + &gpe0_len, OBJ_PROP_FLAG_READ, errp); object_property_add_bool(obj, "memory-hotplug-support", ich9_pm_get_memory_hotplug_support, ich9_pm_set_memory_hotplug_support, diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index 8413348..4dcef37 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -80,7 +80,8 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque) *bus_bsel = (*bsel_alloc)++; object_property_add_uint32_ptr(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, - bus_bsel, &error_abort); + bus_bsel, OBJ_PROP_FLAG_READ, + &error_abort); } return bsel_alloc; @@ -373,9 +374,9 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus, memory_region_add_subregion(address_space_io, s->io_base, &s->io); object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_BASE_PROP, &s->io_base, - &error_abort); + OBJ_PROP_FLAG_READ, &error_abort); object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_LEN_PROP, &s->io_len, - &error_abort); + OBJ_PROP_FLAG_READ, &error_abort); } const VMStateDescription vmstate_acpi_pcihp_pci_status = { diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index b84dbba..964d6f5 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -444,17 +444,17 @@ static void piix4_pm_add_propeties(PIIX4PMState *s) static const uint16_t sci_int = 9; object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_ENABLE_CMD, - &acpi_enable_cmd, NULL); + &acpi_enable_cmd, OBJ_PROP_FLAG_READ, NULL); object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_DISABLE_CMD, - &acpi_disable_cmd, NULL); + &acpi_disable_cmd, OBJ_PROP_FLAG_READ, NULL); object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK, - &gpe0_blk, NULL); + &gpe0_blk, OBJ_PROP_FLAG_READ, NULL); object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK_LEN, - &gpe0_blk_len, NULL); + &gpe0_blk_len, OBJ_PROP_FLAG_READ, NULL); object_property_add_uint16_ptr(OBJECT(s), ACPI_PM_PROP_SCI_INT, - &sci_int, NULL); + &sci_int, OBJ_PROP_FLAG_READ, NULL); object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_PM_IO_BASE, - &s->io_base, NULL); + &s->io_base, OBJ_PROP_FLAG_READ, NULL); } static void piix4_pm_realize(PCIDevice *dev, Error **errp) diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index cb79616..d8186f5 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -643,9 +643,9 @@ static void ich9_lpc_add_properties(ICH9LPCState *lpc) ich9_lpc_get_sci_int, NULL, NULL, NULL, NULL); object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD, - &acpi_enable_cmd, NULL); + &acpi_enable_cmd, OBJ_PROP_FLAG_READ, NULL); object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD, - &acpi_disable_cmd, NULL); + &acpi_disable_cmd, OBJ_PROP_FLAG_READ, NULL); ich9_pm_add_properties(OBJECT(lpc), &lpc->pm, NULL); } diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index e373d34..47e6bb1 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -583,7 +583,8 @@ static void spapr_dr_connector_instance_init(Object *obj) SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj); SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - object_property_add_uint32_ptr(obj, "id", &drc->id, NULL); + object_property_add_uint32_ptr(obj, "id", &drc->id, OBJ_PROP_FLAG_READ, + NULL); object_property_add(obj, "index", "uint32", prop_get_index, NULL, NULL, NULL, NULL); object_property_add(obj, "fdt", "struct", prop_get_fdt, diff --git a/include/qom/object.h b/include/qom/object.h index 2954649..784c97c 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -1664,69 +1664,101 @@ ObjectProperty *object_class_property_add_tm(ObjectClass *klass, void (*get)(Object *, struct tm *, Error **), Error **errp); +typedef enum { + /* Automatically add a getter to the property */ + OBJ_PROP_FLAG_READ = 1 << 0, + /* Automatically add a setter to the property */ + OBJ_PROP_FLAG_WRITE = 1 << 1, + /* Automatically add a getter and a setter to the property */ + OBJ_PROP_FLAG_READWRITE = (OBJ_PROP_FLAG_READ | OBJ_PROP_FLAG_WRITE), +} ObjectPropertyFlags; + /** * object_property_add_uint8_ptr: * @obj: the object to add a property to * @name: the name of the property * @v: pointer to value + * @flags: bitwise-or'd ObjectPropertyFlags * @errp: if an error occurs, a pointer to an area to store the error * * Add an integer property in memory. This function will add a * property of type 'uint8'. */ void object_property_add_uint8_ptr(Object *obj, const char *name, - const uint8_t *v, Error **errp); + const uint8_t *v, ObjectPropertyFlags flags, + Error **errp); + ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, - const uint8_t *v, Error **errp); + const uint8_t *v, + ObjectPropertyFlags flags, + Error **errp); /** * object_property_add_uint16_ptr: * @obj: the object to add a property to * @name: the name of the property * @v: pointer to value + * @flags: bitwise-or'd ObjectPropertyFlags * @errp: if an error occurs, a pointer to an area to store the error * * Add an integer property in memory. This function will add a * property of type 'uint16'. */ void object_property_add_uint16_ptr(Object *obj, const char *name, - const uint16_t *v, Error **errp); + const uint16_t *v, + ObjectPropertyFlags flags, + Error **errp); + ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, - const uint16_t *v, Error **errp); + const uint16_t *v, + ObjectPropertyFlags flags, + Error **errp); /** * object_property_add_uint32_ptr: * @obj: the object to add a property to * @name: the name of the property * @v: pointer to value + * @flags: bitwise-or'd ObjectPropertyFlags * @errp: if an error occurs, a pointer to an area to store the error * * Add an integer property in memory. This function will add a * property of type 'uint32'. */ void object_property_add_uint32_ptr(Object *obj, const char *name, - const uint32_t *v, Error **errp); + const uint32_t *v, + ObjectPropertyFlags flags, + Error **errp); + ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, - const uint32_t *v, Error **errp); + const uint32_t *v, + ObjectPropertyFlags flags, + Error **errp); /** * object_property_add_uint64_ptr: * @obj: the object to add a property to * @name: the name of the property * @v: pointer to value + * @flags: bitwise-or'd ObjectPropertyFlags * @errp: if an error occurs, a pointer to an area to store the error * * Add an integer property in memory. This function will add a * property of type 'uint64'. */ void object_property_add_uint64_ptr(Object *obj, const char *name, - const uint64_t *v, Error **errp); + const uint64_t *v, + ObjectPropertyFlags flags, + Error **Errp); + ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name, - const uint64_t *v, Error **errp); + const uint64_t *v, + ObjectPropertyFlags flags, + Error **Errp); /** * object_property_add_alias: diff --git a/qom/object.c b/qom/object.c index 555c8b9..1812f79 100644 --- a/qom/object.c +++ b/qom/object.c @@ -2498,6 +2498,22 @@ static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name, visit_type_uint8(v, name, &value, errp); } +static void property_set_uint8_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint8_t *field = opaque; + uint8_t value; + Error *local_err = NULL; + + visit_type_uint8(v, name, &value, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + *field = value; +} + static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -2505,6 +2521,22 @@ static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name, visit_type_uint16(v, name, &value, errp); } +static void property_set_uint16_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint16_t *field = opaque; + uint16_t value; + Error *local_err = NULL; + + visit_type_uint16(v, name, &value, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + *field = value; +} + static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -2512,6 +2544,22 @@ static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name, visit_type_uint32(v, name, &value, errp); } +static void property_set_uint32_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint32_t *field = opaque; + uint32_t value; + Error *local_err = NULL; + + visit_type_uint32(v, name, &value, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + *field = value; +} + static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -2519,68 +2567,184 @@ static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name, visit_type_uint64(v, name, &value, errp); } +static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint64_t *field = opaque; + uint64_t value; + Error *local_err = NULL; + + visit_type_uint64(v, name, &value, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + *field = value; +} + void object_property_add_uint8_ptr(Object *obj, const char *name, - const uint8_t *v, Error **errp) + const uint8_t *v, + ObjectPropertyFlags flags, + Error **errp) { - object_property_add(obj, name, "uint8", property_get_uint8_ptr, - NULL, NULL, (void *)v, errp); + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; + + if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { + getter = property_get_uint8_ptr; + } + + if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { + setter = property_set_uint8_ptr; + } + + object_property_add(obj, name, "uint8", + getter, setter, NULL, (void *)v, errp); } ObjectProperty * object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, - const uint8_t *v, Error **errp) + const uint8_t *v, + ObjectPropertyFlags flags, + Error **errp) { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; + + if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { + getter = property_get_uint8_ptr; + } + + if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { + setter = property_set_uint8_ptr; + } + return object_class_property_add(klass, name, "uint8", - property_get_uint8_ptr, - NULL, NULL, (void *)v, errp); + getter, setter, NULL, (void *)v, errp); } void object_property_add_uint16_ptr(Object *obj, const char *name, - const uint16_t *v, Error **errp) + const uint16_t *v, + ObjectPropertyFlags flags, + Error **errp) { - object_property_add(obj, name, "uint16", property_get_uint16_ptr, - NULL, NULL, (void *)v, errp); + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; + + if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { + getter = property_get_uint16_ptr; + } + + if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { + setter = property_set_uint16_ptr; + } + + object_property_add(obj, name, "uint16", + getter, setter, NULL, (void *)v, errp); } ObjectProperty * object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, - const uint16_t *v, Error **errp) + const uint16_t *v, + ObjectPropertyFlags flags, + Error **errp) { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; + + if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { + getter = property_get_uint16_ptr; + } + + if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { + setter = property_set_uint16_ptr; + } + return object_class_property_add(klass, name, "uint16", - property_get_uint16_ptr, - NULL, NULL, (void *)v, errp); + getter, setter, NULL, (void *)v, errp); } void object_property_add_uint32_ptr(Object *obj, const char *name, - const uint32_t *v, Error **errp) + const uint32_t *v, + ObjectPropertyFlags flags, + Error **errp) { - object_property_add(obj, name, "uint32", property_get_uint32_ptr, - NULL, NULL, (void *)v, errp); + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; + + if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { + getter = property_get_uint32_ptr; + } + + if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { + setter = property_set_uint32_ptr; + } + + object_property_add(obj, name, "uint32", + getter, setter, NULL, (void *)v, errp); } ObjectProperty * object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, - const uint32_t *v, Error **errp) + const uint32_t *v, + ObjectPropertyFlags flags, + Error **errp) { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; + + if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { + getter = property_get_uint32_ptr; + } + + if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { + setter = property_set_uint32_ptr; + } + return object_class_property_add(klass, name, "uint32", - property_get_uint32_ptr, - NULL, NULL, (void *)v, errp); + getter, setter, NULL, (void *)v, errp); } void object_property_add_uint64_ptr(Object *obj, const char *name, - const uint64_t *v, Error **errp) + const uint64_t *v, + ObjectPropertyFlags flags, + Error **errp) { - object_property_add(obj, name, "uint64", property_get_uint64_ptr, - NULL, NULL, (void *)v, errp); + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; + + if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { + getter = property_get_uint64_ptr; + } + + if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { + setter = property_set_uint64_ptr; + } + + object_property_add(obj, name, "uint64", + getter, setter, NULL, (void *)v, errp); } ObjectProperty * object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name, - const uint64_t *v, Error **errp) + const uint64_t *v, + ObjectPropertyFlags flags, + Error **errp) { + ObjectPropertyAccessor *getter = NULL; + ObjectPropertyAccessor *setter = NULL; + + if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { + getter = property_get_uint64_ptr; + } + + if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { + setter = property_set_uint64_ptr; + } + return object_class_property_add(klass, name, "uint64", - property_get_uint64_ptr, - NULL, NULL, (void *)v, errp); + getter, setter, NULL, (void *)v, errp); } typedef struct { diff --git a/ui/console.c b/ui/console.c index 179901c..184e173 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1299,8 +1299,8 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, object_property_allow_set_link, OBJ_PROP_LINK_STRONG, &error_abort); - object_property_add_uint32_ptr(obj, "head", - &s->head, &error_abort); + object_property_add_uint32_ptr(obj, "head", &s->head, + OBJ_PROP_FLAG_READ, &error_abort); if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) && (console_type == GRAPHIC_CONSOLE))) { -- cgit v1.1 From 1f63daa0150599165e42d8779a037dd2bc302a4b Mon Sep 17 00:00:00 2001 From: Felipe Franciosi Date: Tue, 4 Feb 2020 13:15:59 +0000 Subject: ich9: fix getter type for sci_int property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When QOM APIs were added to ich9 in 6f1426ab, the getter for sci_int was written using uint32_t. However, the object property is uint8_t. This fixes the getter for correctness. Signed-off-by: Felipe Franciosi Reviewed-by: Marc-André Lureau Signed-off-by: Paolo Bonzini --- hw/isa/lpc_ich9.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index d8186f5..2471463 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -629,9 +629,7 @@ static void ich9_lpc_get_sci_int(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj); - uint32_t value = lpc->sci_gsi; - - visit_type_uint32(v, name, &value, errp); + visit_type_uint8(v, name, &lpc->sci_gsi, errp); } static void ich9_lpc_add_properties(ICH9LPCState *lpc) @@ -639,7 +637,7 @@ static void ich9_lpc_add_properties(ICH9LPCState *lpc) static const uint8_t acpi_enable_cmd = ICH9_APM_ACPI_ENABLE; static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE; - object_property_add(OBJECT(lpc), ACPI_PM_PROP_SCI_INT, "uint32", + object_property_add(OBJECT(lpc), ACPI_PM_PROP_SCI_INT, "uint8", ich9_lpc_get_sci_int, NULL, NULL, NULL, NULL); object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD, -- cgit v1.1 From a8c1e3bbeeb567239cd5a7f0910ab87b91b0872d Mon Sep 17 00:00:00 2001 From: Felipe Franciosi Date: Tue, 4 Feb 2020 13:16:00 +0000 Subject: ich9: Simplify ich9_lpc_initfn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, ich9_lpc_initfn simply serves as a caller to ich9_lpc_add_properties. This simplifies the code a bit by eliminating ich9_lpc_add_properties altogether and executing its logic in the parent object initialiser function. Signed-off-by: Felipe Franciosi Reviewed-by: Marc-André Lureau Signed-off-by: Paolo Bonzini --- hw/isa/lpc_ich9.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 2471463..3d0f4db 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -632,12 +632,14 @@ static void ich9_lpc_get_sci_int(Object *obj, Visitor *v, const char *name, visit_type_uint8(v, name, &lpc->sci_gsi, errp); } -static void ich9_lpc_add_properties(ICH9LPCState *lpc) +static void ich9_lpc_initfn(Object *obj) { + ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj); + static const uint8_t acpi_enable_cmd = ICH9_APM_ACPI_ENABLE; static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE; - object_property_add(OBJECT(lpc), ACPI_PM_PROP_SCI_INT, "uint8", + object_property_add(obj, ACPI_PM_PROP_SCI_INT, "uint8", ich9_lpc_get_sci_int, NULL, NULL, NULL, NULL); object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD, @@ -645,14 +647,7 @@ static void ich9_lpc_add_properties(ICH9LPCState *lpc) object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD, &acpi_disable_cmd, OBJ_PROP_FLAG_READ, NULL); - ich9_pm_add_properties(OBJECT(lpc), &lpc->pm, NULL); -} - -static void ich9_lpc_initfn(Object *obj) -{ - ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj); - - ich9_lpc_add_properties(lpc); + ich9_pm_add_properties(obj, &lpc->pm, NULL); } static void ich9_lpc_realize(PCIDevice *d, Error **errp) -- cgit v1.1 From 64a7b8de42aff54dce4d82585f25060a741531d1 Mon Sep 17 00:00:00 2001 From: Felipe Franciosi Date: Tue, 4 Feb 2020 13:16:01 +0000 Subject: qom/object: Use common get/set uint helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several objects implemented their own uint property getters and setters, despite them being straightforward (without any checks/validations on the values themselves) and identical across objects. This makes use of an enhanced API for object_property_add_uintXX_ptr() which offers default setters. Some of these setters used to update the value even if the type visit failed (eg. because the value being set overflowed over the given type). The new setter introduces a check for these errors, not updating the value if an error occurred. The error is propagated. Signed-off-by: Felipe Franciosi Reviewed-by: Marc-André Lureau Signed-off-by: Paolo Bonzini --- hw/acpi/ich9.c | 95 +++++------------------------------------------- hw/isa/lpc_ich9.c | 12 ++----- hw/misc/edu.c | 13 ++----- hw/pci-host/q35.c | 14 ++------ hw/ppc/spapr.c | 36 ++++--------------- memory.c | 15 ++------ target/arm/cpu.c | 22 ++---------- target/i386/sev.c | 106 +++++------------------------------------------------- 8 files changed, 37 insertions(+), 276 deletions(-) diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 67fe05a..336cace 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -357,81 +357,6 @@ static void ich9_pm_set_cpu_hotplug_legacy(Object *obj, bool value, s->pm.cpu_hotplug_legacy = value; } -static void ich9_pm_get_disable_s3(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ICH9LPCPMRegs *pm = opaque; - uint8_t value = pm->disable_s3; - - visit_type_uint8(v, name, &value, errp); -} - -static void ich9_pm_set_disable_s3(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ICH9LPCPMRegs *pm = opaque; - Error *local_err = NULL; - uint8_t value; - - visit_type_uint8(v, name, &value, &local_err); - if (local_err) { - goto out; - } - pm->disable_s3 = value; -out: - error_propagate(errp, local_err); -} - -static void ich9_pm_get_disable_s4(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ICH9LPCPMRegs *pm = opaque; - uint8_t value = pm->disable_s4; - - visit_type_uint8(v, name, &value, errp); -} - -static void ich9_pm_set_disable_s4(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ICH9LPCPMRegs *pm = opaque; - Error *local_err = NULL; - uint8_t value; - - visit_type_uint8(v, name, &value, &local_err); - if (local_err) { - goto out; - } - pm->disable_s4 = value; -out: - error_propagate(errp, local_err); -} - -static void ich9_pm_get_s4_val(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ICH9LPCPMRegs *pm = opaque; - uint8_t value = pm->s4_val; - - visit_type_uint8(v, name, &value, errp); -} - -static void ich9_pm_set_s4_val(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ICH9LPCPMRegs *pm = opaque; - Error *local_err = NULL; - uint8_t value; - - visit_type_uint8(v, name, &value, &local_err); - if (local_err) { - goto out; - } - pm->s4_val = value; -out: - error_propagate(errp, local_err); -} - static bool ich9_pm_get_enable_tco(Object *obj, Error **errp) { ICH9LPCState *s = ICH9_LPC_DEVICE(obj); @@ -468,18 +393,14 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp) ich9_pm_get_cpu_hotplug_legacy, ich9_pm_set_cpu_hotplug_legacy, NULL); - object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8", - ich9_pm_get_disable_s3, - ich9_pm_set_disable_s3, - NULL, pm, NULL); - object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8", - ich9_pm_get_disable_s4, - ich9_pm_set_disable_s4, - NULL, pm, NULL); - object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8", - ich9_pm_get_s4_val, - ich9_pm_set_s4_val, - NULL, pm, NULL); + object_property_add_uint8_ptr(obj, ACPI_PM_PROP_S3_DISABLED, + &pm->disable_s3, OBJ_PROP_FLAG_READWRITE, + NULL); + object_property_add_uint8_ptr(obj, ACPI_PM_PROP_S4_DISABLED, + &pm->disable_s4, OBJ_PROP_FLAG_READWRITE, + NULL); + object_property_add_uint8_ptr(obj, ACPI_PM_PROP_S4_VAL, + &pm->s4_val, OBJ_PROP_FLAG_READWRITE, NULL); object_property_add_bool(obj, ACPI_PM_PROP_TCO_ENABLED, ich9_pm_get_enable_tco, ich9_pm_set_enable_tco, diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 3d0f4db..fbc3165 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -625,13 +625,6 @@ static const MemoryRegionOps ich9_rst_cnt_ops = { .endianness = DEVICE_LITTLE_ENDIAN }; -static void ich9_lpc_get_sci_int(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj); - visit_type_uint8(v, name, &lpc->sci_gsi, errp); -} - static void ich9_lpc_initfn(Object *obj) { ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj); @@ -639,9 +632,8 @@ static void ich9_lpc_initfn(Object *obj) static const uint8_t acpi_enable_cmd = ICH9_APM_ACPI_ENABLE; static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE; - object_property_add(obj, ACPI_PM_PROP_SCI_INT, "uint8", - ich9_lpc_get_sci_int, - NULL, NULL, NULL, NULL); + object_property_add_uint8_ptr(obj, ACPI_PM_PROP_SCI_INT, + &lpc->sci_gsi, OBJ_PROP_FLAG_READ, NULL); object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD, &acpi_enable_cmd, OBJ_PROP_FLAG_READ, NULL); object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD, diff --git a/hw/misc/edu.c b/hw/misc/edu.c index d5e2bdb..ff10f5b 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -396,21 +396,14 @@ static void pci_edu_uninit(PCIDevice *pdev) msi_uninit(pdev); } -static void edu_obj_uint64(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - uint64_t *val = opaque; - - visit_type_uint64(v, name, val, errp); -} - static void edu_instance_init(Object *obj) { EduState *edu = EDU(obj); edu->dma_mask = (1UL << 28) - 1; - object_property_add(obj, "dma_mask", "uint64", edu_obj_uint64, - edu_obj_uint64, NULL, &edu->dma_mask, NULL); + object_property_add_uint64_ptr(obj, "dma_mask", + &edu->dma_mask, OBJ_PROP_FLAG_READWRITE, + NULL); } static void edu_class_init(ObjectClass *class, void *data) diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 993f467..2bbc90b 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -166,14 +166,6 @@ static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v, visit_type_uint64(v, name, &value, errp); } -static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - PCIExpressHost *e = PCIE_HOST_BRIDGE(obj); - - visit_type_uint64(v, name, &e->size, errp); -} - /* * NOTE: setting defaults for the mch.* fields in this table * doesn't work, because mch is a separate QOM object that is @@ -214,6 +206,7 @@ static void q35_host_initfn(Object *obj) { Q35PCIHost *s = Q35_HOST_DEVICE(obj); PCIHostState *phb = PCI_HOST_BRIDGE(obj); + PCIExpressHost *pehb = PCIE_HOST_BRIDGE(obj); memory_region_init_io(&phb->conf_mem, obj, &pci_host_conf_le_ops, phb, "pci-conf-idx", 4); @@ -243,9 +236,8 @@ static void q35_host_initfn(Object *obj) q35_host_get_pci_hole64_end, NULL, NULL, NULL, NULL); - object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint64", - q35_host_get_mmcfg_size, - NULL, NULL, NULL, NULL); + object_property_add_uint64_ptr(obj, PCIE_HOST_MCFG_SIZE, + &pehb->size, OBJ_PROP_FLAG_READ, NULL); object_property_add_link(obj, MCH_HOST_PROP_RAM_MEM, TYPE_MEMORY_REGION, (Object **) &s->mch.ram_memory, diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index cc10798..41c0f24 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3223,30 +3223,6 @@ static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) } } -static void spapr_get_vsmt(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - visit_type_uint32(v, name, (uint32_t *)opaque, errp); -} - -static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - visit_type_uint32(v, name, (uint32_t *)opaque, errp); -} - -static void spapr_get_kernel_addr(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - visit_type_uint64(v, name, (uint64_t *)opaque, errp); -} - -static void spapr_set_kernel_addr(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - visit_type_uint64(v, name, (uint64_t *)opaque, errp); -} - static char *spapr_get_ic_mode(Object *obj, Error **errp) { SpaprMachineState *spapr = SPAPR_MACHINE(obj); @@ -3344,17 +3320,19 @@ static void spapr_instance_init(Object *obj) object_property_set_description(obj, "resize-hpt", "Resizing of the Hash Page Table (enabled, disabled, required)", NULL); - object_property_add(obj, "vsmt", "uint32", spapr_get_vsmt, - spapr_set_vsmt, NULL, &spapr->vsmt, &error_abort); + object_property_add_uint32_ptr(obj, "vsmt", + &spapr->vsmt, OBJ_PROP_FLAG_READWRITE, + &error_abort); object_property_set_description(obj, "vsmt", "Virtual SMT: KVM behaves as if this were" " the host's SMT mode", &error_abort); + object_property_add_bool(obj, "vfio-no-msix-emulation", spapr_get_msix_emulation, NULL, NULL); - object_property_add(obj, "kernel-addr", "uint64", spapr_get_kernel_addr, - spapr_set_kernel_addr, NULL, &spapr->kernel_addr, - &error_abort); + object_property_add_uint64_ptr(obj, "kernel-addr", + &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE, + &error_abort); object_property_set_description(obj, "kernel-addr", stringify(KERNEL_LOAD_ADDR) " for -kernel is the default", diff --git a/memory.c b/memory.c index 09be40e..404ff4e 100644 --- a/memory.c +++ b/memory.c @@ -1170,15 +1170,6 @@ void memory_region_init(MemoryRegion *mr, memory_region_do_init(mr, owner, name, size); } -static void memory_region_get_addr(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - MemoryRegion *mr = MEMORY_REGION(obj); - uint64_t value = mr->addr; - - visit_type_uint64(v, name, &value, errp); -} - static void memory_region_get_container(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -1242,10 +1233,8 @@ static void memory_region_initfn(Object *obj) NULL, NULL, &error_abort); op->resolve = memory_region_resolve_container; - object_property_add(OBJECT(mr), "addr", "uint64", - memory_region_get_addr, - NULL, /* memory_region_set_addr */ - NULL, NULL, &error_abort); + object_property_add_uint64_ptr(OBJECT(mr), "addr", + &mr->addr, OBJ_PROP_FLAG_READ, &error_abort); object_property_add(OBJECT(mr), "priority", "uint32", memory_region_get_priority, NULL, /* memory_region_set_priority */ diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 3623ece..7fe3670 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1153,22 +1153,6 @@ static void arm_set_pmu(Object *obj, bool value, Error **errp) cpu->has_pmu = value; } -static void arm_get_init_svtor(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ARMCPU *cpu = ARM_CPU(obj); - - visit_type_uint32(v, name, &cpu->init_svtor, errp); -} - -static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - ARMCPU *cpu = ARM_CPU(obj); - - visit_type_uint32(v, name, &cpu->init_svtor, errp); -} - unsigned int gt_cntfrq_period_ns(ARMCPU *cpu) { /* @@ -1288,9 +1272,9 @@ void arm_cpu_post_init(Object *obj) * a simple DEFINE_PROP_UINT32 for this because we want to permit * the property to be set after realize. */ - object_property_add(obj, "init-svtor", "uint32", - arm_get_init_svtor, arm_set_init_svtor, - NULL, NULL, &error_abort); + object_property_add_uint32_ptr(obj, "init-svtor", + &cpu->init_svtor, + OBJ_PROP_FLAG_READWRITE, &error_abort); } qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property); diff --git a/target/i386/sev.c b/target/i386/sev.c index 024bb24..846018a 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -267,109 +267,21 @@ qsev_guest_class_init(ObjectClass *oc, void *data) } static void -qsev_guest_set_handle(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); - uint32_t value; - - visit_type_uint32(v, name, &value, errp); - sev->handle = value; -} - -static void -qsev_guest_set_policy(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); - uint32_t value; - - visit_type_uint32(v, name, &value, errp); - sev->policy = value; -} - -static void -qsev_guest_set_cbitpos(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); - uint32_t value; - - visit_type_uint32(v, name, &value, errp); - sev->cbitpos = value; -} - -static void -qsev_guest_set_reduced_phys_bits(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); - uint32_t value; - - visit_type_uint32(v, name, &value, errp); - sev->reduced_phys_bits = value; -} - -static void -qsev_guest_get_policy(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - uint32_t value; - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); - - value = sev->policy; - visit_type_uint32(v, name, &value, errp); -} - -static void -qsev_guest_get_handle(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - uint32_t value; - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); - - value = sev->handle; - visit_type_uint32(v, name, &value, errp); -} - -static void -qsev_guest_get_cbitpos(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - uint32_t value; - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); - - value = sev->cbitpos; - visit_type_uint32(v, name, &value, errp); -} - -static void -qsev_guest_get_reduced_phys_bits(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - uint32_t value; - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); - - value = sev->reduced_phys_bits; - visit_type_uint32(v, name, &value, errp); -} - -static void qsev_guest_init(Object *obj) { QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE); sev->policy = DEFAULT_GUEST_POLICY; - object_property_add(obj, "policy", "uint32", qsev_guest_get_policy, - qsev_guest_set_policy, NULL, NULL, NULL); - object_property_add(obj, "handle", "uint32", qsev_guest_get_handle, - qsev_guest_set_handle, NULL, NULL, NULL); - object_property_add(obj, "cbitpos", "uint32", qsev_guest_get_cbitpos, - qsev_guest_set_cbitpos, NULL, NULL, NULL); - object_property_add(obj, "reduced-phys-bits", "uint32", - qsev_guest_get_reduced_phys_bits, - qsev_guest_set_reduced_phys_bits, NULL, NULL, NULL); + object_property_add_uint32_ptr(obj, "policy", &sev->policy, + OBJ_PROP_FLAG_READWRITE, NULL); + object_property_add_uint32_ptr(obj, "handle", &sev->handle, + OBJ_PROP_FLAG_READWRITE, NULL); + object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos, + OBJ_PROP_FLAG_READWRITE, NULL); + object_property_add_uint32_ptr(obj, "reduced-phys-bits", + &sev->reduced_phys_bits, + OBJ_PROP_FLAG_READWRITE, NULL); } /* sev guest info */ -- cgit v1.1 From acb9f95a7c6fda1e488e117af582d5c7db7a218e Mon Sep 17 00:00:00 2001 From: Julio Faracco Date: Mon, 2 Mar 2020 17:13:20 -0300 Subject: i386: Fix GCC warning with snprintf when HAX is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When HAX is enabled (--enable-hax), GCC 9.2.1 reports issues with snprintf(). Replacing old snprintf() by g_strdup_printf() fixes the problem with boundary checks of vm_id and vcpu_id and finally the warnings produced by GCC. For more details, one example of warning: CC i386-softmmu/target/i386/hax-posix.o qemu/target/i386/hax-posix.c: In function ‘hax_host_open_vm’: qemu/target/i386/hax-posix.c:124:56: error: ‘%02d’ directive output may be truncated writing between 2 and 11 bytes into a region of size 3 [-Werror=format-truncation=] 124 | snprintf(name, sizeof HAX_VM_DEVFS, "/dev/hax_vm/vm%02d", vm_id); | ^~~~ qemu/target/i386/hax-posix.c:124:41: note: directive argument in the range [-2147483648, 64] 124 | snprintf(name, sizeof HAX_VM_DEVFS, "/dev/hax_vm/vm%02d", vm_id); | ^~~~~~~~~~~~~~~~~~~~ In file included from /usr/include/stdio.h:867, from qemu/include/qemu/osdep.h:99, from qemu/target/i386/hax-posix.c:14: /usr/include/bits/stdio2.h:67:10: note: ‘__builtin___snprintf_chk’ output between 17 and 26 bytes into a destination of size 17 67 | return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | __bos (__s), __fmt, __va_arg_pack ()); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Julio Faracco Signed-off-by: Paolo Bonzini --- target/i386/hax-posix.c | 33 ++------------------------------- target/i386/hax-windows.c | 33 ++------------------------------- 2 files changed, 4 insertions(+), 62 deletions(-) diff --git a/target/i386/hax-posix.c b/target/i386/hax-posix.c index a5426a6..3bad89f 100644 --- a/target/i386/hax-posix.c +++ b/target/i386/hax-posix.c @@ -108,41 +108,12 @@ int hax_mod_version(struct hax_state *hax, struct hax_module_version *version) static char *hax_vm_devfs_string(int vm_id) { - char *name; - - if (vm_id > MAX_VM_ID) { - fprintf(stderr, "Too big VM id\n"); - return NULL; - } - -#define HAX_VM_DEVFS "/dev/hax_vm/vmxx" - name = g_strdup(HAX_VM_DEVFS); - if (!name) { - return NULL; - } - - snprintf(name, sizeof HAX_VM_DEVFS, "/dev/hax_vm/vm%02d", vm_id); - return name; + return g_strdup_printf("/dev/hax_vm/vm%02d", vm_id); } static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id) { - char *name; - - if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) { - fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id); - return NULL; - } - -#define HAX_VCPU_DEVFS "/dev/hax_vmxx/vcpuxx" - name = g_strdup(HAX_VCPU_DEVFS); - if (!name) { - return NULL; - } - - snprintf(name, sizeof HAX_VCPU_DEVFS, "/dev/hax_vm%02d/vcpu%02d", - vm_id, vcpu_id); - return name; + return g_strdup_printf("/dev/hax_vm%02d/vcpu%02d", vm_id, vcpu_id); } int hax_host_create_vm(struct hax_state *hax, int *vmid) diff --git a/target/i386/hax-windows.c b/target/i386/hax-windows.c index 5729ad9..0ba488c 100644 --- a/target/i386/hax-windows.c +++ b/target/i386/hax-windows.c @@ -185,41 +185,12 @@ int hax_mod_version(struct hax_state *hax, struct hax_module_version *version) static char *hax_vm_devfs_string(int vm_id) { - char *name; - - if (vm_id > MAX_VM_ID) { - fprintf(stderr, "Too big VM id\n"); - return NULL; - } - -#define HAX_VM_DEVFS "\\\\.\\hax_vmxx" - name = g_strdup(HAX_VM_DEVFS); - if (!name) { - return NULL; - } - - snprintf(name, sizeof HAX_VM_DEVFS, "\\\\.\\hax_vm%02d", vm_id); - return name; + return g_strdup_printf("/dev/hax_vm/vm%02d", vm_id); } static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id) { - char *name; - - if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) { - fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id); - return NULL; - } - -#define HAX_VCPU_DEVFS "\\\\.\\hax_vmxx_vcpuxx" - name = g_strdup(HAX_VCPU_DEVFS); - if (!name) { - return NULL; - } - - snprintf(name, sizeof HAX_VCPU_DEVFS, "\\\\.\\hax_vm%02d_vcpu%02d", - vm_id, vcpu_id); - return name; + return g_strdup_printf("/dev/hax_vm%02d/vcpu%02d", vm_id, vcpu_id); } int hax_host_create_vm(struct hax_state *hax, int *vmid) -- cgit v1.1 From 4df28c93528b3189b0e918de6579217cc67e4175 Mon Sep 17 00:00:00 2001 From: Sunil Muthuswamy Date: Mon, 24 Feb 2020 19:27:38 +0000 Subject: WHPX: Use proper synchronization primitives while processing WHPX wasn't using the proper synchronization primitives while processing async events, which can cause issues with SMP. Signed-off-by: Sunil Muthuswamy Signed-off-by: Paolo Bonzini --- target/i386/whpx-all.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index cb863b7..c78baac 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -905,9 +905,8 @@ static void whpx_vcpu_process_async_events(CPUState *cpu) if ((cpu->interrupt_request & CPU_INTERRUPT_INIT) && !(env->hflags & HF_SMM_MASK)) { - + whpx_cpu_synchronize_state(cpu); do_cpu_init(x86_cpu); - cpu->vcpu_dirty = true; vcpu->interruptable = true; } @@ -923,17 +922,13 @@ static void whpx_vcpu_process_async_events(CPUState *cpu) } if (cpu->interrupt_request & CPU_INTERRUPT_SIPI) { - if (!cpu->vcpu_dirty) { - whpx_get_registers(cpu); - } + whpx_cpu_synchronize_state(cpu); do_cpu_sipi(x86_cpu); } if (cpu->interrupt_request & CPU_INTERRUPT_TPR) { cpu->interrupt_request &= ~CPU_INTERRUPT_TPR; - if (!cpu->vcpu_dirty) { - whpx_get_registers(cpu); - } + whpx_cpu_synchronize_state(cpu); apic_handle_tpr_access_report(x86_cpu->apic_state, env->eip, env->tpr_access_type); } @@ -1125,8 +1120,10 @@ static int whpx_vcpu_run(CPUState *cpu) static void do_whpx_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) { - whpx_get_registers(cpu); - cpu->vcpu_dirty = true; + if (!cpu->vcpu_dirty) { + whpx_get_registers(cpu); + cpu->vcpu_dirty = true; + } } static void do_whpx_cpu_synchronize_post_reset(CPUState *cpu, -- cgit v1.1 From c355de59aedd746a6b80b804bdd0bd494e9cac2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 5 Mar 2020 01:48:54 +0100 Subject: Makefile: Align 'help' target output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'help' target is displayed unaligned. Add a print-help function and use it. Now if someone want to change the indentation, there is a single place to modify. Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- Makefile | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 7df22fc..6ec19f8 100644 --- a/Makefile +++ b/Makefile @@ -1235,50 +1235,52 @@ endif include $(SRC_PATH)/tests/docker/Makefile.include include $(SRC_PATH)/tests/vm/Makefile.include +print-help-run = printf " %-30s - %s\\n" "$1" "$2" +print-help = $(quiet-@)$(call print-help-run,$1,$2) + .PHONY: help help: @echo 'Generic targets:' - @echo ' all - Build all' + $(call print-help,all,Build all) ifdef CONFIG_MODULES - @echo ' modules - Build all modules' + $(call print-help,modules,Build all modules) endif - @echo ' dir/file.o - Build specified target only' - @echo ' install - Install QEMU, documentation and tools' - @echo ' ctags/TAGS - Generate tags file for editors' - @echo ' cscope - Generate cscope index' + $(call print-help,dir/file.o,Build specified target only) + $(call print-help,install,Install QEMU, documentation and tools) + $(call print-help,ctags/TAGS,Generate tags file for editors) + $(call print-help,cscope,Generate cscope index) @echo '' @$(if $(TARGET_DIRS), \ echo 'Architecture specific targets:'; \ $(foreach t, $(TARGET_DIRS), \ - printf " %-30s - Build for %s\\n" $(t)/all $(t);) \ + $(call print-help-run,$(t)/all,Build for $(t));) \ echo '') @echo 'Cleaning targets:' - @echo ' clean - Remove most generated files but keep the config' + $(call print-help,clean,Remove most generated files but keep the config) ifdef CONFIG_GCOV - @echo ' clean-coverage - Remove coverage files' + $(call print-help,clean-coverage,Remove coverage files) endif - @echo ' distclean - Remove all generated files' - @echo ' dist - Build a distributable tarball' + $(call print-help,distclean,Remove all generated files) + $(call print-help,dist,Build a distributable tarball) @echo '' @echo 'Test targets:' - @echo ' check - Run all tests (check-help for details)' - @echo ' docker - Help about targets running tests inside containers' - @echo ' vm-help - Help about targets running tests inside VM' + $(call print-help,check,Run all tests (check-help for details)) + $(call print-help,docker,Help about targets running tests inside containers) + $(call print-help,vm-help,Help about targets running tests inside VM) @echo '' @echo 'Documentation targets:' - @echo ' html info pdf txt' - @echo ' - Build documentation in specified format' + $(call print-help,html info pdf txt,Build documentation in specified format) ifdef CONFIG_GCOV - @echo ' coverage-report - Create code coverage report' + $(call print-help,coverage-report,Create code coverage report) endif @echo '' ifdef CONFIG_WIN32 @echo 'Windows targets:' - @echo ' installer - Build NSIS-based installer for QEMU' + $(call print-help,installer,Build NSIS-based installer for QEMU) ifdef QEMU_GA_MSI_ENABLED - @echo ' msi - Build MSI-based installer for qemu-ga' + $(call print-help,msi,Build MSI-based installer for qemu-ga) endif @echo '' endif - @echo ' $(MAKE) [targets] (quiet build, default)' - @echo ' $(MAKE) V=1 [targets] (verbose build)' + $(call print-help,$(MAKE) [targets],(quiet build, default)) + $(call print-help,$(MAKE) V=1 [targets],(verbose build)) -- cgit v1.1 From 81ed0a5778cf2d942f33492b0832f86850cc180d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 5 Mar 2020 01:48:55 +0100 Subject: Makefile: Let the 'help' target list the tools targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit List the name of the tool targets when calling 'make help': $ make help [...] Tools targets: qemu-ga - Build qemu-ga tool qemu-keymap - Build qemu-keymap tool elf2dmp - Build elf2dmp tool ivshmem-client - Build ivshmem-client tool ivshmem-server - Build ivshmem-server tool qemu-nbd - Build qemu-nbd tool qemu-img - Build qemu-img tool qemu-io - Build qemu-io tool qemu-edid - Build qemu-edid tool fsdev/virtfs-proxy-helper - Build virtfs-proxy-helper tool scsi/qemu-pr-helper - Build qemu-pr-helper tool Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 6ec19f8..25a7056 100644 --- a/Makefile +++ b/Makefile @@ -1255,6 +1255,11 @@ endif $(foreach t, $(TARGET_DIRS), \ $(call print-help-run,$(t)/all,Build for $(t));) \ echo '') + @$(if $(TOOLS), \ + echo 'Tools targets:'; \ + $(foreach t, $(TOOLS), \ + $(call print-help-run,$(t),Build $(shell basename $(t)) tool);) \ + echo '') @echo 'Cleaning targets:' $(call print-help,clean,Remove most generated files but keep the config) ifdef CONFIG_GCOV -- cgit v1.1 From 2eea51bd018fa48a952010e9bb7480e9d6390ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 5 Mar 2020 13:45:18 +0100 Subject: hw/audio/fmopl: Move ENV_CURVE to .heap to save 32KiB of .bss MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This buffer is only used by the adlib audio device. Move it to the .heap to release 32KiB of .bss (size reported on x86_64 host). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Stefano Garzarella Signed-off-by: Paolo Bonzini --- hw/audio/fmopl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/audio/fmopl.c b/hw/audio/fmopl.c index 173a752..356d4df 100644 --- a/hw/audio/fmopl.c +++ b/hw/audio/fmopl.c @@ -186,7 +186,7 @@ static int32_t *VIB_TABLE; /* envelope output curve table */ /* attack + decay + OFF */ -static int32_t ENV_CURVE[2*EG_ENT+1]; +static int32_t *ENV_CURVE; /* multiple table */ #define ML 2 @@ -1090,6 +1090,7 @@ FM_OPL *OPLCreate(int clock, int rate) OPL->clock = clock; OPL->rate = rate; OPL->max_ch = max_ch; + ENV_CURVE = g_new(int32_t, 2 * EG_ENT + 1); /* init grobal tables */ OPL_initialize(OPL); /* reset chip */ @@ -1127,6 +1128,7 @@ void OPLDestroy(FM_OPL *OPL) #endif OPL_UnLockTable(); free(OPL); + g_free(ENV_CURVE); } /* ---------- Option handlers ---------- */ -- cgit v1.1 From a9d8ba2be58e067bdfbff830eb9ff438d8db7f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 5 Mar 2020 13:45:19 +0100 Subject: hw/audio/intel-hda: Use memory region alias to reduce .rodata by 4.34MB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intel-hda model uses an array of register indexed by the register address. This array also contains a pair of aliased registers at offset 0x2000. This creates a huge hole in the array, which ends up eating 4.6MiB of .rodata (size reported on x86_64 host, building with --extra-cflags=-Os). By using a memory region alias, we reduce this array to 132kB. Before: (qemu) info mtree 00000000febd4000-00000000febd7fff (prio 1, i/o): intel-hda After: (qemu) info mtree 00000000febd4000-00000000febd7fff (prio 1, i/o): intel-hda 00000000febd4000-00000000febd7fff (prio 1, i/o): intel-hda-container 00000000febd4000-00000000febd5fff (prio 0, i/o): intel-hda 00000000febd6000-00000000febd7fff (prio 0, i/o): alias intel-hda-alias @intel-hda 0000000000000000-0000000000001fff Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- hw/audio/intel-hda.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 1bcc3e5..e8d18b7 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -181,7 +181,9 @@ struct IntelHDAState { IntelHDAStream st[8]; /* state */ + MemoryRegion container; MemoryRegion mmio; + MemoryRegion alias; uint32_t rirb_count; int64_t wall_base_ns; @@ -670,12 +672,6 @@ static const struct IntelHDAReg regtab[] = { .offset = offsetof(IntelHDAState, wall_clk), .rhandler = intel_hda_get_wall_clk, }, - [ ICH6_REG_WALLCLK + 0x2000 ] = { - .name = "WALLCLK(alias)", - .size = 4, - .offset = offsetof(IntelHDAState, wall_clk), - .rhandler = intel_hda_get_wall_clk, - }, /* dma engine */ [ ICH6_REG_CORBLBASE ] = { @@ -837,12 +833,6 @@ static const struct IntelHDAReg regtab[] = { .size = 4, \ .offset = offsetof(IntelHDAState, st[_i].lpib), \ }, \ - [ ST_REG(_i, ICH6_REG_SD_LPIB) + 0x2000 ] = { \ - .stream = _i, \ - .name = _t stringify(_i) " LPIB(alias)", \ - .size = 4, \ - .offset = offsetof(IntelHDAState, st[_i].lpib), \ - }, \ [ ST_REG(_i, ICH6_REG_SD_CBL) ] = { \ .stream = _i, \ .name = _t stringify(_i) " CBL", \ @@ -1125,9 +1115,15 @@ static void intel_hda_realize(PCIDevice *pci, Error **errp) error_free(err); } + memory_region_init(&d->container, OBJECT(d), + "intel-hda-container", 0x4000); memory_region_init_io(&d->mmio, OBJECT(d), &intel_hda_mmio_ops, d, - "intel-hda", 0x4000); - pci_register_bar(&d->pci, 0, 0, &d->mmio); + "intel-hda", 0x2000); + memory_region_add_subregion(&d->container, 0x0000, &d->mmio); + memory_region_init_alias(&d->alias, OBJECT(d), "intel-hda-alias", + &d->mmio, 0, 0x2000); + memory_region_add_subregion(&d->container, 0x2000, &d->alias); + pci_register_bar(&d->pci, 0, 0, &d->container); hda_codec_bus_init(DEVICE(pci), &d->codecs, sizeof(d->codecs), intel_hda_response, intel_hda_xfer); -- cgit v1.1 From 092b6d1e885c27222a3ff929c56cb71d3f5df8ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 5 Mar 2020 13:45:22 +0100 Subject: hw/usb/quirks: Use smaller types to reduce .rodata by 10KiB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The USB descriptor sizes are specified as 16-bit for idVendor / idProduct, and 8-bit for bInterfaceClass / bInterfaceSubClass / bInterfaceProtocol. Doing so we reduce the usbredir_raw_serial_ids[] and usbredir_ftdi_serial_ids[] arrays from 16KiB to 6KiB (size reported on x86_64 host, building with --extra-cflags=-Os). Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- hw/usb/quirks.c | 4 ++-- hw/usb/quirks.h | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/hw/usb/quirks.c b/hw/usb/quirks.c index 38a9c56..23ea7a2 100644 --- a/hw/usb/quirks.c +++ b/hw/usb/quirks.c @@ -22,10 +22,10 @@ static bool usb_id_match(const struct usb_device_id *ids, uint8_t interface_protocol) { int i; - for (i = 0; ids[i].vendor_id != -1; i++) { + for (i = 0; ids[i].terminating_entry == 0; i++) { if (ids[i].vendor_id == vendor_id && ids[i].product_id == product_id && - (ids[i].interface_class == -1 || + (ids[i].interface_protocol_used == 0 || (ids[i].interface_class == interface_class && ids[i].interface_subclass == interface_subclass && ids[i].interface_protocol == interface_protocol))) { diff --git a/hw/usb/quirks.h b/hw/usb/quirks.h index 89480be..50ef2f9 100644 --- a/hw/usb/quirks.h +++ b/hw/usb/quirks.h @@ -21,19 +21,23 @@ #include "quirks-pl2303-ids.h" struct usb_device_id { - int vendor_id; - int product_id; - int interface_class; - int interface_subclass; - int interface_protocol; + uint16_t vendor_id; + uint16_t product_id; + uint8_t interface_class; + uint8_t interface_subclass; + uint8_t interface_protocol; + uint8_t interface_protocol_used:1, + terminating_entry:1, + reserved:6; }; #define USB_DEVICE(vendor, product) \ - .vendor_id = vendor, .product_id = product, .interface_class = -1, + .vendor_id = vendor, .product_id = product, .interface_protocol_used = 0, #define USB_DEVICE_AND_INTERFACE_INFO(vend, prod, iclass, isubclass, iproto) \ .vendor_id = vend, .product_id = prod, .interface_class = iclass, \ - .interface_subclass = isubclass, .interface_protocol = iproto + .interface_subclass = isubclass, .interface_protocol = iproto, \ + .interface_protocol_used = 1 static const struct usb_device_id usbredir_raw_serial_ids[] = { /* @@ -206,7 +210,7 @@ static const struct usb_device_id usbredir_raw_serial_ids[] = { { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) }, - { USB_DEVICE(-1, -1) } /* Terminating Entry */ + { .terminating_entry = 1 } /* Terminating Entry */ }; static const struct usb_device_id usbredir_ftdi_serial_ids[] = { @@ -906,7 +910,7 @@ static const struct usb_device_id usbredir_ftdi_serial_ids[] = { { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, - { USB_DEVICE(-1, -1) } /* Terminating Entry */ + { .terminating_entry = 1 } /* Terminating Entry */ }; #undef USB_DEVICE -- cgit v1.1 From 80e8c2ed1c4c3b77fe66ac64b7c3e9348d813e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 5 Mar 2020 13:45:23 +0100 Subject: ui/curses: Make control_characters[] array const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As we only use this array as input, make it const. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Stefano Garzarella Signed-off-by: Paolo Bonzini --- ui/curses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/curses.c b/ui/curses.c index 3a1b714..3bafc10 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -529,7 +529,7 @@ static void font_setup(void) * Control characters are normally non-printable, but VGA does have * well-known glyphs for them. */ - static uint16_t control_characters[0x20] = { + static const uint16_t control_characters[0x20] = { 0x0020, 0x263a, 0x263b, -- cgit v1.1 From 76c51fc3af34a02a5b6ecebe87dc2c2830251d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 5 Mar 2020 13:45:24 +0100 Subject: ui/curses: Move arrays to .heap to save 74KiB of .bss MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We only need these arrays when using the curses display. Move them from the .bss to the .heap (sizes reported on x86_64 host: screen[] is 64KiB, vga_to_curses 7KiB). Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- ui/curses.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ui/curses.c b/ui/curses.c index 3bafc10..a59b23a 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -54,13 +54,13 @@ enum maybe_keycode { }; static DisplayChangeListener *dcl; -static console_ch_t screen[160 * 100]; +static console_ch_t *screen; static WINDOW *screenpad = NULL; static int width, height, gwidth, gheight, invalidate; static int px, py, sminx, sminy, smaxx, smaxy; static const char *font_charset = "CP437"; -static cchar_t vga_to_curses[256]; +static cchar_t *vga_to_curses; static void curses_update(DisplayChangeListener *dcl, int x, int y, int w, int h) @@ -405,6 +405,8 @@ static void curses_refresh(DisplayChangeListener *dcl) static void curses_atexit(void) { endwin(); + g_free(vga_to_curses); + g_free(screen); } /* @@ -783,6 +785,8 @@ static void curses_display_init(DisplayState *ds, DisplayOptions *opts) if (opts->u.curses.charset) { font_charset = opts->u.curses.charset; } + screen = g_new0(console_ch_t, 160 * 100); + vga_to_curses = g_new0(cchar_t, 256); curses_setup(); curses_keyboard_setup(); atexit(curses_atexit); -- cgit v1.1 From 3b2c52c017fa74783435bc1a429a96ae5e5b164b Mon Sep 17 00:00:00 2001 From: Kashyap Chamarthy Date: Tue, 25 Feb 2020 17:56:18 +0100 Subject: qemu-cpu-models.rst: Document -noTSX, mds-no, taa-no, and tsx-ctrl - Add the '-noTSX' variants for CascadeLake and SkyLake. - Document the three MSR bits: 'mds-no', 'taa-no', and 'tsx-ctrl' Two confusing things about 'mds-no' (and the first point applies to the other two MSRs too): (1) The 'mds-no' bit will _not_ show up in the guest's /proc/cpuinfo. Rather it is used to fill in the guest's sysfs: /sys/devices/system/cpu/vulnerabilities/mds:Not affected Paolo confirmed on IRC as such. (2) There are _three_ variants[+] of CascadeLake CPUs, with different stepping levels: 5, 6, and 7. To quote wikichip.org[*]: "note that while steppings 6 & 7 are fully mitigated, earlier stepping 5 is not protected against MSBDS, MLPDS, nor MDSUM" The above is also indicated in the Intel's document[+], as indicated by "No" under the three columns of MFBDS, MSBDS, and MLPDS. I've expressed this in the docs without belabouring the details. [+] https://software.intel.com/security-software-guidance/insights/processors-affected-microarchitectural-data-sampling [*] https://en.wikichip.org/wiki/intel/microarchitectures/cascade_lake#Key_changes_from_Skylake Signed-off-by: Kashyap Chamarthy Message-Id: <20200225165618.6571-3-kchamart@redhat.com> Signed-off-by: Paolo Bonzini --- docs/system/cpu-models-x86.rst.inc | 57 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/docs/system/cpu-models-x86.rst.inc b/docs/system/cpu-models-x86.rst.inc index cbad930..9a23278 100644 --- a/docs/system/cpu-models-x86.rst.inc +++ b/docs/system/cpu-models-x86.rst.inc @@ -49,10 +49,15 @@ mixture of host CPU models between machines, if live migration compatibility is required, use the newest CPU model that is compatible across all desired hosts. -``Skylake-Server``, ``Skylake-Server-IBRS`` +``Cascadelake-Server``, ``Cascadelake-Server-noTSX`` + Intel Xeon Processor (Cascade Lake, 2019), with "stepping" levels 6 + or 7 only. (The Cascade Lake Xeon processor with *stepping 5 is + vulnerable to MDS variants*.) + +``Skylake-Server``, ``Skylake-Server-IBRS``, ``Skylake-Server-IBRS-noTSX`` Intel Xeon Processor (Skylake, 2016) -``Skylake-Client``, ``Skylake-Client-IBRS`` +``Skylake-Client``, ``Skylake-Client-IBRS``, ``Skylake-Client-noTSX-IBRS}`` Intel Core Processor (Skylake, 2015) ``Broadwell``, ``Broadwell-IBRS``, ``Broadwell-noTSX``, ``Broadwell-noTSX-IBRS`` @@ -148,6 +153,54 @@ features are included if using "Host passthrough" or "Host model". Requires the host CPU microcode to support this feature before it can be used for guest CPUs. +``mds-no`` + Recommended to inform the guest OS that the host is *not* vulnerable + to any of the MDS variants ([MFBDS] CVE-2018-12130, [MLPDS] + CVE-2018-12127, [MSBDS] CVE-2018-12126). + + This is an MSR (Model-Specific Register) feature rather than a CPUID feature, + so it will not appear in the Linux ``/proc/cpuinfo`` in the host or + guest. Instead, the host kernel uses it to populate the MDS + vulnerability file in ``sysfs``. + + So it should only be enabled for VMs if the host reports @code{Not + affected} in the ``/sys/devices/system/cpu/vulnerabilities/mds`` file. + +``taa-no`` + Recommended to inform that the guest that the host is ``not`` + vulnerable to CVE-2019-11135, TSX Asynchronous Abort (TAA). + + This too is an MSR feature, so it does not show up in the Linux + ``/proc/cpuinfo`` in the host or guest. + + It should only be enabled for VMs if the host reports ``Not affected`` + in the ``/sys/devices/system/cpu/vulnerabilities/tsx_async_abort`` + file. + +``tsx-ctrl`` + Recommended to inform the guest that it can disable the Intel TSX + (Transactional Synchronization Extensions) feature; or, if the + processor is vulnerable, use the Intel VERW instruction (a + processor-level instruction that performs checks on memory access) as + a mitigation for the TAA vulnerability. (For details, refer to + Intel's `deep dive into MDS + `_.) + + Expose this to the guest OS if and only if: (a) the host has TSX + enabled; *and* (b) the guest has ``rtm`` CPU flag enabled. + + By disabling TSX, KVM-based guests can avoid paying the price of + mitigating TSX-based attacks. + + Note that ``tsx-ctrl`` too is an MSR feature, so it does not show + up in the Linux ``/proc/cpuinfo`` in the host or guest. + + To validate that Intel TSX is indeed disabled for the guest, there are + two ways: (a) check for the *absence* of ``rtm`` in the guest's + ``/proc/cpuinfo``; or (b) the + ``/sys/devices/system/cpu/vulnerabilities/tsx_async_abort`` file in + the guest should report ``Mitigation: TSX disabled``. + Preferred CPU models for AMD x86 hosts ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.1 From 3df261b6676b5850e93d6fab3f7a98f8ee8f19c5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 13 Mar 2020 17:24:47 +0000 Subject: softmmu/vl.c: Handle '-cpu help' and '-device help' before 'no default machine' Currently if you try to ask for the list of CPUs for a target architecture which does not specify a default machine type you just get an error: $ qemu-system-arm -cpu help qemu-system-arm: No machine specified, and there is no default Use -machine help to list supported machines Since the list of CPUs doesn't depend on the machine, this is unnecessarily unhelpful. "-device help" has a similar problem. Move the checks for "did the user ask for -cpu help or -device help" up so they precede the select_machine() call which checks that the user specified a valid machine type. Signed-off-by: Peter Maydell Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index ff2685d..6a28592 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3789,6 +3789,22 @@ void qemu_init(int argc, char **argv, char **envp) */ loc_set_none(); + /* + * Check for -cpu help and -device help before we call select_machine(), + * which will return an error if the architecture has no default machine + * type and the user did not specify one, so that the user doesn't need + * to say '-cpu help -machine something'. + */ + if (cpu_option && is_help_option(cpu_option)) { + list_cpus(cpu_option); + exit(0); + } + + if (qemu_opts_foreach(qemu_find_opts("device"), + device_help_func, NULL, NULL)) { + exit(0); + } + user_register_global_props(); replay_configure(icount_opts); @@ -3877,11 +3893,6 @@ void qemu_init(int argc, char **argv, char **envp) qemu_set_hw_version(machine_class->hw_version); } - if (cpu_option && is_help_option(cpu_option)) { - list_cpus(cpu_option); - exit(0); - } - if (!trace_init_backends()) { exit(1); } @@ -4112,11 +4123,6 @@ void qemu_init(int argc, char **argv, char **envp) fsdev_init_func, NULL, &error_fatal); #endif - if (qemu_opts_foreach(qemu_find_opts("device"), - device_help_func, NULL, NULL)) { - exit(0); - } - /* * Note: we need to create block backends before * machine_set_property(), so machine properties can refer to -- cgit v1.1 From 67cf3f5cf590549b1b8f8e2eb92ca20ed80d8a0a Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 11 Mar 2020 19:23:41 -0400 Subject: Use -isystem for linux-headers dir glibc and Linux-provided headers are known to generate macro redefinition warnings when used together. For example: and duplicate some macro definitions. We normally never see those warnings because GCC suppresses warnings generated by system headers. We carry our own copy of Linux header files, though, and this makes those warnings not be suppressed when glibc headers are included before Linux headers (e.g. if is included before ). Use -isystem instead of -I for linux-headers. This makes the compiler treat our linux-headers directory the same way it treats system-provided Linux headers, and suppress warnings generated by them. Signed-off-by: Eduardo Habkost Reviewed-by: Michael S. Tsirkin Signed-off-by: Paolo Bonzini --- Makefile.target | 2 +- configure | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.target b/Makefile.target index 2d43dc5..934a9f7 100644 --- a/Makefile.target +++ b/Makefile.target @@ -12,7 +12,7 @@ endif $(call set-vpath, $(SRC_PATH):$(BUILD_DIR)) ifdef CONFIG_LINUX -QEMU_CFLAGS += -I../linux-headers +QEMU_CFLAGS += -isystem ../linux-headers endif QEMU_CFLAGS += -iquote .. -iquote $(SRC_PATH)/target/$(TARGET_BASE_ARCH) -DNEED_CPU_H diff --git a/configure b/configure index 44a70cf..06fcd07 100755 --- a/configure +++ b/configure @@ -900,7 +900,7 @@ Linux) linux="yes" linux_user="yes" kvm="yes" - QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$PWD/linux-headers $QEMU_INCLUDES" + QEMU_INCLUDES="-isystem \$(SRC_PATH)/linux-headers -isystem $PWD/linux-headers $QEMU_INCLUDES" supported_os="yes" libudev="yes" ;; -- cgit v1.1 From 5073b5d3ea303d37f4a8e2ea451d7a2eb1817448 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Fri, 13 Mar 2020 15:59:39 +0000 Subject: exec/rom_reset: Free rom data during inmigrate skip Commit 355477f8c73e9 skips rom reset when we're an incoming migration so as not to overwrite shared ram in the ignore-shared migration optimisation. However, it's got an unexpected side effect that because it skips freeing the ROM data, when rom_reset gets called later on, after migration (e.g. during a reboot), the ROM does get reset to the original file contents. Because of seabios/x86's weird reboot process this confuses a reboot into hanging after a migration. Fixes: 355477f8c73e9 ("migration: do not rom_reset() during incoming migration") https://bugzilla.redhat.com/show_bug.cgi?id=1809380 Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Peter Maydell Signed-off-by: Paolo Bonzini --- hw/core/loader.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/hw/core/loader.c b/hw/core/loader.c index d1b78f6..eeef6da 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -1119,19 +1119,26 @@ static void rom_reset(void *unused) { Rom *rom; - /* - * We don't need to fill in the RAM with ROM data because we'll fill - * the data in during the next incoming migration in all cases. Note - * that some of those RAMs can actually be modified by the guest on ARM - * so this is probably the only right thing to do here. - */ - if (runstate_check(RUN_STATE_INMIGRATE)) - return; - QTAILQ_FOREACH(rom, &roms, next) { if (rom->fw_file) { continue; } + /* + * We don't need to fill in the RAM with ROM data because we'll fill + * the data in during the next incoming migration in all cases. Note + * that some of those RAMs can actually be modified by the guest. + */ + if (runstate_check(RUN_STATE_INMIGRATE)) { + if (rom->data && rom->isrom) { + /* + * Free it so that a rom_reset after migration doesn't + * overwrite a potentially modified 'rom'. + */ + rom_free_data(rom); + } + continue; + } + if (rom->data == NULL) { continue; } -- cgit v1.1 From f962cac4c24157aeceff59cbf9dac8b5e30c55da Mon Sep 17 00:00:00 2001 From: Longpeng Date: Mon, 16 Mar 2020 16:37:32 +0800 Subject: cpus: avoid pause_all_vcpus getting stuck due to race We found an issue when repeat reboot in guest during migration, it cause the migration thread never be waken up again.
| | LOCK BQL | ... | main_loop_should_exit | pause_all_vcpus | 1. set all cpus ->stop=true | and then kick | 2. return if all cpus is paused | (by '->stopped == true'), else| 3. qemu_cond_wait [BQL UNLOCK] | |LOCK BQL |... |do_vm_stop | pause_all_vcpus | (A)set all cpus ->stop=true | and then kick | (B)return if all cpus is paused | (by '->stopped == true'), else | (C)qemu_cond_wait [BQL UNLOCK] 4. be waken up and LOCK BQL | (D)be waken up BUT wait for BQL 5. goto 2. | (BQL is still LOCKed) | resume_all_vcpus | 1. set all cpus ->stop=false | and ->stopped=false | ... | BQL UNLOCK | (E)LOCK BQL | (F)goto B. [but stopped is false now!] |Finally, sleep at step 3 forever. resume_all_vcpus should notice this race, so we need to move the change of runstate before pause_all_vcpus in do_vm_stop() and ignore the resume request if runstate is not running. Cc: Dr. David Alan Gilbert Cc: Richard Henderson Signed-off-by: Longpeng Suggested-by: Paolo Bonzini Message-Id: <20200316083732.2010-1-longpeng2@huawei.com> Signed-off-by: Paolo Bonzini --- cpus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpus.c b/cpus.c index b4f8b84..ef441bd 100644 --- a/cpus.c +++ b/cpus.c @@ -1026,9 +1026,9 @@ static int do_vm_stop(RunState state, bool send_stop) int ret = 0; if (runstate_is_running()) { + runstate_set(state); cpu_disable_ticks(); pause_all_vcpus(); - runstate_set(state); vm_state_notify(0, state); if (send_stop) { qapi_event_send_stop(); @@ -1899,6 +1899,10 @@ void resume_all_vcpus(void) { CPUState *cpu; + if (!runstate_is_running()) { + return; + } + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); CPU_FOREACH(cpu) { cpu_resume(cpu); -- cgit v1.1 From 8834dcf47e8543b92e072706d3a5621762bfa106 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 17 Mar 2020 15:17:20 +0100 Subject: lockable: add QEMU_MAKE_LOCKABLE_NONNULL This will be needed for lock guards, because if the lock is NULL the dummy for loop of the lock guard never runs. This can cause confusion and dummy warnings in the compiler, but even if it did not, aborting with a NULL pointer dereference is a less surprising behavior. Signed-off-by: Paolo Bonzini --- include/qemu/lockable.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/include/qemu/lockable.h b/include/qemu/lockable.h index 84ea794..313d4d9 100644 --- a/include/qemu/lockable.h +++ b/include/qemu/lockable.h @@ -65,7 +65,7 @@ qemu_make_lockable(void *x, QemuLockable *lockable) * In C++ it would be different, but then C++ wouldn't need QemuLockable * either... */ -#define QEMU_MAKE_LOCKABLE_(x) qemu_make_lockable((x), &(QemuLockable) { \ +#define QEMU_MAKE_LOCKABLE_(x) (&(QemuLockable) { \ .object = (x), \ .lock = QEMU_LOCK_FUNC(x), \ .unlock = QEMU_UNLOCK_FUNC(x), \ @@ -76,11 +76,24 @@ qemu_make_lockable(void *x, QemuLockable *lockable) * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin). * * Returns a QemuLockable object that can be passed around - * to a function that can operate with locks of any kind. + * to a function that can operate with locks of any kind, or + * NULL if @x is %NULL. */ #define QEMU_MAKE_LOCKABLE(x) \ QEMU_GENERIC(x, \ (QemuLockable *, (x)), \ + qemu_make_lockable((x), QEMU_MAKE_LOCKABLE_(x))) + +/* QEMU_MAKE_LOCKABLE_NONNULL - Make a polymorphic QemuLockable + * + * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin). + * + * Returns a QemuLockable object that can be passed around + * to a function that can operate with locks of any kind. + */ +#define QEMU_MAKE_LOCKABLE_NONNULL(x) \ + QEMU_GENERIC(x, \ + (QemuLockable *, (x)), \ QEMU_MAKE_LOCKABLE_(x)) static inline void qemu_lockable_lock(QemuLockable *x) -- cgit v1.1 From 3284c3ddc48ba8fc853858c95d87dcc2ab160b29 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 16 Mar 2020 11:09:56 +0000 Subject: lockable: add lock guards This patch introduces two lock guard macros that automatically unlock a lock object (QemuMutex and others): void f(void) { QEMU_LOCK_GUARD(&mutex); if (!may_fail()) { return; /* automatically unlocks mutex */ } ... } and: WITH_QEMU_LOCK_GUARD(&mutex) { if (!may_fail()) { return; /* automatically unlocks mutex */ } } /* automatically unlocks mutex here */ ... Convert qemu-timer.c functions that benefit from these macros as an example. Manual qemu_mutex_lock/unlock() callers are left unmodified in cases where clarity would not improve by switching to the macros. Many other QemuMutex users remain in the codebase that might benefit from lock guards. Over time they can be converted, if that is desirable. Signed-off-by: Stefan Hajnoczi [Use QEMU_MAKE_LOCKABLE_NONNULL. - Paolo] Signed-off-by: Paolo Bonzini --- include/qemu/lockable.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ util/qemu-timer.c | 23 +++++++++-------- 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/include/qemu/lockable.h b/include/qemu/lockable.h index 313d4d9..90342ba 100644 --- a/include/qemu/lockable.h +++ b/include/qemu/lockable.h @@ -106,4 +106,69 @@ static inline void qemu_lockable_unlock(QemuLockable *x) x->unlock(x->object); } +static inline QemuLockable *qemu_lockable_auto_lock(QemuLockable *x) +{ + qemu_lockable_lock(x); + return x; +} + +static inline void qemu_lockable_auto_unlock(QemuLockable *x) +{ + if (x) { + qemu_lockable_unlock(x); + } +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuLockable, qemu_lockable_auto_unlock) + +#define WITH_QEMU_LOCK_GUARD_(x, var) \ + for (g_autoptr(QemuLockable) var = \ + qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))); \ + var; \ + qemu_lockable_auto_unlock(var), var = NULL) + +/** + * WITH_QEMU_LOCK_GUARD - Lock a lock object for scope + * + * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin). + * + * This macro defines a lock scope such that entering the scope takes the lock + * and leaving the scope releases the lock. Return statements are allowed + * within the scope and release the lock. Break and continue statements leave + * the scope early and release the lock. + * + * WITH_QEMU_LOCK_GUARD(&mutex) { + * ... + * if (error) { + * return; <-- mutex is automatically unlocked + * } + * + * if (early_exit) { + * break; <-- leave this scope early + * } + * ... + * } + */ +#define WITH_QEMU_LOCK_GUARD(x) \ + WITH_QEMU_LOCK_GUARD_((x), qemu_lockable_auto##__COUNTER__) + +/** + * QEMU_LOCK_GUARD - Lock an object until the end of the scope + * + * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin). + * + * This macro takes a lock until the end of the scope. Return statements + * release the lock. + * + * ... <-- mutex not locked + * QEMU_LOCK_GUARD(&mutex); <-- mutex locked from here onwards + * ... + * if (error) { + * return; <-- mutex is automatically unlocked + * } + */ +#define QEMU_LOCK_GUARD(x) \ + g_autoptr(QemuLockable) qemu_lockable_auto##__COUNTER__ = \ + qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE((x))) + #endif diff --git a/util/qemu-timer.c b/util/qemu-timer.c index ef52d28..d548d3c 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu/main-loop.h" #include "qemu/timer.h" +#include "qemu/lockable.h" #include "sysemu/replay.h" #include "sysemu/cpus.h" @@ -186,13 +187,12 @@ bool timerlist_expired(QEMUTimerList *timer_list) return false; } - qemu_mutex_lock(&timer_list->active_timers_lock); - if (!timer_list->active_timers) { - qemu_mutex_unlock(&timer_list->active_timers_lock); - return false; + WITH_QEMU_LOCK_GUARD(&timer_list->active_timers_lock) { + if (!timer_list->active_timers) { + return false; + } + expire_time = timer_list->active_timers->expire_time; } - expire_time = timer_list->active_timers->expire_time; - qemu_mutex_unlock(&timer_list->active_timers_lock); return expire_time <= qemu_clock_get_ns(timer_list->clock->type); } @@ -225,13 +225,12 @@ int64_t timerlist_deadline_ns(QEMUTimerList *timer_list) * value but ->notify_cb() is called when the deadline changes. Therefore * the caller should notice the change and there is no race condition. */ - qemu_mutex_lock(&timer_list->active_timers_lock); - if (!timer_list->active_timers) { - qemu_mutex_unlock(&timer_list->active_timers_lock); - return -1; + WITH_QEMU_LOCK_GUARD(&timer_list->active_timers_lock) { + if (!timer_list->active_timers) { + return -1; + } + expire_time = timer_list->active_timers->expire_time; } - expire_time = timer_list->active_timers->expire_time; - qemu_mutex_unlock(&timer_list->active_timers_lock); delta = expire_time - qemu_clock_get_ns(timer_list->clock->type); -- cgit v1.1 From ac90871cf8030753a7bcef26fa1662c4e3c90078 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 16 Mar 2020 11:09:57 +0000 Subject: lockable: add QemuRecMutex support The polymorphic locking macros don't support QemuRecMutex yet. Add it so that lock guards can be used with QemuRecMutex. Convert TCG plugins functions that benefit from these macros. Manual qemu_rec_mutex_lock/unlock() callers are left unmodified in cases where clarity would not improve by switching to the macros. Signed-off-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini --- include/qemu/lockable.h | 6 ++++-- plugins/core.c | 7 +++---- plugins/loader.c | 16 ++++++++-------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/include/qemu/lockable.h b/include/qemu/lockable.h index 90342ba..1aeb2cb 100644 --- a/include/qemu/lockable.h +++ b/include/qemu/lockable.h @@ -50,6 +50,7 @@ qemu_make_lockable(void *x, QemuLockable *lockable) #define QEMU_LOCK_FUNC(x) ((QemuLockUnlockFunc *) \ QEMU_GENERIC(x, \ (QemuMutex *, qemu_mutex_lock), \ + (QemuRecMutex *, qemu_rec_mutex_lock), \ (CoMutex *, qemu_co_mutex_lock), \ (QemuSpin *, qemu_spin_lock), \ unknown_lock_type)) @@ -57,6 +58,7 @@ qemu_make_lockable(void *x, QemuLockable *lockable) #define QEMU_UNLOCK_FUNC(x) ((QemuLockUnlockFunc *) \ QEMU_GENERIC(x, \ (QemuMutex *, qemu_mutex_unlock), \ + (QemuRecMutex *, qemu_rec_mutex_unlock), \ (CoMutex *, qemu_co_mutex_unlock), \ (QemuSpin *, qemu_spin_unlock), \ unknown_lock_type)) @@ -73,7 +75,7 @@ qemu_make_lockable(void *x, QemuLockable *lockable) /* QEMU_MAKE_LOCKABLE - Make a polymorphic QemuLockable * - * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin). + * @x: a lock object (currently one of QemuMutex, QemuRecMutex, CoMutex, QemuSpin). * * Returns a QemuLockable object that can be passed around * to a function that can operate with locks of any kind, or @@ -86,7 +88,7 @@ qemu_make_lockable(void *x, QemuLockable *lockable) /* QEMU_MAKE_LOCKABLE_NONNULL - Make a polymorphic QemuLockable * - * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin). + * @x: a lock object (currently one of QemuMutex, QemuRecMutex, CoMutex, QemuSpin). * * Returns a QemuLockable object that can be passed around * to a function that can operate with locks of any kind. diff --git a/plugins/core.c b/plugins/core.c index ed86301..51bfc94 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -15,6 +15,7 @@ #include "qemu/error-report.h" #include "qemu/config-file.h" #include "qapi/error.h" +#include "qemu/lockable.h" #include "qemu/option.h" #include "qemu/rcu_queue.h" #include "qemu/xxhash.h" @@ -150,11 +151,11 @@ do_plugin_register_cb(qemu_plugin_id_t id, enum qemu_plugin_event ev, { struct qemu_plugin_ctx *ctx; - qemu_rec_mutex_lock(&plugin.lock); + QEMU_LOCK_GUARD(&plugin.lock); ctx = plugin_id_to_ctx_locked(id); /* if the plugin is on its way out, ignore this request */ if (unlikely(ctx->uninstalling)) { - goto out_unlock; + return; } if (func) { struct qemu_plugin_cb *cb = ctx->callbacks[ev]; @@ -178,8 +179,6 @@ do_plugin_register_cb(qemu_plugin_id_t id, enum qemu_plugin_event ev, } else { plugin_unregister_cb__locked(ctx, ev); } - out_unlock: - qemu_rec_mutex_unlock(&plugin.lock); } void plugin_register_cb(qemu_plugin_id_t id, enum qemu_plugin_event ev, diff --git a/plugins/loader.c b/plugins/loader.c index 15fc7e5..685d334 100644 --- a/plugins/loader.c +++ b/plugins/loader.c @@ -19,6 +19,7 @@ #include "qemu/error-report.h" #include "qemu/config-file.h" #include "qapi/error.h" +#include "qemu/lockable.h" #include "qemu/option.h" #include "qemu/rcu_queue.h" #include "qemu/qht.h" @@ -367,15 +368,14 @@ void plugin_reset_uninstall(qemu_plugin_id_t id, struct qemu_plugin_reset_data *data; struct qemu_plugin_ctx *ctx; - qemu_rec_mutex_lock(&plugin.lock); - ctx = plugin_id_to_ctx_locked(id); - if (ctx->uninstalling || (reset && ctx->resetting)) { - qemu_rec_mutex_unlock(&plugin.lock); - return; + WITH_QEMU_LOCK_GUARD(&plugin.lock) { + ctx = plugin_id_to_ctx_locked(id); + if (ctx->uninstalling || (reset && ctx->resetting)) { + return; + } + ctx->resetting = reset; + ctx->uninstalling = !reset; } - ctx->resetting = reset; - ctx->uninstalling = !reset; - qemu_rec_mutex_unlock(&plugin.lock); data = g_new(struct qemu_plugin_reset_data, 1); data->ctx = ctx; -- cgit v1.1 From 39fa93c4438e7c5efb93d859224d27d04e5c2160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 10:13:00 +0100 Subject: memory: Correctly return alias region type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since memory region aliases are neither rom nor ram, they are described as i/o, which is often incorrect. Return instead the type of the original region we are aliasing. Signed-off-by: Philippe Mathieu-Daudé --- memory.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/memory.c b/memory.c index 404ff4e..fc99e7f 100644 --- a/memory.c +++ b/memory.c @@ -2819,6 +2819,9 @@ void address_space_destroy(AddressSpace *as) static const char *memory_region_type(MemoryRegion *mr) { + if (mr->alias) { + return memory_region_type(mr->alias); + } if (memory_region_is_ram_device(mr)) { return "ramd"; } else if (memory_region_is_romd(mr)) { -- cgit v1.1 From 83696c8f78303d916fd8d126bc28b67f25320acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 10:58:17 +0100 Subject: memory: Simplify memory_region_init_rom_nomigrate() to ease review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memory_region_init_rom_nomigrate() has the same content than memory_region_init_ram_shared_nomigrate(), with setting the readonly mode. The code is easier to review as creating a readonly ram/shared/nomigrate region. Reviewed-by: Alistair Francis Signed-off-by: Philippe Mathieu-Daudé --- memory.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/memory.c b/memory.c index fc99e7f..601b749 100644 --- a/memory.c +++ b/memory.c @@ -1660,19 +1660,8 @@ void memory_region_init_rom_nomigrate(MemoryRegion *mr, uint64_t size, Error **errp) { - Error *err = NULL; - memory_region_init(mr, owner, name, size); - mr->ram = true; + memory_region_init_ram_shared_nomigrate(mr, owner, name, size, false, errp); mr->readonly = true; - mr->terminates = true; - mr->destructor = memory_region_destructor_ram; - mr->ram_block = qemu_ram_alloc(size, false, mr, &err); - mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; - if (err) { - mr->size = int128_zero(); - object_unparent(OBJECT(mr)); - error_propagate(errp, err); - } } void memory_region_init_rom_device_nomigrate(MemoryRegion *mr, -- cgit v1.1 From 044e2af9f5f55d81be754a0e2ba1d206ad2b3bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 14:45:07 +0100 Subject: scripts/cocci: Rename memory-region-{init-ram -> housekeeping} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As we are going to add various semantic changes related to the memory region API, rename this script to be more generic. Add a 'usage' header, and an entry in MAINTAINERS to avoid checkpatch warning. Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 1 + .../coccinelle/memory-region-housekeeping.cocci | 51 ++++++++++++++++++++++ scripts/coccinelle/memory-region-init-ram.cocci | 38 ---------------- 3 files changed, 52 insertions(+), 38 deletions(-) create mode 100644 scripts/coccinelle/memory-region-housekeeping.cocci delete mode 100644 scripts/coccinelle/memory-region-init-ram.cocci diff --git a/MAINTAINERS b/MAINTAINERS index a88bc28..770126f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2047,6 +2047,7 @@ F: include/exec/ramblock.h F: memory.c F: include/exec/memory-internal.h F: exec.c +F: scripts/coccinelle/memory-region-housekeeping.cocci SPICE M: Gerd Hoffmann diff --git a/scripts/coccinelle/memory-region-housekeeping.cocci b/scripts/coccinelle/memory-region-housekeeping.cocci new file mode 100644 index 0000000..3699c10 --- /dev/null +++ b/scripts/coccinelle/memory-region-housekeeping.cocci @@ -0,0 +1,51 @@ +/* + Usage: + + spatch \ + --macro-file scripts/cocci-macro-file.h \ + --sp-file scripts/coccinelle/memory-region-housekeeping.cocci \ + --keep-comments \ + --in-place \ + --dir . + +*/ + + +// Replace by-hand memory_region_init_ram_nomigrate/vmstate_register_ram +// code sequences with use of the new memory_region_init_ram function. +// Similarly for the _rom and _rom_device functions. +// We don't try to replace sequences with a non-NULL owner, because +// there are none in the tree that can be automatically converted +// (and only a handful that can be manually converted). +@@ +expression MR; +expression NAME; +expression SIZE; +expression ERRP; +@@ +-memory_region_init_ram_nomigrate(MR, NULL, NAME, SIZE, ERRP); ++memory_region_init_ram(MR, NULL, NAME, SIZE, ERRP); + ... +-vmstate_register_ram_global(MR); +@@ +expression MR; +expression NAME; +expression SIZE; +expression ERRP; +@@ +-memory_region_init_rom_nomigrate(MR, NULL, NAME, SIZE, ERRP); ++memory_region_init_rom(MR, NULL, NAME, SIZE, ERRP); + ... +-vmstate_register_ram_global(MR); +@@ +expression MR; +expression OPS; +expression OPAQUE; +expression NAME; +expression SIZE; +expression ERRP; +@@ +-memory_region_init_rom_device_nomigrate(MR, NULL, OPS, OPAQUE, NAME, SIZE, ERRP); ++memory_region_init_rom_device(MR, NULL, OPS, OPAQUE, NAME, SIZE, ERRP); + ... +-vmstate_register_ram_global(MR); diff --git a/scripts/coccinelle/memory-region-init-ram.cocci b/scripts/coccinelle/memory-region-init-ram.cocci deleted file mode 100644 index d290150..0000000 --- a/scripts/coccinelle/memory-region-init-ram.cocci +++ /dev/null @@ -1,38 +0,0 @@ -// Replace by-hand memory_region_init_ram_nomigrate/vmstate_register_ram -// code sequences with use of the new memory_region_init_ram function. -// Similarly for the _rom and _rom_device functions. -// We don't try to replace sequences with a non-NULL owner, because -// there are none in the tree that can be automatically converted -// (and only a handful that can be manually converted). -@@ -expression MR; -expression NAME; -expression SIZE; -expression ERRP; -@@ --memory_region_init_ram_nomigrate(MR, NULL, NAME, SIZE, ERRP); -+memory_region_init_ram(MR, NULL, NAME, SIZE, ERRP); - ... --vmstate_register_ram_global(MR); -@@ -expression MR; -expression NAME; -expression SIZE; -expression ERRP; -@@ --memory_region_init_rom_nomigrate(MR, NULL, NAME, SIZE, ERRP); -+memory_region_init_rom(MR, NULL, NAME, SIZE, ERRP); - ... --vmstate_register_ram_global(MR); -@@ -expression MR; -expression OPS; -expression OPAQUE; -expression NAME; -expression SIZE; -expression ERRP; -@@ --memory_region_init_rom_device_nomigrate(MR, NULL, OPS, OPAQUE, NAME, SIZE, ERRP); -+memory_region_init_rom_device(MR, NULL, OPS, OPAQUE, NAME, SIZE, ERRP); - ... --vmstate_register_ram_global(MR); -- cgit v1.1 From d3ec684d70d98a9fbc56fda1b611d039c90d0c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:23:40 +0100 Subject: scripts/cocci: Patch to replace memory_region_init_{ram,readonly -> rom} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a semantic patch to replace memory_region_init_ram(readonly) by memory_region_init_rom(). Signed-off-by: Philippe Mathieu-Daudé --- scripts/coccinelle/memory-region-housekeeping.cocci | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/scripts/coccinelle/memory-region-housekeeping.cocci b/scripts/coccinelle/memory-region-housekeeping.cocci index 3699c10..ee3923d 100644 --- a/scripts/coccinelle/memory-region-housekeeping.cocci +++ b/scripts/coccinelle/memory-region-housekeeping.cocci @@ -11,6 +11,24 @@ */ +// Replace memory_region_init_ram(readonly) by memory_region_init_rom() +@@ +expression E1, E2, E3, E4, E5; +symbol true; +@@ +( +- memory_region_init_ram(E1, E2, E3, E4, E5); ++ memory_region_init_rom(E1, E2, E3, E4, E5); + ... WHEN != E1 +- memory_region_set_readonly(E1, true); +| +- memory_region_init_ram_nomigrate(E1, E2, E3, E4, E5); ++ memory_region_init_rom_nomigrate(E1, E2, E3, E4, E5); + ... WHEN != E1 +- memory_region_set_readonly(E1, true); +) + + // Replace by-hand memory_region_init_ram_nomigrate/vmstate_register_ram // code sequences with use of the new memory_region_init_ram function. // Similarly for the _rom and _rom_device functions. -- cgit v1.1 From 16260006acf8f3aee589b3fd26a1bbbf7b78ae4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:50:18 +0100 Subject: hw/arm: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/arm/exynos4210.c | 3 +-- hw/arm/mainstone.c | 3 +-- hw/arm/omap_sx1.c | 6 ++---- hw/arm/palm.c | 3 +-- hw/arm/spitz.c | 3 +-- hw/arm/stellaris.c | 3 +-- hw/arm/tosa.c | 3 +-- 7 files changed, 8 insertions(+), 16 deletions(-) diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index 59a27bd..3af6502 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -311,9 +311,8 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) &s->chipid_mem); /* Internal ROM */ - memory_region_init_ram(&s->irom_mem, NULL, "exynos4210.irom", + memory_region_init_rom(&s->irom_mem, NULL, "exynos4210.irom", EXYNOS4210_IROM_SIZE, &error_fatal); - memory_region_set_readonly(&s->irom_mem, true); memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR, &s->irom_mem); /* mirror of iROM */ diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c index 1042017..6bc6436 100644 --- a/hw/arm/mainstone.c +++ b/hw/arm/mainstone.c @@ -124,9 +124,8 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, /* Setup CPU & memory */ mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, machine->cpu_type); - memory_region_init_ram(rom, NULL, "mainstone.rom", MAINSTONE_ROM, + memory_region_init_rom(rom, NULL, "mainstone.rom", MAINSTONE_ROM, &error_fatal); - memory_region_set_readonly(rom, true); memory_region_add_subregion(address_space_mem, 0, rom); /* There are two 32MiB flash devices on the board */ diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c index de5ff44..57829b3 100644 --- a/hw/arm/omap_sx1.c +++ b/hw/arm/omap_sx1.c @@ -131,9 +131,8 @@ static void sx1_init(MachineState *machine, const int version) mpu = omap310_mpu_init(machine->ram, machine->cpu_type); /* External Flash (EMIFS) */ - memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size, + memory_region_init_rom(flash, NULL, "omap_sx1.flash0-0", flash_size, &error_fatal); - memory_region_set_readonly(flash, true); memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash); memory_region_init_io(&cs[0], NULL, &static_ops, &cs0val, @@ -167,9 +166,8 @@ static void sx1_init(MachineState *machine, const int version) if ((version == 1) && (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) { MemoryRegion *flash_1 = g_new(MemoryRegion, 1); - memory_region_init_ram(flash_1, NULL, "omap_sx1.flash1-0", + memory_region_init_rom(flash_1, NULL, "omap_sx1.flash1-0", flash1_size, &error_fatal); - memory_region_set_readonly(flash_1, true); memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1); memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val, diff --git a/hw/arm/palm.c b/hw/arm/palm.c index 99554bd..97ca105 100644 --- a/hw/arm/palm.c +++ b/hw/arm/palm.c @@ -213,9 +213,8 @@ static void palmte_init(MachineState *machine) mpu = omap310_mpu_init(machine->ram, machine->cpu_type); /* External Flash (EMIFS) */ - memory_region_init_ram(flash, NULL, "palmte.flash", flash_size, + memory_region_init_rom(flash, NULL, "palmte.flash", flash_size, &error_fatal); - memory_region_set_readonly(flash, true); memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash); memory_region_init_io(&cs[0], NULL, &static_ops, &cs0val, "palmte-cs0", diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index cbfa693..c28d9b5 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -929,8 +929,7 @@ static void spitz_common_init(MachineState *machine, sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M); - memory_region_init_ram(rom, NULL, "spitz.rom", SPITZ_ROM, &error_fatal); - memory_region_set_readonly(rom, true); + memory_region_init_rom(rom, NULL, "spitz.rom", SPITZ_ROM, &error_fatal); memory_region_add_subregion(address_space_mem, 0, rom); /* Setup peripherals */ diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 221a786..d136ba1 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -1300,9 +1300,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) sram_size = ((board->dc0 >> 18) + 1) * 1024; /* Flash programming is done via the SCU, so pretend it is ROM. */ - memory_region_init_ram(flash, NULL, "stellaris.flash", flash_size, + memory_region_init_rom(flash, NULL, "stellaris.flash", flash_size, &error_fatal); - memory_region_set_readonly(flash, true); memory_region_add_subregion(system_memory, 0, flash); memory_region_init_ram(sram, NULL, "stellaris.sram", sram_size, diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c index 4d95a1f..5dee2d7 100644 --- a/hw/arm/tosa.c +++ b/hw/arm/tosa.c @@ -226,8 +226,7 @@ static void tosa_init(MachineState *machine) mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size); - memory_region_init_ram(rom, NULL, "tosa.rom", TOSA_ROM, &error_fatal); - memory_region_set_readonly(rom, true); + memory_region_init_rom(rom, NULL, "tosa.rom", TOSA_ROM, &error_fatal); memory_region_add_subregion(address_space_mem, 0, rom); tmio = tc6393xb_init(address_space_mem, 0x10000000, -- cgit v1.1 From 52013bcea02530bb18691356489dd2612f0eab8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:50:29 +0100 Subject: hw/display: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/display/cg3.c | 5 ++--- hw/display/tcx.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/display/cg3.c b/hw/display/cg3.c index 4fb67c6..a1ede10 100644 --- a/hw/display/cg3.c +++ b/hw/display/cg3.c @@ -287,9 +287,8 @@ static void cg3_initfn(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); CG3State *s = CG3(obj); - memory_region_init_ram_nomigrate(&s->rom, obj, "cg3.prom", FCODE_MAX_ROM_SIZE, - &error_fatal); - memory_region_set_readonly(&s->rom, true); + memory_region_init_rom_nomigrate(&s->rom, obj, "cg3.prom", + FCODE_MAX_ROM_SIZE, &error_fatal); sysbus_init_mmio(sbd, &s->rom); memory_region_init_io(&s->reg, obj, &cg3_reg_ops, s, "cg3.reg", diff --git a/hw/display/tcx.c b/hw/display/tcx.c index ca458f9..76de16e 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -755,9 +755,8 @@ static void tcx_initfn(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); TCXState *s = TCX(obj); - memory_region_init_ram_nomigrate(&s->rom, obj, "tcx.prom", FCODE_MAX_ROM_SIZE, - &error_fatal); - memory_region_set_readonly(&s->rom, true); + memory_region_init_rom_nomigrate(&s->rom, obj, "tcx.prom", + FCODE_MAX_ROM_SIZE, &error_fatal); sysbus_init_mmio(sbd, &s->rom); /* 2/STIP : Stippler */ -- cgit v1.1 From 9400f3435d4c69d906326c27fdf0f96c3a4a9998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:51:23 +0100 Subject: hw/m68k: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/m68k/q800.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index c5699f6..81749e7 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -399,13 +399,12 @@ static void q800_init(MachineState *machine) uint8_t *ptr; /* allocate and load BIOS */ rom = g_malloc(sizeof(*rom)); - memory_region_init_ram(rom, NULL, "m68k_mac.rom", MACROM_SIZE, + memory_region_init_rom(rom, NULL, "m68k_mac.rom", MACROM_SIZE, &error_abort); if (bios_name == NULL) { bios_name = MACROM_FILENAME; } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - memory_region_set_readonly(rom, true); memory_region_add_subregion(get_system_memory(), MACROM_ADDR, rom); /* Load MacROM binary */ -- cgit v1.1 From fcd3b0855ea43bc7ce0a75527cd53c734c236be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:51:23 +0100 Subject: hw/net: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/net/dp8393x.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index 81fc13e..1563c11 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -986,13 +986,12 @@ static void dp8393x_realize(DeviceState *dev, Error **errp) s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s); - memory_region_init_ram(&s->prom, OBJECT(dev), - "dp8393x-prom", SONIC_PROM_SIZE, &local_err); + memory_region_init_rom(&s->prom, OBJECT(dev), "dp8393x-prom", + SONIC_PROM_SIZE, &local_err); if (local_err) { error_propagate(errp, local_err); return; } - memory_region_set_readonly(&s->prom, true); prom = memory_region_get_ram_ptr(&s->prom); checksum = 0; for (i = 0; i < 6; i++) { -- cgit v1.1 From 4f1c3fd35eb56dbe479e6d66ce296ccc67a440fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:51:23 +0100 Subject: hw/pci-host: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Acked-by: David Gibson Signed-off-by: Philippe Mathieu-Daudé --- hw/pci-host/prep.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 1aff72b..1a02e9a 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -325,9 +325,8 @@ static void raven_realize(PCIDevice *d, Error **errp) d->config[0x0D] = 0x10; // latency_timer d->config[0x34] = 0x00; // capabilities_pointer - memory_region_init_ram_nomigrate(&s->bios, OBJECT(s), "bios", BIOS_SIZE, - &error_fatal); - memory_region_set_readonly(&s->bios, true); + memory_region_init_rom_nomigrate(&s->bios, OBJECT(s), "bios", BIOS_SIZE, + &error_fatal); memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SIZE), &s->bios); if (s->bios_name) { -- cgit v1.1 From 1bbd95cb0838c249ea8994def90b509c5a30803e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:51:36 +0100 Subject: hw/ppc: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Acked-by: David Gibson Signed-off-by: Philippe Mathieu-Daudé --- hw/ppc/mac_newworld.c | 3 +-- hw/ppc/mac_oldworld.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index b8189bf..b2ec372 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -155,13 +155,12 @@ static void ppc_core99_init(MachineState *machine) memory_region_add_subregion(get_system_memory(), 0, machine->ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE, + memory_region_init_rom(bios, NULL, "ppc_core99.bios", BIOS_SIZE, &error_fatal); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - memory_region_set_readonly(bios, true); memory_region_add_subregion(get_system_memory(), PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 440c406..faaa165 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -129,13 +129,12 @@ static void ppc_heathrow_init(MachineState *machine) memory_region_add_subregion(sysmem, 0, machine->ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE, + memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE, &error_fatal); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - memory_region_set_readonly(bios, true); memory_region_add_subregion(sysmem, PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ -- cgit v1.1 From cc588b2a127d78be7707f9968f4a5b90aed042b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:51:24 +0100 Subject: hw/riscv: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/riscv/sifive_e.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index a254cad..a1974ef 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -208,9 +208,8 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) memmap[SIFIVE_E_PWM2].base, memmap[SIFIVE_E_PWM2].size); /* Flash memory */ - memory_region_init_ram(&s->xip_mem, NULL, "riscv.sifive.e.xip", - memmap[SIFIVE_E_XIP].size, &error_fatal); - memory_region_set_readonly(&s->xip_mem, true); + memory_region_init_rom(&s->xip_mem, NULL, "riscv.sifive.e.xip", + memmap[SIFIVE_E_XIP].size, &error_fatal); memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_XIP].base, &s->xip_mem); } -- cgit v1.1 From 5ccc751ef8cd74757966a066cfd938ac2e4efd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:51:24 +0100 Subject: hw/sh4: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/sh4/shix.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c index 68b14ee..f410c08 100644 --- a/hw/sh4/shix.c +++ b/hw/sh4/shix.c @@ -53,8 +53,7 @@ static void shix_init(MachineState *machine) cpu = SUPERH_CPU(cpu_create(machine->cpu_type)); /* Allocate memory space */ - memory_region_init_ram(rom, NULL, "shix.rom", 0x4000, &error_fatal); - memory_region_set_readonly(rom, true); + memory_region_init_rom(rom, NULL, "shix.rom", 0x4000, &error_fatal); memory_region_add_subregion(sysmem, 0x00000000, rom); memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000, &error_fatal); -- cgit v1.1 From ec7b217510c06aaa8bb4ab49022ef990a3cac9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:51:24 +0100 Subject: hw/sparc: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Reviewed-by: KONRAD Frederic Signed-off-by: Philippe Mathieu-Daudé --- hw/sparc/leon3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 5fa58aa..8f024da 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -255,8 +255,7 @@ static void leon3_generic_hw_init(MachineState *machine) /* Allocate BIOS */ prom_size = 8 * MiB; - memory_region_init_ram(prom, NULL, "Leon3.bios", prom_size, &error_fatal); - memory_region_set_readonly(prom, true); + memory_region_init_rom(prom, NULL, "Leon3.bios", prom_size, &error_fatal); memory_region_add_subregion(address_space_mem, LEON3_PROM_OFFSET, prom); /* Load boot prom */ -- cgit v1.1 From cf949cbb7079d3856ba61ceab44880ac88f0d7eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:52:31 +0100 Subject: scripts/cocci: Patch to detect potential use of memory_region_init_rom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a semantic patch to detect potential replacement of memory_region_init_ram(readonly) by memory_region_init_rom(). Signed-off-by: Philippe Mathieu-Daudé --- scripts/coccinelle/memory-region-housekeeping.cocci | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/scripts/coccinelle/memory-region-housekeeping.cocci b/scripts/coccinelle/memory-region-housekeeping.cocci index ee3923d..9cdde71 100644 --- a/scripts/coccinelle/memory-region-housekeeping.cocci +++ b/scripts/coccinelle/memory-region-housekeeping.cocci @@ -29,6 +29,25 @@ symbol true; ) +@possible_memory_region_init_rom@ +expression E1, E2, E3, E4, E5; +position p; +@@ +( + memory_region_init_ram@p(E1, E2, E3, E4, E5); + ... + memory_region_set_readonly(E1, true); +| + memory_region_init_ram_nomigrate@p(E1, E2, E3, E4, E5); + ... + memory_region_set_readonly(E1, true); +) +@script:python@ +p << possible_memory_region_init_rom.p; +@@ +cocci.print_main("potential use of memory_region_init_rom*() in ", p) + + // Replace by-hand memory_region_init_ram_nomigrate/vmstate_register_ram // code sequences with use of the new memory_region_init_ram function. // Similarly for the _rom and _rom_device functions. -- cgit v1.1 From bb2f4e8d77c4b39ffc04614e0bbd71b3b3c3b340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 19:55:35 +0100 Subject: scripts/cocci: Patch to remove unnecessary memory_region_set_readonly() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a semantic patch to remove memory_region_set_readonly() calls on ROM memory regions. Signed-off-by: Philippe Mathieu-Daudé --- scripts/coccinelle/memory-region-housekeeping.cocci | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/scripts/coccinelle/memory-region-housekeeping.cocci b/scripts/coccinelle/memory-region-housekeeping.cocci index 9cdde71..5e6b31d 100644 --- a/scripts/coccinelle/memory-region-housekeeping.cocci +++ b/scripts/coccinelle/memory-region-housekeeping.cocci @@ -48,6 +48,21 @@ p << possible_memory_region_init_rom.p; cocci.print_main("potential use of memory_region_init_rom*() in ", p) +// Do not call memory_region_set_readonly() on ROM alias +@@ +expression ROM, E1, E2, E3, E4; +expression ALIAS, E5, E6, E7, E8; +@@ +( + memory_region_init_rom(ROM, E1, E2, E3, E4); +| + memory_region_init_rom_nomigrate(ROM, E1, E2, E3, E4); +) + ... + memory_region_init_alias(ALIAS, E5, E6, ROM, E7, E8); +- memory_region_set_readonly(ALIAS, true); + + // Replace by-hand memory_region_init_ram_nomigrate/vmstate_register_ram // code sequences with use of the new memory_region_init_ram function. // Similarly for the _rom and _rom_device functions. -- cgit v1.1 From 84969111e656eb594ac123a23aa120ff5e157ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 21 Feb 2020 16:05:08 +0100 Subject: scripts/cocci: Patch to let devices own their MemoryRegions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a device creates a MemoryRegion without setting its ownership, the MemoryRegion is added to the machine "/unattached" container in the QOM tree. Example with the Samsung SMDKC210 board: $ arm-softmmu/qemu-system-arm -M smdkc210 -S -monitor stdio (qemu) info qom-tree /machine (smdkc210-machine) /unattached (container) /io[0] (qemu:memory-region) /exynos4210.dram0[0] (qemu:memory-region) /exynos4210.irom[0] (qemu:memory-region) /exynos4210.iram[0] (qemu:memory-region) /exynos4210.chipid[0] (qemu:memory-region) ... /device[26] (exynos4210.uart) /exynos4210.uart[0] (qemu:memory-region) /soc (exynos4210) ^ \__ [*] The irom/iram/chipid regions should go under 'soc' at [*]. Add a semantic patch to let the device own the memory region. Signed-off-by: Philippe Mathieu-Daudé --- .../coccinelle/memory-region-housekeeping.cocci | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/scripts/coccinelle/memory-region-housekeeping.cocci b/scripts/coccinelle/memory-region-housekeeping.cocci index 5e6b31d..c768d81 100644 --- a/scripts/coccinelle/memory-region-housekeeping.cocci +++ b/scripts/coccinelle/memory-region-housekeeping.cocci @@ -101,3 +101,59 @@ expression ERRP; +memory_region_init_rom_device(MR, NULL, OPS, OPAQUE, NAME, SIZE, ERRP); ... -vmstate_register_ram_global(MR); + + +// Device is owner +@@ +typedef DeviceState; +identifier device_fn, dev, obj; +expression E1, E2, E3, E4, E5; +@@ +static void device_fn(DeviceState *dev, ...) +{ + ... + Object *obj = OBJECT(dev); + <+... +( +- memory_region_init(E1, NULL, E2, E3); ++ memory_region_init(E1, obj, E2, E3); +| +- memory_region_init_io(E1, NULL, E2, E3, E4, E5); ++ memory_region_init_io(E1, obj, E2, E3, E4, E5); +| +- memory_region_init_alias(E1, NULL, E2, E3, E4, E5); ++ memory_region_init_alias(E1, obj, E2, E3, E4, E5); +| +- memory_region_init_rom(E1, NULL, E2, E3, E4); ++ memory_region_init_rom(E1, obj, E2, E3, E4); +| +- memory_region_init_ram_shared_nomigrate(E1, NULL, E2, E3, E4, E5); ++ memory_region_init_ram_shared_nomigrate(E1, obj, E2, E3, E4, E5); +) + ...+> +} +@@ +identifier device_fn, dev; +expression E1, E2, E3, E4, E5; +@@ +static void device_fn(DeviceState *dev, ...) +{ + <+... +( +- memory_region_init(E1, NULL, E2, E3); ++ memory_region_init(E1, OBJECT(dev), E2, E3); +| +- memory_region_init_io(E1, NULL, E2, E3, E4, E5); ++ memory_region_init_io(E1, OBJECT(dev), E2, E3, E4, E5); +| +- memory_region_init_alias(E1, NULL, E2, E3, E4, E5); ++ memory_region_init_alias(E1, OBJECT(dev), E2, E3, E4, E5); +| +- memory_region_init_rom(E1, NULL, E2, E3, E4); ++ memory_region_init_rom(E1, OBJECT(dev), E2, E3, E4); +| +- memory_region_init_ram_shared_nomigrate(E1, NULL, E2, E3, E4, E5); ++ memory_region_init_ram_shared_nomigrate(E1, OBJECT(dev), E2, E3, E4, E5); +) + ...+> +} -- cgit v1.1 From de95af9967a777263894165e3ba576581a82da4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 22 Feb 2020 18:11:51 +0100 Subject: hw/core: Let devices own the MemoryRegion they create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid orphan memory regions being added in the /unattached QOM container. This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/core/platform-bus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c index 22c5f76..d494e5c 100644 --- a/hw/core/platform-bus.c +++ b/hw/core/platform-bus.c @@ -187,7 +187,8 @@ static void platform_bus_realize(DeviceState *dev, Error **errp) d = SYS_BUS_DEVICE(dev); pbus = PLATFORM_BUS_DEVICE(dev); - memory_region_init(&pbus->mmio, NULL, "platform bus", pbus->mmio_size); + memory_region_init(&pbus->mmio, OBJECT(dev), "platform bus", + pbus->mmio_size); sysbus_init_mmio(d, &pbus->mmio); pbus->used_irqs = bitmap_new(pbus->num_irqs); -- cgit v1.1 From b9fc4f6e6218439684abbae863bbcb2ecef9201e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 22 Feb 2020 18:12:09 +0100 Subject: hw/display: Let devices own the MemoryRegion they create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid orphan memory regions being added in the /unattached QOM container. This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/display/g364fb.c | 3 ++- hw/display/macfb.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index 55185c9..adcba96 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -477,7 +477,8 @@ static void g364fb_init(DeviceState *dev, G364State *s) s->con = graphic_console_init(dev, 0, &g364fb_ops, s); - memory_region_init_io(&s->mem_ctrl, NULL, &g364fb_ctrl_ops, s, "ctrl", 0x180000); + memory_region_init_io(&s->mem_ctrl, OBJECT(dev), &g364fb_ctrl_ops, s, + "ctrl", 0x180000); memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram", s->vram_size, s->vram); vmstate_register_ram(&s->mem_vram, dev); diff --git a/hw/display/macfb.c b/hw/display/macfb.c index 8bff16d..b68faff 100644 --- a/hw/display/macfb.c +++ b/hw/display/macfb.c @@ -362,8 +362,8 @@ static void macfb_common_realize(DeviceState *dev, MacfbState *s, Error **errp) return; } - memory_region_init_io(&s->mem_ctrl, NULL, &macfb_ctrl_ops, s, "macfb-ctrl", - 0x1000); + memory_region_init_io(&s->mem_ctrl, OBJECT(dev), &macfb_ctrl_ops, s, + "macfb-ctrl", 0x1000); memory_region_init_ram_nomigrate(&s->mem_vram, OBJECT(s), "macfb-vram", MACFB_VRAM_SIZE, errp); -- cgit v1.1 From a8457764877c7d4070e5369e98d27876470ac6d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 22 Feb 2020 18:12:37 +0100 Subject: hw/dma: Let devices own the MemoryRegion they create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid orphan memory regions being added in the /unattached QOM container. This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/dma/i8257.c | 2 +- hw/dma/rc4030.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c index bad8deb..ef15c06 100644 --- a/hw/dma/i8257.c +++ b/hw/dma/i8257.c @@ -553,7 +553,7 @@ static void i8257_realize(DeviceState *dev, Error **errp) I8257State *d = I8257(dev); int i; - memory_region_init_io(&d->channel_io, NULL, &channel_io_ops, d, + memory_region_init_io(&d->channel_io, OBJECT(dev), &channel_io_ops, d, "dma-chan", 8 << d->dshift); memory_region_add_subregion(isa_address_space_io(isa), d->base, &d->channel_io); diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c index 21e2c36..7434d27 100644 --- a/hw/dma/rc4030.c +++ b/hw/dma/rc4030.c @@ -679,9 +679,9 @@ static void rc4030_realize(DeviceState *dev, Error **errp) s->periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rc4030_periodic_timer, s); - memory_region_init_io(&s->iomem_chipset, NULL, &rc4030_ops, s, + memory_region_init_io(&s->iomem_chipset, o, &rc4030_ops, s, "rc4030.chipset", 0x300); - memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s, + memory_region_init_io(&s->iomem_jazzio, o, &jazzio_ops, s, "rc4030.jazzio", 0x00001000); memory_region_init_iommu(&s->dma_mr, sizeof(s->dma_mr), -- cgit v1.1 From 414c47d234d6b12756d987bd93b9c8a04d009675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 22 Feb 2020 18:12:57 +0100 Subject: hw/riscv: Let devices own the MemoryRegion they create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid orphan memory regions being added in the /unattached QOM container. This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/riscv/sifive_e.c | 6 +++--- hw/riscv/sifive_u.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index a1974ef..646553a 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -145,8 +145,8 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) &error_abort); /* Mask ROM */ - memory_region_init_rom(&s->mask_rom, NULL, "riscv.sifive.e.mrom", - memmap[SIFIVE_E_MROM].size, &error_fatal); + memory_region_init_rom(&s->mask_rom, OBJECT(dev), "riscv.sifive.e.mrom", + memmap[SIFIVE_E_MROM].size, &error_fatal); memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_MROM].base, &s->mask_rom); @@ -208,7 +208,7 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) memmap[SIFIVE_E_PWM2].base, memmap[SIFIVE_E_PWM2].size); /* Flash memory */ - memory_region_init_rom(&s->xip_mem, NULL, "riscv.sifive.e.xip", + memory_region_init_rom(&s->xip_mem, OBJECT(dev), "riscv.sifive.e.xip", memmap[SIFIVE_E_XIP].size, &error_fatal); memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_XIP].base, &s->xip_mem); diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 156a003..662d42a 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -497,7 +497,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) &error_abort); /* boot rom */ - memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom", + memory_region_init_rom(mask_rom, OBJECT(dev), "riscv.sifive.u.mrom", memmap[SIFIVE_U_MROM].size, &error_fatal); memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base, mask_rom); -- cgit v1.1 From 41e82da57dbb6cad8ef1c9a281a9aac2265a0586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 22 Feb 2020 18:11:33 +0100 Subject: hw/char: Let devices own the MemoryRegion they create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid orphan memory regions being added in the /unattached QOM container. This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/char/serial.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/char/serial.c b/hw/char/serial.c index 9298881..2ab8b69 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -997,7 +997,7 @@ static void serial_io_realize(DeviceState *dev, Error **errp) return; } - memory_region_init_io(&s->io, NULL, &serial_io_ops, s, "serial", 8); + memory_region_init_io(&s->io, OBJECT(dev), &serial_io_ops, s, "serial", 8); sysbus_init_mmio(SYS_BUS_DEVICE(sio), &s->io); sysbus_init_irq(SYS_BUS_DEVICE(sio), &s->irq); } @@ -1106,8 +1106,9 @@ static void serial_mm_realize(DeviceState *dev, Error **errp) return; } - memory_region_init_io(&s->io, NULL, &serial_mm_ops[smm->endianness], smm, - "serial", 8 << smm->regshift); + memory_region_init_io(&s->io, OBJECT(dev), + &serial_mm_ops[smm->endianness], smm, "serial", + 8 << smm->regshift); sysbus_init_mmio(SYS_BUS_DEVICE(smm), &s->io); sysbus_init_irq(SYS_BUS_DEVICE(smm), &smm->serial.irq); } -- cgit v1.1 From 30ade0c41653e94954971921d2ebeb25e5a206db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 16:58:53 +0100 Subject: hw/arm/stm32: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scripts/coccinelle/memory-region-housekeeping.cocci reported: * TODO [[view:./hw/arm/stm32f205_soc.c::face=ovl-face1::linb=96::colb=4::cole=26][potential use of memory_region_init_rom*() in ./hw/arm/stm32f205_soc.c::96]] * TODO [[view:./hw/arm/stm32f405_soc.c::face=ovl-face1::linb=98::colb=4::cole=26][potential use of memory_region_init_rom*() in ./hw/arm/stm32f405_soc.c::98]] We can indeed replace the memory_region_init_ram() and memory_region_set_readonly() calls by memory_region_init_rom(). Signed-off-by: Philippe Mathieu-Daudé --- hw/arm/stm32f205_soc.c | 4 +--- hw/arm/stm32f405_soc.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c index 627fd44..2de5627 100644 --- a/hw/arm/stm32f205_soc.c +++ b/hw/arm/stm32f205_soc.c @@ -93,12 +93,10 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) MemoryRegion *flash = g_new(MemoryRegion, 1); MemoryRegion *flash_alias = g_new(MemoryRegion, 1); - memory_region_init_ram(flash, NULL, "STM32F205.flash", FLASH_SIZE, + memory_region_init_rom(flash, NULL, "STM32F205.flash", FLASH_SIZE, &error_fatal); memory_region_init_alias(flash_alias, NULL, "STM32F205.flash.alias", flash, 0, FLASH_SIZE); - - memory_region_set_readonly(flash, true); memory_region_set_readonly(flash_alias, true); memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash); diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c index 9bcad97..b8fca13 100644 --- a/hw/arm/stm32f405_soc.c +++ b/hw/arm/stm32f405_soc.c @@ -95,7 +95,7 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) Error *err = NULL; int i; - memory_region_init_ram(&s->flash, NULL, "STM32F405.flash", FLASH_SIZE, + memory_region_init_rom(&s->flash, NULL, "STM32F405.flash", FLASH_SIZE, &err); if (err != NULL) { error_propagate(errp, err); @@ -103,8 +103,6 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) } memory_region_init_alias(&s->flash_alias, NULL, "STM32F405.flash.alias", &s->flash, 0, FLASH_SIZE); - - memory_region_set_readonly(&s->flash, true); memory_region_set_readonly(&s->flash_alias, true); memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash); -- cgit v1.1 From 34b7645880750f0b8b7819249a3e039795137508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 17:04:51 +0100 Subject: hw/ppc/ppc405: Use memory_region_init_rom() with read-only regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scripts/coccinelle/memory-region-housekeeping.cocci reported: * TODO [[view:./hw/ppc/ppc405_boards.c::face=ovl-face1::linb=195::colb=8::cole=30][potential use of memory_region_init_rom*() in ./hw/ppc/ppc405_boards.c::195]] * TODO [[view:./hw/ppc/ppc405_boards.c::face=ovl-face1::linb=464::colb=8::cole=30][potential use of memory_region_init_rom*() in ./hw/ppc/ppc405_boards.c::464]] We can indeed replace the memory_region_init_ram() and memory_region_set_readonly() calls by memory_region_init_rom(). Acked-by: David Gibson Signed-off-by: Philippe Mathieu-Daudé --- hw/ppc/ppc405_boards.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index de93c40..e6bffb9 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -199,7 +199,7 @@ static void ref405ep_init(MachineState *machine) #endif { bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE, + memory_region_init_rom(bios, NULL, "ef405ep.bios", BIOS_SIZE, &error_fatal); if (bios_name == NULL) @@ -223,7 +223,6 @@ static void ref405ep_init(MachineState *machine) /* Avoid an uninitialized variable warning */ bios_size = -1; } - memory_region_set_readonly(bios, true); } /* Register FPGA */ ref405ep_fpga_init(sysmem, 0xF0300000); @@ -471,7 +470,7 @@ static void taihu_405ep_init(MachineState *machine) if (bios_name == NULL) bios_name = BIOS_FILENAME; bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE, + memory_region_init_rom(bios, NULL, "taihu_405ep.bios", BIOS_SIZE, &error_fatal); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { @@ -489,7 +488,6 @@ static void taihu_405ep_init(MachineState *machine) error_report("Could not load PowerPC BIOS '%s'", bios_name); exit(1); } - memory_region_set_readonly(bios, true); } /* Register Linux flash */ dinfo = drive_get(IF_PFLASH, 0, fl_idx); -- cgit v1.1 From 5b871c1b62036ef06eaf96ec03bbad801fcf9b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 16:59:18 +0100 Subject: hw/arm: Remove unnecessary memory_region_set_readonly() on ROM alias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/arm/exynos4210.c | 1 - hw/arm/stm32f205_soc.c | 1 - hw/arm/stm32f405_soc.c | 1 - 3 files changed, 3 deletions(-) diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index 3af6502..4e1fd7e 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -320,7 +320,6 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) &s->irom_mem, 0, EXYNOS4210_IROM_SIZE); - memory_region_set_readonly(&s->irom_alias_mem, true); memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR, &s->irom_alias_mem); diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c index 2de5627..6e93726 100644 --- a/hw/arm/stm32f205_soc.c +++ b/hw/arm/stm32f205_soc.c @@ -97,7 +97,6 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) &error_fatal); memory_region_init_alias(flash_alias, NULL, "STM32F205.flash.alias", flash, 0, FLASH_SIZE); - memory_region_set_readonly(flash_alias, true); memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash); memory_region_add_subregion(system_memory, 0, flash_alias); diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c index b8fca13..d590cd0 100644 --- a/hw/arm/stm32f405_soc.c +++ b/hw/arm/stm32f405_soc.c @@ -103,7 +103,6 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) } memory_region_init_alias(&s->flash_alias, NULL, "STM32F405.flash.alias", &s->flash, 0, FLASH_SIZE); - memory_region_set_readonly(&s->flash_alias, true); memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash); memory_region_add_subregion(system_memory, 0, &s->flash_alias); -- cgit v1.1 From 32b9523ad5b44dea87792d5d8f71a87e8cc5803b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 24 Feb 2020 18:32:23 +0100 Subject: hw/arm: Let devices own the MemoryRegion they create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid orphan memory regions being added in the /unattached QOM container. This commit was produced with the Coccinelle script scripts/coccinelle/memory-region-housekeeping.cocci. Signed-off-by: Philippe Mathieu-Daudé --- hw/arm/exynos4210.c | 12 ++++++------ hw/arm/fsl-imx25.c | 10 +++++----- hw/arm/fsl-imx31.c | 6 +++--- hw/arm/fsl-imx6.c | 6 +++--- hw/arm/fsl-imx6ul.c | 9 +++++---- hw/arm/msf2-soc.c | 6 +++--- hw/arm/nrf51_soc.c | 2 +- hw/arm/stm32f205_soc.c | 8 ++++---- hw/arm/stm32f405_soc.c | 9 +++++---- hw/arm/xlnx-zynqmp.c | 11 +++++------ 10 files changed, 40 insertions(+), 39 deletions(-) diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index 4e1fd7e..1f7253e 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -305,20 +305,20 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp) /*** Memory ***/ /* Chip-ID and OMR */ - memory_region_init_io(&s->chipid_mem, NULL, &exynos4210_chipid_and_omr_ops, - NULL, "exynos4210.chipid", sizeof(chipid_and_omr)); + memory_region_init_io(&s->chipid_mem, OBJECT(socdev), + &exynos4210_chipid_and_omr_ops, NULL, + "exynos4210.chipid", sizeof(chipid_and_omr)); memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR, &s->chipid_mem); /* Internal ROM */ - memory_region_init_rom(&s->irom_mem, NULL, "exynos4210.irom", + memory_region_init_rom(&s->irom_mem, OBJECT(socdev), "exynos4210.irom", EXYNOS4210_IROM_SIZE, &error_fatal); memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR, &s->irom_mem); /* mirror of iROM */ - memory_region_init_alias(&s->irom_alias_mem, NULL, "exynos4210.irom_alias", - &s->irom_mem, - 0, + memory_region_init_alias(&s->irom_alias_mem, OBJECT(socdev), + "exynos4210.irom_alias", &s->irom_mem, 0, EXYNOS4210_IROM_SIZE); memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR, &s->irom_alias_mem); diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c index a3f829f..6f1a82c 100644 --- a/hw/arm/fsl-imx25.c +++ b/hw/arm/fsl-imx25.c @@ -303,16 +303,16 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) } /* initialize 2 x 16 KB ROM */ - memory_region_init_rom(&s->rom[0], NULL, - "imx25.rom0", FSL_IMX25_ROM0_SIZE, &err); + memory_region_init_rom(&s->rom[0], OBJECT(dev), "imx25.rom0", + FSL_IMX25_ROM0_SIZE, &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM0_ADDR, &s->rom[0]); - memory_region_init_rom(&s->rom[1], NULL, - "imx25.rom1", FSL_IMX25_ROM1_SIZE, &err); + memory_region_init_rom(&s->rom[1], OBJECT(dev), "imx25.rom1", + FSL_IMX25_ROM1_SIZE, &err); if (err) { error_propagate(errp, err); return; @@ -331,7 +331,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) &s->iram); /* internal RAM (128 KB) is aliased over 128 MB - 128 KB */ - memory_region_init_alias(&s->iram_alias, NULL, "imx25.iram_alias", + memory_region_init_alias(&s->iram_alias, OBJECT(dev), "imx25.iram_alias", &s->iram, 0, FSL_IMX25_IRAM_ALIAS_SIZE); memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ALIAS_ADDR, &s->iram_alias); diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c index 55e90d1..8472d2e 100644 --- a/hw/arm/fsl-imx31.c +++ b/hw/arm/fsl-imx31.c @@ -206,7 +206,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) } /* On a real system, the first 16k is a `secure boot rom' */ - memory_region_init_rom(&s->secure_rom, NULL, "imx31.secure_rom", + memory_region_init_rom(&s->secure_rom, OBJECT(dev), "imx31.secure_rom", FSL_IMX31_SECURE_ROM_SIZE, &err); if (err) { error_propagate(errp, err); @@ -216,7 +216,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) &s->secure_rom); /* There is also a 16k ROM */ - memory_region_init_rom(&s->rom, NULL, "imx31.rom", + memory_region_init_rom(&s->rom, OBJECT(dev), "imx31.rom", FSL_IMX31_ROM_SIZE, &err); if (err) { error_propagate(errp, err); @@ -236,7 +236,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp) &s->iram); /* internal RAM (16 KB) is aliased over 256 MB - 16 KB */ - memory_region_init_alias(&s->iram_alias, NULL, "imx31.iram_alias", + memory_region_init_alias(&s->iram_alias, OBJECT(dev), "imx31.iram_alias", &s->iram, 0, FSL_IMX31_IRAM_ALIAS_SIZE); memory_region_add_subregion(get_system_memory(), FSL_IMX31_IRAM_ALIAS_ADDR, &s->iram_alias); diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index ecc6285..9c09f71 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -405,7 +405,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) } /* ROM memory */ - memory_region_init_rom(&s->rom, NULL, "imx6.rom", + memory_region_init_rom(&s->rom, OBJECT(dev), "imx6.rom", FSL_IMX6_ROM_SIZE, &err); if (err) { error_propagate(errp, err); @@ -415,7 +415,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) &s->rom); /* CAAM memory */ - memory_region_init_rom(&s->caam, NULL, "imx6.caam", + memory_region_init_rom(&s->caam, OBJECT(dev), "imx6.caam", FSL_IMX6_CAAM_MEM_SIZE, &err); if (err) { error_propagate(errp, err); @@ -435,7 +435,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) &s->ocram); /* internal OCRAM (256 KB) is aliased over 1 MB */ - memory_region_init_alias(&s->ocram_alias, NULL, "imx6.ocram_alias", + memory_region_init_alias(&s->ocram_alias, OBJECT(dev), "imx6.ocram_alias", &s->ocram, 0, FSL_IMX6_OCRAM_ALIAS_SIZE); memory_region_add_subregion(get_system_memory(), FSL_IMX6_OCRAM_ALIAS_ADDR, &s->ocram_alias); diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c index c405b68..f4a9ed6 100644 --- a/hw/arm/fsl-imx6ul.c +++ b/hw/arm/fsl-imx6ul.c @@ -543,7 +543,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) /* * ROM memory */ - memory_region_init_rom(&s->rom, NULL, "imx6ul.rom", + memory_region_init_rom(&s->rom, OBJECT(dev), "imx6ul.rom", FSL_IMX6UL_ROM_SIZE, &error_abort); memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_ROM_ADDR, &s->rom); @@ -551,7 +551,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) /* * CAAM memory */ - memory_region_init_rom(&s->caam, NULL, "imx6ul.caam", + memory_region_init_rom(&s->caam, OBJECT(dev), "imx6ul.caam", FSL_IMX6UL_CAAM_MEM_SIZE, &error_abort); memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_CAAM_MEM_ADDR, &s->caam); @@ -568,8 +568,9 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) /* * internal OCRAM (128 KB) is aliased over 512 KB */ - memory_region_init_alias(&s->ocram_alias, NULL, "imx6ul.ocram_alias", - &s->ocram, 0, FSL_IMX6UL_OCRAM_ALIAS_SIZE); + memory_region_init_alias(&s->ocram_alias, OBJECT(dev), + "imx6ul.ocram_alias", &s->ocram, 0, + FSL_IMX6UL_OCRAM_ALIAS_SIZE); memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_OCRAM_ALIAS_ADDR, &s->ocram_alias); } diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c index 8f84692..588d643 100644 --- a/hw/arm/msf2-soc.c +++ b/hw/arm/msf2-soc.c @@ -96,7 +96,7 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) MemoryRegion *nvm_alias = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); - memory_region_init_rom(nvm, NULL, "MSF2.eNVM", s->envm_size, + memory_region_init_rom(nvm, OBJECT(dev_soc), "MSF2.eNVM", s->envm_size, &error_fatal); /* * On power-on, the eNVM region 0x60000000 is automatically @@ -104,8 +104,8 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp) * start address (0x0). We do not support remapping other eNVM, * eSRAM and DDR regions by guest(via Sysreg) currently. */ - memory_region_init_alias(nvm_alias, NULL, "MSF2.eNVM", - nvm, 0, s->envm_size); + memory_region_init_alias(nvm_alias, OBJECT(dev_soc), "MSF2.eNVM", nvm, 0, + s->envm_size); memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS, nvm); memory_region_add_subregion(system_memory, 0, nvm_alias); diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index 4817a76..57eff63 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -165,7 +165,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) } /* STUB Peripherals */ - memory_region_init_io(&s->clock, NULL, &clock_ops, NULL, + memory_region_init_io(&s->clock, OBJECT(dev_soc), &clock_ops, NULL, "nrf51_soc.clock", 0x1000); memory_region_add_subregion_overlap(&s->container, NRF51_IOMEM_BASE, &s->clock, -1); diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c index 6e93726..118c342 100644 --- a/hw/arm/stm32f205_soc.c +++ b/hw/arm/stm32f205_soc.c @@ -93,10 +93,10 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) MemoryRegion *flash = g_new(MemoryRegion, 1); MemoryRegion *flash_alias = g_new(MemoryRegion, 1); - memory_region_init_rom(flash, NULL, "STM32F205.flash", FLASH_SIZE, - &error_fatal); - memory_region_init_alias(flash_alias, NULL, "STM32F205.flash.alias", - flash, 0, FLASH_SIZE); + memory_region_init_rom(flash, OBJECT(dev_soc), "STM32F205.flash", + FLASH_SIZE, &error_fatal); + memory_region_init_alias(flash_alias, OBJECT(dev_soc), + "STM32F205.flash.alias", flash, 0, FLASH_SIZE); memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash); memory_region_add_subregion(system_memory, 0, flash_alias); diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c index d590cd0..4f10ce6 100644 --- a/hw/arm/stm32f405_soc.c +++ b/hw/arm/stm32f405_soc.c @@ -95,14 +95,15 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) Error *err = NULL; int i; - memory_region_init_rom(&s->flash, NULL, "STM32F405.flash", FLASH_SIZE, - &err); + memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F405.flash", + FLASH_SIZE, &err); if (err != NULL) { error_propagate(errp, err); return; } - memory_region_init_alias(&s->flash_alias, NULL, "STM32F405.flash.alias", - &s->flash, 0, FLASH_SIZE); + memory_region_init_alias(&s->flash_alias, OBJECT(dev_soc), + "STM32F405.flash.alias", &s->flash, 0, + FLASH_SIZE); memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash); memory_region_add_subregion(system_memory, 0, &s->flash_alias); diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index cab0160..49f1c8d 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -318,9 +318,9 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) ddr_low_size = XLNX_ZYNQMP_MAX_LOW_RAM_SIZE; ddr_high_size = ram_size - XLNX_ZYNQMP_MAX_LOW_RAM_SIZE; - memory_region_init_alias(&s->ddr_ram_high, NULL, - "ddr-ram-high", s->ddr_ram, - ddr_low_size, ddr_high_size); + memory_region_init_alias(&s->ddr_ram_high, OBJECT(dev), + "ddr-ram-high", s->ddr_ram, ddr_low_size, + ddr_high_size); memory_region_add_subregion(get_system_memory(), XLNX_ZYNQMP_HIGH_RAM_START, &s->ddr_ram_high); @@ -330,9 +330,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) ddr_low_size = ram_size; } - memory_region_init_alias(&s->ddr_ram_low, NULL, - "ddr-ram-low", s->ddr_ram, - 0, ddr_low_size); + memory_region_init_alias(&s->ddr_ram_low, OBJECT(dev), "ddr-ram-low", + s->ddr_ram, 0, ddr_low_size); memory_region_add_subregion(get_system_memory(), 0, &s->ddr_ram_low); /* Create the four OCM banks */ -- cgit v1.1