diff options
Diffstat (limited to 'hw')
43 files changed, 513 insertions, 253 deletions
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index ab895ad490..7088c907bd 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -186,6 +186,15 @@ static void aspeed_board_init(MachineState *machine, &error_abort); object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs", &error_abort); + if (machine->kernel_filename) { + /* + * When booting with a -kernel command line there is no u-boot + * that runs to unlock the SCU. In this case set the default to + * be unlocked as the kernel expects + */ + object_property_set_int(OBJECT(&bmc->soc), ASPEED_SCU_PROT_KEY, + "hw-prot-key", &error_abort); + } object_property_set_bool(OBJECT(&bmc->soc), true, "realized", &error_abort); diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 5aa3d2ddd9..c83b7e207b 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -154,6 +154,8 @@ static void aspeed_soc_init(Object *obj) "hw-strap1", &error_abort); object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu), "hw-strap2", &error_abort); + object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu), + "hw-prot-key", &error_abort); object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename); object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL); diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c index f1441ec6cf..750162cc95 100644 --- a/hw/arm/exynos4_boards.c +++ b/hw/arm/exynos4_boards.c @@ -27,7 +27,6 @@ #include "qemu-common.h" #include "cpu.h" #include "sysemu/sysemu.h" -#include "sysemu/qtest.h" #include "hw/sysbus.h" #include "net/net.h" #include "hw/arm/arm.h" @@ -129,13 +128,6 @@ exynos4_boards_init_common(MachineState *machine, Exynos4BoardType board_type) { Exynos4BoardState *s = g_new(Exynos4BoardState, 1); - MachineClass *mc = MACHINE_GET_CLASS(machine); - - if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) { - error_report("%s board supports only %d CPU cores, ignoring smp_cpus" - " value", - mc->name, EXYNOS4210_NCPUS); - } exynos4_board_binfo.ram_size = exynos4_board_ram_size[board_type]; exynos4_board_binfo.board_id = exynos4_board_id[board_type]; @@ -189,6 +181,8 @@ static void nuri_class_init(ObjectClass *oc, void *data) mc->desc = "Samsung NURI board (Exynos4210)"; mc->init = nuri_init; mc->max_cpus = EXYNOS4210_NCPUS; + mc->min_cpus = EXYNOS4210_NCPUS; + mc->default_cpus = EXYNOS4210_NCPUS; mc->ignore_memory_transaction_failures = true; } @@ -205,6 +199,8 @@ static void smdkc210_class_init(ObjectClass *oc, void *data) mc->desc = "Samsung SMDKC210 board (Exynos4210)"; mc->init = smdkc210_init; mc->max_cpus = EXYNOS4210_NCPUS; + mc->min_cpus = EXYNOS4210_NCPUS; + mc->default_cpus = EXYNOS4210_NCPUS; mc->ignore_memory_transaction_failures = true; } diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index 354c6b25a8..287392bbdc 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -34,6 +34,7 @@ #include "hw/ide/ahci.h" #include "hw/cpu/a9mpcore.h" #include "hw/cpu/a15mpcore.h" +#include "qemu/log.h" #define SMP_BOOT_ADDR 0x100 #define SMP_BOOT_REG 0x40 @@ -117,14 +118,26 @@ static void hb_regs_write(void *opaque, hwaddr offset, } } - regs[offset/4] = value; + if (offset / 4 >= NUM_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "highbank: bad write offset 0x%" HWADDR_PRIx "\n", offset); + return; + } + regs[offset / 4] = value; } static uint64_t hb_regs_read(void *opaque, hwaddr offset, unsigned size) { + uint32_t value; uint32_t *regs = opaque; - uint32_t value = regs[offset/4]; + + if (offset / 4 >= NUM_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "highbank: bad read offset 0x%" HWADDR_PRIx "\n", offset); + return 0; + } + value = regs[offset / 4]; if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) { value |= 0x30000000; diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c index 5941c9f751..cd5fa8c3dc 100644 --- a/hw/arm/raspi.c +++ b/hw/arm/raspi.c @@ -167,6 +167,8 @@ static void raspi2_machine_init(MachineClass *mc) mc->no_floppy = 1; mc->no_cdrom = 1; mc->max_cpus = BCM2836_NCPUS; + mc->min_cpus = BCM2836_NCPUS; + mc->default_cpus = BCM2836_NCPUS; mc->default_ram_size = 1024 * 1024 * 1024; mc->ignore_memory_transaction_failures = true; }; diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c index e2d15a1c9d..bbe7d046e4 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -24,6 +24,7 @@ #include "qemu/error-report.h" #include "exec/address-spaces.h" #include "qemu/log.h" +#include "sysemu/qtest.h" typedef struct XlnxZCU102 { MachineState parent_obj; @@ -164,6 +165,11 @@ static void xlnx_ep108_init(MachineState *machine) { XlnxZCU102 *s = EP108_MACHINE(machine); + if (!qtest_enabled()) { + info_report("The Xilinx EP108 machine is deprecated, please use the " + "ZCU102 machine (which has the same features) instead."); + } + xlnx_zynqmp_init(s, machine); } @@ -185,6 +191,8 @@ static void xlnx_ep108_machine_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_IDE; mc->units_per_default_bus = 1; mc->ignore_memory_transaction_failures = true; + mc->max_cpus = XLNX_ZYNQMP_NUM_APU_CPUS + XLNX_ZYNQMP_NUM_RPU_CPUS; + mc->default_cpus = XLNX_ZYNQMP_NUM_APU_CPUS; } static const TypeInfo xlnx_ep108_machine_init_typeinfo = { @@ -235,12 +243,14 @@ static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); - mc->desc = "Xilinx ZynqMP ZCU102 board"; + mc->desc = "Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5s based on " \ + "the value of smp"; mc->init = xlnx_zcu102_init; mc->block_default_type = IF_IDE; mc->units_per_default_bus = 1; mc->ignore_memory_transaction_failures = true; mc->max_cpus = XLNX_ZYNQMP_NUM_APU_CPUS + XLNX_ZYNQMP_NUM_RPU_CPUS; + mc->default_cpus = XLNX_ZYNQMP_NUM_APU_CPUS; } static const TypeInfo xlnx_zcu102_machine_init_typeinfo = { diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index d4b6560194..c707c66322 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -98,8 +98,9 @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu, { Error *err = NULL; int i; + int num_rpus = MIN(smp_cpus - XLNX_ZYNQMP_NUM_APU_CPUS, XLNX_ZYNQMP_NUM_RPU_CPUS); - for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) { + for (i = 0; i < num_rpus; i++) { char *name; object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]), @@ -132,8 +133,9 @@ static void xlnx_zynqmp_init(Object *obj) { XlnxZynqMPState *s = XLNX_ZYNQMP(obj); int i; + int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS); - for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) { + for (i = 0; i < num_apus; i++) { object_initialize(&s->apu_cpu[i], sizeof(s->apu_cpu[i]), "cortex-a53-" TYPE_ARM_CPU); object_property_add_child(obj, "apu-cpu[*]", OBJECT(&s->apu_cpu[i]), @@ -182,6 +184,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) MemoryRegion *system_memory = get_system_memory(); uint8_t i; uint64_t ram_size; + int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS); const char *boot_cpu = s->boot_cpu ? s->boot_cpu : "apu-cpu[0]"; ram_addr_t ddr_low_size, ddr_high_size; qemu_irq gic_spi[GIC_NUM_SPI_INTR]; @@ -233,10 +236,10 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32); qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2); - qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS); + qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", num_apus); /* Realize APUs before realizing the GIC. KVM requires this. */ - for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) { + for (i = 0; i < num_apus; i++) { char *name; object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC, @@ -292,7 +295,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) } } - for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) { + for (i = 0; i < num_apus; i++) { qemu_irq irq; sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i, @@ -307,11 +310,14 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) } if (s->has_rpu) { - xlnx_zynqmp_create_rpu(s, boot_cpu, &err); - if (err) { - error_propagate(errp, err); - return; - } + info_report("The 'has_rpu' property is no longer required, to use the " + "RPUs just use -smp 6."); + } + + xlnx_zynqmp_create_rpu(s, boot_cpu, &err); + if (err) { + error_propagate(errp, err); + return; } if (!s->boot_cpu_ptr) { diff --git a/hw/char/serial.c b/hw/char/serial.c index 376bd2f240..eb72191ee7 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -1005,7 +1005,7 @@ static void serial_mm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { SerialState *s = opaque; - value &= ~0u >> (32 - (size * 8)); + value &= 255; serial_ioport_write(s, addr >> s->it_shift, value, 1); } @@ -1014,16 +1014,22 @@ static const MemoryRegionOps serial_mm_ops[3] = { .read = serial_mm_read, .write = serial_mm_write, .endianness = DEVICE_NATIVE_ENDIAN, + .valid.max_access_size = 8, + .impl.max_access_size = 8, }, [DEVICE_LITTLE_ENDIAN] = { .read = serial_mm_read, .write = serial_mm_write, .endianness = DEVICE_LITTLE_ENDIAN, + .valid.max_access_size = 8, + .impl.max_access_size = 8, }, [DEVICE_BIG_ENDIAN] = { .read = serial_mm_read, .write = serial_mm_write, .endianness = DEVICE_BIG_ENDIAN, + .valid.max_access_size = 8, + .impl.max_access_size = 8, }, }; diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 6eddac911e..7f1822421a 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1758,7 +1758,7 @@ static void sm501_sysbus_class_init(ObjectClass *klass, void *data) dc->reset = sm501_reset_sysbus; dc->vmsd = &vmstate_sm501_sysbus; /* Note: pointer property "chr-state" 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/display/vga.c b/hw/display/vga.c index 1d19f6bc48..a64a0942da 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1666,9 +1666,9 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) /* scanline wraps from end of video memory to the start */ assert(force_shadow); update = memory_region_snapshot_get_dirty(&s->vram, snap, - page0, 0); + page0, s->vbe_size - page0); update |= memory_region_snapshot_get_dirty(&s->vram, snap, - page1, 0); + 0, page1); } else { update = memory_region_snapshot_get_dirty(&s->vram, snap, page0, page1 - page0); diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 43bbe09ea0..274e365713 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -322,6 +322,18 @@ static pixman_format_code_t get_pixman_format(uint32_t virtio_gpu_format) } } +static uint32_t calc_image_hostmem(pixman_format_code_t pformat, + uint32_t width, uint32_t height) +{ + /* Copied from pixman/pixman-bits-image.c, skip integer overflow check. + * pixman_image_create_bits will fail in case it overflow. + */ + + int bpp = PIXMAN_FORMAT_BPP(pformat); + int stride = ((width * bpp + 0x1f) >> 5) * sizeof(uint32_t); + return height * stride; +} + static void virtio_gpu_resource_create_2d(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd) { @@ -366,7 +378,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g, return; } - res->hostmem = PIXMAN_FORMAT_BPP(pformat) * c2d.width * c2d.height; + res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height); if (res->hostmem + g->hostmem < g->conf.max_hostmem) { res->image = pixman_image_create_bits(pformat, c2d.width, @@ -1087,7 +1099,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, return -EINVAL; } - res->hostmem = PIXMAN_FORMAT_BPP(pformat) * res->width * res->height; + res->hostmem = calc_image_hostmem(pformat, res->width, res->height); res->addrs = g_new(uint64_t, res->iov_cnt); res->iov = g_new(struct iovec, res->iov_cnt); diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index cdc3fed6ca..0e6673a911 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -679,10 +679,9 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) if (cursor.width > 256 || cursor.height > 256 || cursor.bpp > 32 - || SVGA_BITMAP_SIZE(x, y) - > sizeof(cursor.mask) / sizeof(cursor.mask[0]) + || SVGA_BITMAP_SIZE(x, y) > ARRAY_SIZE(cursor.mask) || SVGA_PIXMAP_SIZE(x, y, cursor.bpp) - > sizeof(cursor.image) / sizeof(cursor.image[0])) { + > ARRAY_SIZE(cursor.image)) { goto badcmd; } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e11a65b545..c3afe5b7f1 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1448,6 +1448,28 @@ void pc_memory_init(PCMachineState *pcms, pcms->ioapic_as = &address_space_memory; } +/* + * The 64bit pci hole starts after "above 4G RAM" and + * potentially the space reserved for memory hotplug. + */ +uint64_t pc_pci_hole64_start(void) +{ + PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); + PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); + uint64_t hole64_start = 0; + + if (pcmc->has_reserved_memory && pcms->hotplug_memory.base) { + hole64_start = pcms->hotplug_memory.base; + if (!pcmc->broken_reserved_end) { + hole64_start += memory_region_size(&pcms->hotplug_memory.mr); + } + } else { + hole64_start = 0x100000000ULL + pcms->above_4g_mem_size; + } + + return ROUND_UP(hole64_start, 1ULL << 30); +} + qemu_irq pc_allocate_cpu_irq(void) { return qemu_allocate_irq(pic_irq_request, NULL, 0); @@ -2325,6 +2347,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) mc->cpu_index_to_instance_props = pc_cpu_index_to_props; mc->get_default_cpu_node_id = pc_get_default_cpu_node_id; mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids; + mc->auto_enable_numa_with_memhp = true; mc->has_hotpluggable_cpus = true; mc->default_boot_order = "cad"; mc->hot_add_cpu = pc_hot_add_cpu; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index f79d5cb694..5e47528993 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -446,6 +446,7 @@ static void pc_i440fx_2_10_machine_options(MachineClass *m) m->is_default = 0; m->alias = NULL; SET_MACHINE_COMPAT(m, PC_COMPAT_2_10); + m->auto_enable_numa_with_memhp = false; } 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 da3ea602e1..d6060043ac 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -318,6 +318,7 @@ static void pc_q35_2_10_machine_options(MachineClass *m) m->alias = NULL; SET_MACHINE_COMPAT(m, PC_COMPAT_2_10); m->numa_auto_assign_ram = numa_legacy_auto_assign_ram; + m->auto_enable_numa_with_memhp = false; } DEFINE_Q35_MACHINE(v2_10, "pc-q35-2.10", NULL, diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index be46639b63..5d9c8834ad 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -977,7 +977,7 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) if (region >= cpu->pmsav7_dregion) { return 0; } - return (cpu->env.pmsav7.drbar[region] & 0x1f) | (region & 0xf); + return (cpu->env.pmsav7.drbar[region] & ~0x1f) | (region & 0xf); } case 0xda0: /* MPU_RASR (v7M), MPU_RLAR (v8M) */ case 0xda8: /* MPU_RASR_A1 (v7M), MPU_RLAR_A1 (v8M) */ diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index 37c4386ae3..36139a4db6 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -35,15 +35,6 @@ #include "hw/i386/x86-iommu.h" #include "trace.h" -//#define DEBUG_IOAPIC - -#ifdef DEBUG_IOAPIC -#define DPRINTF(fmt, ...) \ - do { printf("ioapic: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) -#endif - #define APIC_DELIVERY_MODE_SHIFT 8 #define APIC_POLARITY_SHIFT 14 #define APIC_TRIG_MODE_SHIFT 15 @@ -157,7 +148,7 @@ static void ioapic_set_irq(void *opaque, int vector, int level) * to GSI 2. GSI maps to ioapic 1-1. This is not * the cleanest way of doing it but it should work. */ - DPRINTF("%s: %s vec %x\n", __func__, level ? "raise" : "lower", vector); + trace_ioapic_set_irq(vector, level); if (vector == 0) { vector = 2; } @@ -290,11 +281,10 @@ ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size) } } } - DPRINTF("read: %08x = %08x\n", s->ioregsel, val); break; } - trace_ioapic_mem_read(addr, size, val); + trace_ioapic_mem_read(addr, s->ioregsel, size, val); return val; } @@ -335,7 +325,7 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, int index; addr &= 0xff; - trace_ioapic_mem_write(addr, size, val); + trace_ioapic_mem_write(addr, s->ioregsel, size, val); switch (addr) { case IOAPIC_IOREGSEL: @@ -345,7 +335,6 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, if (size != 4) { break; } - DPRINTF("write: %08x = %08" PRIx64 "\n", s->ioregsel, val); switch (s->ioregsel) { case IOAPIC_REG_ID: s->id = (val >> IOAPIC_ID_SHIFT) & IOAPIC_ID_MASK; diff --git a/hw/intc/trace-events b/hw/intc/trace-events index b86f242b0f..b298fac7c6 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -18,8 +18,9 @@ apic_mem_writel(uint64_t addr, uint32_t val) "0x%"PRIx64" = 0x%08x" ioapic_set_remote_irr(int n) "set remote irr for pin %d" ioapic_clear_remote_irr(int n, int vector) "clear remote irr for pin %d vector %d" ioapic_eoi_broadcast(int vector) "EOI broadcast for vector %d" -ioapic_mem_read(uint8_t addr, uint8_t size, uint32_t val) "ioapic mem read addr 0x%"PRIx8" size 0x%"PRIx8" retval 0x%"PRIx32 -ioapic_mem_write(uint8_t addr, uint8_t size, uint32_t val) "ioapic mem write addr 0x%"PRIx8" size 0x%"PRIx8" val 0x%"PRIx32 +ioapic_mem_read(uint8_t addr, uint8_t regsel, uint8_t size, uint32_t val) "ioapic mem read addr 0x%"PRIx8" regsel: 0x%"PRIx8" size 0x%"PRIx8" retval 0x%"PRIx32 +ioapic_mem_write(uint8_t addr, uint8_t regsel, uint8_t size, uint32_t val) "ioapic mem write addr 0x%"PRIx8" regsel: 0x%"PRIx8" size 0x%"PRIx8" val 0x%"PRIx32 +ioapic_set_irq(int vector, int level) "vector: %d level: %d" # hw/intc/slavio_intctl.c slavio_intctl_mem_readl(uint32_t cpu, uint64_t addr, uint32_t ret) "read cpu %d reg 0x%"PRIx64" = 0x%x" diff --git a/hw/intc/xics.c b/hw/intc/xics.c index cc9816e7f2..a1cc0e420c 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -40,11 +40,17 @@ void icp_pic_print_info(ICPState *icp, Monitor *mon) { + ICPStateClass *icpc = ICP_GET_CLASS(icp); int cpu_index = icp->cs ? icp->cs->cpu_index : -1; if (!icp->output) { return; } + + if (icpc->synchronize_state) { + icpc->synchronize_state(icp); + } + monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n", cpu_index, icp->xirr, icp->xirr_owner, icp->pending_priority, icp->mfrr); @@ -52,6 +58,7 @@ void icp_pic_print_info(ICPState *icp, Monitor *mon) void ics_pic_print_info(ICSState *ics, Monitor *mon) { + ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics); uint32_t i; monitor_printf(mon, "ICS %4x..%4x %p\n", @@ -61,6 +68,10 @@ void ics_pic_print_info(ICSState *ics, Monitor *mon) return; } + if (icsc->synchronize_state) { + icsc->synchronize_state(ics); + } + for (i = 0; i < ics->nr_irqs; i++) { ICSIRQState *irq = ics->irqs + i; diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 3091ad3ac2..89fb20e2c5 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -81,6 +81,18 @@ static void icp_get_kvm_state(ICPState *icp) & KVM_REG_PPC_ICP_PPRI_MASK; } +static void do_icp_synchronize_state(CPUState *cpu, run_on_cpu_data arg) +{ + icp_get_kvm_state(arg.host_ptr); +} + +static void icp_synchronize_state(ICPState *icp) +{ + if (icp->cs) { + run_on_cpu(icp->cs, do_icp_synchronize_state, RUN_ON_CPU_HOST_PTR(icp)); + } +} + static int icp_set_kvm_state(ICPState *icp, int version_id) { uint64_t state; @@ -156,6 +168,7 @@ static void icp_kvm_class_init(ObjectClass *klass, void *data) icpc->post_load = icp_set_kvm_state; icpc->realize = icp_kvm_realize; icpc->reset = icp_kvm_reset; + icpc->synchronize_state = icp_synchronize_state; } static const TypeInfo icp_kvm_info = { @@ -234,6 +247,11 @@ static void ics_get_kvm_state(ICSState *ics) } } +static void ics_synchronize_state(ICSState *ics) +{ + ics_get_kvm_state(ics); +} + static int ics_set_kvm_state(ICSState *ics, int version_id) { uint64_t state; @@ -347,6 +365,7 @@ static void ics_kvm_class_init(ObjectClass *klass, void *data) icsc->realize = ics_kvm_realize; icsc->pre_save = ics_get_kvm_state; icsc->post_load = ics_set_kvm_state; + icsc->synchronize_state = ics_synchronize_state; } static const TypeInfo ics_kvm_info = { diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 19202d90cf..10c88a84b4 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -9,7 +9,7 @@ common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o common-obj-$(CONFIG_EDU) += edu.o common-obj-y += unimp.o -common-obj-y += vmcoreinfo.o +common-obj-$(CONFIG_FW_CFG_DMA) += vmcoreinfo.o obj-$(CONFIG_VMPORT) += vmport.o diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index 95022d3607..74537ce975 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -85,7 +85,6 @@ #define BMC_REV TO_REG(0x19C) #define BMC_DEV_ID TO_REG(0x1A4) -#define PROT_KEY_UNLOCK 0x1688A8A8 #define SCU_IO_REGION_SIZE 0x1000 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = { @@ -192,7 +191,7 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data, } if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 && - s->regs[PROT_KEY] != PROT_KEY_UNLOCK) { + s->regs[PROT_KEY] != ASPEED_SCU_PROT_KEY) { qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__); return; } @@ -246,6 +245,7 @@ static void aspeed_scu_reset(DeviceState *dev) s->regs[SILICON_REV] = s->silicon_rev; s->regs[HW_STRAP1] = s->hw_strap1; s->regs[HW_STRAP2] = s->hw_strap2; + s->regs[PROT_KEY] = s->hw_prot_key; } static uint32_t aspeed_silicon_revs[] = { @@ -299,6 +299,7 @@ static Property aspeed_scu_properties[] = { DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0), DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0), DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0), + DEFINE_PROP_UINT32("hw-prot-key", AspeedSCUState, hw_prot_key, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/misc/vmcoreinfo.c b/hw/misc/vmcoreinfo.c index a618e12677..31db57ab44 100644 --- a/hw/misc/vmcoreinfo.c +++ b/hw/misc/vmcoreinfo.c @@ -79,6 +79,7 @@ static void vmcoreinfo_device_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_vmcoreinfo; dc->realize = vmcoreinfo_realize; dc->hotpluggable = false; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo vmcoreinfo_device_info = { diff --git a/hw/net/e1000.c b/hw/net/e1000.c index c0abee4f7e..05a00cba31 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -503,7 +503,7 @@ putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse) n = cse + 1; if (sloc < n-1) { sum = net_checksum_add(n-css, data+css); - stw_be_p(data + sloc, net_checksum_finish(sum)); + stw_be_p(data + sloc, net_checksum_finish_nozero(sum)); } } diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index 80b8f47c4b..1c0def555b 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -754,8 +754,8 @@ static void read_cb(EEPRO100State *s) static void tx_command(EEPRO100State *s) { - uint32_t tbd_array = le32_to_cpu(s->tx.tbd_array_addr); - uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff); + uint32_t tbd_array = s->tx.tbd_array_addr; + uint16_t tcb_bytes = s->tx.tcb_bytes & 0x3fff; /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */ uint8_t buf[2600]; uint16_t size = 0; @@ -774,23 +774,11 @@ static void tx_command(EEPRO100State *s) } assert(tcb_bytes <= sizeof(buf)); while (size < tcb_bytes) { - uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address); - uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4); -#if 0 - uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6); -#endif - if (tx_buffer_size == 0) { - /* Prevent an endless loop. */ - logout("loop in %s:%u\n", __FILE__, __LINE__); - break; - } - tbd_address += 8; TRACE(RXTX, logout ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n", - tx_buffer_address, tx_buffer_size)); - tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size); - pci_dma_read(&s->dev, tx_buffer_address, &buf[size], tx_buffer_size); - size += tx_buffer_size; + tbd_address, tcb_bytes)); + pci_dma_read(&s->dev, tbd_address, &buf[size], tcb_bytes); + size += tcb_bytes; } if (tbd_array == 0xffffffff) { /* Simplified mode. Was already handled by code above. */ diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c index cef1c2e0d1..98a5030ace 100644 --- a/hw/net/net_rx_pkt.c +++ b/hw/net/net_rx_pkt.c @@ -518,7 +518,7 @@ _net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt) cntr += net_checksum_add_iov(pkt->vec, pkt->vec_len, pkt->l4hdr_off, csl, cso); - csum = net_checksum_finish(cntr); + csum = net_checksum_finish_nozero(cntr); trace_net_rx_pkt_l4_csum_calc_csum(pkt->l4hdr_off, csl, cntr, csum); diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c index 20b25496e5..e29c881bc2 100644 --- a/hw/net/net_tx_pkt.c +++ b/hw/net/net_tx_pkt.c @@ -486,7 +486,7 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt) net_checksum_add_iov(iov, iov_len, pkt->virt_hdr.csum_start, csl, cso); /* Put the checksum obtained into the packet */ - csum = cpu_to_be16(net_checksum_finish(csum_cntr)); + csum = cpu_to_be16(net_checksum_finish_nozero(csum_cntr)); iov_from_buf(iov, iov_len, csum_offset, &csum, sizeof csum); } diff --git a/hw/net/vmware_utils.h b/hw/net/vmware_utils.h index 550060170e..6b1e251595 100644 --- a/hw/net/vmware_utils.h +++ b/hw/net/vmware_utils.h @@ -83,6 +83,7 @@ vmw_shmem_ld16(PCIDevice *d, hwaddr addr) { uint16_t res; pci_dma_read(d, addr, &res, 2); + res = le16_to_cpu(res); VMW_SHPRN("SHMEM load16: %" PRIx64 " (value 0x%X)", addr, res); return res; } @@ -91,6 +92,7 @@ static inline void vmw_shmem_st16(PCIDevice *d, hwaddr addr, uint16_t value) { VMW_SHPRN("SHMEM store16: %" PRIx64 " (value 0x%X)", addr, value); + value = cpu_to_le16(value); pci_dma_write(d, addr, &value, 2); } @@ -99,6 +101,7 @@ vmw_shmem_ld32(PCIDevice *d, hwaddr addr) { uint32_t res; pci_dma_read(d, addr, &res, 4); + res = le32_to_cpu(res); VMW_SHPRN("SHMEM load32: %" PRIx64 " (value 0x%X)", addr, res); return res; } @@ -107,6 +110,7 @@ static inline void vmw_shmem_st32(PCIDevice *d, hwaddr addr, uint32_t value) { VMW_SHPRN("SHMEM store32: %" PRIx64 " (value 0x%X)", addr, value); + value = cpu_to_le32(value); pci_dma_write(d, addr, &value, 4); } @@ -115,6 +119,7 @@ vmw_shmem_ld64(PCIDevice *d, hwaddr addr) { uint64_t res; pci_dma_read(d, addr, &res, 8); + res = le64_to_cpu(res); VMW_SHPRN("SHMEM load64: %" PRIx64 " (value %" PRIx64 ")", addr, res); return res; } @@ -123,6 +128,7 @@ static inline void vmw_shmem_st64(PCIDevice *d, hwaddr addr, uint64_t value) { VMW_SHPRN("SHMEM store64: %" PRIx64 " (value %" PRIx64 ")", addr, value); + value = cpu_to_le64(value); pci_dma_write(d, addr, &value, 8); } diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 8c4bae5394..b8404cb2e2 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -222,7 +222,7 @@ vmxnet3_dump_tx_descr(struct Vmxnet3_TxDesc *descr) "addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, " "dtype: %d, ext1: %d, msscof: %d, hlen: %d, om: %d, " "eop: %d, cq: %d, ext2: %d, ti: %d, tci: %d", - le64_to_cpu(descr->addr), descr->len, descr->gen, descr->rsvd, + descr->addr, descr->len, descr->gen, descr->rsvd, descr->dtype, descr->ext1, descr->msscof, descr->hlen, descr->om, descr->eop, descr->cq, descr->ext2, descr->ti, descr->tci); } @@ -241,7 +241,7 @@ vmxnet3_dump_rx_descr(struct Vmxnet3_RxDesc *descr) { VMW_PKPRN("RX DESCR: addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, " "dtype: %d, ext1: %d, btype: %d", - le64_to_cpu(descr->addr), descr->len, descr->gen, + descr->addr, descr->len, descr->gen, descr->rsvd, descr->dtype, descr->ext1, descr->btype); } @@ -535,7 +535,8 @@ static void vmxnet3_complete_packet(VMXNET3State *s, int qidx, uint32_t tx_ridx) memset(&txcq_descr, 0, sizeof(txcq_descr)); txcq_descr.txdIdx = tx_ridx; txcq_descr.gen = vmxnet3_ring_curr_gen(&s->txq_descr[qidx].comp_ring); - + txcq_descr.val1 = cpu_to_le32(txcq_descr.val1); + txcq_descr.val2 = cpu_to_le32(txcq_descr.val2); vmxnet3_ring_write_curr_cell(d, &s->txq_descr[qidx].comp_ring, &txcq_descr); /* Flush changes in TX descriptor before changing the counter value */ @@ -685,6 +686,16 @@ vmxnet3_on_rx_done_update_stats(VMXNET3State *s, } } +static inline void +vmxnet3_ring_read_curr_txdesc(PCIDevice *pcidev, Vmxnet3Ring *ring, + struct Vmxnet3_TxDesc *txd) +{ + vmxnet3_ring_read_curr_cell(pcidev, ring, txd); + txd->addr = le64_to_cpu(txd->addr); + txd->val1 = le32_to_cpu(txd->val1); + txd->val2 = le32_to_cpu(txd->val2); +} + static inline bool vmxnet3_pop_next_tx_descr(VMXNET3State *s, int qidx, @@ -694,12 +705,12 @@ vmxnet3_pop_next_tx_descr(VMXNET3State *s, Vmxnet3Ring *ring = &s->txq_descr[qidx].tx_ring; PCIDevice *d = PCI_DEVICE(s); - vmxnet3_ring_read_curr_cell(d, ring, txd); + vmxnet3_ring_read_curr_txdesc(d, ring, txd); if (txd->gen == vmxnet3_ring_curr_gen(ring)) { /* Only read after generation field verification */ smp_rmb(); /* Re-read to be sure we got the latest version */ - vmxnet3_ring_read_curr_cell(d, ring, txd); + vmxnet3_ring_read_curr_txdesc(d, ring, txd); VMXNET3_RING_DUMP(VMW_RIPRN, "TX", qidx, ring); *descr_idx = vmxnet3_ring_curr_cell_idx(ring); vmxnet3_inc_tx_consumption_counter(s, qidx); @@ -749,7 +760,7 @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx) if (!s->skip_current_tx_pkt) { data_len = (txd.len > 0) ? txd.len : VMXNET3_MAX_TX_BUF_SIZE; - data_pa = le64_to_cpu(txd.addr); + data_pa = txd.addr; if (!net_tx_pkt_add_raw_fragment(s->tx_pkt, data_pa, @@ -792,6 +803,9 @@ vmxnet3_read_next_rx_descr(VMXNET3State *s, int qidx, int ridx, Vmxnet3Ring *ring = &s->rxq_descr[qidx].rx_ring[ridx]; *didx = vmxnet3_ring_curr_cell_idx(ring); vmxnet3_ring_read_curr_cell(d, ring, dbuf); + dbuf->addr = le64_to_cpu(dbuf->addr); + dbuf->val1 = le32_to_cpu(dbuf->val1); + dbuf->ext1 = le32_to_cpu(dbuf->ext1); } static inline uint8_t @@ -811,6 +825,9 @@ vmxnet3_pop_rxc_descr(VMXNET3State *s, int qidx, uint32_t *descr_gen) pci_dma_read(PCI_DEVICE(s), daddr, &rxcd, sizeof(struct Vmxnet3_RxCompDesc)); + rxcd.val1 = le32_to_cpu(rxcd.val1); + rxcd.val2 = le32_to_cpu(rxcd.val2); + rxcd.val3 = le32_to_cpu(rxcd.val3); ring_gen = vmxnet3_ring_curr_gen(&s->rxq_descr[qidx].comp_ring); if (rxcd.gen != ring_gen) { @@ -972,7 +989,8 @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt, data = (uint8_t *)pkt_data + vhdr->csum_start; len = pkt_len - vhdr->csum_start; /* Put the checksum obtained into the packet */ - stw_be_p(data + vhdr->csum_offset, net_raw_checksum(data, len)); + stw_be_p(data + vhdr->csum_offset, + net_checksum_finish_nozero(net_checksum_add(len, data))); vhdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM; vhdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID; @@ -1060,6 +1078,16 @@ vmxnet3_pci_dma_writev(PCIDevice *pci_dev, } } +static void +vmxnet3_pci_dma_write_rxcd(PCIDevice *pcidev, dma_addr_t pa, + struct Vmxnet3_RxCompDesc *rxcd) +{ + rxcd->val1 = cpu_to_le32(rxcd->val1); + rxcd->val2 = cpu_to_le32(rxcd->val2); + rxcd->val3 = cpu_to_le32(rxcd->val3); + pci_dma_write(pcidev, pa, rxcd, sizeof(*rxcd)); +} + static bool vmxnet3_indicate_packet(VMXNET3State *s) { @@ -1098,15 +1126,14 @@ vmxnet3_indicate_packet(VMXNET3State *s) } chunk_size = MIN(bytes_left, rxd.len); - vmxnet3_pci_dma_writev(d, data, bytes_copied, - le64_to_cpu(rxd.addr), chunk_size); + vmxnet3_pci_dma_writev(d, data, bytes_copied, rxd.addr, chunk_size); bytes_copied += chunk_size; bytes_left -= chunk_size; vmxnet3_dump_rx_descr(&rxd); if (ready_rxcd_pa != 0) { - pci_dma_write(d, ready_rxcd_pa, &rxcd, sizeof(rxcd)); + vmxnet3_pci_dma_write_rxcd(d, ready_rxcd_pa, &rxcd); } memset(&rxcd, 0, sizeof(struct Vmxnet3_RxCompDesc)); @@ -1138,7 +1165,7 @@ vmxnet3_indicate_packet(VMXNET3State *s) rxcd.eop = 1; rxcd.err = (bytes_left != 0); - pci_dma_write(d, ready_rxcd_pa, &rxcd, sizeof(rxcd)); + vmxnet3_pci_dma_write_rxcd(d, ready_rxcd_pa, &rxcd); /* Flush RX descriptor changes */ smp_wmb(); diff --git a/hw/net/vmxnet3.h b/hw/net/vmxnet3.h index f9352c4a27..5b3b76ba7a 100644 --- a/hw/net/vmxnet3.h +++ b/hw/net/vmxnet3.h @@ -226,39 +226,49 @@ enum { struct Vmxnet3_TxDesc { __le64 addr; + union { + struct { #ifdef __BIG_ENDIAN_BITFIELD - u32 msscof:14; /* MSS, checksum offset, flags */ - u32 ext1:1; - u32 dtype:1; /* descriptor type */ - u32 rsvd:1; - u32 gen:1; /* generation bit */ - u32 len:14; + u32 msscof:14; /* MSS, checksum offset, flags */ + u32 ext1:1; + u32 dtype:1; /* descriptor type */ + u32 rsvd:1; + u32 gen:1; /* generation bit */ + u32 len:14; #else - u32 len:14; - u32 gen:1; /* generation bit */ - u32 rsvd:1; - u32 dtype:1; /* descriptor type */ - u32 ext1:1; - u32 msscof:14; /* MSS, checksum offset, flags */ + u32 len:14; + u32 gen:1; /* generation bit */ + u32 rsvd:1; + u32 dtype:1; /* descriptor type */ + u32 ext1:1; + u32 msscof:14; /* MSS, checksum offset, flags */ #endif /* __BIG_ENDIAN_BITFIELD */ - + }; + u32 val1; + }; + + union { + struct { #ifdef __BIG_ENDIAN_BITFIELD - u32 tci:16; /* Tag to Insert */ - u32 ti:1; /* VLAN Tag Insertion */ - u32 ext2:1; - u32 cq:1; /* completion request */ - u32 eop:1; /* End Of Packet */ - u32 om:2; /* offload mode */ - u32 hlen:10; /* header len */ + u32 tci:16; /* Tag to Insert */ + u32 ti:1; /* VLAN Tag Insertion */ + u32 ext2:1; + u32 cq:1; /* completion request */ + u32 eop:1; /* End Of Packet */ + u32 om:2; /* offload mode */ + u32 hlen:10; /* header len */ #else - u32 hlen:10; /* header len */ - u32 om:2; /* offload mode */ - u32 eop:1; /* End Of Packet */ - u32 cq:1; /* completion request */ - u32 ext2:1; - u32 ti:1; /* VLAN Tag Insertion */ - u32 tci:16; /* Tag to Insert */ + u32 hlen:10; /* header len */ + u32 om:2; /* offload mode */ + u32 eop:1; /* End Of Packet */ + u32 cq:1; /* completion request */ + u32 ext2:1; + u32 ti:1; /* VLAN Tag Insertion */ + u32 tci:16; /* Tag to Insert */ #endif /* __BIG_ENDIAN_BITFIELD */ + }; + u32 val2; + }; }; /* TxDesc.OM values */ @@ -291,33 +301,57 @@ struct Vmxnet3_TxDataDesc { #define VMXNET3_TCD_GEN_DWORD_SHIFT 3 struct Vmxnet3_TxCompDesc { - u32 txdIdx:12; /* Index of the EOP TxDesc */ - u32 ext1:20; - + union { + struct { +#ifdef __BIG_ENDIAN_BITFIELD + u32 ext1:20; + u32 txdIdx:12; /* Index of the EOP TxDesc */ +#else + u32 txdIdx:12; /* Index of the EOP TxDesc */ + u32 ext1:20; +#endif + }; + u32 val1; + }; __le32 ext2; __le32 ext3; - u32 rsvd:24; - u32 type:7; /* completion type */ - u32 gen:1; /* generation bit */ + union { + struct { +#ifdef __BIG_ENDIAN_BITFIELD + u32 gen:1; /* generation bit */ + u32 type:7; /* completion type */ + u32 rsvd:24; +#else + u32 rsvd:24; + u32 type:7; /* completion type */ + u32 gen:1; /* generation bit */ +#endif + }; + u32 val2; + }; }; struct Vmxnet3_RxDesc { __le64 addr; - + union { + struct { #ifdef __BIG_ENDIAN_BITFIELD - u32 gen:1; /* Generation bit */ - u32 rsvd:15; - u32 dtype:1; /* Descriptor type */ - u32 btype:1; /* Buffer Type */ - u32 len:14; + u32 gen:1; /* Generation bit */ + u32 rsvd:15; + u32 dtype:1; /* Descriptor type */ + u32 btype:1; /* Buffer Type */ + u32 len:14; #else - u32 len:14; - u32 btype:1; /* Buffer Type */ - u32 dtype:1; /* Descriptor type */ - u32 rsvd:15; - u32 gen:1; /* Generation bit */ + u32 len:14; + u32 btype:1; /* Buffer Type */ + u32 dtype:1; /* Descriptor type */ + u32 rsvd:15; + u32 gen:1; /* Generation bit */ #endif + }; + u32 val1; + }; u32 ext1; }; @@ -330,66 +364,80 @@ struct Vmxnet3_RxDesc { #define VMXNET3_RXD_GEN_SHIFT 31 struct Vmxnet3_RxCompDesc { + union { + struct { #ifdef __BIG_ENDIAN_BITFIELD - u32 ext2:1; - u32 cnc:1; /* Checksum Not Calculated */ - u32 rssType:4; /* RSS hash type used */ - u32 rqID:10; /* rx queue/ring ID */ - u32 sop:1; /* Start of Packet */ - u32 eop:1; /* End of Packet */ - u32 ext1:2; - u32 rxdIdx:12; /* Index of the RxDesc */ + u32 ext2:1; + u32 cnc:1; /* Checksum Not Calculated */ + u32 rssType:4; /* RSS hash type used */ + u32 rqID:10; /* rx queue/ring ID */ + u32 sop:1; /* Start of Packet */ + u32 eop:1; /* End of Packet */ + u32 ext1:2; + u32 rxdIdx:12; /* Index of the RxDesc */ #else - u32 rxdIdx:12; /* Index of the RxDesc */ - u32 ext1:2; - u32 eop:1; /* End of Packet */ - u32 sop:1; /* Start of Packet */ - u32 rqID:10; /* rx queue/ring ID */ - u32 rssType:4; /* RSS hash type used */ - u32 cnc:1; /* Checksum Not Calculated */ - u32 ext2:1; + u32 rxdIdx:12; /* Index of the RxDesc */ + u32 ext1:2; + u32 eop:1; /* End of Packet */ + u32 sop:1; /* Start of Packet */ + u32 rqID:10; /* rx queue/ring ID */ + u32 rssType:4; /* RSS hash type used */ + u32 cnc:1; /* Checksum Not Calculated */ + u32 ext2:1; #endif /* __BIG_ENDIAN_BITFIELD */ + }; + u32 val1; + }; __le32 rssHash; /* RSS hash value */ + union { + struct { #ifdef __BIG_ENDIAN_BITFIELD - u32 tci:16; /* Tag stripped */ - u32 ts:1; /* Tag is stripped */ - u32 err:1; /* Error */ - u32 len:14; /* data length */ + u32 tci:16; /* Tag stripped */ + u32 ts:1; /* Tag is stripped */ + u32 err:1; /* Error */ + u32 len:14; /* data length */ #else - u32 len:14; /* data length */ - u32 err:1; /* Error */ - u32 ts:1; /* Tag is stripped */ - u32 tci:16; /* Tag stripped */ + u32 len:14; /* data length */ + u32 err:1; /* Error */ + u32 ts:1; /* Tag is stripped */ + u32 tci:16; /* Tag stripped */ #endif /* __BIG_ENDIAN_BITFIELD */ + }; + u32 val2; + }; - + union { + struct { #ifdef __BIG_ENDIAN_BITFIELD - u32 gen:1; /* generation bit */ - u32 type:7; /* completion type */ - u32 fcs:1; /* Frame CRC correct */ - u32 frg:1; /* IP Fragment */ - u32 v4:1; /* IPv4 */ - u32 v6:1; /* IPv6 */ - u32 ipc:1; /* IP Checksum Correct */ - u32 tcp:1; /* TCP packet */ - u32 udp:1; /* UDP packet */ - u32 tuc:1; /* TCP/UDP Checksum Correct */ - u32 csum:16; + u32 gen:1; /* generation bit */ + u32 type:7; /* completion type */ + u32 fcs:1; /* Frame CRC correct */ + u32 frg:1; /* IP Fragment */ + u32 v4:1; /* IPv4 */ + u32 v6:1; /* IPv6 */ + u32 ipc:1; /* IP Checksum Correct */ + u32 tcp:1; /* TCP packet */ + u32 udp:1; /* UDP packet */ + u32 tuc:1; /* TCP/UDP Checksum Correct */ + u32 csum:16; #else - u32 csum:16; - u32 tuc:1; /* TCP/UDP Checksum Correct */ - u32 udp:1; /* UDP packet */ - u32 tcp:1; /* TCP packet */ - u32 ipc:1; /* IP Checksum Correct */ - u32 v6:1; /* IPv6 */ - u32 v4:1; /* IPv4 */ - u32 frg:1; /* IP Fragment */ - u32 fcs:1; /* Frame CRC correct */ - u32 type:7; /* completion type */ - u32 gen:1; /* generation bit */ + u32 csum:16; + u32 tuc:1; /* TCP/UDP Checksum Correct */ + u32 udp:1; /* UDP packet */ + u32 tcp:1; /* TCP packet */ + u32 ipc:1; /* IP Checksum Correct */ + u32 v6:1; /* IPv6 */ + u32 v4:1; /* IPv4 */ + u32 frg:1; /* IP Fragment */ + u32 fcs:1; /* Frame CRC correct */ + u32 type:7; /* completion type */ + u32 gen:1; /* generation bit */ #endif /* __BIG_ENDIAN_BITFIELD */ + }; + u32 val3; + }; }; /* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */ diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs index 666db37da2..1b05023662 100644 --- a/hw/pci-bridge/Makefile.objs +++ b/hw/pci-bridge/Makefile.objs @@ -1,5 +1,5 @@ -common-obj-y += pci_bridge_dev.o pcie_pci_bridge.o -common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o +common-obj-y += pci_bridge_dev.o +common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o pcie_pci_bridge.o common-obj-$(CONFIG_PXB) += pci_expander_bridge.o common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o common-obj-$(CONFIG_IOH3420) += ioh3420.o diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index a7e2256870..a684a7cca9 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -50,6 +50,7 @@ typedef struct I440FXState { PCIHostState parent_obj; Range pci_hole; uint64_t pci_hole64_size; + bool pci_hole64_fix; uint32_t short_root_bus; } I440FXState; @@ -112,6 +113,9 @@ struct PCII440FXState { #define I440FX_PAM_SIZE 7 #define I440FX_SMRAM 0x72 +/* Keep it 2G to comply with older win32 guests */ +#define I440FX_PCI_HOST_HOLE64_SIZE_DEFAULT (1ULL << 31) + /* Older coreboot versions (4.0 and older) read a config register that doesn't * exist in real hardware, to get the RAM size from QEMU. */ @@ -238,29 +242,52 @@ static void i440fx_pcihost_get_pci_hole_end(Object *obj, Visitor *v, visit_type_uint32(v, name, &value, errp); } +/* + * The 64bit PCI hole start is set by the Guest firmware + * as the address of the first 64bit PCI MEM resource. + * If no PCI device has resources on the 64bit area, + * the 64bit PCI hole will start after "over 4G RAM" and the + * reserved space for memory hotplug if any. + */ static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { PCIHostState *h = PCI_HOST_BRIDGE(obj); + I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj); Range w64; uint64_t value; pci_bus_get_w64_range(h->bus, &w64); value = range_is_empty(&w64) ? 0 : range_lob(&w64); + if (!value && s->pci_hole64_fix) { + value = pc_pci_hole64_start(); + } visit_type_uint64(v, name, &value, errp); } +/* + * The 64bit PCI hole end is set by the Guest firmware + * as the address of the last 64bit PCI MEM resource. + * Then it is expanded to the PCI_HOST_PROP_PCI_HOLE64_SIZE + * that can be configured by the user. + */ static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { PCIHostState *h = PCI_HOST_BRIDGE(obj); + I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj); + uint64_t hole64_start = pc_pci_hole64_start(); Range w64; - uint64_t value; + uint64_t value, hole64_end; pci_bus_get_w64_range(h->bus, &w64); value = range_is_empty(&w64) ? 0 : range_upb(&w64) + 1; + hole64_end = ROUND_UP(hole64_start + s->pci_hole64_size, 1ULL << 30); + if (s->pci_hole64_fix && value < hole64_end) { + value = hole64_end; + } visit_type_uint64(v, name, &value, errp); } @@ -863,8 +890,9 @@ static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge, static Property i440fx_props[] = { DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, I440FXState, - pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE), + pci_hole64_size, I440FX_PCI_HOST_HOLE64_SIZE_DEFAULT), DEFINE_PROP_UINT32("short_root_bus", I440FXState, short_root_bus, 0), + DEFINE_PROP_BOOL("x-pci-hole64-fix", I440FXState, pci_hole64_fix, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index ddaa7d1b44..6cb9a8d121 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -37,6 +37,8 @@ * Q35 host */ +#define Q35_PCI_HOST_HOLE64_SIZE_DEFAULT (1ULL << 35) + static void q35_host_realize(DeviceState *dev, Error **errp) { PCIHostState *pci = PCI_HOST_BRIDGE(dev); @@ -99,29 +101,52 @@ static void q35_host_get_pci_hole_end(Object *obj, Visitor *v, visit_type_uint32(v, name, &value, errp); } +/* + * The 64bit PCI hole start is set by the Guest firmware + * as the address of the first 64bit PCI MEM resource. + * If no PCI device has resources on the 64bit area, + * the 64bit PCI hole will start after "over 4G RAM" and the + * reserved space for memory hotplug if any. + */ static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { PCIHostState *h = PCI_HOST_BRIDGE(obj); + Q35PCIHost *s = Q35_HOST_DEVICE(obj); Range w64; uint64_t value; pci_bus_get_w64_range(h->bus, &w64); value = range_is_empty(&w64) ? 0 : range_lob(&w64); + if (!value && s->pci_hole64_fix) { + value = pc_pci_hole64_start(); + } visit_type_uint64(v, name, &value, errp); } +/* + * The 64bit PCI hole end is set by the Guest firmware + * as the address of the last 64bit PCI MEM resource. + * Then it is expanded to the PCI_HOST_PROP_PCI_HOLE64_SIZE + * that can be configured by the user. + */ static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { PCIHostState *h = PCI_HOST_BRIDGE(obj); + Q35PCIHost *s = Q35_HOST_DEVICE(obj); + uint64_t hole64_start = pc_pci_hole64_start(); Range w64; - uint64_t value; + uint64_t value, hole64_end; pci_bus_get_w64_range(h->bus, &w64); value = range_is_empty(&w64) ? 0 : range_upb(&w64) + 1; + hole64_end = ROUND_UP(hole64_start + s->mch.pci_hole64_size, 1ULL << 30); + if (s->pci_hole64_fix && value < hole64_end) { + value = hole64_end; + } visit_type_uint64(v, name, &value, errp); } @@ -133,16 +158,25 @@ static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name, visit_type_uint64(v, name, &e->size, errp); } +/* + * NOTE: setting defaults for the mch.* fields in this table + * doesn't work, because mch is a separate QOM object that is + * zeroed by the object_initialize(&s->mch, ...) call inside + * q35_host_initfn(). The default values for those + * properties need to be initialized manually by + * q35_host_initfn() after the object_initialize() call. + */ static Property q35_host_props[] = { DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, Q35PCIHost, parent_obj.base_addr, MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT), DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost, - mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE), + mch.pci_hole64_size, Q35_PCI_HOST_HOLE64_SIZE_DEFAULT), DEFINE_PROP_UINT32("short_root_bus", Q35PCIHost, mch.short_root_bus, 0), DEFINE_PROP_SIZE(PCI_HOST_BELOW_4G_MEM_SIZE, Q35PCIHost, mch.below_4g_mem_size, 0), DEFINE_PROP_SIZE(PCI_HOST_ABOVE_4G_MEM_SIZE, Q35PCIHost, mch.above_4g_mem_size, 0), + DEFINE_PROP_BOOL("x-pci-hole64-fix", Q35PCIHost, pci_hole64_fix, true), DEFINE_PROP_END_OF_LIST(), }; @@ -174,7 +208,9 @@ static void q35_host_initfn(Object *obj) object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL); qdev_prop_set_int32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0)); qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false); - + /* mch's object_initialize resets the default value, set it again */ + qdev_prop_set_uint64(DEVICE(s), PCI_HOST_PROP_PCI_HOLE64_SIZE, + Q35_PCI_HOST_HOLE64_SIZE_DEFAULT); object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32", q35_host_get_pci_hole_start, NULL, NULL, NULL, NULL); diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 5ed3c8dca4..b2d139bd9a 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1030,6 +1030,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, pci_dev->devfn = devfn; pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev); + pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); memory_region_init(&pci_dev->bus_master_container_region, OBJECT(pci_dev), "bus master container", UINT64_MAX); @@ -1039,7 +1040,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, if (qdev_hotplug) { pci_init_bus_master(pci_dev); } - pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); pci_dev->irq_state = 0; pci_config_alloc(pci_dev); diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 9178e70132..5cf0dabef3 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -729,15 +729,13 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, return dev; } -static qemu_irq *ppce500_init_mpic(MachineState *machine, PPCE500Params *params, - MemoryRegion *ccsr, qemu_irq **irqs) +static DeviceState *ppce500_init_mpic(MachineState *machine, + PPCE500Params *params, + MemoryRegion *ccsr, + qemu_irq **irqs) { - qemu_irq *mpic; DeviceState *dev = NULL; SysBusDevice *s; - int i; - - mpic = g_new0(qemu_irq, 256); if (kvm_enabled()) { Error *err = NULL; @@ -756,15 +754,11 @@ static qemu_irq *ppce500_init_mpic(MachineState *machine, PPCE500Params *params, dev = ppce500_init_mpic_qemu(params, irqs); } - for (i = 0; i < 256; i++) { - mpic[i] = qdev_get_gpio_in(dev, i); - } - s = SYS_BUS_DEVICE(dev); memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET, s->mmio[0].memory); - return mpic; + return dev; } static void ppce500_power_off(void *opaque, int line, int on) @@ -796,8 +790,8 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and * 4 respectively */ unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4}; - qemu_irq **irqs, *mpic; - DeviceState *dev; + qemu_irq **irqs; + DeviceState *dev, *mpicdev; CPUPPCState *firstenv = NULL; MemoryRegion *ccsr_addr_space; SysBusDevice *s; @@ -866,18 +860,18 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) memory_region_add_subregion(address_space_mem, params->ccsrbar_base, ccsr_addr_space); - mpic = ppce500_init_mpic(machine, params, ccsr_addr_space, irqs); + mpicdev = ppce500_init_mpic(machine, params, ccsr_addr_space, irqs); /* Serial */ if (serial_hds[0]) { serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, - 0, mpic[42], 399193, + 0, qdev_get_gpio_in(mpicdev, 42), 399193, serial_hds[0], DEVICE_BIG_ENDIAN); } if (serial_hds[1]) { serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET, - 0, mpic[42], 399193, + 0, qdev_get_gpio_in(mpicdev, 42), 399193, serial_hds[1], DEVICE_BIG_ENDIAN); } @@ -895,7 +889,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); for (i = 0; i < PCI_NUM_PINS; i++) { - sysbus_connect_irq(s, i, mpic[pci_irq_nrs[i]]); + sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, pci_irq_nrs[i])); } memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, @@ -926,7 +920,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) dev = qdev_create(NULL, "mpc8xxx_gpio"); s = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); - sysbus_connect_irq(s, 0, mpic[MPC8XXX_GPIO_IRQ]); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8XXX_GPIO_IRQ)); memory_region_add_subregion(ccsr_addr_space, MPC8XXX_GPIO_OFFSET, sysbus_mmio_get_region(s, 0)); @@ -946,7 +940,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) for (i = 0; i < params->platform_bus_num_irqs; i++) { int irqn = params->platform_bus_first_irq + i; - sysbus_connect_irq(s, i, mpic[irqn]); + sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn)); } memory_region_add_subregion(address_space_mem, diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d682f013d4..6285f7211f 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -44,6 +44,7 @@ #include "migration/register.h" #include "mmu-hash64.h" #include "mmu-book3s-v3.h" +#include "cpu-models.h" #include "qom/cpu.h" #include "hw/boards.h" @@ -252,9 +253,10 @@ static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu) } /* Populate the "ibm,pa-features" property */ -static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset, - bool legacy_guest) +static void spapr_populate_pa_features(PowerPCCPU *cpu, void *fdt, int offset, + bool legacy_guest) { + CPUPPCState *env = &cpu->env; uint8_t pa_features_206[] = { 6, 0, 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; uint8_t pa_features_207[] = { 24, 0, @@ -287,23 +289,22 @@ static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset, /* 60: NM atomic, 62: RNG */ 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ }; - uint8_t *pa_features; + uint8_t *pa_features = NULL; size_t pa_size; - switch (POWERPC_MMU_VER(env->mmu_model)) { - case POWERPC_MMU_VER_2_06: + if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 0, cpu->compat_pvr)) { pa_features = pa_features_206; pa_size = sizeof(pa_features_206); - break; - case POWERPC_MMU_VER_2_07: + } + if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 0, cpu->compat_pvr)) { pa_features = pa_features_207; pa_size = sizeof(pa_features_207); - break; - case POWERPC_MMU_VER_3_00: + } + if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, cpu->compat_pvr)) { pa_features = pa_features_300; pa_size = sizeof(pa_features_300); - break; - default: + } + if (!pa_features) { return; } @@ -340,7 +341,6 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr) CPU_FOREACH(cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; DeviceClass *dc = DEVICE_GET_CLASS(cs); int index = spapr_vcpu_id(cpu); int compat_smt = MIN(smp_threads, ppc_compat_max_threads(cpu)); @@ -384,7 +384,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr) return ret; } - spapr_populate_pa_features(env, fdt, offset, + spapr_populate_pa_features(cpu, fdt, offset, spapr->cas_legacy_guest_workaround); } return ret; @@ -579,7 +579,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, page_sizes_prop, page_sizes_prop_size))); } - spapr_populate_pa_features(env, fdt, offset, false); + spapr_populate_pa_features(cpu, fdt, offset, false); _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", cs->cpu_index / vcpus_per_socket))); @@ -949,7 +949,11 @@ static void spapr_dt_ov5_platform_support(void *fdt, int chosen) 26, 0x40, /* Radix options: GTSE == yes. */ }; - if (kvm_enabled()) { + if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0, + first_ppc_cpu->compat_pvr)) { + /* If we're in a pre POWER9 compat mode then the guest should do hash */ + val[3] = 0x00; /* Hash */ + } else if (kvm_enabled()) { if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { val[3] = 0x80; /* OV5_MMU_BOTH */ } else if (kvmppc_has_cap_mmu_radix()) { @@ -958,13 +962,8 @@ static void spapr_dt_ov5_platform_support(void *fdt, int chosen) val[3] = 0x00; /* Hash */ } } else { - if (first_ppc_cpu->env.mmu_model & POWERPC_MMU_V3) { - /* V3 MMU supports both hash and radix (with dynamic switching) */ - val[3] = 0xC0; - } else { - /* Otherwise we can only do hash */ - val[3] = 0x00; - } + /* V3 MMU supports both hash and radix in tcg (with dynamic switching) */ + val[3] = 0xC0; } _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", val, sizeof(val))); @@ -1412,6 +1411,19 @@ static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque) } } +static int spapr_reset_drcs(Object *child, void *opaque) +{ + sPAPRDRConnector *drc = + (sPAPRDRConnector *) object_dynamic_cast(child, + TYPE_SPAPR_DR_CONNECTOR); + + if (drc) { + spapr_drc_reset(drc); + } + + return 0; +} + static void ppc_spapr_reset(void) { MachineState *machine = MACHINE(qdev_get_machine()); @@ -1435,6 +1447,14 @@ static void ppc_spapr_reset(void) } qemu_devices_reset(); + + /* DRC reset may cause a device to be unplugged. This will cause troubles + * if this device is used by another device (eg, a running vhost backend + * will crash QEMU if the DIMM holding the vring goes away). To avoid such + * situations, we reset DRCs after all devices have been reset. + */ + object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL); + spapr_clear_pending_events(spapr); /* diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 915e9b51c4..e3b122968e 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -455,11 +455,6 @@ void spapr_drc_reset(sPAPRDRConnector *drc) } } -static void drc_reset(void *opaque) -{ - spapr_drc_reset(SPAPR_DR_CONNECTOR(opaque)); -} - bool spapr_drc_needed(void *opaque) { sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque; @@ -518,7 +513,6 @@ static void realize(DeviceState *d, Error **errp) } vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc, drc); - qemu_register_reset(drc_reset, drc); trace_spapr_drc_realize_complete(spapr_drc_index(drc)); } @@ -529,7 +523,6 @@ static void unrealize(DeviceState *d, Error **errp) gchar *name; trace_spapr_drc_unrealize(spapr_drc_index(drc)); - qemu_unregister_reset(drc_reset, drc); vmstate_unregister(DEVICE(drc), &vmstate_spapr_drc, drc); root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); name = g_strdup_printf("%x", spapr_drc_index(drc)); diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 0d59d1534d..be22a6b289 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1636,6 +1636,12 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, spapr->cas_legacy_guest_workaround = !spapr_ovec_test(ov1_guest, OV1_PPC_3_00); if (!spapr->cas_reboot) { + /* If ppc_spapr_reset() did not set up a HPT but one is necessary + * (because the guest isn't going to use radix) then set it up here. */ + if ((spapr->patb_entry & PATBE1_GR) && !guest_radix) { + /* legacy hash or new hash: */ + spapr_setup_hpt_and_vrma(spapr); + } spapr->cas_reboot = (spapr_h_cas_compose_response(spapr, args[1], args[2], ov5_updates) != 0); @@ -1644,13 +1650,6 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, if (spapr->cas_reboot) { qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); - } else { - /* If ppc_spapr_reset() did not set up a HPT but one is necessary - * (because the guest isn't going to use radix) then set it up here. */ - if ((spapr->patb_entry & PATBE1_GR) && !guest_radix) { - /* legacy hash or new hash: */ - spapr_setup_hpt_and_vrma(spapr); - } } return H_SUCCESS; diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index e7a58e81f7..2b1e1409bf 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -715,7 +715,7 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, pbdev->pdev = pdev; pbdev->iommu = s390_pci_get_iommu(s, pdev->bus, pdev->devfn); pbdev->iommu->pbdev = pbdev; - pbdev->state = ZPCI_FS_STANDBY; + pbdev->state = ZPCI_FS_DISABLED; if (s390_pci_msix_init(pbdev)) { error_setg(errp, "MSI-X support is mandatory " diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c index 500fa6a067..f7561e23fa 100644 --- a/hw/scsi/vhost-user-scsi.c +++ b/hw/scsi/vhost-user-scsi.c @@ -135,6 +135,8 @@ static Property vhost_user_scsi_properties[] = { DEFINE_PROP_CHR("chardev", VirtIOSCSICommon, conf.chardev), DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0), DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, 1), + DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size, + 128), DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors, 0xFFFF), DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSICommon, conf.cmd_per_lun, 128), diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 9aaec8e3ef..e1a68104d6 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -71,15 +71,21 @@ typedef struct TPMEmulator { ptm_cap caps; /* capabilities of the TPM */ uint8_t cur_locty_number; /* last set locality */ Error *migration_blocker; + + QemuMutex mutex; } TPMEmulator; -static int tpm_emulator_ctrlcmd(CharBackend *dev, unsigned long cmd, void *msg, +static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg, size_t msg_len_in, size_t msg_len_out) { + CharBackend *dev = &tpm->ctrl_chr; uint32_t cmd_no = cpu_to_be32(cmd); ssize_t n = sizeof(uint32_t) + msg_len_in; uint8_t *buf = NULL; + int ret = -1; + + qemu_mutex_lock(&tpm->mutex); buf = g_alloca(n); memcpy(buf, &cmd_no, sizeof(cmd_no)); @@ -87,17 +93,21 @@ static int tpm_emulator_ctrlcmd(CharBackend *dev, unsigned long cmd, void *msg, n = qemu_chr_fe_write_all(dev, buf, n); if (n <= 0) { - return -1; + goto end; } if (msg_len_out != 0) { n = qemu_chr_fe_read_all(dev, msg, msg_len_out); if (n <= 0) { - return -1; + goto end; } } - return 0; + ret = 0; + +end: + qemu_mutex_unlock(&tpm->mutex); + return ret; } static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu, @@ -154,7 +164,7 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number, DPRINTF("setting locality : 0x%x", locty_number); loc.u.req.loc = locty_number; - if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_SET_LOCALITY, &loc, + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc, sizeof(loc), sizeof(loc)) < 0) { error_setg(errp, "tpm-emulator: could not set locality : %s", strerror(errno)); @@ -202,8 +212,8 @@ error: static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu) { DPRINTF("%s", __func__); - if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_GET_CAPABILITY, - &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) { + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY, + &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) { error_report("tpm-emulator: probing failed : %s", strerror(errno)); return -1; } @@ -254,8 +264,8 @@ static int tpm_emulator_startup_tpm(TPMBackend *tb) ptm_res res; DPRINTF("%s", __func__); - if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_INIT, &init, sizeof(init), - sizeof(init)) < 0) { + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init), + sizeof(init)) < 0) { error_report("tpm-emulator: could not send INIT: %s", strerror(errno)); goto err_exit; @@ -278,7 +288,7 @@ static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb) ptm_est est; DPRINTF("%s", __func__); - if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_GET_TPMESTABLISHED, &est, + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_TPMESTABLISHED, &est, 0, sizeof(est)) < 0) { error_report("tpm-emulator: Could not get the TPM established flag: %s", strerror(errno)); @@ -302,7 +312,7 @@ static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb, } reset_est.u.req.loc = tpm_emu->cur_locty_number; - if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_RESET_TPMESTABLISHED, + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_RESET_TPMESTABLISHED, &reset_est, sizeof(reset_est), sizeof(reset_est)) < 0) { error_report("tpm-emulator: Could not reset the establishment bit: %s", @@ -330,7 +340,7 @@ static void tpm_emulator_cancel_cmd(TPMBackend *tb) return; } - if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_CANCEL_TPM_CMD, &res, 0, + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_CANCEL_TPM_CMD, &res, 0, sizeof(res)) < 0) { error_report("tpm-emulator: Could not cancel command: %s", strerror(errno)); @@ -378,8 +388,8 @@ static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu) qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1); - if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_SET_DATAFD, &res, 0, - sizeof(res)) || res != 0) { + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_DATAFD, &res, 0, + sizeof(res)) < 0 || res != 0) { error_report("tpm-emulator: Failed to send CMD_SET_DATAFD: %s", strerror(errno)); goto err_exit; @@ -501,6 +511,7 @@ static void tpm_emulator_inst_init(Object *obj) DPRINTF("%s", __func__); tpm_emu->options = g_new0(TPMEmulatorOptions, 1); tpm_emu->cur_locty_number = ~0; + qemu_mutex_init(&tpm_emu->mutex); } /* @@ -510,8 +521,7 @@ static void tpm_emulator_shutdown(TPMEmulator *tpm_emu) { ptm_res res; - if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_SHUTDOWN, &res, 0, - sizeof(res)) < 0) { + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0, sizeof(res)) < 0) { error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s", strerror(errno)); } else if (res != 0) { @@ -536,6 +546,8 @@ static void tpm_emulator_inst_finalize(Object *obj) migrate_del_blocker(tpm_emu->migration_blocker); error_free(tpm_emu->migration_blocker); } + + qemu_mutex_destroy(&tpm_emu->mutex); } static void tpm_emulator_class_init(ObjectClass *klass, void *data) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 7402528b25..42d647d363 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -545,7 +545,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, uint8_t v; if (tpm_backend_had_startup_error(s->be_driver)) { - return val; + return 0; } switch (offset) { @@ -1008,6 +1008,10 @@ TPMVersion tpm_tis_get_tpm_version(Object *obj) { TPMState *s = TPM(obj); + if (tpm_backend_had_startup_error(s->be_driver)) { + return TPM_VERSION_UNSPEC; + } + return tpm_backend_get_tpm_version(s->be_driver); } diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 5884ce3480..ea532dc35f 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -2491,6 +2491,7 @@ static void virtio_device_realize(DeviceState *dev, Error **errp) virtio_bus_device_plugged(vdev, &err); if (err != NULL) { error_propagate(errp, err); + vdc->unrealize(dev, NULL); return; } |