aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/boot.c5
-rw-r--r--hw/core/qdev.c17
-rw-r--r--hw/i386/x86.c4
-rw-r--r--hw/intc/loongarch_extioi.c41
-rw-r--r--hw/intc/trace-events3
-rw-r--r--hw/loongarch/acpi-build.c51
-rw-r--r--hw/loongarch/virt.c53
-rw-r--r--hw/nvme/ctrl.c29
-rw-r--r--hw/nvme/nvme.h4
-rw-r--r--hw/s390x/css.c51
-rw-r--r--hw/s390x/s390-pci-inst.c29
-rw-r--r--hw/s390x/s390-virtio-ccw.c138
-rw-r--r--hw/vfio/migration.c2
-rw-r--r--hw/xen/meson.build2
14 files changed, 314 insertions, 115 deletions
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index b106f31..15c2bf1 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -764,10 +764,15 @@ static void do_cpu_reset(void *opaque)
}
if (cpu_isar_feature(aa64_sve, cpu)) {
env->cp15.cptr_el[3] |= R_CPTR_EL3_EZ_MASK;
+ env->vfp.zcr_el[3] = 0xf;
}
if (cpu_isar_feature(aa64_sme, cpu)) {
env->cp15.cptr_el[3] |= R_CPTR_EL3_ESM_MASK;
env->cp15.scr_el3 |= SCR_ENTP2;
+ env->vfp.smcr_el[3] = 0xf;
+ }
+ if (cpu_isar_feature(aa64_hcx, cpu)) {
+ env->cp15.scr_el3 |= SCR_HXEN;
}
/* AArch64 kernels never boot in secure mode */
assert(!info->secure_boot);
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 0806d8f..0145501 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -147,8 +147,21 @@ bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp)
DeviceState *qdev_new(const char *name)
{
- if (!object_class_by_name(name)) {
- module_load_qom_one(name);
+ ObjectClass *oc = object_class_by_name(name);
+#ifdef CONFIG_MODULES
+ if (!oc) {
+ int rv = module_load_qom(name, &error_fatal);
+ if (rv > 0) {
+ oc = object_class_by_name(name);
+ } else {
+ error_report("could not find a module for type '%s'", name);
+ exit(1);
+ }
+ }
+#endif
+ if (!oc) {
+ error_report("unknown type '%s'", name);
+ abort();
}
return DEVICE(object_new(name));
}
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index bd50a06..78cc131 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -140,6 +140,10 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version)
exit(EXIT_FAILURE);
}
+ if (kvm_enabled()) {
+ kvm_set_max_apic_id(x86ms->apic_id_limit);
+ }
+
possible_cpus = mc->possible_cpu_arch_ids(ms);
for (i = 0; i < ms->smp.cpus; i++) {
x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, &error_fatal);
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index 2280396..4b8ec3f 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -68,44 +68,46 @@ static void extioi_setirq(void *opaque, int irq, int level)
extioi_update_irq(s, irq, level);
}
-static uint64_t extioi_readw(void *opaque, hwaddr addr, unsigned size)
+static MemTxResult extioi_readw(void *opaque, hwaddr addr, uint64_t *data,
+ unsigned size, MemTxAttrs attrs)
{
LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
unsigned long offset = addr & 0xffff;
- uint32_t index, cpu, ret = 0;
+ uint32_t index, cpu;
switch (offset) {
case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
index = (offset - EXTIOI_NODETYPE_START) >> 2;
- ret = s->nodetype[index];
+ *data = s->nodetype[index];
break;
case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
index = (offset - EXTIOI_IPMAP_START) >> 2;
- ret = s->ipmap[index];
+ *data = s->ipmap[index];
break;
case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
index = (offset - EXTIOI_ENABLE_START) >> 2;
- ret = s->enable[index];
+ *data = s->enable[index];
break;
case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1:
index = (offset - EXTIOI_BOUNCE_START) >> 2;
- ret = s->bounce[index];
+ *data = s->bounce[index];
break;
case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
- index = ((offset - EXTIOI_COREISR_START) & 0x1f) >> 2;
- cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
- ret = s->coreisr[cpu][index];
+ index = (offset - EXTIOI_COREISR_START) >> 2;
+ /* using attrs to get current cpu index */
+ cpu = attrs.requester_id;
+ *data = s->coreisr[cpu][index];
break;
case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1:
index = (offset - EXTIOI_COREMAP_START) >> 2;
- ret = s->coremap[index];
+ *data = s->coremap[index];
break;
default:
break;
}
- trace_loongarch_extioi_readw(addr, ret);
- return ret;
+ trace_loongarch_extioi_readw(addr, *data);
+ return MEMTX_OK;
}
static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\
@@ -127,8 +129,9 @@ static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\
}
}
-static void extioi_writew(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
+static MemTxResult extioi_writew(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size,
+ MemTxAttrs attrs)
{
LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
int i, cpu, index, old_data, irq;
@@ -183,8 +186,9 @@ static void extioi_writew(void *opaque, hwaddr addr,
s->bounce[index] = val;
break;
case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
- index = ((offset - EXTIOI_COREISR_START) & 0x1f) >> 2;
- cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
+ index = (offset - EXTIOI_COREISR_START) >> 2;
+ /* using attrs to get current cpu index */
+ cpu = attrs.requester_id;
old_data = s->coreisr[cpu][index];
s->coreisr[cpu][index] = old_data & ~val;
/* write 1 to clear interrrupt */
@@ -231,11 +235,12 @@ static void extioi_writew(void *opaque, hwaddr addr,
default:
break;
}
+ return MEMTX_OK;
}
static const MemoryRegionOps extioi_ops = {
- .read = extioi_readw,
- .write = extioi_writew,
+ .read_with_attrs = extioi_readw,
+ .write_with_attrs = extioi_writew,
.impl.min_access_size = 4,
.impl.max_access_size = 4,
.valid.min_access_size = 4,
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 0a90c1c..6fbc204 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -306,6 +306,5 @@ loongarch_msi_set_irq(int irq_num) "set msi irq %d"
# loongarch_extioi.c
loongarch_extioi_setirq(int irq, int level) "set extirq irq %d level %d"
-loongarch_extioi_readw(uint64_t addr, uint32_t val) "addr: 0x%"PRIx64 "val: 0x%x"
+loongarch_extioi_readw(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64
loongarch_extioi_writew(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64
-
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index 378a6d9..68dfb9f 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -31,6 +31,9 @@
#include "hw/acpi/generic_event_device.h"
#include "hw/pci-host/gpex.h"
+#include "sysemu/tpm.h"
+#include "hw/platform-bus.h"
+#include "hw/acpi/aml-build.h"
#define ACPI_BUILD_ALIGN_SIZE 0x1000
#define ACPI_BUILD_TABLE_SIZE 0x20000
@@ -275,6 +278,41 @@ static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams)
acpi_dsdt_add_gpex(scope, &cfg);
}
+#ifdef CONFIG_TPM
+static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms)
+{
+ PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
+ hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
+ SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
+ MemoryRegion *sbdev_mr;
+ hwaddr tpm_base;
+
+ if (!sbdev) {
+ return;
+ }
+
+ tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+ assert(tpm_base != -1);
+
+ tpm_base += pbus_base;
+
+ sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+
+ Aml *dev = aml_device("TPM0");
+ aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+ aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
+ aml_append(dev, aml_name_decl("_UID", aml_int(0)));
+
+ Aml *crs = aml_resource_template();
+ aml_append(crs,
+ aml_memory32_fixed(tpm_base,
+ (uint32_t)memory_region_size(sbdev_mr),
+ AML_READ_WRITE));
+ aml_append(dev, aml_name_decl("_CRS", crs));
+ aml_append(scope, dev);
+}
+#endif
+
/* build DSDT */
static void
build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
@@ -289,7 +327,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
build_uart_device_aml(dsdt);
build_pci_device_aml(dsdt, lams);
build_la_ged_aml(dsdt, machine);
-
+#ifdef CONFIG_TPM
+ acpi_dsdt_add_tpm(dsdt, lams);
+#endif
/* System State Package */
scope = aml_scope("\\");
pkg = aml_package(4);
@@ -359,6 +399,15 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
lams->oem_table_id);
}
+#ifdef CONFIG_TPM
+ /* TPM info */
+ if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0) {
+ acpi_add_table(table_offsets, tables_blob);
+ build_tpm2(tables_blob, tables->linker,
+ tables->tcpalog, lams->oem_id,
+ lams->oem_table_id);
+ }
+#endif
/* Add tables supplied by user (if any) */
for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
unsigned len = acpi_table_len(u);
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 4b595a9..5e4c279 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -41,6 +41,36 @@
#include "hw/platform-bus.h"
#include "hw/display/ramfb.h"
#include "hw/mem/pc-dimm.h"
+#include "sysemu/tpm.h"
+
+static void fdt_add_rtc_node(LoongArchMachineState *lams)
+{
+ char *nodename;
+ hwaddr base = VIRT_RTC_REG_BASE;
+ hwaddr size = VIRT_RTC_LEN;
+ MachineState *ms = MACHINE(lams);
+
+ nodename = g_strdup_printf("/rtc@%" PRIx64, base);
+ qemu_fdt_add_subnode(ms->fdt, nodename);
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "loongson,ls7a-rtc");
+ qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 0x0, base, size);
+ g_free(nodename);
+}
+
+static void fdt_add_uart_node(LoongArchMachineState *lams)
+{
+ char *nodename;
+ hwaddr base = VIRT_UART_BASE;
+ hwaddr size = VIRT_UART_SIZE;
+ MachineState *ms = MACHINE(lams);
+
+ nodename = g_strdup_printf("/serial@%" PRIx64, base);
+ qemu_fdt_add_subnode(ms->fdt, nodename);
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "ns16550a");
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0x0, base, 0x0, size);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "clock-frequency", 100000000);
+ g_free(nodename);
+}
static void create_fdt(LoongArchMachineState *lams)
{
@@ -159,7 +189,6 @@ static void fdt_add_pcie_node(const LoongArchMachineState *lams)
1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
2, base_mmio, 2, size_mmio);
g_free(nodename);
- qemu_fdt_dumpdtb(ms->fdt, lams->fdt_size);
}
static void fdt_add_irqchip_node(LoongArchMachineState *lams)
@@ -423,6 +452,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *
qdev_get_gpio_in(pch_pic,
VIRT_UART_IRQ - PCH_PIC_IRQ_OFFSET),
115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
+ fdt_add_uart_node(lams);
/* Network init */
for (i = 0; i < nb_nics; i++) {
@@ -443,6 +473,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *
sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE,
qdev_get_gpio_in(pch_pic,
VIRT_RTC_IRQ - PCH_PIC_IRQ_OFFSET));
+ fdt_add_rtc_node(lams);
pm_mem = g_new(MemoryRegion, 1);
memory_region_init_io(pm_mem, NULL, &loongarch_virt_pm_ops,
@@ -656,6 +687,7 @@ static void loongarch_init(MachineState *machine)
MemoryRegion *address_space_mem = get_system_memory();
LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
int i;
+ hwaddr fdt_base;
if (!cpu_model) {
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
@@ -760,12 +792,16 @@ static void loongarch_init(MachineState *machine)
lams->machine_done.notify = virt_machine_done;
qemu_add_machine_init_done_notifier(&lams->machine_done);
fdt_add_pcie_node(lams);
-
- /* load fdt */
- MemoryRegion *fdt_rom = g_new(MemoryRegion, 1);
- memory_region_init_rom(fdt_rom, NULL, "fdt", VIRT_FDT_SIZE, &error_fatal);
- memory_region_add_subregion(get_system_memory(), VIRT_FDT_BASE, fdt_rom);
- rom_add_blob_fixed("fdt", machine->fdt, lams->fdt_size, VIRT_FDT_BASE);
+ /*
+ * Since lowmem region starts from 0, FDT base address is located
+ * at 2 MiB to avoid NULL pointer access.
+ *
+ * Put the FDT into the memory map as a ROM image: this will ensure
+ * the FDT is copied again upon reset, even if addr points into RAM.
+ */
+ fdt_base = 2 * MiB;
+ qemu_fdt_dumpdtb(machine->fdt, lams->fdt_size);
+ rom_add_blob_fixed("fdt", machine->fdt, lams->fdt_size, fdt_base);
}
bool loongarch_is_acpi_enabled(LoongArchMachineState *lams)
@@ -925,6 +961,9 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
object_class_property_set_description(oc, "acpi",
"Enable ACPI");
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
+#ifdef CONFIG_TPM
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+#endif
}
static const TypeInfo loongarch_machine_types[] = {
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index d38fdd9..ac3885c 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -1401,13 +1401,7 @@ static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req)
QTAILQ_REMOVE(&req->sq->out_req_list, req, entry);
QTAILQ_INSERT_TAIL(&cq->req_list, req, entry);
- if (req->sq->ioeventfd_enabled) {
- /* Post CQE directly since we are in main loop thread */
- nvme_post_cqes(cq);
- } else {
- /* Schedule the timer to post CQE later since we are in vcpu thread */
- timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
- }
+ qemu_bh_schedule(cq->bh);
}
static void nvme_process_aers(void *opaque)
@@ -3040,7 +3034,8 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req)
goto invalid;
}
- if (ns->pif && format != 0x1) {
+ if ((ns->pif == 0x0 && format != 0x0) ||
+ (ns->pif != 0x0 && format != 0x1)) {
status = NVME_INVALID_FORMAT | NVME_DNR;
goto invalid;
}
@@ -4252,7 +4247,7 @@ static void nvme_cq_notifier(EventNotifier *e)
nvme_irq_deassert(n, cq);
}
- nvme_post_cqes(cq);
+ qemu_bh_schedule(cq->bh);
}
static int nvme_init_cq_ioeventfd(NvmeCQueue *cq)
@@ -4307,7 +4302,7 @@ static void nvme_free_sq(NvmeSQueue *sq, NvmeCtrl *n)
uint16_t offset = sq->sqid << 3;
n->sq[sq->sqid] = NULL;
- timer_free(sq->timer);
+ qemu_bh_delete(sq->bh);
if (sq->ioeventfd_enabled) {
memory_region_del_eventfd(&n->iomem,
0x1000 + offset, 4, false, 0, &sq->notifier);
@@ -4381,7 +4376,8 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr,
sq->io_req[i].sq = sq;
QTAILQ_INSERT_TAIL(&(sq->req_list), &sq->io_req[i], entry);
}
- sq->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, nvme_process_sq, sq);
+
+ sq->bh = qemu_bh_new(nvme_process_sq, sq);
if (n->dbbuf_enabled) {
sq->db_addr = n->dbbuf_dbs + (sqid << 3);
@@ -4698,7 +4694,7 @@ static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n)
uint16_t offset = (cq->cqid << 3) + (1 << 2);
n->cq[cq->cqid] = NULL;
- timer_free(cq->timer);
+ qemu_bh_delete(cq->bh);
if (cq->ioeventfd_enabled) {
memory_region_del_eventfd(&n->iomem,
0x1000 + offset, 4, false, 0, &cq->notifier);
@@ -4768,7 +4764,7 @@ static void nvme_init_cq(NvmeCQueue *cq, NvmeCtrl *n, uint64_t dma_addr,
}
}
n->cq[cqid] = cq;
- cq->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, nvme_post_cqes, cq);
+ cq->bh = qemu_bh_new(nvme_post_cqes, cq);
}
static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeRequest *req)
@@ -6910,9 +6906,9 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
if (start_sqs) {
NvmeSQueue *sq;
QTAILQ_FOREACH(sq, &cq->sq_list, entry) {
- timer_mod(sq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
+ qemu_bh_schedule(sq->bh);
}
- timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
+ qemu_bh_schedule(cq->bh);
}
if (cq->tail == cq->head) {
@@ -6981,7 +6977,8 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
pci_dma_write(&n->parent_obj, sq->db_addr, &sq->tail,
sizeof(sq->tail));
}
- timer_mod(sq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
+
+ qemu_bh_schedule(sq->bh);
}
}
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index 79f5c28..7adf042 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -375,7 +375,7 @@ typedef struct NvmeSQueue {
uint64_t dma_addr;
uint64_t db_addr;
uint64_t ei_addr;
- QEMUTimer *timer;
+ QEMUBH *bh;
EventNotifier notifier;
bool ioeventfd_enabled;
NvmeRequest *io_req;
@@ -396,7 +396,7 @@ typedef struct NvmeCQueue {
uint64_t dma_addr;
uint64_t db_addr;
uint64_t ei_addr;
- QEMUTimer *timer;
+ QEMUBH *bh;
EventNotifier notifier;
bool ioeventfd_enabled;
QTAILQ_HEAD(, NvmeSQueue) sq_list;
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 7d9523f..95d1b3a 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1522,21 +1522,37 @@ IOInstEnding css_do_xsch(SubchDev *sch)
IOInstEnding css_do_csch(SubchDev *sch)
{
SCHIB *schib = &sch->curr_status;
+ uint16_t old_scsw_ctrl;
+ IOInstEnding ccode;
if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
return IOINST_CC_NOT_OPERATIONAL;
}
+ /*
+ * Save the current scsw.ctrl in case CSCH fails and we need
+ * to revert the scsw to the status quo ante.
+ */
+ old_scsw_ctrl = schib->scsw.ctrl;
+
/* Trigger the clear function. */
schib->scsw.ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL);
schib->scsw.ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND;
- return do_subchannel_work(sch);
+ ccode = do_subchannel_work(sch);
+
+ if (ccode != IOINST_CC_EXPECTED) {
+ schib->scsw.ctrl = old_scsw_ctrl;
+ }
+
+ return ccode;
}
IOInstEnding css_do_hsch(SubchDev *sch)
{
SCHIB *schib = &sch->curr_status;
+ uint16_t old_scsw_ctrl;
+ IOInstEnding ccode;
if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
return IOINST_CC_NOT_OPERATIONAL;
@@ -1553,6 +1569,12 @@ IOInstEnding css_do_hsch(SubchDev *sch)
return IOINST_CC_BUSY;
}
+ /*
+ * Save the current scsw.ctrl in case HSCH fails and we need
+ * to revert the scsw to the status quo ante.
+ */
+ old_scsw_ctrl = schib->scsw.ctrl;
+
/* Trigger the halt function. */
schib->scsw.ctrl |= SCSW_FCTL_HALT_FUNC;
schib->scsw.ctrl &= ~SCSW_FCTL_START_FUNC;
@@ -1564,7 +1586,13 @@ IOInstEnding css_do_hsch(SubchDev *sch)
}
schib->scsw.ctrl |= SCSW_ACTL_HALT_PEND;
- return do_subchannel_work(sch);
+ ccode = do_subchannel_work(sch);
+
+ if (ccode != IOINST_CC_EXPECTED) {
+ schib->scsw.ctrl = old_scsw_ctrl;
+ }
+
+ return ccode;
}
static void css_update_chnmon(SubchDev *sch)
@@ -1605,6 +1633,8 @@ static void css_update_chnmon(SubchDev *sch)
IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb)
{
SCHIB *schib = &sch->curr_status;
+ uint16_t old_scsw_ctrl, old_scsw_flags;
+ IOInstEnding ccode;
if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
return IOINST_CC_NOT_OPERATIONAL;
@@ -1626,11 +1656,26 @@ IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb)
}
sch->orb = *orb;
sch->channel_prog = orb->cpa;
+
+ /*
+ * Save the current scsw.ctrl and scsw.flags in case SSCH fails and we need
+ * to revert the scsw to the status quo ante.
+ */
+ old_scsw_ctrl = schib->scsw.ctrl;
+ old_scsw_flags = schib->scsw.flags;
+
/* Trigger the start function. */
schib->scsw.ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND);
schib->scsw.flags &= ~SCSW_FLAGS_MASK_PNO;
- return do_subchannel_work(sch);
+ ccode = do_subchannel_work(sch);
+
+ if (ccode != IOINST_CC_EXPECTED) {
+ schib->scsw.ctrl = old_scsw_ctrl;
+ schib->scsw.flags = old_scsw_flags;
+ }
+
+ return ccode;
}
static void copy_irb_to_guest(IRB *dest, const IRB *src, const PMCW *pmcw,
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 20a9bcc..7cc4bcf 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -677,8 +677,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
S390PCIBusDevice *pbdev;
S390PCIIOMMU *iommu;
S390IOTLBEntry entry;
- hwaddr start, end;
+ hwaddr start, end, sstart;
uint32_t dma_avail;
+ bool again;
if (env->psw.mask & PSW_MASK_PSTATE) {
s390_program_interrupt(env, PGM_PRIVILEGED, ra);
@@ -691,7 +692,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
}
fh = env->regs[r1] >> 32;
- start = env->regs[r2];
+ sstart = start = env->regs[r2];
end = start + env->regs[r2 + 1];
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
@@ -732,6 +733,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
goto err;
}
+ retry:
+ start = sstart;
+ again = false;
while (start < end) {
error = s390_guest_io_table_walk(iommu->g_iota, start, &entry);
if (error) {
@@ -739,13 +743,24 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
}
start += entry.len;
- while (entry.iova < start && entry.iova < end &&
- (dma_avail > 0 || entry.perm == IOMMU_NONE)) {
- dma_avail = s390_pci_update_iotlb(iommu, &entry);
- entry.iova += TARGET_PAGE_SIZE;
- entry.translated_addr += TARGET_PAGE_SIZE;
+ while (entry.iova < start && entry.iova < end) {
+ if (dma_avail > 0 || entry.perm == IOMMU_NONE) {
+ dma_avail = s390_pci_update_iotlb(iommu, &entry);
+ entry.iova += TARGET_PAGE_SIZE;
+ entry.translated_addr += TARGET_PAGE_SIZE;
+ } else {
+ /*
+ * We are unable to make a new mapping at this time, continue
+ * on and hopefully free up more space. Then attempt another
+ * pass.
+ */
+ again = true;
+ break;
+ }
}
}
+ if (again && dma_avail > 0)
+ goto retry;
err:
if (error) {
pbdev->state = ZPCI_FS_ERROR;
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 806de32..560ddbb 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -43,6 +43,7 @@
#include "sysemu/sysemu.h"
#include "hw/s390x/pv.h"
#include "migration/blocker.h"
+#include "qapi/visitor.h"
static Error *pv_mig_blocker;
@@ -84,8 +85,15 @@ out:
static void s390_init_cpus(MachineState *machine)
{
MachineClass *mc = MACHINE_GET_CLASS(machine);
+ S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
int i;
+ if (machine->smp.threads > s390mc->max_threads) {
+ error_report("S390 does not support more than %d threads.",
+ s390mc->max_threads);
+ exit(1);
+ }
+
/* initialize possible_cpus */
mc->possible_cpu_arch_ids(machine);
@@ -589,38 +597,6 @@ static ram_addr_t s390_fixup_ram_size(ram_addr_t sz)
return newsz;
}
-static void ccw_machine_class_init(ObjectClass *oc, void *data)
-{
- MachineClass *mc = MACHINE_CLASS(oc);
- NMIClass *nc = NMI_CLASS(oc);
- HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
- S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
-
- s390mc->ri_allowed = true;
- s390mc->cpu_model_allowed = true;
- s390mc->css_migration_enabled = true;
- s390mc->hpage_1m_allowed = true;
- mc->init = ccw_init;
- mc->reset = s390_machine_reset;
- mc->block_default_type = IF_VIRTIO;
- mc->no_cdrom = 1;
- mc->no_floppy = 1;
- mc->no_parallel = 1;
- mc->no_sdcard = 1;
- mc->max_cpus = S390_MAX_CPUS;
- mc->has_hotpluggable_cpus = true;
- assert(!mc->get_hotplug_handler);
- mc->get_hotplug_handler = s390_get_hotplug_handler;
- mc->cpu_index_to_instance_props = s390_cpu_index_to_props;
- mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
- /* it is overridden with 'host' cpu *in kvm_arch_init* */
- mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu");
- hc->plug = s390_machine_device_plug;
- hc->unplug_request = s390_machine_device_unplug_request;
- nc->nmi_monitor_handler = s390_nmi;
- mc->default_ram_id = "s390.ram";
-}
-
static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
@@ -710,19 +686,29 @@ bool hpage_1m_allowed(void)
return get_machine_class()->hpage_1m_allowed;
}
-static char *machine_get_loadparm(Object *obj, Error **errp)
+static void machine_get_loadparm(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+ char *str = g_strndup((char *) ms->loadparm, sizeof(ms->loadparm));
- /* make a NUL-terminated string */
- return g_strndup((char *) ms->loadparm, sizeof(ms->loadparm));
+ visit_type_str(v, name, &str, errp);
+ g_free(str);
}
-static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
+static void machine_set_loadparm(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+ char *val;
int i;
+ if (!visit_type_str(v, name, &val, errp)) {
+ return;
+ }
+
for (i = 0; i < sizeof(ms->loadparm) && val[i]; i++) {
uint8_t c = qemu_toupper(val[i]); /* mimic HMC */
@@ -740,34 +726,73 @@ static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
ms->loadparm[i] = ' '; /* pad right with spaces */
}
}
-static inline void s390_machine_initfn(Object *obj)
+
+static void ccw_machine_class_init(ObjectClass *oc, void *data)
{
- object_property_add_bool(obj, "aes-key-wrap",
- machine_get_aes_key_wrap,
- machine_set_aes_key_wrap);
- object_property_set_description(obj, "aes-key-wrap",
+ MachineClass *mc = MACHINE_CLASS(oc);
+ NMIClass *nc = NMI_CLASS(oc);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
+ S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
+
+ s390mc->ri_allowed = true;
+ s390mc->cpu_model_allowed = true;
+ s390mc->css_migration_enabled = true;
+ s390mc->hpage_1m_allowed = true;
+ s390mc->max_threads = 1;
+ mc->init = ccw_init;
+ mc->reset = s390_machine_reset;
+ mc->block_default_type = IF_VIRTIO;
+ mc->no_cdrom = 1;
+ mc->no_floppy = 1;
+ mc->no_parallel = 1;
+ mc->no_sdcard = 1;
+ mc->max_cpus = S390_MAX_CPUS;
+ mc->has_hotpluggable_cpus = true;
+ assert(!mc->get_hotplug_handler);
+ mc->get_hotplug_handler = s390_get_hotplug_handler;
+ mc->cpu_index_to_instance_props = s390_cpu_index_to_props;
+ mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
+ /* it is overridden with 'host' cpu *in kvm_arch_init* */
+ mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu");
+ hc->plug = s390_machine_device_plug;
+ hc->unplug_request = s390_machine_device_unplug_request;
+ nc->nmi_monitor_handler = s390_nmi;
+ mc->default_ram_id = "s390.ram";
+
+ object_class_property_add_bool(oc, "aes-key-wrap",
+ machine_get_aes_key_wrap,
+ machine_set_aes_key_wrap);
+ object_class_property_set_description(oc, "aes-key-wrap",
"enable/disable AES key wrapping using the CPACF wrapping key");
- object_property_set_bool(obj, "aes-key-wrap", true, NULL);
- object_property_add_bool(obj, "dea-key-wrap",
- machine_get_dea_key_wrap,
- machine_set_dea_key_wrap);
- object_property_set_description(obj, "dea-key-wrap",
+ object_class_property_add_bool(oc, "dea-key-wrap",
+ machine_get_dea_key_wrap,
+ machine_set_dea_key_wrap);
+ object_class_property_set_description(oc, "dea-key-wrap",
"enable/disable DEA key wrapping using the CPACF wrapping key");
- object_property_set_bool(obj, "dea-key-wrap", true, NULL);
- object_property_add_str(obj, "loadparm",
- machine_get_loadparm, machine_set_loadparm);
- object_property_set_description(obj, "loadparm",
+
+ object_class_property_add(oc, "loadparm", "loadparm",
+ machine_get_loadparm, machine_set_loadparm,
+ NULL, NULL);
+ object_class_property_set_description(oc, "loadparm",
"Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted"
" to upper case) to pass to machine loader, boot manager,"
" and guest kernel");
- object_property_add_bool(obj, "zpcii-disable",
- machine_get_zpcii_disable,
- machine_set_zpcii_disable);
- object_property_set_description(obj, "zpcii-disable",
+ object_class_property_add_bool(oc, "zpcii-disable",
+ machine_get_zpcii_disable,
+ machine_set_zpcii_disable);
+ object_class_property_set_description(oc, "zpcii-disable",
"disable zPCI interpretation facilties");
- object_property_set_bool(obj, "zpcii-disable", false, NULL);
+}
+
+static inline void s390_machine_initfn(Object *obj)
+{
+ S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+
+ ms->aes_key_wrap = true;
+ ms->dea_key_wrap = true;
+ ms->zpcii_disable = false;
}
static const TypeInfo ccw_machine_info = {
@@ -842,8 +867,11 @@ static void ccw_machine_7_1_instance_options(MachineState *machine)
static void ccw_machine_7_1_class_options(MachineClass *mc)
{
+ S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
+
ccw_machine_7_2_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len);
+ s390mc->max_threads = S390_MAX_CPUS;
}
DEFINE_CCW_MACHINE(7_1, "7.1", false);
diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
index 3de4252..c74453e 100644
--- a/hw/vfio/migration.c
+++ b/hw/vfio/migration.c
@@ -806,7 +806,7 @@ static int vfio_migration_init(VFIODevice *vbasedev,
}
vbasedev->migration = g_new0(VFIOMigration, 1);
- vbasedev->migration->device_state = VFIO_DEVICE_STATE_RUNNING;
+ vbasedev->migration->device_state = VFIO_DEVICE_STATE_V1_RUNNING;
vbasedev->migration->vm_running = runstate_is_running();
ret = vfio_region_setup(obj, vbasedev, &vbasedev->migration->region,
diff --git a/hw/xen/meson.build b/hw/xen/meson.build
index 08dc1f6..ae0ace3 100644
--- a/hw/xen/meson.build
+++ b/hw/xen/meson.build
@@ -18,7 +18,7 @@ if have_xen_pci_passthrough
'xen_pt_msi.c',
))
else
- xen_specific_ss.add('xen_pt_stub.c')
+ xen_specific_ss.add(files('xen_pt_stub.c'))
endif
specific_ss.add_all(when: ['CONFIG_XEN', xen], if_true: xen_specific_ss)