diff options
Diffstat (limited to 'hw')
98 files changed, 750 insertions, 318 deletions
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index f3ebca4f7a..a2486566af 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -452,6 +452,11 @@ static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs) return telldir(fs->dir.stream); } +static bool local_is_mapped_file_metadata(FsContext *fs_ctx, const char *name) +{ + return !strcmp(name, VIRTFS_META_DIR); +} + static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs) { struct dirent *entry; @@ -465,8 +470,8 @@ again: if (ctx->export_flags & V9FS_SM_MAPPED) { entry->d_type = DT_UNKNOWN; } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { - if (!strcmp(entry->d_name, VIRTFS_META_DIR)) { - /* skp the meta data directory */ + if (local_is_mapped_file_metadata(ctx, entry->d_name)) { + /* skip the meta data directory */ goto again; } entry->d_type = DT_UNKNOWN; @@ -559,6 +564,12 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, int err = -1; int dirfd; + if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && + local_is_mapped_file_metadata(fs_ctx, name)) { + errno = EINVAL; + return -1; + } + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); if (dirfd == -1) { return -1; @@ -605,6 +616,12 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, int err = -1; int dirfd; + if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && + local_is_mapped_file_metadata(fs_ctx, name)) { + errno = EINVAL; + return -1; + } + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); if (dirfd == -1) { return -1; @@ -694,6 +711,12 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, int err = -1; int dirfd; + if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && + local_is_mapped_file_metadata(fs_ctx, name)) { + errno = EINVAL; + return -1; + } + /* * Mark all the open to not follow symlinks */ @@ -752,6 +775,12 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, int err = -1; int dirfd; + if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && + local_is_mapped_file_metadata(fs_ctx, name)) { + errno = EINVAL; + return -1; + } + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); if (dirfd == -1) { return -1; @@ -826,6 +855,12 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath, int ret = -1; int odirfd, ndirfd; + if (ctx->export_flags & V9FS_SM_MAPPED_FILE && + local_is_mapped_file_metadata(ctx, name)) { + errno = EINVAL; + return -1; + } + odirfd = local_opendir_nofollow(ctx, odirpath); if (odirfd == -1) { goto out; @@ -1096,6 +1131,12 @@ static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path, static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, const char *name, V9fsPath *target) { + if (ctx->export_flags & V9FS_SM_MAPPED_FILE && + local_is_mapped_file_metadata(ctx, name)) { + errno = EINVAL; + return -1; + } + if (dir_path) { v9fs_path_sprintf(target, "%s/%s", dir_path->data, name); } else if (strcmp(name, "/")) { @@ -1116,6 +1157,13 @@ static int local_renameat(FsContext *ctx, V9fsPath *olddir, int ret; int odirfd, ndirfd; + if (ctx->export_flags & V9FS_SM_MAPPED_FILE && + (local_is_mapped_file_metadata(ctx, old_name) || + local_is_mapped_file_metadata(ctx, new_name))) { + errno = EINVAL; + return -1; + } + odirfd = local_opendir_nofollow(ctx, olddir->data); if (odirfd == -1) { return -1; @@ -1206,6 +1254,12 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir, int ret; int dirfd; + if (ctx->export_flags & V9FS_SM_MAPPED_FILE && + local_is_mapped_file_metadata(ctx, name)) { + errno = EINVAL; + return -1; + } + dirfd = local_opendir_nofollow(ctx, dir->data); if (dirfd == -1) { return -1; diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c index 9c7f41af99..5df97c90fa 100644 --- a/hw/9pfs/xen-9p-backend.c +++ b/hw/9pfs/xen-9p-backend.c @@ -332,12 +332,14 @@ static int xen_9pfs_connect(struct XenDevice *xendev) str = g_strdup_printf("ring-ref%u", i); if (xenstore_read_fe_int(&xen_9pdev->xendev, str, &xen_9pdev->rings[i].ref) == -1) { + g_free(str); goto out; } g_free(str); str = g_strdup_printf("event-channel-%u", i); if (xenstore_read_fe_int(&xen_9pdev->xendev, str, &xen_9pdev->rings[i].evtchn) == -1) { + g_free(str); goto out; } g_free(str); @@ -378,7 +380,7 @@ static int xen_9pfs_connect(struct XenDevice *xendev) if (xen_9pdev->rings[i].evtchndev == NULL) { goto out; } - fcntl(xenevtchn_fd(xen_9pdev->rings[i].evtchndev), F_SETFD, FD_CLOEXEC); + qemu_set_cloexec(xenevtchn_fd(xen_9pdev->rings[i].evtchndev)); xen_9pdev->rings[i].local_port = xenevtchn_bind_interdomain (xen_9pdev->rings[i].evtchndev, xendev->dom, diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 4ddfb68b24..36a6cc450e 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -24,6 +24,7 @@ #include "hw/acpi/aml-build.h" #include "qemu/bswap.h" #include "qemu/bitops.h" +#include "sysemu/numa.h" static GArray *build_alloc_array(void) { @@ -1636,3 +1637,28 @@ void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, numamem->base_addr = cpu_to_le64(base); numamem->range_length = cpu_to_le64(len); } + +/* + * ACPI spec 5.2.17 System Locality Distance Information Table + * (Revision 2.0 or later) + */ +void build_slit(GArray *table_data, BIOSLinker *linker) +{ + int slit_start, i, j; + slit_start = table_data->len; + + acpi_data_push(table_data, sizeof(AcpiTableHeader)); + + build_append_int_noprefix(table_data, nb_numa_nodes, 8); + for (i = 0; i < nb_numa_nodes; i++) { + for (j = 0; j < nb_numa_nodes; j++) { + assert(numa_info[i].distance[j]); + build_append_int_noprefix(table_data, numa_info[i].distance[j], 1); + } + } + + build_header(linker, table_data, + (void *)(table_data->data + slit_start), + "SLIT", + table_data->len - slit_start, 1, NULL, NULL); +} diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index 8c719d3f9d..a233fe17cf 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -503,7 +503,6 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, /* build Processor object for each processor */ for (i = 0; i < arch_ids->len; i++) { - int j; Aml *dev; Aml *uid = aml_int(i); GArray *madt_buf = g_array_new(0, 1, 1); @@ -557,9 +556,9 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, * as a result _PXM is required for all CPUs which might * be hot-plugged. For simplicity, add it for all CPUs. */ - j = numa_get_node_for_cpu(i); - if (j < nb_numa_nodes) { - aml_append(dev, aml_name_decl("_PXM", aml_int(j))); + if (arch_ids->cpus[i].props.has_node_id) { + aml_append(dev, aml_name_decl("_PXM", + aml_int(arch_ids->cpus[i].props.node_id))); } aml_append(cpus_dev, dev); diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index c409374ab8..f276967365 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -705,7 +705,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data) * Reason: part of PIIX4 southbridge, needs to be wired up, * e.g. by mips_malta_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->hotpluggable = false; hc->plug = piix4_device_plug_cb; hc->unplug_request = piix4_device_unplug_request_cb; diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index fe2d5a764c..324626847c 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -1076,7 +1076,7 @@ static void sl_nand_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_sl_nand_info; dc->props = sl_nand_properties; /* Reason: init() method uses drive_get() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo sl_nand_info = { diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 6e5f3399f2..e5852067f5 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -486,30 +486,25 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) AcpiSystemResourceAffinityTable *srat; AcpiSratProcessorGiccAffinity *core; AcpiSratMemoryAffinity *numamem; - int i, j, srat_start; + int i, srat_start; uint64_t mem_base; - uint32_t *cpu_node = g_malloc0(vms->smp_cpus * sizeof(uint32_t)); - - for (i = 0; i < vms->smp_cpus; i++) { - j = numa_get_node_for_cpu(i); - if (j < nb_numa_nodes) { - cpu_node[i] = j; - } - } + MachineClass *mc = MACHINE_GET_CLASS(vms); + const CPUArchIdList *cpu_list = mc->possible_cpu_arch_ids(MACHINE(vms)); srat_start = table_data->len; srat = acpi_data_push(table_data, sizeof(*srat)); srat->reserved1 = cpu_to_le32(1); - for (i = 0; i < vms->smp_cpus; ++i) { + for (i = 0; i < cpu_list->len; ++i) { + int node_id = cpu_list->cpus[i].props.has_node_id ? + cpu_list->cpus[i].props.node_id : 0; core = acpi_data_push(table_data, sizeof(*core)); core->type = ACPI_SRAT_PROCESSOR_GICC; core->length = sizeof(*core); - core->proximity = cpu_to_le32(cpu_node[i]); + core->proximity = cpu_to_le32(node_id); core->acpi_processor_uid = cpu_to_le32(i); core->flags = cpu_to_le32(1); } - g_free(cpu_node); mem_base = vms->memmap[VIRT_MEM].base; for (i = 0; i < nb_numa_nodes; ++i) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 5f62a0321e..c7c8159dfd 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -338,7 +338,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) { int cpu; int addr_cells = 1; - unsigned int i; + const MachineState *ms = MACHINE(vms); /* * From Documentation/devicetree/bindings/arm/cpus.txt @@ -369,6 +369,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); + CPUState *cs = CPU(armcpu); qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "cpu"); @@ -389,9 +390,9 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) armcpu->mp_affinity); } - i = numa_get_node_for_cpu(cpu); - if (i < nb_numa_nodes) { - qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id", i); + if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) { + qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id", + ms->possible_cpus->cpus[cs->cpu_index].props.node_id); } g_free(nodename); @@ -1194,10 +1195,35 @@ void virt_machine_done(Notifier *notifier, void *data) virt_build_smbios(vms); } +static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx) +{ + uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER; + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); + + if (!vmc->disallow_affinity_adjustment) { + /* Adjust MPIDR like 64-bit KVM hosts, which incorporate the + * GIC's target-list limitations. 32-bit KVM hosts currently + * always create clusters of 4 CPUs, but that is expected to + * change when they gain support for gicv3. When KVM is enabled + * it will override the changes we make here, therefore our + * purposes are to make TCG consistent (with 64-bit KVM hosts) + * and to improve SGI efficiency. + */ + if (vms->gic_version == 3) { + clustersz = GICV3_TARGETLIST_BITS; + } else { + clustersz = GIC_TARGETLIST_BITS; + } + } + return arm_cpu_mp_affinity(idx, clustersz); +} + static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine); + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *possible_cpus; qemu_irq pic[NUM_IRQS]; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *secure_sysmem = NULL; @@ -1210,7 +1236,6 @@ static void machvirt_init(MachineState *machine) CPUClass *cc; Error *err = NULL; bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); - uint8_t clustersz; if (!cpu_model) { cpu_model = "cortex-a15"; @@ -1263,10 +1288,8 @@ static void machvirt_init(MachineState *machine) */ if (vms->gic_version == 3) { virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / 0x20000; - clustersz = GICV3_TARGETLIST_BITS; } else { virt_max_cpus = GIC_NCPU; - clustersz = GIC_TARGETLIST_BITS; } if (max_cpus > virt_max_cpus) { @@ -1324,21 +1347,35 @@ static void machvirt_init(MachineState *machine) exit(1); } - for (n = 0; n < smp_cpus; n++) { - Object *cpuobj = object_new(typename); - if (!vmc->disallow_affinity_adjustment) { - /* Adjust MPIDR like 64-bit KVM hosts, which incorporate the - * GIC's target-list limitations. 32-bit KVM hosts currently - * always create clusters of 4 CPUs, but that is expected to - * change when they gain support for gicv3. When KVM is enabled - * it will override the changes we make here, therefore our - * purposes are to make TCG consistent (with 64-bit KVM hosts) - * and to improve SGI efficiency. - */ - uint8_t aff1 = n / clustersz; - uint8_t aff0 = n % clustersz; - object_property_set_int(cpuobj, (aff1 << ARM_AFF1_SHIFT) | aff0, - "mp-affinity", NULL); + possible_cpus = mc->possible_cpu_arch_ids(machine); + for (n = 0; n < possible_cpus->len; n++) { + Object *cpuobj; + CPUState *cs; + int node_id; + + if (n >= smp_cpus) { + break; + } + + cpuobj = object_new(typename); + object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id, + "mp-affinity", NULL); + + cs = CPU(cpuobj); + cs->cpu_index = n; + + node_id = possible_cpus->cpus[cs->cpu_index].props.node_id; + if (!possible_cpus->cpus[cs->cpu_index].props.has_node_id) { + /* by default CPUState::numa_node was 0 if it's not set via CLI + * keep it this way for now but in future we probably should + * refuse to start up with incomplete numa mapping */ + node_id = 0; + } + if (cs->numa_node == CPU_UNSET_NUMA_NODE_ID) { + cs->numa_node = node_id; + } else { + /* CPU isn't device_add compatible yet, this shouldn't happen */ + error_setg(&error_abort, "user set node-id not implemented"); } if (!vms->secure) { @@ -1518,6 +1555,46 @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp) } } +static CpuInstanceProperties +virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); + + assert(cpu_index < possible_cpus->len); + return possible_cpus->cpus[cpu_index].props; +} + +static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) +{ + int n; + VirtMachineState *vms = VIRT_MACHINE(ms); + + if (ms->possible_cpus) { + assert(ms->possible_cpus->len == max_cpus); + return ms->possible_cpus; + } + + ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + + sizeof(CPUArchId) * max_cpus); + ms->possible_cpus->len = max_cpus; + for (n = 0; n < ms->possible_cpus->len; n++) { + ms->possible_cpus->cpus[n].arch_id = + virt_cpu_mp_affinity(vms, n); + ms->possible_cpus->cpus[n].props.has_thread_id = true; + ms->possible_cpus->cpus[n].props.thread_id = n; + + /* default distribution of CPUs over NUMA nodes */ + if (nb_numa_nodes) { + /* preset values but do not enable them i.e. 'has_node_id = false', + * numa init code will enable them later if manual mapping wasn't + * present on CLI */ + ms->possible_cpus->cpus[n].props.node_id = n % nb_numa_nodes; + } + } + return ms->possible_cpus; +} + static void virt_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1534,6 +1611,8 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) mc->pci_allow_0_address = true; /* We know we will never create a pre-ARMv7 CPU which needs 1K pages */ mc->minimum_page_bits = 12; + mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids; + mc->cpu_index_to_instance_props = virt_cpu_index_to_props; } static const TypeInfo virt_machine_info = { diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c index 511b004287..4f65f8c199 100644 --- a/hw/audio/marvell_88w8618.c +++ b/hw/audio/marvell_88w8618.c @@ -292,7 +292,7 @@ static void mv88w8618_audio_class_init(ObjectClass *klass, void *data) dc->vmsd = &mv88w8618_audio_vmsd; dc->props = mv88w8618_audio_properties; /* Reason: pointer property "wm8750" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo mv88w8618_audio_info = { diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 798002277b..9b99358d87 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -223,7 +223,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data) dc->vmsd = &vmstate_spk; dc->props = pcspk_properties; /* Reason: realize sets global pcspk_state */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo pcspk_info = { diff --git a/hw/block/nvme.c b/hw/block/nvme.c index ae303d44e5..7428db9f0c 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -227,6 +227,29 @@ static uint16_t nvme_flush(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, return NVME_NO_COMPLETE; } +static uint16_t nvme_write_zeros(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, + NvmeRequest *req) +{ + NvmeRwCmd *rw = (NvmeRwCmd *)cmd; + const uint8_t lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas); + const uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds; + uint64_t slba = le64_to_cpu(rw->slba); + uint32_t nlb = le16_to_cpu(rw->nlb) + 1; + uint64_t aio_slba = slba << (data_shift - BDRV_SECTOR_BITS); + uint32_t aio_nlb = nlb << (data_shift - BDRV_SECTOR_BITS); + + if (slba + nlb > ns->id_ns.nsze) { + return NVME_LBA_RANGE | NVME_DNR; + } + + req->has_sg = false; + block_acct_start(blk_get_stats(n->conf.blk), &req->acct, 0, + BLOCK_ACCT_WRITE); + req->aiocb = blk_aio_pwrite_zeroes(n->conf.blk, aio_slba, aio_nlb, + BDRV_REQ_MAY_UNMAP, nvme_rw_cb, req); + return NVME_NO_COMPLETE; +} + static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd, NvmeRequest *req) { @@ -279,6 +302,8 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) switch (cmd->opcode) { case NVME_CMD_FLUSH: return nvme_flush(n, ns, cmd, req); + case NVME_CMD_WRITE_ZEROS: + return nvme_write_zeros(n, ns, cmd, req); case NVME_CMD_WRITE: case NVME_CMD_READ: return nvme_rw(n, ns, cmd, req); @@ -895,6 +920,7 @@ static int nvme_init(PCIDevice *pci_dev) id->sqes = (0x6 << 4) | 0x6; id->cqes = (0x4 << 4) | 0x4; id->nn = cpu_to_le32(n->num_namespaces); + id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS); id->psd[0].mp = cpu_to_le16(0x9c4); id->psd[0].enlat = cpu_to_le32(0x10); id->psd[0].exlat = cpu_to_le32(0x4); diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 8fb0c10756..a0d15649f9 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -179,6 +179,7 @@ enum NvmeIoCommands { NVME_CMD_READ = 0x02, NVME_CMD_WRITE_UNCOR = 0x04, NVME_CMD_COMPARE = 0x05, + NVME_CMD_WRITE_ZEROS = 0x08, NVME_CMD_DSM = 0x09, }; diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 98c16a7a9a..604d37dfc8 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -42,9 +42,7 @@ static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq, static void virtio_blk_free_request(VirtIOBlockReq *req) { - if (req) { - g_free(req); - } + g_free(req); } static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status) diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c index 58f1f02902..46012673c3 100644 --- a/hw/core/generic-loader.c +++ b/hw/core/generic-loader.c @@ -137,20 +137,21 @@ static void generic_loader_realize(DeviceState *dev, Error **errp) #endif if (s->file) { + AddressSpace *as = s->cpu ? s->cpu->as : NULL; + if (!s->force_raw) { size = load_elf_as(s->file, NULL, NULL, &entry, NULL, NULL, - big_endian, 0, 0, 0, s->cpu->as); + big_endian, 0, 0, 0, as); if (size < 0) { size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL, - s->cpu->as); + as); } } if (size < 0 || s->force_raw) { /* Default to the maximum size being the machine's ram size */ - size = load_image_targphys_as(s->file, s->addr, ram_size, - s->cpu->as); + size = load_image_targphys_as(s->file, s->addr, ram_size, as); } else { s->addr = entry; } diff --git a/hw/core/machine.c b/hw/core/machine.c index ada9eea483..fd6a436064 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -17,8 +17,10 @@ #include "qapi/visitor.h" #include "hw/sysbus.h" #include "sysemu/sysemu.h" +#include "sysemu/numa.h" #include "qemu/error-report.h" #include "qemu/cutils.h" +#include "sysemu/numa.h" static char *machine_get_accel(Object *obj, Error **errp) { @@ -388,6 +390,102 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine) return head; } +/** + * machine_set_cpu_numa_node: + * @machine: machine object to modify + * @props: specifies which cpu objects to assign to + * numa node specified by @props.node_id + * @errp: if an error occurs, a pointer to an area to store the error + * + * Associate NUMA node specified by @props.node_id with cpu slots that + * match socket/core/thread-ids specified by @props. It's recommended to use + * query-hotpluggable-cpus.props values to specify affected cpu slots, + * which would lead to exact 1:1 mapping of cpu slots to NUMA node. + * + * However for CLI convenience it's possible to pass in subset of properties, + * which would affect all cpu slots that match it. + * Ex for pc machine: + * -smp 4,cores=2,sockets=2 -numa node,nodeid=0 -numa node,nodeid=1 \ + * -numa cpu,node-id=0,socket_id=0 \ + * -numa cpu,node-id=1,socket_id=1 + * will assign all child cores of socket 0 to node 0 and + * of socket 1 to node 1. + * + * On attempt of reassigning (already assigned) cpu slot to another NUMA node, + * return error. + * Empty subset is disallowed and function will return with error in this case. + */ +void machine_set_cpu_numa_node(MachineState *machine, + const CpuInstanceProperties *props, Error **errp) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + bool match = false; + int i; + + if (!mc->possible_cpu_arch_ids) { + error_setg(errp, "mapping of CPUs to NUMA node is not supported"); + return; + } + + /* disabling node mapping is not supported, forbid it */ + assert(props->has_node_id); + + /* force board to initialize possible_cpus if it hasn't been done yet */ + mc->possible_cpu_arch_ids(machine); + + for (i = 0; i < machine->possible_cpus->len; i++) { + CPUArchId *slot = &machine->possible_cpus->cpus[i]; + + /* reject unsupported by board properties */ + if (props->has_thread_id && !slot->props.has_thread_id) { + error_setg(errp, "thread-id is not supported"); + return; + } + + if (props->has_core_id && !slot->props.has_core_id) { + error_setg(errp, "core-id is not supported"); + return; + } + + if (props->has_socket_id && !slot->props.has_socket_id) { + error_setg(errp, "socket-id is not supported"); + return; + } + + /* skip slots with explicit mismatch */ + if (props->has_thread_id && props->thread_id != slot->props.thread_id) { + continue; + } + + if (props->has_core_id && props->core_id != slot->props.core_id) { + continue; + } + + if (props->has_socket_id && props->socket_id != slot->props.socket_id) { + continue; + } + + /* reject assignment if slot is already assigned, for compatibility + * of legacy cpu_index mapping with SPAPR core based mapping do not + * error out if cpu thread and matched core have the same node-id */ + if (slot->props.has_node_id && + slot->props.node_id != props->node_id) { + error_setg(errp, "CPU is already assigned to node-id: %" PRId64, + slot->props.node_id); + return; + } + + /* assign slot to node as it's matched '-numa cpu' key */ + match = true; + slot->props.node_id = props->node_id; + slot->props.has_node_id = props->has_node_id; + } + + if (!match) { + error_setg(errp, "no match found"); + } +} + static void machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -400,6 +498,7 @@ static void machine_class_init(ObjectClass *oc, void *data) * On Linux, each node's border has to be 8MB aligned */ mc->numa_mem_align_shift = 23; + mc->numa_auto_assign_ram = numa_default_auto_assign_ram; object_class_property_add_str(oc, "accel", machine_get_accel, machine_set_accel, &error_abort); @@ -580,6 +679,69 @@ bool machine_mem_merge(MachineState *machine) return machine->mem_merge; } +static char *cpu_slot_to_string(const CPUArchId *cpu) +{ + GString *s = g_string_new(NULL); + if (cpu->props.has_socket_id) { + g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id); + } + if (cpu->props.has_core_id) { + if (s->len) { + g_string_append_printf(s, ", "); + } + g_string_append_printf(s, "core-id: %"PRId64, cpu->props.core_id); + } + if (cpu->props.has_thread_id) { + if (s->len) { + g_string_append_printf(s, ", "); + } + g_string_append_printf(s, "thread-id: %"PRId64, cpu->props.thread_id); + } + return g_string_free(s, false); +} + +static void machine_numa_validate(MachineState *machine) +{ + int i; + GString *s = g_string_new(NULL); + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(machine); + + assert(nb_numa_nodes); + for (i = 0; i < possible_cpus->len; i++) { + const CPUArchId *cpu_slot = &possible_cpus->cpus[i]; + + /* at this point numa mappings are initilized by CLI options + * or with default mappings so it's sufficient to list + * all not yet mapped CPUs here */ + /* TODO: make it hard error in future */ + if (!cpu_slot->props.has_node_id) { + char *cpu_str = cpu_slot_to_string(cpu_slot); + g_string_append_printf(s, "%sCPU %d [%s]", s->len ? ", " : "", i, + cpu_str); + g_free(cpu_str); + } + } + if (s->len) { + error_report("warning: CPU(s) not present in any NUMA nodes: %s", + s->str); + error_report("warning: All CPU(s) up to maxcpus should be described " + "in NUMA config, ability to start up with partial NUMA " + "mappings is obsoleted and will be removed in future"); + } + g_string_free(s, true); +} + +void machine_run_board_init(MachineState *machine) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(machine); + + if (nb_numa_nodes) { + machine_numa_validate(machine); + } + machine_class->init(machine); +} + static void machine_class_finalize(ObjectClass *klass, void *data) { MachineClass *mc = MACHINE_CLASS(klass); diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c index 1485d5b285..f9d76c4641 100644 --- a/hw/core/or-irq.c +++ b/hw/core/or-irq.c @@ -91,7 +91,7 @@ static void or_irq_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_or_irq; /* Reason: Needs to be wired up to work, e.g. see stm32f205_soc.c */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo or_irq_type_info = { diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 02b632f6b3..1863db9d0a 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -1118,6 +1118,7 @@ static void device_class_init(ObjectClass *class, void *data) * should override it in their class_init() */ dc->hotpluggable = true; + dc->user_creatable = true; } void device_reset(DeviceState *dev) diff --git a/hw/core/register.c b/hw/core/register.c index dc335a79a9..da38ef3a54 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -288,7 +288,7 @@ static void register_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); /* Reason: needs to be wired up to work */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo register_info = { diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index c0f560b289..5d0887f499 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -326,6 +326,17 @@ static void sysbus_device_class_init(ObjectClass *klass, void *data) DeviceClass *k = DEVICE_CLASS(klass); k->init = sysbus_device_init; k->bus_type = TYPE_SYSTEM_BUS; + /* + * device_add plugs devices into a suitable bus. For "real" buses, + * that actually connects the device. For sysbus, the connections + * need to be made separately, and device_add can't do that. The + * device would be left unconnected, and will probably not work + * + * However, a few machines can handle device_add/-device with + * a few specific sysbus devices. In those cases, the device + * subclass needs to override it and set user_creatable=true. + */ + k->user_creatable = false; } static const TypeInfo sysbus_device_type_info = { diff --git a/hw/display/cg3.c b/hw/display/cg3.c index 7ef8a96496..1de15a1d34 100644 --- a/hw/display/cg3.c +++ b/hw/display/cg3.c @@ -94,7 +94,8 @@ static void cg3_update_display(void *opaque) uint32_t dval; int x, y, y_start; unsigned int width, height; - ram_addr_t page, page_min, page_max; + ram_addr_t page; + DirtyBitmapSnapshot *snap = NULL; if (surface_bits_per_pixel(surface) != 32) { return; @@ -103,29 +104,32 @@ static void cg3_update_display(void *opaque) height = s->height; y_start = -1; - page_min = -1; - page_max = 0; - page = 0; pix = memory_region_get_ram_ptr(&s->vram_mem); data = (uint32_t *)surface_data(surface); - memory_region_sync_dirty_bitmap(&s->vram_mem); + if (!s->full_update) { + memory_region_sync_dirty_bitmap(&s->vram_mem); + snap = memory_region_snapshot_and_clear_dirty(&s->vram_mem, 0x0, + memory_region_size(&s->vram_mem), + DIRTY_MEMORY_VGA); + } + for (y = 0; y < height; y++) { - int update = s->full_update; + int update; page = (ram_addr_t)y * width; - update |= memory_region_get_dirty(&s->vram_mem, page, width, - DIRTY_MEMORY_VGA); + + if (s->full_update) { + update = 1; + } else { + update = memory_region_snapshot_get_dirty(&s->vram_mem, snap, page, + width); + } + if (update) { if (y_start < 0) { y_start = y; } - if (page < page_min) { - page_min = page; - } - if (page > page_max) { - page_max = page; - } for (x = 0; x < width; x++) { dval = *pix++; @@ -134,7 +138,7 @@ static void cg3_update_display(void *opaque) } } else { if (y_start >= 0) { - dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start); + dpy_gfx_update(s->con, 0, y_start, width, y - y_start); y_start = -1; } pix += width; @@ -143,17 +147,14 @@ static void cg3_update_display(void *opaque) } s->full_update = 0; if (y_start >= 0) { - dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start); - } - if (page_max >= page_min) { - memory_region_reset_dirty(&s->vram_mem, - page_min, page_max - page_min, DIRTY_MEMORY_VGA); + dpy_gfx_update(s->con, 0, y_start, width, y - y_start); } /* vsync interrupt? */ if (s->regs[0] & CG3_CR_ENABLE_INTS) { s->regs[1] |= CG3_SR_PENDING_INT; qemu_irq_raise(s->irq); } + g_free(snap); } static void cg3_invalidate_display(void *opaque) diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c index b72fdb1717..3c97d56434 100644 --- a/hw/display/jazz_led.c +++ b/hw/display/jazz_led.c @@ -227,13 +227,13 @@ static void jazz_led_invalidate_display(void *opaque) static void jazz_led_text_update(void *opaque, console_ch_t *chardata) { LedState *s = opaque; - char buf[2]; + char buf[3]; dpy_text_cursor(s->con, -1, -1); qemu_console_resize(s->con, 2, 1); /* TODO: draw the segments */ - snprintf(buf, 2, "%02hhx\n", s->segments); + snprintf(buf, 3, "%02hhx", s->segments); console_write_ch(chardata++, ATTR2CHTYPE(buf[0], QEMU_COLOR_BLUE, QEMU_COLOR_BLACK, 1)); console_write_ch(chardata++, ATTR2CHTYPE(buf[1], QEMU_COLOR_BLUE, diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 2094adbc9c..9d254ef2e1 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1414,6 +1414,7 @@ static void sm501_update_display(void *opaque) { SM501State *s = (SM501State *)opaque; DisplaySurface *surface = qemu_console_surface(s->con); + DirtyBitmapSnapshot *snap; int y, c_x = 0, c_y = 0; int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0; int width = get_width(s, crt); @@ -1425,9 +1426,7 @@ static void sm501_update_display(void *opaque) draw_hwc_line_func *draw_hwc_line = NULL; int full_update = 0; int y_start = -1; - ram_addr_t page_min = ~0l; - ram_addr_t page_max = 0l; - ram_addr_t offset; + ram_addr_t offset = 0; uint32_t *palette; uint8_t hwc_palette[3 * 3]; uint8_t *hwc_src = NULL; @@ -1479,17 +1478,17 @@ static void sm501_update_display(void *opaque) /* draw each line according to conditions */ memory_region_sync_dirty_bitmap(&s->local_mem_region); + snap = memory_region_snapshot_and_clear_dirty(&s->local_mem_region, + offset, width * height * src_bpp, DIRTY_MEMORY_VGA); for (y = 0, offset = 0; y < height; y++, offset += width * src_bpp) { int update, update_hwc; - ram_addr_t page0 = offset; - ram_addr_t page1 = offset + width * src_bpp - 1; /* check if hardware cursor is enabled and we're within its range */ update_hwc = draw_hwc_line && c_y <= y && y < c_y + SM501_HWC_HEIGHT; update = full_update || update_hwc; /* check dirty flags for each line */ - update |= memory_region_get_dirty(&s->local_mem_region, page0, - page1 - page0, DIRTY_MEMORY_VGA); + update |= memory_region_snapshot_get_dirty(&s->local_mem_region, snap, + offset, width * src_bpp); /* draw line and change status */ if (update) { @@ -1507,12 +1506,6 @@ static void sm501_update_display(void *opaque) if (y_start < 0) { y_start = y; } - if (page0 < page_min) { - page_min = page0; - } - if (page1 > page_max) { - page_max = page1; - } } else { if (y_start >= 0) { /* flush to display */ @@ -1521,18 +1514,12 @@ static void sm501_update_display(void *opaque) } } } + g_free(snap); /* complete flush to display */ if (y_start >= 0) { dpy_gfx_update(s->con, 0, y_start, width, y - y_start); } - - /* clear dirty flags */ - if (page_min != ~0l) { - memory_region_reset_dirty(&s->local_mem_region, - page_min, page_max + TARGET_PAGE_SIZE, - DIRTY_MEMORY_VGA); - } } static const GraphicHwOps sm501_ops = { diff --git a/hw/display/tcx.c b/hw/display/tcx.c index 0e66dcd055..6593c1d6af 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -104,36 +104,23 @@ static void tcx_set_dirty(TCXState *s, ram_addr_t addr, int len) } } -static int tcx_check_dirty(TCXState *s, ram_addr_t addr, int len) +static int tcx_check_dirty(TCXState *s, DirtyBitmapSnapshot *snap, + ram_addr_t addr, int len) { int ret; - ret = memory_region_get_dirty(&s->vram_mem, addr, len, DIRTY_MEMORY_VGA); + ret = memory_region_snapshot_get_dirty(&s->vram_mem, snap, addr, len); if (s->depth == 24) { - ret |= memory_region_get_dirty(&s->vram_mem, - s->vram24_offset + addr * 4, len * 4, - DIRTY_MEMORY_VGA); - ret |= memory_region_get_dirty(&s->vram_mem, - s->cplane_offset + addr * 4, len * 4, - DIRTY_MEMORY_VGA); + ret |= memory_region_snapshot_get_dirty(&s->vram_mem, snap, + s->vram24_offset + addr * 4, len * 4); + ret |= memory_region_snapshot_get_dirty(&s->vram_mem, snap, + s->cplane_offset + addr * 4, len * 4); } return ret; } -static void tcx_reset_dirty(TCXState *s, ram_addr_t addr, int len) -{ - memory_region_reset_dirty(&s->vram_mem, addr, len, DIRTY_MEMORY_VGA); - - if (s->depth == 24) { - memory_region_reset_dirty(&s->vram_mem, s->vram24_offset + addr * 4, - len * 4, DIRTY_MEMORY_VGA); - memory_region_reset_dirty(&s->vram_mem, s->cplane_offset + addr * 4, - len * 4, DIRTY_MEMORY_VGA); - } -} - static void update_palette_entries(TCXState *s, int start, int end) { DisplaySurface *surface = qemu_console_surface(s->con); @@ -233,7 +220,8 @@ static void tcx_update_display(void *opaque) { TCXState *ts = opaque; DisplaySurface *surface = qemu_console_surface(ts->con); - ram_addr_t page, page_min, page_max; + ram_addr_t page; + DirtyBitmapSnapshot *snap = NULL; int y, y_start, dd, ds; uint8_t *d, *s; @@ -243,22 +231,20 @@ static void tcx_update_display(void *opaque) page = 0; y_start = -1; - page_min = -1; - page_max = 0; d = surface_data(surface); s = ts->vram; dd = surface_stride(surface); ds = 1024; memory_region_sync_dirty_bitmap(&ts->vram_mem); + snap = memory_region_snapshot_and_clear_dirty(&ts->vram_mem, 0x0, + memory_region_size(&ts->vram_mem), + DIRTY_MEMORY_VGA); + for (y = 0; y < ts->height; y++, page += ds) { - if (tcx_check_dirty(ts, page, ds)) { + if (tcx_check_dirty(ts, snap, page, ds)) { if (y_start < 0) y_start = y; - if (page < page_min) - page_min = page; - if (page > page_max) - page_max = page; tcx_draw_line32(ts, d, s, ts->width); if (y >= ts->cursy && y < ts->cursy + 32 && ts->cursx < ts->width) { @@ -280,17 +266,15 @@ static void tcx_update_display(void *opaque) dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); } - /* reset modified pages */ - if (page_max >= page_min) { - tcx_reset_dirty(ts, page_min, page_max - page_min); - } + g_free(snap); } static void tcx24_update_display(void *opaque) { TCXState *ts = opaque; DisplaySurface *surface = qemu_console_surface(ts->con); - ram_addr_t page, page_min, page_max; + ram_addr_t page; + DirtyBitmapSnapshot *snap = NULL; int y, y_start, dd, ds; uint8_t *d, *s; uint32_t *cptr, *s24; @@ -301,8 +285,6 @@ static void tcx24_update_display(void *opaque) page = 0; y_start = -1; - page_min = -1; - page_max = 0; d = surface_data(surface); s = ts->vram; s24 = ts->vram24; @@ -311,14 +293,15 @@ static void tcx24_update_display(void *opaque) ds = 1024; memory_region_sync_dirty_bitmap(&ts->vram_mem); + snap = memory_region_snapshot_and_clear_dirty(&ts->vram_mem, 0x0, + memory_region_size(&ts->vram_mem), + DIRTY_MEMORY_VGA); + for (y = 0; y < ts->height; y++, page += ds) { - if (tcx_check_dirty(ts, page, ds)) { + if (tcx_check_dirty(ts, snap, page, ds)) { if (y_start < 0) y_start = y; - if (page < page_min) - page_min = page; - if (page > page_max) - page_max = page; + tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); if (y >= ts->cursy && y < ts->cursy+32 && ts->cursx < ts->width) { tcx_draw_cursor32(ts, d, y, ts->width); @@ -341,10 +324,7 @@ static void tcx24_update_display(void *opaque) dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); } - /* reset modified pages */ - if (page_max >= page_min) { - tcx_reset_dirty(ts, page_min, page_max - page_min); - } + g_free(snap); } static void tcx_invalidate_display(void *opaque) diff --git a/hw/display/vga.c b/hw/display/vga.c index b2516c8d21..dcc95f88e2 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1630,7 +1630,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) if (!full_update) { vga_sync_dirty_bitmap(s); snap = memory_region_snapshot_and_clear_dirty(&s->vram, addr1, - bwidth * height, + line_offset * height, DIRTY_MEMORY_VGA); } diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c index f49b7fe8cd..8c106a662d 100644 --- a/hw/display/virtio-gpu-3d.c +++ b/hw/display/virtio-gpu-3d.c @@ -600,6 +600,22 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g) } } +void virtio_gpu_gl_block(void *opaque, bool block) +{ + VirtIOGPU *g = opaque; + + if (block) { + g->renderer_blocked++; + } else { + g->renderer_blocked--; + } + assert(g->renderer_blocked >= 0); + + if (g->renderer_blocked == 0) { + virtio_gpu_process_cmdq(g); + } +} + int virtio_gpu_virgl_init(VirtIOGPU *g) { int ret; diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index e1056f34df..cfb5dfa336 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -929,28 +929,14 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) return 0; } -static void virtio_gpu_gl_block(void *opaque, bool block) -{ - VirtIOGPU *g = opaque; - - if (block) { - g->renderer_blocked++; - } else { - g->renderer_blocked--; - } - assert(g->renderer_blocked >= 0); - - if (g->renderer_blocked == 0) { - virtio_gpu_process_cmdq(g); - } -} - const GraphicHwOps virtio_gpu_ops = { .invalidate = virtio_gpu_invalidate_display, .gfx_update = virtio_gpu_update_display, .text_update = virtio_gpu_text_update, .ui_info = virtio_gpu_ui_info, +#ifdef CONFIG_VIRGL .gl_block = virtio_gpu_gl_block, +#endif }; static const VMStateDescription vmstate_virtio_gpu_scanout = { diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c index 8bd82e8bc8..bd23e893bf 100644 --- a/hw/dma/i8257.c +++ b/hw/dma/i8257.c @@ -601,7 +601,7 @@ static void i8257_class_init(ObjectClass *klass, void *data) idc->schedule = i8257_dma_schedule; idc->register_channel = i8257_dma_register_channel; /* Reason: needs to be wired up by isa_bus_dma() to work */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo i8257_info = { diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 9d545e412e..9c6bdc6295 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -305,7 +305,7 @@ static void sparc32_dma_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_dma; dc->props = sparc32_dma_properties; /* Reason: pointer property "iommu_opaque" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo sparc32_dma_info = { diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c index dabef4a119..1df394eb12 100644 --- a/hw/gpio/omap_gpio.c +++ b/hw/gpio/omap_gpio.c @@ -773,7 +773,7 @@ static void omap_gpio_class_init(ObjectClass *klass, void *data) dc->reset = omap_gpif_reset; dc->props = omap_gpio_properties; /* Reason: pointer property "clk" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo omap_gpio_info = { @@ -804,7 +804,7 @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data) dc->reset = omap2_gpif_reset; dc->props = omap2_gpio_properties; /* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo omap2_gpio_info = { diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c index f7c92ea00c..f6e80bee25 100644 --- a/hw/i2c/omap_i2c.c +++ b/hw/i2c/omap_i2c.c @@ -491,7 +491,7 @@ static void omap_i2c_class_init(ObjectClass *klass, void *data) dc->props = omap_i2c_properties; dc->reset = omap_i2c_reset; /* Reason: pointer properties "iclk", "fclk" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = omap_i2c_realize; } diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c index 5b7bd891bc..b13ec0fe7a 100644 --- a/hw/i2c/smbus_eeprom.c +++ b/hw/i2c/smbus_eeprom.c @@ -123,7 +123,7 @@ static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data) sc->read_data = eeprom_read_data; dc->props = smbus_eeprom_properties; /* Reason: pointer property "data" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo smbus_eeprom_info = { diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c index 48fab22625..ea51e09186 100644 --- a/hw/i2c/smbus_ich9.c +++ b/hw/i2c/smbus_ich9.c @@ -103,7 +103,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data) * Reason: part of ICH9 southbridge, needs to be wired up by * pc_q35_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index c75f73ebb1..afcadacd2e 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2335,7 +2335,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) srat->reserved1 = cpu_to_le32(1); for (i = 0; i < apic_ids->len; i++) { - int j = numa_get_node_for_cpu(i); + int node_id = apic_ids->cpus[i].props.has_node_id ? + apic_ids->cpus[i].props.node_id : 0; uint32_t apic_id = apic_ids->cpus[i].arch_id; if (apic_id < 255) { @@ -2345,9 +2346,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) core->type = ACPI_SRAT_PROCESSOR_APIC; core->length = sizeof(*core); core->local_apic_id = apic_id; - if (j < nb_numa_nodes) { - core->proximity_lo = j; - } + core->proximity_lo = node_id; memset(core->proximity_hi, 0, 3); core->local_sapic_eid = 0; core->flags = cpu_to_le32(1); @@ -2358,9 +2357,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) core->type = ACPI_SRAT_PROCESSOR_x2APIC; core->length = sizeof(*core); core->x2apic_id = cpu_to_le32(apic_id); - if (j < nb_numa_nodes) { - core->proximity_domain = cpu_to_le32(j); - } + core->proximity_domain = cpu_to_le32(node_id); core->flags = cpu_to_le32(1); } } @@ -2707,6 +2704,10 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) if (pcms->numa_nodes) { acpi_add_table(table_offsets, tables_blob); build_srat(tables_blob, tables->linker, machine); + if (have_numa_distance) { + acpi_add_table(table_offsets, tables_blob); + build_slit(tables_blob, tables->linker); + } } if (acpi_get_mcfg(&mcfg)) { acpi_add_table(table_offsets, tables_blob); diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 516ebae952..329058dac8 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -1199,6 +1199,8 @@ static void amdvi_class_init(ObjectClass *klass, void* data) dc->vmsd = &vmstate_amdvi; dc->hotpluggable = false; dc_class->realize = amdvi_realize; + /* Supported by the pc-q35-* machine types */ + dc->user_creatable = true; } static const TypeInfo amdvi = { diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index a12b1761f5..9ba2162cd9 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -3019,6 +3019,8 @@ static void vtd_class_init(ObjectClass *klass, void *data) dc->hotpluggable = false; x86_class->realize = vtd_realize; x86_class->int_remap = vtd_int_remap; + /* Supported by the pc-q35-* machine types */ + dc->user_creatable = true; } static const TypeInfo vtd_info = { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 8063241140..816bfa872c 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -597,7 +597,7 @@ static void port92_class_initfn(ObjectClass *klass, void *data) * wiring: its A20 output line needs to be wired up by * port92_init(). */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo port92_info = { @@ -747,7 +747,9 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms) { FWCfgState *fw_cfg; uint64_t *numa_fw_cfg; - int i, j; + int i; + const CPUArchIdList *cpus; + MachineClass *mc = MACHINE_GET_CLASS(pcms); fw_cfg = fw_cfg_init_io_dma(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4, as); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus); @@ -782,12 +784,12 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms) */ numa_fw_cfg = g_new0(uint64_t, 1 + pcms->apic_id_limit + nb_numa_nodes); numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes); - for (i = 0; i < max_cpus; i++) { - unsigned int apic_id = x86_cpu_apic_id_from_index(i); + cpus = mc->possible_cpu_arch_ids(MACHINE(pcms)); + for (i = 0; i < cpus->len; i++) { + unsigned int apic_id = cpus->cpus[i].arch_id; assert(apic_id < pcms->apic_id_limit); - j = numa_get_node_for_cpu(i); - if (j < nb_numa_nodes) { - numa_fw_cfg[apic_id + 1] = cpu_to_le64(j); + if (cpus->cpus[i].props.has_node_id) { + numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id); } } for (i = 0; i < nb_numa_nodes; i++) { @@ -1891,6 +1893,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { int idx; + int node_id; CPUState *cs; CPUArchId *cpu_slot; X86CPUTopoInfo topo; @@ -1980,6 +1983,22 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev, cs = CPU(cpu); cs->cpu_index = idx; + + node_id = cpu_slot->props.node_id; + if (!cpu_slot->props.has_node_id) { + /* by default CPUState::numa_node was 0 if it's not set via CLI + * keep it this way for now but in future we probably should + * refuse to start up with incomplete numa mapping */ + node_id = 0; + } + if (cs->numa_node == CPU_UNSET_NUMA_NODE_ID) { + cs->numa_node = node_id; + } else if (cs->numa_node != node_id) { + error_setg(errp, "node-id %d must match numa node specified" + "with -numa option for cpu-index %d", + cs->numa_node, cs->cpu_index); + return; + } } static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, @@ -2241,12 +2260,14 @@ static void pc_machine_reset(void) } } -static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index) +static CpuInstanceProperties +pc_cpu_index_to_props(MachineState *ms, unsigned cpu_index) { - X86CPUTopoInfo topo; - x86_topo_ids_from_idx(smp_cores, smp_threads, cpu_index, - &topo); - return topo.pkg_id; + MachineClass *mc = MACHINE_GET_CLASS(ms); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); + + assert(cpu_index < possible_cpus->len); + return possible_cpus->cpus[cpu_index].props; } static const CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *ms) @@ -2278,6 +2299,15 @@ static const CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *ms) ms->possible_cpus->cpus[i].props.core_id = topo.core_id; ms->possible_cpus->cpus[i].props.has_thread_id = true; ms->possible_cpus->cpus[i].props.thread_id = topo.smt_id; + + /* default distribution of CPUs over NUMA nodes */ + if (nb_numa_nodes) { + /* preset values but do not enable them i.e. 'has_node_id = false', + * numa init code will enable them later if manual mapping wasn't + * present on CLI */ + ms->possible_cpus->cpus[i].props.node_id = + topo.pkg_id % nb_numa_nodes; + } } return ms->possible_cpus; } @@ -2321,7 +2351,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) pcmc->save_tsc_khz = true; pcmc->linuxboot_dma_enabled = true; mc->get_hotplug_handler = pc_get_hotpug_handler; - mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id; + mc->cpu_index_to_instance_props = pc_cpu_index_to_props; mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids; mc->has_hotpluggable_cpus = true; mc->default_boot_order = "cad"; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 8f3d85ca58..2234bd0461 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -54,6 +54,7 @@ #endif #include "migration/migration.h" #include "kvm_i386.h" +#include "sysemu/numa.h" #define MAX_IDE_BUS 2 @@ -442,6 +443,7 @@ static void pc_i440fx_2_10_machine_options(MachineClass *m) pc_i440fx_machine_options(m); m->alias = "pc"; m->is_default = 1; + m->numa_auto_assign_ram = numa_legacy_auto_assign_ram; } DEFINE_I440FX_MACHINE(v2_10, "pc-i440fx-2.10", NULL, diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index cf9a788ec7..f243203844 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -47,6 +47,7 @@ #include "hw/usb.h" #include "qemu/error-report.h" #include "migration/migration.h" +#include "sysemu/numa.h" /* ICH9 AHCI has 6 ports */ #define MAX_SATA_PORTS 6 @@ -305,6 +306,7 @@ static void pc_q35_2_10_machine_options(MachineClass *m) { pc_q35_machine_options(m); m->alias = "q35"; + m->numa_auto_assign_ram = numa_legacy_auto_assign_ram; } DEFINE_Q35_MACHINE(v2_10, "pc-q35-2.10", NULL, diff --git a/hw/i386/xen/xen-mapcache.c b/hw/i386/xen/xen-mapcache.c index 31debdfb2c..e60156c04f 100644 --- a/hw/i386/xen/xen-mapcache.c +++ b/hw/i386/xen/xen-mapcache.c @@ -62,6 +62,7 @@ typedef struct MapCacheRev { hwaddr paddr_index; hwaddr size; QTAILQ_ENTRY(MapCacheRev) next; + bool dma; } MapCacheRev; typedef struct MapCache { @@ -202,7 +203,7 @@ static void xen_remap_bucket(MapCacheEntry *entry, } static uint8_t *xen_map_cache_unlocked(hwaddr phys_addr, hwaddr size, - uint8_t lock) + uint8_t lock, bool dma) { MapCacheEntry *entry, *pentry = NULL; hwaddr address_index; @@ -289,6 +290,7 @@ tryagain: if (lock) { MapCacheRev *reventry = g_malloc0(sizeof(MapCacheRev)); entry->lock++; + reventry->dma = dma; reventry->vaddr_req = mapcache->last_entry->vaddr_base + address_offset; reventry->paddr_index = mapcache->last_entry->paddr_index; reventry->size = entry->size; @@ -300,12 +302,12 @@ tryagain: } uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, - uint8_t lock) + uint8_t lock, bool dma) { uint8_t *p; mapcache_lock(); - p = xen_map_cache_unlocked(phys_addr, size, lock); + p = xen_map_cache_unlocked(phys_addr, size, lock, dma); mapcache_unlock(); return p; } @@ -426,8 +428,11 @@ void xen_invalidate_map_cache(void) mapcache_lock(); QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { - DPRINTF("There should be no locked mappings at this time, " - "but "TARGET_FMT_plx" -> %p is present\n", + if (!reventry->dma) { + continue; + } + fprintf(stderr, "Locked DMA mapping while invalidating mapcache!" + " "TARGET_FMT_plx" -> %p is present\n", reventry->paddr_index, reventry->vaddr_req); } diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c index 3ee0c1814a..46c038110c 100644 --- a/hw/input/virtio-input-hid.c +++ b/hw/input/virtio-input-hid.c @@ -484,12 +484,14 @@ static struct virtio_input_config virtio_tablet_config[] = { .select = VIRTIO_INPUT_CFG_ABS_INFO, .subsel = ABS_X, .size = sizeof(virtio_input_absinfo), - .u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE - 1), + .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), + .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), },{ .select = VIRTIO_INPUT_CFG_ABS_INFO, .subsel = ABS_Y, .size = sizeof(virtio_input_absinfo), - .u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE - 1), + .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN), + .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX), }, { /* end of list */ }, }; diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c index 6d15a887c6..4747da9a8d 100644 --- a/hw/input/vmmouse.c +++ b/hw/input/vmmouse.c @@ -286,7 +286,7 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data) dc->vmsd = &vmstate_vmmouse; dc->props = vmmouse_properties; /* Reason: pointer property "ps2_mouse" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo vmmouse_info = { diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index c3829e31b5..1ef56f8d10 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -501,7 +501,7 @@ static void apic_common_class_init(ObjectClass *klass, void *data) * Reason: APIC and CPU need to be wired up by * x86_cpu_apic_create() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo apic_common_type = { diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c index 64a6f4b4ba..1bfde2f09e 100644 --- a/hw/intc/etraxfs_pic.c +++ b/hw/intc/etraxfs_pic.c @@ -173,7 +173,7 @@ static void etraxfs_pic_class_init(ObjectClass *klass, void *data) dc->props = etraxfs_pic_properties; /* * Note: pointer property "interrupt_vector" may remain null, thus - * no need for dc->cannot_instantiate_with_device_add_yet = true; + * no need for dc->user_creatable = false; */ } diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c index ac7e63f38b..94659ee256 100644 --- a/hw/intc/grlib_irqmp.c +++ b/hw/intc/grlib_irqmp.c @@ -360,7 +360,7 @@ static void grlib_irqmp_class_init(ObjectClass *klass, void *data) dc->reset = grlib_irqmp_reset; dc->props = grlib_irqmp_properties; /* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = grlib_irqmp_realize; } diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c index d9a5e8b217..c2fd563b5b 100644 --- a/hw/intc/i8259_common.c +++ b/hw/intc/i8259_common.c @@ -144,7 +144,7 @@ static void pic_common_class_init(ObjectClass *klass, void *data) * wiring of the slave to the master is hard-coded in device model * code. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo pic_common_type = { diff --git a/hw/intc/nios2_iic.c b/hw/intc/nios2_iic.c index 190b6fdbf3..016426f964 100644 --- a/hw/intc/nios2_iic.c +++ b/hw/intc/nios2_iic.c @@ -80,7 +80,7 @@ static void altera_iic_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); /* Reason: needs to be wired up, e.g. by nios2_10m50_ghrd_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = altera_iic_realize; } diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c index 877be67971..ccdda89dab 100644 --- a/hw/intc/omap_intc.c +++ b/hw/intc/omap_intc.c @@ -401,7 +401,7 @@ static void omap_intc_class_init(ObjectClass *klass, void *data) dc->reset = omap_inth_reset; dc->props = omap_intc_properties; /* Reason: pointer property "clk" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = omap_intc_realize; } @@ -656,7 +656,7 @@ static void omap2_intc_class_init(ObjectClass *klass, void *data) dc->reset = omap_inth_reset; dc->props = omap2_intc_properties; /* Reason: pointer property "iclk", "fclk" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->realize = omap2_intc_realize; } diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 42e0e0ef84..dd93531ae3 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -213,6 +213,7 @@ static void ics_get_kvm_state(ICSState *ics) irq->priority = irq->saved_priority; } + irq->status = 0; if (state & KVM_XICS_PENDING) { if (state & KVM_XICS_LEVEL_SENSITIVE) { irq->status |= XICS_STATUS_ASSERTED; @@ -228,6 +229,12 @@ static void ics_get_kvm_state(ICSState *ics) | XICS_STATUS_REJECTED; } } + if (state & KVM_XICS_PRESENTED) { + irq->status |= XICS_STATUS_PRESENTED; + } + if (state & KVM_XICS_QUEUED) { + irq->status |= XICS_STATUS_QUEUED; + } } } @@ -265,6 +272,12 @@ static int ics_set_kvm_state(ICSState *ics, int version_id) state |= KVM_XICS_PENDING; } } + if (irq->status & XICS_STATUS_PRESENTED) { + state |= KVM_XICS_PRESENTED; + } + if (irq->status & XICS_STATUS_QUEUED) { + state |= KVM_XICS_QUEUED; + } ret = ioctl(kernel_xics_fd, KVM_SET_DEVICE_ATTR, &attr); if (ret != 0) { diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index a0866c3856..e2215dcf4d 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -805,7 +805,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) * Reason: part of ICH9 southbridge, needs to be wired up by * pc_q35_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; hc->plug = ich9_pm_device_plug_cb; hc->unplug_request = ich9_pm_device_unplug_request_cb; hc->unplug = ich9_pm_device_unplug_cb; diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 5500fcc4d6..f811eba59d 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -123,7 +123,7 @@ static void piix4_class_init(ObjectClass *klass, void *data) * Reason: part of PIIX4 southbridge, needs to be wired up, * e.g. by mips_malta_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->hotpluggable = false; } diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 41d5254f8e..50dc83df77 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -494,7 +494,7 @@ static void via_class_init(ObjectClass *klass, void *data) * Reason: part of VIA VT82C686 southbridge, needs to be wired up, * e.g. by mips_fulong2e_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo via_info = { diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index 1834d22a61..457a08a2fe 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -189,7 +189,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, ram_size - initrd_offset); } if (initrd_size < 0) { - error_report("qemu: could not load initrd '%s'", + error_report("could not load initrd '%s'", initrd_filename); exit(EXIT_FAILURE); } diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index 4811843ab6..e8b2eef688 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -1224,7 +1224,7 @@ static void gt64120_pci_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo gt64120_pci_info = { diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c index be40930b8b..165500223f 100644 --- a/hw/misc/vmport.c +++ b/hw/misc/vmport.c @@ -163,7 +163,7 @@ static void vmport_class_initfn(ObjectClass *klass, void *data) dc->realize = vmport_realizefn; /* Reason: realize sets global port_state */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo vmport_info = { diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index efa33ad40a..b53fcaa8bc 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -934,7 +934,7 @@ static void dp8393x_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_dp8393x; dc->props = dp8393x_properties; /* Reason: dma_mr property can't be set */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo dp8393x_info = { diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c index efaa49faae..013c8d0a41 100644 --- a/hw/net/etraxfs_eth.c +++ b/hw/net/etraxfs_eth.c @@ -630,7 +630,7 @@ static void etraxfs_eth_class_init(ObjectClass *klass, void *data) k->init = fs_eth_init; dc->props = etraxfs_eth_properties; /* Reason: pointer properties "dma_out", "dma_in" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo etraxfs_eth_info = { diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c index aa2b0d5a85..9da1932970 100644 --- a/hw/net/fsl_etsec/etsec.c +++ b/hw/net/fsl_etsec/etsec.c @@ -416,6 +416,8 @@ static void etsec_class_init(ObjectClass *klass, void *data) dc->realize = etsec_realize; dc->reset = etsec_reset; dc->props = etsec_properties; + /* Supported by ppce500 machine */ + dc->user_creatable = true; } static TypeInfo etsec_info = { diff --git a/hw/net/lance.c b/hw/net/lance.c index 573d724bcf..92b0c68274 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -165,7 +165,7 @@ static void lance_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_lance; dc->props = lance_properties; /* Reason: pointer property "dma" */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo lance_info = { diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c index e0a9aff2f4..2b31f5b844 100644 --- a/hw/nios2/boot.c +++ b/hw/nios2/boot.c @@ -197,7 +197,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, ram_size - initrd_offset); } if (initrd_size < 0) { - error_report("qemu: could not load initrd '%s'", + error_report("could not load initrd '%s'", initrd_filename); exit(EXIT_FAILURE); } diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c index 840c96198a..cca93620ac 100644 --- a/hw/pci-bridge/dec.c +++ b/hw/pci-bridge/dec.c @@ -128,7 +128,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo dec_21154_pci_host_info = { diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c index 6ac187fa32..ff59abf208 100644 --- a/hw/pci-bridge/pci_expander_bridge.c +++ b/hw/pci-bridge/pci_expander_bridge.c @@ -150,7 +150,7 @@ static void pxb_host_class_init(ObjectClass *class, void *data) dc->fw_name = "pci"; /* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address; hc->root_bus_path = pxb_host_root_bus_path; } diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 653e711121..edc88f4c65 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -810,7 +810,7 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo pbm_pci_host_info = { diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index 1999ece590..85a3bb0dd2 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -825,7 +825,7 @@ static void bonito_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo bonito_info = { diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c index 66055ee5cc..e2629ce70d 100644 --- a/hw/pci-host/gpex.c +++ b/hw/pci-host/gpex.c @@ -136,7 +136,7 @@ static void gpex_root_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo gpex_root_info = { diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c index 2c8acdaaca..2e281f6155 100644 --- a/hw/pci-host/grackle.c +++ b/hw/pci-host/grackle.c @@ -134,7 +134,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo grackle_pci_info = { diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index bf4221d4bf..2d02de12d9 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -685,7 +685,7 @@ static void pci_piix3_class_init(ObjectClass *klass, void *data) * Reason: part of PIIX3 southbridge, needs to be wired up by * pc_piix.c's pc_init1() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo piix3_pci_type_info = { @@ -739,7 +739,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; dc->hotpluggable = false; } @@ -868,7 +868,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) dc->fw_name = "pci"; dc->props = i440fx_props; /* Reason: needs to be wired up by pc_init1 */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo i440fx_pcihost_info = { diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index e502bc0505..becc0eeb76 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -508,7 +508,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo e500_host_bridge_info = { diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 260a119a9e..900a6edfcf 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -364,7 +364,7 @@ static void raven_class_init(ObjectClass *klass, void *data) * Reason: PCI-facing part of the host bridge, not usable without * the host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo raven_info = { diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 344f77b10c..cd5c49616e 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -156,7 +156,7 @@ static void q35_host_class_init(ObjectClass *klass, void *data) dc->realize = q35_host_realize; dc->props = mch_props; /* Reason: needs to be wired up by pc_q35_init */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->fw_name = "pci"; } @@ -549,7 +549,7 @@ static void mch_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo mch_info = { diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index df342ac3cb..6cf5e59f86 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -366,7 +366,7 @@ static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo unin_main_pci_host_info = { @@ -390,7 +390,7 @@ static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo u3_agp_pci_host_info = { @@ -414,7 +414,7 @@ static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo unin_agp_pci_host_info = { @@ -438,7 +438,7 @@ static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo unin_internal_pci_host_info = { diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c index 27fde46126..aa1fdf75fd 100644 --- a/hw/pci-host/versatile.c +++ b/hw/pci-host/versatile.c @@ -479,7 +479,7 @@ static void versatile_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo versatile_pci_host_info = { diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c index 8b71e2d950..a968cea2af 100644 --- a/hw/pci-host/xilinx-pcie.c +++ b/hw/pci-host/xilinx-pcie.c @@ -309,7 +309,7 @@ static void xilinx_pcie_root_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo xilinx_pcie_root_info = { diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 68aaedc06d..bae1c0ac99 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -80,6 +80,8 @@ #define CLOCKFREQ (266UL * 1000UL * 1000UL) #define BUSFREQ (100UL * 1000UL * 1000UL) +#define NDRV_VGA_FILENAME "qemu_vga.ndrv" + /* UniN device */ static void unin_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) @@ -160,7 +162,8 @@ static void ppc_core99_init(MachineState *machine) MACIOIDEState *macio_ide; BusState *adb_bus; MacIONVRAMState *nvr; - int bios_size; + int bios_size, ndrv_size; + uint8_t *ndrv_file; MemoryRegion *pic_mem, *escc_mem; MemoryRegion *escc_bar = g_new(MemoryRegion, 1); int ppc_boot_device; @@ -494,6 +497,19 @@ static void ppc_core99_init(MachineState *machine) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_NVRAM_ADDR, nvram_addr); + /* MacOS NDRV VGA driver */ + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, NDRV_VGA_FILENAME); + if (filename) { + ndrv_size = get_image_size(filename); + if (ndrv_size != -1) { + ndrv_file = g_malloc(ndrv_size); + ndrv_size = load_image(filename, ndrv_file); + + fw_cfg_add_file(fw_cfg, "ndrv/qemu_vga.ndrv", ndrv_file, ndrv_size); + } + g_free(filename); + } + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 5df94e239b..97bb8541d7 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -53,6 +53,8 @@ #define CLOCKFREQ 266000000UL #define BUSFREQ 66000000UL +#define NDRV_VGA_FILENAME "qemu_vga.ndrv" + static void fw_cfg_boot_set(void *opaque, const char *boot_device, Error **errp) { @@ -99,7 +101,8 @@ static void ppc_heathrow_init(MachineState *machine) MACIOIDEState *macio_ide; DeviceState *dev; BusState *adb_bus; - int bios_size; + int bios_size, ndrv_size; + uint8_t *ndrv_file; MemoryRegion *pic_mem; MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1); uint16_t ppc_boot_device; @@ -355,6 +358,19 @@ static void ppc_heathrow_init(MachineState *machine) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); + /* MacOS NDRV VGA driver */ + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, NDRV_VGA_FILENAME); + if (filename) { + ndrv_size = get_image_size(filename); + if (ndrv_size != -1) { + ndrv_file = g_malloc(ndrv_size); + ndrv_size = load_image(filename, ndrv_file); + + fw_cfg_add_file(fw_cfg, "ndrv/qemu_vga.ndrv", ndrv_file, ndrv_size); + } + g_free(filename); + } + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index d4bcdb027f..231ed9735b 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -511,7 +511,7 @@ static void ppc_powernv_reset(void) * This is the internal simulator but it could also be an external * BMC. */ - obj = object_resolve_path_type("", TYPE_IPMI_BMC, NULL); + obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL); if (obj) { pnv->bmc = IPMI_BMC(obj); } @@ -610,7 +610,7 @@ static void ppc_powernv_init(MachineState *machine) /* Create the processor chips */ chip_typename = g_strdup_printf(TYPE_PNV_CHIP "-%s", machine->cpu_model); if (!object_class_by_name(chip_typename)) { - error_report("qemu: invalid CPU model '%s' for %s machine", + error_report("invalid CPU model '%s' for %s machine", machine->cpu_model, MACHINE_GET_CLASS(machine)->name); exit(1); } diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index dc19682970..6953f8b9ac 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -351,7 +351,7 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo ppc4xx_host_bridge_info = { diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c index 60baffaf1d..23bcf1b138 100644 --- a/hw/ppc/ppc_booke.c +++ b/hw/ppc/ppc_booke.c @@ -282,7 +282,6 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val) ppc_tb_t *tb_env = env->tb_env; booke_timer_t *booke_timer = tb_env->opaque; - tb_env = env->tb_env; env->spr[SPR_BOOKE_TCR] = val; kvmppc_set_tcr(cpu); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 80d12d005c..0980d733cd 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -219,7 +219,7 @@ static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset, /* 16: Vector */ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */ - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 18 - 23 */ + 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */ 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */ /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */ @@ -855,6 +855,8 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt) * option vector 5: */ static void spapr_dt_ov5_platform_support(void *fdt, int chosen) { + PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); + char val[2 * 3] = { 24, 0x00, /* Hash/Radix, filled in below. */ 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ @@ -870,8 +872,13 @@ static void spapr_dt_ov5_platform_support(void *fdt, int chosen) val[1] = 0x00; /* Hash */ } } else { - /* TODO: TCG case, hash */ - val[1] = 0x00; + if (first_ppc_cpu->env.mmu_model & POWERPC_MMU_V3) { + /* V3 MMU supports both hash and radix (with dynamic switching) */ + val[1] = 0xC0; + } else { + /* Otherwise we can only do hash */ + val[1] = 0x00; + } } _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", val, sizeof(val))); @@ -2101,8 +2108,8 @@ static void ppc_spapr_init(MachineState *machine) } spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); - if (kvmppc_has_cap_mmu_radix()) { - /* KVM always allows GTSE with radix... */ + if (!kvm_enabled() || kvmppc_has_cap_mmu_radix()) { + /* KVM and TCG always allow GTSE with radix... */ spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE); } /* ... but not with hash (currently). */ @@ -2824,9 +2831,11 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); Error *local_err = NULL; CPUCore *cc = CPU_CORE(dev); + sPAPRCPUCore *sc = SPAPR_CPU_CORE(dev); char *base_core_type = spapr_get_cpu_core_type(machine->cpu_model); const char *type = object_get_typename(OBJECT(dev)); CPUArchId *core_slot; + int node_id; int index; if (dev->hotplugged && !mc->has_hotpluggable_cpus) { @@ -2861,6 +2870,21 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, goto out; } + node_id = core_slot->props.node_id; + if (!core_slot->props.has_node_id) { + /* by default CPUState::numa_node was 0 if it's not set via CLI + * keep it this way for now but in future we probably should + * refuse to start up with incomplete numa mapping */ + node_id = 0; + } + if (sc->node_id == CPU_UNSET_NUMA_NODE_ID) { + sc->node_id = node_id; + } else if (sc->node_id != node_id) { + error_setg(&local_err, "node-id %d must match numa node specified" + "with -numa option for cpu-index %d", sc->node_id, cc->core_id); + goto out; + } + out: g_free(base_core_type); error_propagate(errp, local_err); @@ -2981,11 +3005,18 @@ static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, return NULL; } -static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index) +static CpuInstanceProperties +spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) { - /* Allocate to NUMA nodes on a "socket" basis (not that concept of - * socket means much for the paravirtualized PAPR platform) */ - return cpu_index / smp_threads / smp_cores; + CPUArchId *core_slot; + MachineClass *mc = MACHINE_GET_CLASS(machine); + + /* make sure possible_cpu are intialized */ + mc->possible_cpu_arch_ids(machine); + /* get CPU core slot containing thread that matches cpu_index */ + core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); + assert(core_slot); + return core_slot->props; } static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) @@ -3012,8 +3043,15 @@ static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) machine->possible_cpus->cpus[i].arch_id = core_id; machine->possible_cpus->cpus[i].props.has_core_id = true; machine->possible_cpus->cpus[i].props.core_id = core_id; - /* TODO: add 'has_node/node' here to describe - to which node core belongs */ + + /* default distribution of CPUs over NUMA nodes */ + if (nb_numa_nodes) { + /* preset values but do not enable them i.e. 'has_node_id = false', + * numa init code will enable them later if manual mapping wasn't + * present on CLI */ + machine->possible_cpus->cpus[i].props.node_id = + core_id / smp_threads / smp_cores % nb_numa_nodes; + } } return machine->possible_cpus; } @@ -3138,7 +3176,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) hc->pre_plug = spapr_machine_device_pre_plug; hc->plug = spapr_machine_device_plug; hc->unplug = spapr_machine_device_unplug; - mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id; + mc->cpu_index_to_instance_props = spapr_cpu_index_to_props; mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; hc->unplug_request = spapr_machine_device_unplug_request; @@ -3242,6 +3280,7 @@ static void spapr_machine_2_9_class_options(MachineClass *mc) { spapr_machine_2_10_class_options(mc); SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_9); + mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram; } DEFINE_SPAPR_MACHINE(2_9, "2.9", false); diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 4389ef4c2a..a17ea07ef1 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -176,13 +176,11 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) const char *typename = object_class_get_name(scc->cpu_class); size_t size = object_type_get_instance_size(typename); Error *local_err = NULL; - int core_node_id = numa_get_node_for_cpu(cc->core_id);; void *obj; int i, j; sc->threads = g_malloc0(size * cc->nr_threads); for (i = 0; i < cc->nr_threads; i++) { - int node_id; char id[32]; CPUState *cs; @@ -192,17 +190,8 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) cs = CPU(obj); cs->cpu_index = cc->core_id + i; - /* Set NUMA node for the added CPUs */ - node_id = numa_get_node_for_cpu(cs->cpu_index); - if (node_id != core_node_id) { - error_setg(&local_err, "Invalid node-id=%d of thread[cpu-index: %d]" - " on CPU[core-id: %d, node-id: %d], node-id must be the same", - node_id, cs->cpu_index, cc->core_id, core_node_id); - goto err; - } - if (node_id < nb_numa_nodes) { - cs->numa_node = node_id; - } + /* Set NUMA node for the threads belonged to core */ + cs->numa_node = sc->node_id; snprintf(id, sizeof(id), "thread[%d]", i); object_property_add_child(OBJECT(sc), id, obj, &local_err); @@ -263,6 +252,11 @@ static const char *spapr_core_models[] = { "POWER9_v1.0", }; +static Property spapr_cpu_core_properties[] = { + DEFINE_PROP_INT32("node-id", sPAPRCPUCore, node_id, CPU_UNSET_NUMA_NODE_ID), + DEFINE_PROP_END_OF_LIST() +}; + void spapr_cpu_core_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -270,6 +264,7 @@ void spapr_cpu_core_class_init(ObjectClass *oc, void *data) dc->realize = spapr_cpu_core_realize; dc->unrealize = spapr_cpu_core_unrealizefn; + dc->props = spapr_cpu_core_properties; scc->cpu_class = cpu_class_by_name(TYPE_POWERPC_CPU, data); g_assert(scc->cpu_class); } diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index a1cdc875b1..9fa5545991 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -675,7 +675,7 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) /* * Reason: it crashes FIXME find and document the real reason */ - dk->cannot_instantiate_with_device_add_yet = true; + dk->user_creatable = false; } static const TypeInfo spapr_dr_connector_info = { diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 9f18f75b88..0d608d6e28 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -936,7 +936,7 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu, target_ulong opcode, target_ulong *args) { - CPUPPCState *env = &cpu->env; + CPUState *cs; target_ulong flags = args[0]; target_ulong proc_tbl = args[1]; target_ulong page_size = args[2]; @@ -992,16 +992,12 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu, spapr_check_setup_free_hpt(spapr, spapr->patb_entry, cproc); spapr->patb_entry = cproc; /* Save new process table */ - if ((flags & FLAG_RADIX) || (flags & FLAG_HASH_PROC_TBL)) { - /* Use Process TBL */ - env->spr[SPR_LPCR] |= LPCR_UPRT; - } else { - env->spr[SPR_LPCR] &= ~LPCR_UPRT; - } - if (flags & FLAG_GTSE) { /* Partition Uses Guest Translation Shootdwn */ - env->spr[SPR_LPCR] |= LPCR_GTSE; - } else { - env->spr[SPR_LPCR] &= ~LPCR_GTSE; + + /* Update the UPRT and GTSE bits in the LPCR for all cpus */ + CPU_FOREACH(cs) { + set_spr(cs, SPR_LPCR, LPCR_UPRT | LPCR_GTSE, + ((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? LPCR_UPRT : 0) | + ((flags & FLAG_GTSE) ? LPCR_GTSE : 0)); } if (kvm_enabled()) { diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index e7567e2e8f..a7cff32bbf 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1994,6 +1994,8 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) dc->props = spapr_phb_properties; dc->reset = spapr_phb_reset; dc->vmsd = &vmstate_spapr_pci; + /* Supported by TYPE_SPAPR_MACHINE */ + dc->user_creatable = true; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); hp->plug = spapr_phb_hot_plug_child; hp->unplug = spapr_phb_hot_unplug_child; diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index a8a1bab50a..66a6fbeb8c 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -872,7 +872,6 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); - dc->cannot_instantiate_with_device_add_yet = true; dc->reset = s390_pcihost_reset; k->init = s390_pcihost_init; hc->plug = s390_pcihost_hot_plug; diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index b4f6dd58dd..83d6023894 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -505,10 +505,10 @@ static void sclp_realize(DeviceState *dev, Error **errp) ret = s390_set_memory_limit(machine->maxram_size, &hw_limit); if (ret == -E2BIG) { - error_setg(&err, "qemu: host supports a maximum of %" PRIu64 " GB", + error_setg(&err, "host supports a maximum of %" PRIu64 " GB", hw_limit >> 30); } else if (ret) { - error_setg(&err, "qemu: setting the guest size failed"); + error_setg(&err, "setting the guest size failed"); } out: diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 1f2f0ed44a..4008c81002 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -299,7 +299,7 @@ static void milkymist_memcard_class_init(ObjectClass *klass, void *data) dc->reset = milkymist_memcard_reset; dc->vmsd = &vmstate_milkymist_memcard; /* Reason: init() method uses drive_get_next() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo milkymist_memcard_info = { diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index 82c63a4fb5..55c8098ecd 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -515,7 +515,7 @@ static void pl181_class_init(ObjectClass *klass, void *data) k->vmsd = &vmstate_pl181; k->reset = pl181_reset; /* Reason: init() method uses drive_get_next() */ - k->cannot_instantiate_with_device_add_yet = true; + k->user_creatable = false; k->realize = pl181_realize; } diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c index 1747628f3d..38395c082b 100644 --- a/hw/sh4/sh_pci.c +++ b/hw/sh4/sh_pci.c @@ -171,7 +171,7 @@ static void sh_pci_host_class_init(ObjectClass *klass, void *data) * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo sh_pci_host_info = { diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c index e18299a482..976d5200f1 100644 --- a/hw/timer/i8254_common.c +++ b/hw/timer/i8254_common.c @@ -287,7 +287,7 @@ static void pit_common_class_init(ObjectClass *klass, void *data) * wired to the HPET, and because of that, some wiring is always * done by board code. */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static const TypeInfo pit_common_type = { diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 4165450250..93de3e1cc5 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -973,7 +973,7 @@ static void rtc_class_initfn(ObjectClass *klass, void *data) dc->vmsd = &vmstate_rtc; dc->props = mc146818rtc_properties; /* Reason: needs to be wired up by rtc_init() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->user_creatable = false; } static void rtc_finalize(Object *obj) diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c index 19dd587207..8910bf0f27 100644 --- a/hw/tricore/tricore_testboard.c +++ b/hw/tricore/tricore_testboard.c @@ -50,7 +50,7 @@ static void tricore_load_kernel(CPUTriCoreState *env) NULL, 0, EM_TRICORE, 1, 0); if (kernel_size <= 0) { - error_report("qemu: no kernel file '%s'", + error_report("no kernel file '%s'", tricoretb_binfo.kernel_filename); exit(1); } diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 9fe7333946..47b7519910 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -208,6 +208,7 @@ static void usb_hub_wakeup(USBPort *port1) USBHubPort *port = &s->ports[port1->index]; if (port->wPortStatus & PORT_STAT_SUSPEND) { + port->wPortStatus &= ~PORT_STAT_SUSPEND; port->wPortChange |= PORT_STAT_C_SUSPEND; usb_wakeup(s->intr, 0); } diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 6d5137383b..83a4f0e6fb 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -513,27 +513,18 @@ static USBDevice *usb_serial_init(USBBus *bus, const char *filename) { USBDevice *dev; Chardev *cdrv; - uint32_t vendorid = 0, productid = 0; char label[32]; static int index; while (*filename && *filename != ':') { const char *p; - char *e; + if (strstart(filename, "vendorid=", &p)) { - vendorid = strtol(p, &e, 16); - if (e == p || (*e && *e != ',' && *e != ':')) { - error_report("bogus vendor ID %s", p); - return NULL; - } - filename = e; + error_report("vendorid is not supported anymore"); + return NULL; } else if (strstart(filename, "productid=", &p)) { - productid = strtol(p, &e, 16); - if (e == p || (*e && *e != ',' && *e != ':')) { - error_report("bogus product ID %s", p); - return NULL; - } - filename = e; + error_report("productid is not supported anymore"); + return NULL; } else { error_report("unrecognized serial USB option %s", filename); return NULL; @@ -554,10 +545,7 @@ static USBDevice *usb_serial_init(USBBus *bus, const char *filename) dev = usb_create(bus, "usb-serial"); qdev_prop_set_chr(&dev->qdev, "chardev", cdrv); - if (vendorid) - qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid); - if (productid) - qdev_prop_set_uint16(&dev->qdev, "productid", productid); + return dev; } diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 757b8b3f5a..49cb1829b5 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -813,7 +813,10 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq, if (p->b.bError) { DPRINTF(s, D_VERBOSE, "error %d\n", p->b.bError); } - memcpy(p->abData, data, len); + if (len) { + g_assert_nonnull(data); + memcpy(p->abData, data, len); + } ccid_reset_error_status(s); usb_wakeup(s->bulk, 0); } diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index a2d3143bf4..77d8e1137a 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -50,7 +50,7 @@ /* Very pessimistic, let's hope it's enough for all cases */ #define EV_QUEUE (((3 * 24) + 16) * MAXSLOTS) -#define TRB_LINK_LIMIT 4 +#define TRB_LINK_LIMIT 32 #define COMMAND_LIMIT 256 #define TRANSFER_LIMIT 256 @@ -1790,9 +1790,6 @@ static void xhci_stall_ep(XHCITransfer *xfer) } } -static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, - XHCIEPContext *epctx); - static int xhci_setup_packet(XHCITransfer *xfer) { USBEndpoint *ep; @@ -1806,7 +1803,7 @@ static int xhci_setup_packet(XHCITransfer *xfer) ep = xhci_epid_to_usbep(xfer->epctx); if (!ep) { DPRINTF("xhci: slot %d has no device\n", - xfer->slotid); + xfer->epctx->slotid); return -1; } } @@ -1980,7 +1977,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx { uint64_t mfindex; - DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid); + DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", epctx->slotid, epctx->epid); xfer->in_xfer = epctx->type>>2; diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index b001a27f05..ad5ef783a6 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -229,21 +229,10 @@ static void usbredir_log(void *priv, int level, const char *msg) static void usbredir_log_data(USBRedirDevice *dev, const char *desc, const uint8_t *data, int len) { - int i, j, n; - if (dev->debug < usbredirparser_debug_data) { return; } - - for (i = 0; i < len; i += j) { - char buf[128]; - - n = sprintf(buf, "%s", desc); - for (j = 0; j < 8 && i + j < len; j++) { - n += sprintf(buf + n, " %02X", data[i + j]); - } - error_report("%s", buf); - } + qemu_hexdump((char *)data, stderr, desc, len); } /* diff --git a/hw/vfio/amd-xgbe.c b/hw/vfio/amd-xgbe.c index 2c60310cf9..fab196cebf 100644 --- a/hw/vfio/amd-xgbe.c +++ b/hw/vfio/amd-xgbe.c @@ -38,6 +38,8 @@ static void vfio_amd_xgbe_class_init(ObjectClass *klass, void *data) dc->realize = amd_xgbe_realize; dc->desc = "VFIO AMD XGBE"; dc->vmsd = &vfio_platform_amd_xgbe_vmstate; + /* Supported by TYPE_VIRT_MACHINE */ + dc->user_creatable = true; } static const TypeInfo vfio_amd_xgbe_dev_info = { diff --git a/hw/vfio/calxeda-xgmac.c b/hw/vfio/calxeda-xgmac.c index bb15d588e5..7bb17af7ad 100644 --- a/hw/vfio/calxeda-xgmac.c +++ b/hw/vfio/calxeda-xgmac.c @@ -38,6 +38,8 @@ static void vfio_calxeda_xgmac_class_init(ObjectClass *klass, void *data) dc->realize = calxeda_xgmac_realize; dc->desc = "VFIO Calxeda XGMAC"; dc->vmsd = &vfio_platform_calxeda_xgmac_vmstate; + /* Supported by TYPE_VIRT_MACHINE */ + dc->user_creatable = true; } static const TypeInfo vfio_calxeda_xgmac_dev_info = { diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c index c85f1637e4..3570f37e56 100644 --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen_backend.c @@ -147,7 +147,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev, qdev_unplug(DEVICE(xendev), NULL); return NULL; } - fcntl(xenevtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC); + qemu_set_cloexec(xenevtchn_fd(xendev->evtchndev)); if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) { xendev->gnttabdev = xengnttab_open(NULL, 0); @@ -619,6 +619,8 @@ static void xendev_class_init(ObjectClass *klass, void *data) dc->props = xendev_properties; set_bit(DEVICE_CATEGORY_MISC, dc->categories); + /* xen-backend devices can be plugged/unplugged dynamically */ + dc->user_creatable = true; } static const TypeInfo xendev_type_info = { |