2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
8.1.91
8.1.92
6 changes: 3 additions & 3 deletions docs/devel/s390-cpu-topology.rst
Expand Up @@ -15,7 +15,7 @@ have default values:
-smp 1,drawers=3,books=3,sockets=2,cores=2,maxcpus=36 \
-device z14-s390x-cpu,core-id=19,entitlement=high \
-device z14-s390x-cpu,core-id=11,entitlement=low \
-device z14-s390x-cpu,core-id=112,entitlement=high \
-device z14-s390x-cpu,core-id=12,entitlement=high \
...
Additions to query-cpus-fast
Expand Down Expand Up @@ -78,15 +78,15 @@ modifiers for all configured vCPUs.
"dedicated": true,
"thread-id": 537005,
"props": {
"core-id": 112,
"core-id": 12,
"socket-id": 0,
"drawer-id": 3,
"book-id": 2
},
"cpu-state": "operating",
"entitlement": "high",
"qom-path": "/machine/peripheral-anon/device[2]",
"cpu-index": 112,
"cpu-index": 12,
"target": "s390x"
}
]
Expand Down
8 changes: 4 additions & 4 deletions hw/audio/via-ac97.c
Expand Up @@ -211,14 +211,14 @@ static void out_cb(void *opaque, int avail)
AUD_set_active_out(s->vo, 0);
}
if (c->type & STAT_EOL) {
pci_set_irq(&s->dev, 1);
via_isa_set_irq(&s->dev, 0, 1);
}
}
if (CLEN_IS_FLAG(c)) {
c->stat |= STAT_FLAG;
c->stat |= STAT_PAUSED;
if (c->type & STAT_FLAG) {
pci_set_irq(&s->dev, 1);
via_isa_set_irq(&s->dev, 0, 1);
}
}
if (CLEN_IS_STOP(c)) {
Expand Down Expand Up @@ -305,13 +305,13 @@ static void sgd_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
if (val & STAT_EOL) {
s->aur.stat &= ~(STAT_EOL | STAT_PAUSED);
if (s->aur.type & STAT_EOL) {
pci_set_irq(&s->dev, 0);
via_isa_set_irq(&s->dev, 0, 0);
}
}
if (val & STAT_FLAG) {
s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED);
if (s->aur.type & STAT_FLAG) {
pci_set_irq(&s->dev, 0);
via_isa_set_irq(&s->dev, 0, 0);
}
}
break;
Expand Down
4 changes: 4 additions & 0 deletions hw/avr/atmega.c
Expand Up @@ -233,6 +233,10 @@ static void atmega_realize(DeviceState *dev, Error **errp)

/* CPU */
object_initialize_child(OBJECT(dev), "cpu", &s->cpu, mc->cpu_type);

object_property_set_uint(OBJECT(&s->cpu), "init-sp",
mc->io_size + mc->sram_size - 1, &error_abort);

qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
cpudev = DEVICE(&s->cpu);

Expand Down
14 changes: 9 additions & 5 deletions hw/dma/xlnx_csu_dma.c
Expand Up @@ -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 */
Expand Down Expand Up @@ -335,18 +335,22 @@ static uint64_t addr_pre_write(RegisterInfo *reg, uint64_t val)
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) {
s->r_size_last_word = !!(val & R_SIZE_LAST_WORD_MASK);
}

/* Size is word aligned */
return val & R_SIZE_SIZE_MASK;
return size;
}

static uint64_t size_post_read(RegisterInfo *reg, uint64_t val)
Expand Down
8 changes: 8 additions & 0 deletions hw/input/stellaris_gamepad.c
Expand Up @@ -63,6 +63,13 @@ static void stellaris_gamepad_realize(DeviceState *dev, Error **errp)
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);
Expand Down Expand Up @@ -92,6 +99,7 @@ static const TypeInfo stellaris_gamepad_info[] = {
.name = TYPE_STELLARIS_GAMEPAD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StellarisGamepad),
.instance_finalize = stellaris_gamepad_finalize,
.class_init = stellaris_gamepad_class_init,
},
};
Expand Down
79 changes: 52 additions & 27 deletions hw/isa/vt82c686.c
Expand Up @@ -549,6 +549,7 @@ struct ViaISAState {
PCIDevice dev;
qemu_irq cpu_intr;
qemu_irq *isa_irqs_in;
uint16_t irq_state[ISA_NUM_IRQS];
ViaSuperIOState via_sio;
MC146818RtcState rtc;
PCIIDEState ide;
Expand Down Expand Up @@ -592,15 +593,9 @@ static const TypeInfo via_isa_info = {
},
};

static void via_isa_request_i8259_irq(void *opaque, int irq, int level)
{
ViaISAState *s = opaque;
qemu_set_irq(s->cpu_intr, level);
}

static int via_isa_get_pci_irq(const ViaISAState *s, int irq_num)
static int via_isa_get_pci_irq(const ViaISAState *s, int pin)
{
switch (irq_num) {
switch (pin) {
case 0:
return s->dev.config[0x55] >> 4;
case 1:
Expand All @@ -613,29 +608,60 @@ static int via_isa_get_pci_irq(const ViaISAState *s, int irq_num)
return 0;
}

static void via_isa_set_pci_irq(void *opaque, int irq_num, int level)
void via_isa_set_irq(PCIDevice *d, int pin, int level)
{
ViaISAState *s = opaque;
PCIBus *bus = pci_get_bus(&s->dev);
int i, pic_level, pic_irq = via_isa_get_pci_irq(s, irq_num);
ViaISAState *s = VIA_ISA(pci_get_function_0(d));
uint8_t irq = d->config[PCI_INTERRUPT_LINE], max_irq = 15;
int f = PCI_FUNC(d->devfn);
uint16_t mask = BIT(f);

switch (f) {
case 0: /* PIRQ/PINT inputs */
irq = via_isa_get_pci_irq(s, pin);
f = 8 + pin; /* Use function 8-11 for PCI interrupt inputs */
break;
case 2: /* USB ports 0-1 */
case 3: /* USB ports 2-3 */
case 5: /* AC97 audio */
max_irq = 14;
break;
}

/* IRQ 0: disabled, IRQ 2,8,13: reserved */
if (!pic_irq) {
/* Keep track of the state of all sources */
if (level) {
s->irq_state[0] |= mask;
} else {
s->irq_state[0] &= ~mask;
}
if (irq == 0 || irq == 0xff) {
return; /* disabled */
}
if (unlikely(irq > max_irq || irq == 2)) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid ISA IRQ routing %d for %d",
irq, f);
return;
}
if (unlikely(pic_irq == 2 || pic_irq == 8 || pic_irq == 13)) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid ISA IRQ routing");
/* Record source state at mapped IRQ */
if (level) {
s->irq_state[irq] |= mask;
} else {
s->irq_state[irq] &= ~mask;
}
/* Make sure there are no stuck bits if mapping has changed */
s->irq_state[irq] &= s->irq_state[0];
/* ISA IRQ level is the OR of all sources routed to it */
qemu_set_irq(s->isa_irqs_in[irq], !!s->irq_state[irq]);
}

/* The pic level is the logical OR of all the PCI irqs mapped to it. */
pic_level = 0;
for (i = 0; i < PCI_NUM_PINS; i++) {
if (pic_irq == via_isa_get_pci_irq(s, i)) {
pic_level |= pci_bus_get_irq_level(bus, i);
}
}
/* Now we change the pic irq level according to the via irq mappings. */
qemu_set_irq(s->isa_irqs_in[pic_irq], pic_level);
static void via_isa_pirq(void *opaque, int pin, int level)
{
via_isa_set_irq(opaque, pin, level);
}

static void via_isa_request_i8259_irq(void *opaque, int irq, int level)
{
ViaISAState *s = opaque;
qemu_set_irq(s->cpu_intr, level);
}

static void via_isa_realize(PCIDevice *d, Error **errp)
Expand All @@ -648,6 +674,7 @@ static void via_isa_realize(PCIDevice *d, Error **errp)
int i;

qdev_init_gpio_out(dev, &s->cpu_intr, 1);
qdev_init_gpio_in_named(dev, via_isa_pirq, "pirq", PCI_NUM_PINS);
isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1);
isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(d),
errp);
Expand All @@ -661,8 +688,6 @@ static void via_isa_realize(PCIDevice *d, Error **errp)
i8254_pit_init(isa_bus, 0x40, 0, NULL);
i8257_dma_init(isa_bus, 0);

qdev_init_gpio_in_named(dev, via_isa_set_pci_irq, "pirq", PCI_NUM_PINS);

/* RTC */
qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000);
if (!qdev_realize(DEVICE(&s->rtc), BUS(isa_bus), errp)) {
Expand Down
8 changes: 8 additions & 0 deletions hw/misc/mps2-scc.c
Expand Up @@ -329,6 +329,13 @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
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,
Expand Down Expand Up @@ -385,6 +392,7 @@ static const TypeInfo mps2_scc_info = {
.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,
};

Expand Down
67 changes: 56 additions & 11 deletions hw/net/can/xlnx-zynqmp-can.c
Expand Up @@ -434,6 +434,52 @@ static bool tx_ready_check(XlnxZynqMPCANState *s)
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;
Expand All @@ -451,9 +497,7 @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
}

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)) {
/*
Expand Down Expand Up @@ -734,14 +778,18 @@ static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
}
}

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);
Expand Down Expand Up @@ -902,14 +950,11 @@ static const RegisterAccessInfo can_regs_info[] = {
.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,
Expand Down