Merge tag 'misc-next-20231128' of https://github.com/philmd/qemu into staging
Misc fixes for 8.2
* buildsys: Invoke bash via 'env' (Samuel)
* doc: Fix example in s390-cpu-topology.rst (Zhao)
* HW: Fix AVR ATMega reset stack (Gihun) and VT82C686 IRQ routing (Zoltan)
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmVl7MUACgkQ4+MsLN6t
# wN4nsQ//U7/GGrMaNJF369pC0UfC0dfD39RoD9jmmrWUQB17baMvXo+BMBcELX0Q
# BtgRjIYwnywnVZlB11JL5Ql9ykSRqd7VeqnZfH//GqQO+ySF7jl6ekNT6YNjUbWu
# iF9bU3o0/LAVl/3pe9LQ4q/yOjzERA5o4JKYviHZYcWE811/5lBNgER4iPyCz6a8
# aGI3S5PGmq6a9x5266jkY2WWldDy7D1ujkuvxxc4tgnmbBjL21soJ/oRLOBjGTNl
# hCRfDTEiFZm7OxjV7oB03Nr3EGGStGdy0aPhhtFwzZxQ9yV7d2DLsbYGgwzZYkKQ
# 9v4DtGqYyvDA7LBmfxOrnzL0WXgN4xO3qekLqHDtChDzFFEYwtHvH0duPUiQv1Yu
# qHyOsfB58rKzWHeo0ACEjMWGdD1opCXCeoJlEf/saiQ5EgyBwph/z2mWYN4yak5H
# Zu3xF15BcnyavC6sVeuE+rT574dhCzOtH8Vf3WVwqfL5D5cyCjHlmPSAXXMqBkmh
# BMOD8O210n6IdzuuOQ038t3yGvIc0YysOmQgfLjRYlZa884q3wExgrufH+NYbGMj
# bFthPjLKgHm+q4k2mH65G98xwXQFT6rdHanw2iEJcPJbhhk9SNWYgaQ0r0Oi2Pfd
# zCQ22F1j9UqGcqKh+8tzAfjayRyQUJtgizPXEWanADkpIDYxrRk=
# =323/
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 28 Nov 2023 08:36:05 EST
# gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE
* tag 'misc-next-20231128' of https://github.com/philmd/qemu:
docs/s390: Fix wrong command example in s390-cpu-topology.rst
hw/avr/atmega: Fix wrong initial value of stack pointer
hw/audio/via-ac97: Route interrupts using via_isa_set_irq()
hw/isa/vt82c686: Route PIRQ inputs using via_isa_set_irq()
hw/usb/vt82c686-uhci-pci: Use ISA instead of PCI interrupts
hw/isa/vt82c686: Bring back via_isa_set_irq()
target/hexagon/idef-parser/prepare: use env to invoke bash
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/block/export/vhost-user-blk-server.c b/block/export/vhost-user-blk-server.c
index fe2cee3..16f4838 100644
--- a/block/export/vhost-user-blk-server.c
+++ b/block/export/vhost-user-blk-server.c
@@ -283,6 +283,7 @@
{
VuBlkExport *vexp = opaque;
+ vexp->vu_server.quiescing = true;
vhost_user_server_detach_aio_context(&vexp->vu_server);
}
@@ -291,19 +292,23 @@
{
VuBlkExport *vexp = opaque;
+ vexp->vu_server.quiescing = false;
vhost_user_server_attach_aio_context(&vexp->vu_server, vexp->export.ctx);
}
/*
- * Ensures that bdrv_drained_begin() waits until in-flight requests complete.
+ * Ensures that bdrv_drained_begin() waits until in-flight requests complete
+ * and the server->co_trip coroutine has terminated. It will be restarted in
+ * vhost_user_server_attach_aio_context().
*
* Called with vexp->export.ctx acquired.
*/
static bool vu_blk_drained_poll(void *opaque)
{
VuBlkExport *vexp = opaque;
+ VuServer *server = &vexp->vu_server;
- return vhost_user_server_has_in_flight(&vexp->vu_server);
+ return server->co_trip || vhost_user_server_has_in_flight(server);
}
static const BlockDevOps vu_blk_dev_ops = {
diff --git a/block/vmdk.c b/block/vmdk.c
index d87f6d9..d6971c7 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -351,29 +351,41 @@
BDRVVmdkState *s = bs->opaque;
int ret = 0;
- desc = g_malloc0(DESC_SIZE);
- tmp_desc = g_malloc0(DESC_SIZE);
- ret = bdrv_co_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
+ size_t desc_buf_size;
+
+ if (s->desc_offset == 0) {
+ desc_buf_size = bdrv_getlength(bs->file->bs);
+ if (desc_buf_size > 16ULL << 20) {
+ error_report("VMDK description file too big");
+ return -EFBIG;
+ }
+ } else {
+ desc_buf_size = DESC_SIZE;
+ }
+
+ desc = g_malloc0(desc_buf_size);
+ tmp_desc = g_malloc0(desc_buf_size);
+ ret = bdrv_co_pread(bs->file, s->desc_offset, desc_buf_size, desc, 0);
if (ret < 0) {
goto out;
}
- desc[DESC_SIZE - 1] = '\0';
+ desc[desc_buf_size - 1] = '\0';
tmp_str = strstr(desc, "parentCID");
if (tmp_str == NULL) {
ret = -EINVAL;
goto out;
}
- pstrcpy(tmp_desc, DESC_SIZE, tmp_str);
+ pstrcpy(tmp_desc, desc_buf_size, tmp_str);
p_name = strstr(desc, "CID");
if (p_name != NULL) {
p_name += sizeof("CID");
- snprintf(p_name, DESC_SIZE - (p_name - desc), "%" PRIx32 "\n", cid);
- pstrcat(desc, DESC_SIZE, tmp_desc);
+ snprintf(p_name, desc_buf_size - (p_name - desc), "%" PRIx32 "\n", cid);
+ pstrcat(desc, desc_buf_size, tmp_desc);
}
- ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
+ ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, desc_buf_size, desc, 0);
out:
g_free(desc);
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 91632f7..840006e 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -689,23 +689,36 @@
Property *prop = opaque;
uint32_t *alenptr = object_field_prop_ptr(obj, prop);
void **arrayptr = (void *)obj + prop->arrayoffset;
- char *elem = *arrayptr;
- GenericList *list;
- const size_t list_elem_size = sizeof(*list) + prop->arrayfieldsize;
+ char *elemptr = *arrayptr;
+ ArrayElementList *list = NULL, *elem;
+ ArrayElementList **tail = &list;
+ const size_t size = sizeof(*list);
int i;
bool ok;
- if (!visit_start_list(v, name, &list, list_elem_size, errp)) {
+ /* At least the string output visitor needs a real list */
+ for (i = 0; i < *alenptr; i++) {
+ elem = g_new0(ArrayElementList, 1);
+ elem->value = elemptr;
+ elemptr += prop->arrayfieldsize;
+
+ *tail = elem;
+ tail = &elem->next;
+ }
+
+ if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) {
return;
}
- for (i = 0; i < *alenptr; i++) {
- Property elem_prop = array_elem_prop(obj, prop, name, elem);
+ elem = list;
+ while (elem) {
+ Property elem_prop = array_elem_prop(obj, prop, name, elem->value);
prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp);
if (*errp) {
goto out_obj;
}
- elem += prop->arrayfieldsize;
+ elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem,
+ size);
}
/* visit_check_list() can only fail for input visitors */
@@ -714,6 +727,12 @@
out_obj:
visit_end_list(v, (void**) &list);
+
+ while (list) {
+ elem = list;
+ list = elem->next;
+ g_free(elem);
+ }
}
static void default_prop_array(ObjectProperty *op, const Property *prop)
diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c
index e890898..bc1505a 100644
--- a/hw/dma/xlnx_csu_dma.c
+++ b/hw/dma/xlnx_csu_dma.c
@@ -33,13 +33,13 @@
/*
* Ref: UG1087 (v1.7) February 8, 2019
- * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
+ * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers
* CSUDMA Module section
*/
REG32(ADDR, 0x0)
FIELD(ADDR, ADDR, 2, 30) /* wo */
REG32(SIZE, 0x4)
- FIELD(SIZE, SIZE, 2, 27) /* wo */
+ FIELD(SIZE, SIZE, 2, 27)
FIELD(SIZE, LAST_WORD, 0, 1) /* rw, only exists in SRC */
REG32(STATUS, 0x8)
FIELD(STATUS, DONE_CNT, 13, 3) /* wtc */
@@ -335,10 +335,14 @@
static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val)
{
XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+ uint64_t size = val & R_SIZE_SIZE_MASK;
if (s->regs[R_SIZE] != 0) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Starting DMA while already running.\n", __func__);
+ if (size || s->is_dst) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Starting DMA while already running.\n",
+ __func__);
+ }
}
if (!s->is_dst) {
@@ -346,7 +350,7 @@
}
/* Size is word aligned */
- return val & R_SIZE_SIZE_MASK;
+ return size;
}
static uint64_t size_post_read(RegisterInfo *reg, uint64_t val)
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 2d3124e..3f3c484 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -163,14 +163,19 @@
uint32_t val = pci_default_read_config(pd, addr, len);
uint8_t mode = pd->config[PCI_CLASS_PROG];
- if ((mode & 0xf) == 0xa && ranges_overlap(addr, len,
- PCI_BASE_ADDRESS_0, 16)) {
- /* BARs always read back zero in legacy mode */
- for (int i = addr; i < addr + len; i++) {
- if (i >= PCI_BASE_ADDRESS_0 && i < PCI_BASE_ADDRESS_0 + 16) {
- val &= ~(0xffULL << ((i - addr) << 3));
+ if ((mode & 0xf) == 0xa) {
+ if (ranges_overlap(addr, len, PCI_BASE_ADDRESS_0, 16)) {
+ /* BARs 0-3 always read back zero in legacy mode */
+ for (int i = addr; i < addr + len; i++) {
+ if (i >= PCI_BASE_ADDRESS_0 && i < PCI_BASE_ADDRESS_0 + 16) {
+ val &= ~(0xffULL << ((i - addr) << 3));
+ }
}
}
+ if (addr == PCI_BASE_ADDRESS_4 && val == PCI_BASE_ADDRESS_SPACE_IO) {
+ /* BAR4 default value if unset */
+ val = 0xcc00 | PCI_BASE_ADDRESS_SPACE_IO;
+ }
}
return val;
diff --git a/hw/input/stellaris_gamepad.c b/hw/input/stellaris_gamepad.c
index 06a0c0c..9dfa620 100644
--- a/hw/input/stellaris_gamepad.c
+++ b/hw/input/stellaris_gamepad.c
@@ -63,6 +63,13 @@
qemu_input_handler_register(dev, &stellaris_gamepad_handler);
}
+static void stellaris_gamepad_finalize(Object *obj)
+{
+ StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
+
+ g_free(s->keycodes);
+}
+
static void stellaris_gamepad_reset_enter(Object *obj, ResetType type)
{
StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
@@ -92,6 +99,7 @@
.name = TYPE_STELLARIS_GAMEPAD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StellarisGamepad),
+ .instance_finalize = stellaris_gamepad_finalize,
.class_init = stellaris_gamepad_class_init,
},
};
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
index b3b42a7..fe5034d 100644
--- a/hw/misc/mps2-scc.c
+++ b/hw/misc/mps2-scc.c
@@ -329,6 +329,13 @@
s->oscclk = g_new0(uint32_t, s->num_oscclk);
}
+static void mps2_scc_finalize(Object *obj)
+{
+ MPS2SCC *s = MPS2_SCC(obj);
+
+ g_free(s->oscclk_reset);
+}
+
static const VMStateDescription mps2_scc_vmstate = {
.name = "mps2-scc",
.version_id = 3,
@@ -385,6 +392,7 @@
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MPS2SCC),
.instance_init = mps2_scc_init,
+ .instance_finalize = mps2_scc_finalize,
.class_init = mps2_scc_class_init,
};
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
index e93e6c5..f60e480 100644
--- a/hw/net/can/xlnx-zynqmp-can.c
+++ b/hw/net/can/xlnx-zynqmp-can.c
@@ -434,6 +434,52 @@
return true;
}
+static void read_tx_frame(XlnxZynqMPCANState *s, Fifo32 *fifo, uint32_t *data)
+{
+ unsigned used = fifo32_num_used(fifo);
+ bool is_txhpb = fifo == &s->txhpb_fifo;
+
+ assert(used > 0);
+ used %= CAN_FRAME_SIZE;
+
+ /*
+ * Frame Message Format
+ *
+ * Each frame includes four words (16 bytes). Software must read and write
+ * all four words regardless of the actual number of data bytes and valid
+ * fields in the message.
+ * If software misbehave (not writing all four words), we use the previous
+ * registers content to initialize each missing word.
+ *
+ * If used is 1 then ID, DLC and DATA1 are missing.
+ * if used is 2 then ID and DLC are missing.
+ * if used is 3 then only ID is missing.
+ */
+ if (used > 0) {
+ data[0] = s->regs[is_txhpb ? R_TXHPB_ID : R_TXFIFO_ID];
+ } else {
+ data[0] = fifo32_pop(fifo);
+ }
+ if (used == 1 || used == 2) {
+ data[1] = s->regs[is_txhpb ? R_TXHPB_DLC : R_TXFIFO_DLC];
+ } else {
+ data[1] = fifo32_pop(fifo);
+ }
+ if (used == 1) {
+ data[2] = s->regs[is_txhpb ? R_TXHPB_DATA1 : R_TXFIFO_DATA1];
+ } else {
+ data[2] = fifo32_pop(fifo);
+ }
+ /* DATA2 triggered the transfer thus is always available */
+ data[3] = fifo32_pop(fifo);
+
+ if (used) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Incomplete CAN frame (only %u/%u slots used)\n",
+ TYPE_XLNX_ZYNQMP_CAN, used, CAN_FRAME_SIZE);
+ }
+}
+
static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
{
qemu_can_frame frame;
@@ -451,9 +497,7 @@
}
while (!fifo32_is_empty(fifo)) {
- for (i = 0; i < CAN_FRAME_SIZE; i++) {
- data[i] = fifo32_pop(fifo);
- }
+ read_tx_frame(s, fifo, data);
if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
/*
@@ -734,14 +778,18 @@
}
}
-static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
+static uint64_t can_rxfifo_post_read_id(RegisterInfo *reg, uint64_t val)
{
XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
+ unsigned used = fifo32_num_used(&s->rx_fifo);
- if (!fifo32_is_empty(&s->rx_fifo)) {
- val = fifo32_pop(&s->rx_fifo);
- } else {
+ if (used < CAN_FRAME_SIZE) {
ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
+ } else {
+ val = s->regs[R_RXFIFO_ID] = fifo32_pop(&s->rx_fifo);
+ s->regs[R_RXFIFO_DLC] = fifo32_pop(&s->rx_fifo);
+ s->regs[R_RXFIFO_DATA1] = fifo32_pop(&s->rx_fifo);
+ s->regs[R_RXFIFO_DATA2] = fifo32_pop(&s->rx_fifo);
}
can_update_irq(s);
@@ -902,14 +950,11 @@
.post_write = can_tx_post_write,
},{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
.ro = 0xffffffff,
- .post_read = can_rxfifo_pre_read,
+ .post_read = can_rxfifo_post_read_id,
},{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
.rsvd = 0xfff0000,
- .post_read = can_rxfifo_pre_read,
},{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
- .post_read = can_rxfifo_pre_read,
},{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
- .post_read = can_rxfifo_pre_read,
},{ .name = "AFR", .addr = A_AFR,
.rsvd = 0xfffffff0,
.post_write = can_filter_enable_post_write,
diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c
index 655c40b..f7b849f 100644
--- a/hw/nvram/xlnx-efuse.c
+++ b/hw/nvram/xlnx-efuse.c
@@ -224,6 +224,13 @@
}
}
+static void efuse_finalize(Object *obj)
+{
+ XlnxEFuse *s = XLNX_EFUSE(obj);
+
+ g_free(s->ro_bits);
+}
+
static void efuse_prop_set_drive(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -280,6 +287,7 @@
.name = TYPE_XLNX_EFUSE,
.parent = TYPE_DEVICE,
.instance_size = sizeof(XlnxEFuse),
+ .instance_finalize = efuse_finalize,
.class_init = efuse_class_init,
};
diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c
index beb5661..2480af3 100644
--- a/hw/nvram/xlnx-versal-efuse-ctrl.c
+++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
@@ -726,6 +726,13 @@
sysbus_init_irq(sbd, &s->irq_efuse_imr);
}
+static void efuse_ctrl_finalize(Object *obj)
+{
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
+
+ g_free(s->extra_pg0_lock_spec);
+}
+
static const VMStateDescription vmstate_efuse_ctrl = {
.name = TYPE_XLNX_VERSAL_EFUSE_CTRL,
.version_id = 1,
@@ -764,6 +771,7 @@
.instance_size = sizeof(XlnxVersalEFuseCtrl),
.class_init = efuse_ctrl_class_init,
.instance_init = efuse_ctrl_init,
+ .instance_finalize = efuse_ctrl_finalize,
};
static void efuse_ctrl_register_types(void)
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index a3955c6..0bdfad7 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -973,6 +973,8 @@
DB_PRINT_L(0, "addr=" HWADDR_FMT_plx " = %x\n", addr, (unsigned)value);
addr >>= 2;
+ assert(addr < XLNX_SPIPS_R_MAX);
+
switch (addr) {
case R_CONFIG:
mask = ~(R_CONFIG_RSVD | MAN_START_COM);
@@ -1299,7 +1301,7 @@
}
memory_region_init_io(&s->iomem, OBJECT(s), xsc->reg_ops, s,
- "spi", XLNX_ZYNQMP_SPIPS_R_MAX * 4);
+ "spi", xsc->reg_size);
sysbus_init_mmio(sbd, &s->iomem);
s->irqline = -1;
@@ -1435,6 +1437,7 @@
dc->realize = xilinx_qspips_realize;
xsc->reg_ops = &qspips_ops;
+ xsc->reg_size = XLNX_SPIPS_R_MAX * 4;
xsc->rx_fifo_size = RXFF_A_Q;
xsc->tx_fifo_size = TXFF_A_Q;
}
@@ -1450,6 +1453,7 @@
dc->vmsd = &vmstate_xilinx_spips;
xsc->reg_ops = &spips_ops;
+ xsc->reg_size = XLNX_SPIPS_R_MAX * 4;
xsc->rx_fifo_size = RXFF_A;
xsc->tx_fifo_size = TXFF_A;
}
@@ -1464,6 +1468,7 @@
dc->vmsd = &vmstate_xlnx_zynqmp_qspips;
device_class_set_props(dc, xilinx_zynqmp_qspips_properties);
xsc->reg_ops = &xlnx_zynqmp_qspips_ops;
+ xsc->reg_size = XLNX_ZYNQMP_SPIPS_R_MAX * 4;
xsc->rx_fifo_size = RXFF_A_Q;
xsc->tx_fifo_size = TXFF_A_Q;
}
diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c
index 9459fbf..cbdfe4c 100644
--- a/hw/virtio/virtio-iommu-pci.c
+++ b/hw/virtio/virtio-iommu-pci.c
@@ -95,10 +95,18 @@
TYPE_VIRTIO_IOMMU);
}
+static void virtio_iommu_pci_instance_finalize(Object *obj)
+{
+ VirtIOIOMMUPCI *dev = VIRTIO_IOMMU_PCI(obj);
+
+ g_free(dev->vdev.prop_resv_regions);
+}
+
static const VirtioPCIDeviceTypeInfo virtio_iommu_pci_info = {
.generic_name = TYPE_VIRTIO_IOMMU_PCI,
.instance_size = sizeof(VirtIOIOMMUPCI),
.instance_init = virtio_iommu_pci_instance_init,
+ .instance_finalize = virtio_iommu_pci_instance_finalize,
.class_init = virtio_iommu_pci_class_init,
};
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 205dbf2..e433879 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -2391,6 +2391,7 @@
.parent = t->parent ? t->parent : TYPE_VIRTIO_PCI,
.instance_size = t->instance_size,
.instance_init = t->instance_init,
+ .instance_finalize = t->instance_finalize,
.class_size = t->class_size,
.abstract = true,
.interfaces = t->interfaces,
diff --git a/include/hw/misc/xlnx-versal-cframe-reg.h b/include/hw/misc/xlnx-versal-cframe-reg.h
index a14fbd7..0091505 100644
--- a/include/hw/misc/xlnx-versal-cframe-reg.h
+++ b/include/hw/misc/xlnx-versal-cframe-reg.h
@@ -12,7 +12,7 @@
* https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
*
* [2] Versal ACAP Register Reference,
- * https://www.xilinx.com/htmldocs/registers/am012/am012-versal-register-reference.html
+ * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/CFRAME_REG-Module
*/
#ifndef HW_MISC_XLNX_VERSAL_CFRAME_REG_H
#define HW_MISC_XLNX_VERSAL_CFRAME_REG_H
diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h
index 86fb841..be62bab 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -12,7 +12,7 @@
* https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
*
* [2] Versal ACAP Register Reference,
- * https://www.xilinx.com/htmldocs/registers/am012/am012-versal-register-reference.html
+ * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/CFU_CSR-Module
*/
#ifndef HW_MISC_XLNX_VERSAL_CFU_APB_H
#define HW_MISC_XLNX_VERSAL_CFU_APB_H
diff --git a/include/hw/misc/xlnx-versal-pmc-iou-slcr.h b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h
index f7d24c9..0c4a4fd 100644
--- a/include/hw/misc/xlnx-versal-pmc-iou-slcr.h
+++ b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h
@@ -34,7 +34,7 @@
* https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
*
* [2] Versal ACAP Register Reference,
- * https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___pmc_iop_slcr.html
+ * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/PMC_IOP_SLCR-Module
*
* QEMU interface:
* + sysbus MMIO region 0: MemoryRegion for the device's registers
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
index 1386d5a..7a754bf 100644
--- a/include/hw/ssi/xilinx_spips.h
+++ b/include/hw/ssi/xilinx_spips.h
@@ -33,7 +33,9 @@
typedef struct XilinxSPIPS XilinxSPIPS;
+/* For SPIPS, QSPIPS. */
#define XLNX_SPIPS_R_MAX (0x100 / 4)
+/* For ZYNQMP_QSPIPS. */
#define XLNX_ZYNQMP_SPIPS_R_MAX (0x200 / 4)
/* Bite off 4k chunks at a time */
@@ -125,6 +127,7 @@
SysBusDeviceClass parent_class;
const MemoryRegionOps *reg_ops;
+ uint64_t reg_size;
uint32_t rx_fifo_size;
uint32_t tx_fifo_size;
diff --git a/include/hw/ssi/xlnx-versal-ospi.h b/include/hw/ssi/xlnx-versal-ospi.h
index 5d131d3..4ac975a 100644
--- a/include/hw/ssi/xlnx-versal-ospi.h
+++ b/include/hw/ssi/xlnx-versal-ospi.h
@@ -34,7 +34,7 @@
* https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
*
* [2] Versal ACAP Register Reference,
- * https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___ospi.html
+ * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/OSPI-Module
*
*
* QEMU interface:
diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
index 5a3f182..59d8801 100644
--- a/include/hw/virtio/virtio-pci.h
+++ b/include/hw/virtio/virtio-pci.h
@@ -246,6 +246,7 @@
size_t instance_size;
size_t class_size;
void (*instance_init)(Object *obj);
+ void (*instance_finalize)(Object *obj);
void (*class_init)(ObjectClass *klass, void *data);
InterfaceInfo *interfaces;
} VirtioPCIDeviceTypeInfo;
diff --git a/include/qemu/vhost-user-server.h b/include/qemu/vhost-user-server.h
index 64ad701..0417ec0 100644
--- a/include/qemu/vhost-user-server.h
+++ b/include/qemu/vhost-user-server.h
@@ -45,6 +45,7 @@
/* Protected by ctx lock */
bool in_qio_channel_yield;
bool wait_idle;
+ bool quiescing;
VuDev vu_dev;
QIOChannel *ioc; /* The I/O channel with the client */
QIOChannelSocket *sioc; /* The underlying data channel with the client */
diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin
index 8d1dc0d..48c3707 100644
--- a/pc-bios/bios-256k.bin
+++ b/pc-bios/bios-256k.bin
Binary files differ
diff --git a/pc-bios/bios-microvm.bin b/pc-bios/bios-microvm.bin
index 1a96d55..c98351e 100644
--- a/pc-bios/bios-microvm.bin
+++ b/pc-bios/bios-microvm.bin
Binary files differ
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index a4e7fef..7e2d062 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/pc-bios/vgabios-ati.bin b/pc-bios/vgabios-ati.bin
index 27b785e3..e10cd26 100644
--- a/pc-bios/vgabios-ati.bin
+++ b/pc-bios/vgabios-ati.bin
Binary files differ
diff --git a/pc-bios/vgabios-bochs-display.bin b/pc-bios/vgabios-bochs-display.bin
index 598a3db..416036d 100644
--- a/pc-bios/vgabios-bochs-display.bin
+++ b/pc-bios/vgabios-bochs-display.bin
Binary files differ
diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin
index 2b02029..4ffaa43 100644
--- a/pc-bios/vgabios-cirrus.bin
+++ b/pc-bios/vgabios-cirrus.bin
Binary files differ
diff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin
index ebd6abe..1b7a383 100644
--- a/pc-bios/vgabios-qxl.bin
+++ b/pc-bios/vgabios-qxl.bin
Binary files differ
diff --git a/pc-bios/vgabios-ramfb.bin b/pc-bios/vgabios-ramfb.bin
index ab2f20d..dba6cb8 100644
--- a/pc-bios/vgabios-ramfb.bin
+++ b/pc-bios/vgabios-ramfb.bin
Binary files differ
diff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin
index 84588dd..0d541c5 100644
--- a/pc-bios/vgabios-stdvga.bin
+++ b/pc-bios/vgabios-stdvga.bin
Binary files differ
diff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin
index 41308e0..2ce3557 100644
--- a/pc-bios/vgabios-virtio.bin
+++ b/pc-bios/vgabios-virtio.bin
Binary files differ
diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin
index d382d0a..b7cab15 100644
--- a/pc-bios/vgabios-vmware.bin
+++ b/pc-bios/vgabios-vmware.bin
Binary files differ
diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin
index 62799d0..ee748f6 100644
--- a/pc-bios/vgabios.bin
+++ b/pc-bios/vgabios.bin
Binary files differ
diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
index 71ddc92..c0cb72d 100644
--- a/qapi/string-output-visitor.c
+++ b/qapi/string-output-visitor.c
@@ -74,11 +74,27 @@
static void string_output_set(StringOutputVisitor *sov, char *string)
{
- if (sov->string) {
- g_string_free(sov->string, true);
+ switch (sov->list_mode) {
+ case LM_STARTED:
+ sov->list_mode = LM_IN_PROGRESS;
+ /* fall through */
+ case LM_NONE:
+ if (sov->string) {
+ g_string_free(sov->string, true);
+ }
+ sov->string = g_string_new(string);
+ g_free(string);
+ break;
+
+ case LM_IN_PROGRESS:
+ case LM_END:
+ g_string_append(sov->string, ", ");
+ g_string_append(sov->string, string);
+ break;
+
+ default:
+ abort();
}
- sov->string = g_string_new(string);
- g_free(string);
}
static void string_output_append(StringOutputVisitor *sov, int64_t a)
diff --git a/roms/seabios b/roms/seabios
index 1e1da7a..a6ed6b7 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 1e1da7a963007d03a4e0e9a9e0ff17990bb1608d
+Subproject commit a6ed6b701f0a57db0569ab98b0661c12a6ec3ff8
diff --git a/target/arm/helper.c b/target/arm/helper.c
index ff19709..2746d3f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2646,11 +2646,28 @@
gt->ctl = deposit32(gt->ctl, 2, 1, istatus);
if (istatus) {
- /* Next transition is when count rolls back over to zero */
- nexttick = UINT64_MAX;
+ /*
+ * Next transition is when (count - offset) rolls back over to 0.
+ * If offset > count then this is when count == offset;
+ * if offset <= count then this is when count == offset + 2^64
+ * For the latter case we set nexttick to an "as far in future
+ * as possible" value and let the code below handle it.
+ */
+ if (offset > count) {
+ nexttick = offset;
+ } else {
+ nexttick = UINT64_MAX;
+ }
} else {
- /* Next transition is when we hit cval */
- nexttick = gt->cval + offset;
+ /*
+ * Next transition is when (count - offset) == cval, i.e.
+ * when count == (cval + offset).
+ * If that would overflow, then again we set up the next interrupt
+ * for "as far in the future as possible" for the code below.
+ */
+ if (uadd64_overflow(gt->cval, offset, &nexttick)) {
+ nexttick = UINT64_MAX;
+ }
}
/*
* Note that the desired next expiry time might be beyond the
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
index 5d34755..95454b5 100644
--- a/target/arm/syndrome.h
+++ b/target/arm/syndrome.h
@@ -216,7 +216,7 @@
static inline uint32_t syn_sve_access_trap(void)
{
- return EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT;
+ return (EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL;
}
/*
@@ -242,12 +242,12 @@
static inline uint32_t syn_pactrap(void)
{
- return EC_PACTRAP << ARM_EL_EC_SHIFT;
+ return (EC_PACTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL;
}
static inline uint32_t syn_btitrap(int btype)
{
- return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype;
+ return (EC_BTITRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL | btype;
}
static inline uint32_t syn_bxjtrap(int cv, int cond, int rm)
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index 2bcb1f7..0634c7b 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -84,6 +84,8 @@
echo "=== Testing big twoGbMaxExtentFlat ==="
_make_test_img -o "subformat=twoGbMaxExtentFlat" 1000G
_img_info --format-specific | _filter_img_info --format-specific
+$QEMU_IO -c "write 990G 512 -P 89" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read 990G 512 -P 89" "$TEST_IMG" | _filter_qemu_io
_cleanup_test_img
echo
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 2b83c0c..275ee7c 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -2032,6 +2032,10 @@
virtual size: 2147483648
filename: TEST_DIR/t-f500.IMGFMT
format: FLAT
+wrote 512/512 bytes at offset 1063004405760
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 1063004405760
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Testing malformed VMFS extent description line ===
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Invalid extent line: RW 12582912 VMFS "dummy.IMGFMT" 1
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
index e67ebd2..3ff38f2 100644
--- a/tests/qemu-iotests/testenv.py
+++ b/tests/qemu-iotests/testenv.py
@@ -40,7 +40,7 @@ def get_default_machine(qemu_prog: str) -> str:
machines = outp.split('\n')
try:
- default_machine = next(m for m in machines if m.endswith(' (default)'))
+ default_machine = next(m for m in machines if ' (default)' in m)
except StopIteration:
return ''
default_machine = default_machine.split(' ', 1)[0]
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index 77c5018..4b03ef6 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -45,7 +45,8 @@
# Running
QEMU_BASE_MACHINE=-M virt -cpu max -display none
-QEMU_OPTS+=$(QEMU_BASE_MACHINE) -semihosting-config enable=on,target=native,chardev=output -kernel
+QEMU_BASE_ARGS=-semihosting-config enable=on,target=native,chardev=output
+QEMU_OPTS+=$(QEMU_BASE_MACHINE) $(QEMU_BASE_ARGS) -kernel
# console test is manual only
QEMU_SEMIHOST=-serial none -chardev stdio,mux=on,id=stdio0 -semihosting-config enable=on,chardev=stdio0 -mon chardev=stdio0,mode=readline
@@ -56,6 +57,10 @@
run-plugin-semiconsole-with-%: semiconsole
$(call skip-test, $<, "MANUAL ONLY")
+# vtimer test needs EL2
+QEMU_EL2_MACHINE=-machine virt,virtualization=on,gic-version=2 -cpu cortex-a57 -smp 4
+run-vtimer: QEMU_OPTS=$(QEMU_EL2_MACHINE) $(QEMU_BASE_ARGS) -kernel
+
# Simple Record/Replay Test
.PHONY: memory-record
run-memory-record: memory-record memory
diff --git a/tests/tcg/aarch64/system/vtimer.c b/tests/tcg/aarch64/system/vtimer.c
new file mode 100644
index 0000000..42f2f77
--- /dev/null
+++ b/tests/tcg/aarch64/system/vtimer.c
@@ -0,0 +1,48 @@
+/*
+ * Simple Virtual Timer Test
+ *
+ * Copyright (c) 2020 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <inttypes.h>
+#include <minilib.h>
+
+/* grabbed from Linux */
+#define __stringify_1(x...) #x
+#define __stringify(x...) __stringify_1(x)
+
+#define read_sysreg(r) ({ \
+ uint64_t __val; \
+ asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \
+ __val; \
+})
+
+#define write_sysreg(r, v) do { \
+ uint64_t __val = (uint64_t)(v); \
+ asm volatile("msr " __stringify(r) ", %x0" \
+ : : "rZ" (__val)); \
+} while (0)
+
+int main(void)
+{
+ int i;
+
+ ml_printf("VTimer Test\n");
+
+ write_sysreg(cntvoff_el2, 1);
+ write_sysreg(cntv_cval_el0, -1);
+ write_sysreg(cntv_ctl_el0, 1);
+
+ ml_printf("cntvoff_el2=%lx\n", read_sysreg(cntvoff_el2));
+ ml_printf("cntv_cval_el0=%lx\n", read_sysreg(cntv_cval_el0));
+ ml_printf("cntv_ctl_el0=%lx\n", read_sysreg(cntv_ctl_el0));
+
+ /* Now read cval a few times */
+ for (i = 0; i < 10; i++) {
+ ml_printf("%d: cntv_cval_el0=%lx\n", i, read_sysreg(cntv_cval_el0));
+ }
+
+ return 0;
+}
diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c
index 5ccc6d2..a9a48ff 100644
--- a/util/vhost-user-server.c
+++ b/util/vhost-user-server.c
@@ -132,8 +132,7 @@
qio_channel_yield(ioc, G_IO_IN);
server->in_qio_channel_yield = false;
} else {
- /* Wait until attached to an AioContext again */
- qemu_coroutine_yield();
+ return false;
}
continue;
} else {
@@ -201,8 +200,16 @@
VuServer *server = opaque;
VuDev *vu_dev = &server->vu_dev;
- while (!vu_dev->broken && vu_dispatch(vu_dev)) {
- /* Keep running */
+ while (!vu_dev->broken) {
+ if (server->quiescing) {
+ server->co_trip = NULL;
+ aio_wait_kick();
+ return;
+ }
+ /* vu_dispatch() returns false if server->ctx went away */
+ if (!vu_dispatch(vu_dev) && server->ctx) {
+ break;
+ }
}
if (vhost_user_server_has_in_flight(server)) {
@@ -353,8 +360,7 @@
qio_channel_set_follow_coroutine_ctx(server->ioc, true);
- server->co_trip = qemu_coroutine_create(vu_client_trip, server);
-
+ /* Attaching the AioContext starts the vu_client_trip coroutine */
aio_context_acquire(server->ctx);
vhost_user_server_attach_aio_context(server, server->ctx);
aio_context_release(server->ctx);
@@ -413,8 +419,25 @@
NULL, NULL, vu_fd_watch);
}
- assert(!server->in_qio_channel_yield);
- aio_co_schedule(ctx, server->co_trip);
+ if (server->co_trip) {
+ /*
+ * The caller didn't fully shut down co_trip (this can happen on
+ * non-polling drains like in bdrv_graph_wrlock()). This is okay as long
+ * as it no longer tries to shut it down and we're guaranteed to still
+ * be in the same AioContext as before.
+ *
+ * co_ctx can still be NULL if we get multiple calls and only just
+ * scheduled a new coroutine in the else branch.
+ */
+ AioContext *co_ctx = qemu_coroutine_get_aio_context(server->co_trip);
+
+ assert(!server->quiescing);
+ assert(!co_ctx || co_ctx == ctx);
+ } else {
+ server->co_trip = qemu_coroutine_create(vu_client_trip, server);
+ assert(!server->in_qio_channel_yield);
+ aio_co_schedule(ctx, server->co_trip);
+ }
}
/* Called with server->ctx acquired */