From 08b9e0ba623c4468fe94026a9bdd086526ef62f0 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Wed, 5 Jul 2017 06:33:32 +0800 Subject: vhost: fix a memory leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vhost exists a call for g_file_get_contents, but not call g_free. Signed-off-by: Peng Hao Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Marc-André Lureau --- hw/virtio/vhost-backend.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'hw') diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index cb055e8..7f09efa 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -52,11 +52,13 @@ static int vhost_kernel_memslots_limit(struct vhost_dev *dev) &s, NULL, NULL)) { uint64_t val = g_ascii_strtoull(s, NULL, 10); if (!((val == G_MAXUINT64 || !val) && errno)) { + g_free(s); return val; } error_report("ignoring invalid max_mem_regions value in vhost module:" " %s", s); } + g_free(s); return limit; } -- cgit v1.1 From 5df04f1762ef78c08fd69e19dcedf3d9ba8c9b86 Mon Sep 17 00:00:00 2001 From: Felipe Franciosi Date: Wed, 14 Jun 2017 18:44:38 +0100 Subject: vhost-user: fix legacy cross-endian configurations Currently, vhost-user does not implement any means for notifying the backend about guest endianess. This commit introduces a new message called VHOST_USER_SET_VRING_ENDIAN which is analogous to the ioctl() called VHOST_SET_VRING_ENDIAN used for kernel vhost backends. Such message is necessary for backends supporting legacy (pre-1.0) virtio devices running in big-endian guests. Signed-off-by: Felipe Franciosi Signed-off-by: Mike Cui --- hw/virtio/vhost-user.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 2203011..093675e 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -33,6 +33,7 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_REPLY_ACK = 3, VHOST_USER_PROTOCOL_F_NET_MTU = 4, VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, + VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, VHOST_USER_PROTOCOL_F_MAX }; @@ -63,6 +64,7 @@ typedef enum VhostUserRequest { VHOST_USER_NET_SET_MTU = 20, VHOST_USER_SET_SLAVE_REQ_FD = 21, VHOST_USER_IOTLB_MSG = 22, + VHOST_USER_SET_VRING_ENDIAN = 23, VHOST_USER_MAX } VhostUserRequest; @@ -367,8 +369,25 @@ static int vhost_user_set_vring_addr(struct vhost_dev *dev, static int vhost_user_set_vring_endian(struct vhost_dev *dev, struct vhost_vring_state *ring) { - error_report("vhost-user trying to send unhandled ioctl"); - return -1; + bool cross_endian = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CROSS_ENDIAN); + VhostUserMsg msg = { + .request = VHOST_USER_SET_VRING_ENDIAN, + .flags = VHOST_USER_VERSION, + .payload.state = *ring, + .size = sizeof(msg.payload.state), + }; + + if (!cross_endian) { + error_report("vhost-user trying to send unhandled ioctl"); + return -1; + } + + if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + return -1; + } + + return 0; } static int vhost_set_vring(struct vhost_dev *dev, -- cgit v1.1 From 892721d91d9deb2affe4e61334b1dd1b43728f92 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Mon, 17 Jul 2017 17:02:29 +0800 Subject: intel_iommu: fix iova for pt IOMMUTLBEntry.iova is returned incorrectly on one PT path (though mostly we cannot really trigger this path, even if we do, we are mostly disgarding this value, so it didn't break anything). Fix it by converting the VTD_PAGE_MASK into the correct definition VTD_PAGE_MASK_4K, then remove VTD_PAGE_MASK. Fixes: b93130 ("intel_iommu: cleanup vtd_{do_}iommu_translate()") Signed-off-by: Peter Xu Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/intel_iommu.c | 4 ++-- hw/i386/intel_iommu_internal.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index e398746..e0b0498 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -1139,9 +1139,9 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, * Also, let's ignore IOTLB caching as well for PT devices. */ if (vtd_ce_get_type(&ce) == VTD_CONTEXT_TT_PASS_THROUGH) { - entry->iova = addr & VTD_PAGE_MASK; + entry->iova = addr & VTD_PAGE_MASK_4K; entry->translated_addr = entry->iova; - entry->addr_mask = VTD_PAGE_MASK; + entry->addr_mask = ~VTD_PAGE_MASK_4K; entry->perm = IOMMU_RW; trace_vtd_translate_pt(source_id, entry->iova); diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index f50ecd8..0e73a65 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -384,7 +384,6 @@ typedef struct VTDIOTLBPageInvInfo VTDIOTLBPageInvInfo; /* Pagesize of VTD paging structures, including root and context tables */ #define VTD_PAGE_SHIFT 12 #define VTD_PAGE_SIZE (1ULL << VTD_PAGE_SHIFT) -#define VTD_PAGE_MASK (VTD_PAGE_SIZE - 1) #define VTD_PAGE_SHIFT_4K 12 #define VTD_PAGE_MASK_4K (~((1ULL << VTD_PAGE_SHIFT_4K) - 1)) -- cgit v1.1 From 07f7b73398de3b60f28301a9af2a2338710105c7 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Mon, 17 Jul 2017 17:02:30 +0800 Subject: intel_iommu: use access_flags for iotlb It was cached by read/write separately. Let's merge them. Signed-off-by: Peter Xu Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/intel_iommu.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'hw') diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index e0b0498..a7bf87a 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -237,8 +237,7 @@ out: static void vtd_update_iotlb(IntelIOMMUState *s, uint16_t source_id, uint16_t domain_id, hwaddr addr, uint64_t slpte, - bool read_flags, bool write_flags, - uint32_t level) + uint8_t access_flags, uint32_t level) { VTDIOTLBEntry *entry = g_malloc(sizeof(*entry)); uint64_t *key = g_malloc(sizeof(*key)); @@ -253,8 +252,7 @@ static void vtd_update_iotlb(IntelIOMMUState *s, uint16_t source_id, entry->gfn = gfn; entry->domain_id = domain_id; entry->slpte = slpte; - entry->read_flags = read_flags; - entry->write_flags = write_flags; + entry->access_flags = access_flags; entry->mask = vtd_slpt_level_page_mask(level); *key = vtd_get_iotlb_key(gfn, source_id, level); g_hash_table_replace(s->iotlb, key, entry); @@ -1087,6 +1085,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, bool is_fpd_set = false; bool reads = true; bool writes = true; + uint8_t access_flags; VTDIOTLBEntry *iotlb_entry; /* @@ -1101,8 +1100,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->slpte, iotlb_entry->domain_id); slpte = iotlb_entry->slpte; - reads = iotlb_entry->read_flags; - writes = iotlb_entry->write_flags; + access_flags = iotlb_entry->access_flags; page_mask = iotlb_entry->mask; goto out; } @@ -1172,13 +1170,14 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, } page_mask = vtd_slpt_level_page_mask(level); + access_flags = IOMMU_ACCESS_FLAG(reads, writes); vtd_update_iotlb(s, source_id, VTD_CONTEXT_ENTRY_DID(ce.hi), addr, slpte, - reads, writes, level); + access_flags, level); out: entry->iova = addr & page_mask; entry->translated_addr = vtd_get_slpte_addr(slpte) & page_mask; entry->addr_mask = ~page_mask; - entry->perm = IOMMU_ACCESS_FLAG(reads, writes); + entry->perm = access_flags; return true; error: -- cgit v1.1 From 208fa0e43645edd0b0d8f838857dfc79daff40a8 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 28 Jul 2017 11:09:05 +0200 Subject: pc: make 'pc.rom' readonly when machine has PCI enabled looking at bios ROM mapping in QEMU it seems that only isapc (i.e. not PCI enabled machine) requires ROM being mapped as RW in other cases BIOS is mapped as RO. Do the same for option ROM 'pc.rom' when machine has PCI enabled. As useful side-effect pc.rom MemoryRegion stops being put in vhost memory map (filtered out by vhost_section()), which reduces number of entries by 1. Coincidentally it fixes migration failure reported in "[PATCH V2] vhost: fix a migration failed because of vhost region merge" where following destination CLI with /sys/module/vhost/parameters/max_mem_regions = 8 export DIMMSCOUNT=6 QEMU -enable-kvm \ -netdev type=tap,id=guest0,vhost=on,script=no,vhostforce \ -device virtio-net-pci,netdev=guest0 \ -m 256,slots=256,maxmem=2G \ `i=0; while [ $i -lt $DIMMSCOUNT ]; do echo \ "-object memory-backend-ram,id=m$i,size=128M \ -device pc-dimm,id=d$i,memdev=m$i"; i=$(($i + 1)); \ done` will fail to startup with error: "-device pc-dimm,id=d5,memdev=m5: a used vhost backend has no free memory slots left" while it's possible to add the 6th DIMM during hotplug on source. Issue is caused by the fact that number of entries in vhost map is bigger on 1 entry, when -device is processed, than after guest boots up, and that offending entry belongs to 'pc.rom', it's not like vhost intends to do IO in ROM range so making it RO hides region from vhost and makes number of entries in vhost memory map at -device/machine_done time match number of entries after guest boots. Signed-off-by: Igor Mammedov Reported-by: Peng Hao Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'hw') diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 22e1603..5943539 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1443,6 +1443,9 @@ void pc_memory_init(PCMachineState *pcms, option_rom_mr = g_malloc(sizeof(*option_rom_mr)); memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE, &error_fatal); + if (pcmc->pci_enabled) { + memory_region_set_readonly(option_rom_mr, true); + } memory_region_add_subregion_overlap(rom_memory, PC_ROM_MIN_VGA, option_rom_mr, -- cgit v1.1 From 3a3fcc75f92ab0d71ba0e7511af7dc575c4b4f6c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 24 Jul 2017 15:50:20 +0200 Subject: pc: acpi: force FADT rev1 for 440fx based machine types w2k used to boot on QEMU until revision of FADT has been bumped to rev3 (commit 77af8a2b hw/i386: Use Rev3 FADT (ACPI 2.0) instead of Rev1 to improve guest OS support.) Keep PC machine at rev1 to remain compatible and Q35 at rev3 where w2k isn't supported anyway so OSX could run as well. Signed-off-by: Igor Mammedov Tested-by: John Arbuckle Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6b7bade..b9c245c 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -90,6 +90,7 @@ typedef struct AcpiMcfgInfo { } AcpiMcfgInfo; typedef struct AcpiPmInfo { + bool force_rev1_fadt; bool s3_disabled; bool s4_disabled; bool pcihp_bridge_en; @@ -129,10 +130,13 @@ static void acpi_get_pm_info(AcpiPmInfo *pm) Object *obj = NULL; QObject *o; + pm->force_rev1_fadt = false; pm->cpu_hp_io_base = 0; pm->pcihp_io_base = 0; pm->pcihp_io_len = 0; if (piix) { + /* w2k requires FADT(rev1) or it won't boot, keep PC compatible */ + pm->force_rev1_fadt = true; obj = piix; pm->cpu_hp_io_base = PIIX4_CPU_HOTPLUG_IO_BASE; pm->pcihp_io_base = @@ -304,6 +308,9 @@ static void fadt_setup(AcpiFadtDescriptorRev3 *fadt, AcpiPmInfo *pm) fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL); } fadt->century = RTC_CENTURY; + if (pm->force_rev1_fadt) { + return; + } fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_RESET_REG_SUP); fadt->reset_value = 0xf; @@ -342,6 +349,8 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm, unsigned fw_ctrl_offset = (char *)&fadt->firmware_ctrl - table_data->data; unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data; unsigned xdsdt_entry_offset = (char *)&fadt->x_dsdt - table_data->data; + int fadt_size = sizeof(*fadt); + int rev = 3; /* FACS address to be filled by Guest linker */ bios_linker_loader_add_pointer(linker, @@ -353,12 +362,17 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm, bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt), ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); - bios_linker_loader_add_pointer(linker, - ACPI_BUILD_TABLE_FILE, xdsdt_entry_offset, sizeof(fadt->x_dsdt), - ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); + if (pm->force_rev1_fadt) { + rev = 1; + fadt_size = offsetof(typeof(*fadt), reset_register); + } else { + bios_linker_loader_add_pointer(linker, + ACPI_BUILD_TABLE_FILE, xdsdt_entry_offset, sizeof(fadt->x_dsdt), + ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); + } build_header(linker, table_data, - (void *)fadt, "FACP", sizeof(*fadt), 3, oem_id, oem_table_id); + (void *)fadt, "FACP", fadt_size, rev, oem_id, oem_table_id); } void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, -- cgit v1.1