diff --git a/docs/interop/vhost-user.txt b/docs/interop/vhost-user.txt index 481ab56e35..954771d0d8 100644 --- a/docs/interop/vhost-user.txt +++ b/docs/interop/vhost-user.txt @@ -326,6 +326,7 @@ Protocol features #define VHOST_USER_PROTOCOL_F_REPLY_ACK 3 #define VHOST_USER_PROTOCOL_F_MTU 4 #define VHOST_USER_PROTOCOL_F_SLAVE_REQ 5 +#define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN 6 Master message types -------------------- @@ -580,6 +581,21 @@ Master message types This request should be send only when VIRTIO_F_IOMMU_PLATFORM feature has been successfully negotiated. + * VHOST_USER_SET_VRING_ENDIAN + + Id: 23 + Equivalent ioctl: VHOST_SET_VRING_ENDIAN + Master payload: vring state description + + Set the endianess of a VQ for legacy devices. Little-endian is indicated + with state.num set to 0 and big-endian is indicated with state.num set + to 1. Other values are invalid. + This request should be sent only when VHOST_USER_PROTOCOL_F_CROSS_ENDIAN + has been negotiated. + Backends that negotiated this feature should handle both endianesses + and expect this message once (per VQ) during device configuration + (ie. before the master starts the VQ). + Slave message types ------------------- diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6b7bade183..b9c245c9bb 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, diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index e398746b4b..a7bf87a19e 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; } @@ -1139,9 +1137,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); @@ -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: diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index f50ecd8b73..0e73a65bf2 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)) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 22e16031b0..59435390ba 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, diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index cb055e8f21..7f09efab8b 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; } diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 2203011125..093675ed98 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, diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 08d8a26d13..ac15e6be14 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -103,8 +103,7 @@ struct VTDIOTLBEntry { uint16_t domain_id; uint64_t slpte; uint64_t mask; - bool read_flags; - bool write_flags; + uint8_t access_flags; }; /* VT-d Source-ID Qualifier types */ diff --git a/net/vhost-user.c b/net/vhost-user.c index 36f32a2d84..c23927c912 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -151,6 +151,10 @@ static void vhost_user_cleanup(NetClientState *nc) s->vhost_net = NULL; } if (nc->queue_index == 0) { + if (s->watch) { + g_source_remove(s->watch); + s->watch = 0; + } qemu_chr_fe_deinit(&s->chr, true); } diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 63da978f0b..564da45f65 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -108,7 +108,7 @@ static void test_acpi_rsdt_table(test_data *data) /* compute the table entries in rsdt */ tables_nr = (rsdt_table->length - sizeof(AcpiRsdtDescriptorRev1)) / sizeof(uint32_t); - g_assert_cmpint(tables_nr, >, 0); + g_assert(tables_nr > 0); /* get the addresses of the tables pointed by rsdt */ tables = g_new0(uint32_t, tables_nr); diff --git a/tests/pxe-test.c b/tests/pxe-test.c index 34282d3704..cf6e225330 100644 --- a/tests/pxe-test.c +++ b/tests/pxe-test.c @@ -25,7 +25,7 @@ static void test_pxe_one(const char *params, bool ipv6) { char *args; - args = g_strdup_printf("-machine accel=tcg -nodefaults -boot order=n " + args = g_strdup_printf("-machine accel=kvm:tcg -nodefaults -boot order=n " "-netdev user,id=" NETNAME ",tftp=./,bootfile=%s," "ipv4=%s,ipv6=%s %s", disk, ipv6 ? "off" : "on", ipv6 ? "on" : "off", params); diff --git a/tests/vmgenid-test.c b/tests/vmgenid-test.c index a49de9233b..3d5c1c3615 100644 --- a/tests/vmgenid-test.c +++ b/tests/vmgenid-test.c @@ -132,7 +132,7 @@ static char disk[] = "tests/vmgenid-test-disk-XXXXXX"; static char *guid_cmd_strdup(const char *guid) { - return g_strdup_printf("-machine accel=tcg " + return g_strdup_printf("-machine accel=kvm:tcg " "-device vmgenid,id=testvgid,guid=%s " "-drive id=hd0,if=none,file=%s,format=raw " "-device ide-hd,drive=hd0 ",