From 593a1cdd66ac83c1cefdd4cc5dd6338006fc202c Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Mon, 9 Jul 2018 19:02:36 +0200 Subject: sm501: Update screen on frame buffer address change When the guest changes the address of the frame buffer we need to refresh the screen to correctly display the new content. This fixes display update problems when changing between screens on AmigaOS. Signed-off-by: BALATON Zoltan Signed-off-by: David Gibson --- hw/display/sm501.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 3661a89f60..9ab29d35dd 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1235,6 +1235,7 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, if (value & 0x8000000) { qemu_log_mask(LOG_UNIMP, "Panel external memory not supported\n"); } + s->do_full_update = true; break; case SM501_DC_PANEL_FB_OFFSET: s->dc_panel_fb_offset = value & 0x3FF03FF0; @@ -1298,6 +1299,7 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, if (value & 0x8000000) { qemu_log_mask(LOG_UNIMP, "CRT external memory not supported\n"); } + s->do_full_update = true; break; case SM501_DC_CRT_FB_OFFSET: s->dc_crt_fb_offset = value & 0x3FF03FF0; -- cgit v1.2.3 From ccc2cef8b3f1dedd059924eb8ec1a87eff8ef607 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 10 Jul 2018 11:40:52 +1000 Subject: spapr: Correct inverted test in spapr_pc_dimm_node() This function was introduced between v2.11 and v2.12 to replace obsolete ways of specifying the NUMA nodes for DIMMs. It's used to find the correct node for an LMB, by locating which DIMM object it lies within. Unfortunately, one of the checks is inverted, so we check whether the address is less than two different things, rather than actually checking a range. This introduced a regression, meaning that after a reboot qemu will advertise incorrect node information for memory to the guest. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Reviewed-by: Igor Mammedov --- hw/ppc/spapr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3f5e1d3ec2..421b2dd09b 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -665,7 +665,7 @@ static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr) if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) { PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data; - if (pcdimm_info->addr >= addr && + if (addr >= pcdimm_info->addr && addr < (pcdimm_info->addr + pcdimm_info->size)) { return pcdimm_info->node; } -- cgit v1.2.3 From b585395b655a6c1f9d9ebf1f0890e76d0708eed6 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Thu, 12 Jul 2018 12:01:49 +0200 Subject: ppc/xics: fix ICP reset path Recent cleanup in commit a028dd423ee6 dropped the ICPStateClass::reset handler. It is now up to child ICP classes to call the DeviceClass::reset handler of the parent class, thanks to device_class_set_parent_reset(). This is a better object programming pattern, but unfortunately it causes QEMU to crash during CPU hotplug: (qemu) device_add host-spapr-cpu-core,id=core1,core-id=1 Segmentation fault (core dumped) When the hotplug path tries to reset the ICP device, we end up calling: static void icp_kvm_reset(DeviceState *dev) { ICPStateClass *icpc = ICP_GET_CLASS(dev); icpc->parent_reset(dev); but icpc->parent_reset is NULL... This happens because icp_kvm_class_init() calls: device_class_set_parent_reset(dc, icp_kvm_reset, &icpc->parent_reset); but dc->reset, ie, DeviceClass::reset for the TYPE_ICP type, is itself NULL. This patch hence sets DeviceClass::reset for the TYPE_ICP type to point to icp_reset(). It then registers a reset handler that calls DeviceClass::reset. If the ICP subtype has configured its own reset handler with device_class_set_parent_reset(), this ensures it will be called first and it can then call ICPStateClass::parent_reset safely. This fixes the reset path for the TYPE_KVM_ICP type, which is the only subtype that defines its own reset function. Reported-by: Satheesh Rajendran Suggested-by: David Gibson Fixes: a028dd423ee6dfd091a8c63028240832bf10f671 Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- hw/intc/xics.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/hw/intc/xics.c b/hw/intc/xics.c index b9f1a3c972..c90c893228 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -291,7 +291,7 @@ static const VMStateDescription vmstate_icp_server = { }, }; -static void icp_reset(void *dev) +static void icp_reset(DeviceState *dev) { ICPState *icp = ICP(dev); @@ -303,6 +303,13 @@ static void icp_reset(void *dev) qemu_set_irq(icp->output, 0); } +static void icp_reset_handler(void *dev) +{ + DeviceClass *dc = DEVICE_GET_CLASS(dev); + + dc->reset(dev); +} + static void icp_realize(DeviceState *dev, Error **errp) { ICPState *icp = ICP(dev); @@ -345,7 +352,7 @@ static void icp_realize(DeviceState *dev, Error **errp) return; } - qemu_register_reset(icp_reset, dev); + qemu_register_reset(icp_reset_handler, dev); vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp); } @@ -354,7 +361,7 @@ static void icp_unrealize(DeviceState *dev, Error **errp) ICPState *icp = ICP(dev); vmstate_unregister(NULL, &vmstate_icp_server, icp); - qemu_unregister_reset(icp_reset, dev); + qemu_unregister_reset(icp_reset_handler, dev); } static void icp_class_init(ObjectClass *klass, void *data) @@ -363,6 +370,7 @@ static void icp_class_init(ObjectClass *klass, void *data) dc->realize = icp_realize; dc->unrealize = icp_unrealize; + dc->reset = icp_reset; } static const TypeInfo icp_info = { -- cgit v1.2.3 From fd8e3381a00feb1e9878f6a3e2de11295f041f67 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 12 Jul 2018 14:00:52 -0700 Subject: etsec: fix IRQ (un)masking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interrupt conditions occurring while masked are not being signaled when later unmasked. The fix is to raise/lower IRQs when IMASK is changed. To avoid problems like this in future, consolidate IRQ pin update logic in one function. Also fix probable typo "IEVENT_TXF | IEVENT_TXF", and update IRQ pins on reset. Signed-off-by: Michael Davidsaver Reviewed-by: Cédric Le Goater Signed-off-by: David Gibson --- hw/net/fsl_etsec/etsec.c | 68 +++++++++++++++++++++++--------------------- hw/net/fsl_etsec/etsec.h | 2 ++ hw/net/fsl_etsec/registers.h | 10 +++++++ hw/net/fsl_etsec/rings.c | 12 +------- 4 files changed, 49 insertions(+), 43 deletions(-) diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c index 9da1932970..0b66274ce3 100644 --- a/hw/net/fsl_etsec/etsec.c +++ b/hw/net/fsl_etsec/etsec.c @@ -49,6 +49,28 @@ static const int debug_etsec; } \ } while (0) +/* call after any change to IEVENT or IMASK */ +void etsec_update_irq(eTSEC *etsec) +{ + uint32_t ievent = etsec->regs[IEVENT].value; + uint32_t imask = etsec->regs[IMASK].value; + uint32_t active = ievent & imask; + + int tx = !!(active & IEVENT_TX_MASK); + int rx = !!(active & IEVENT_RX_MASK); + int err = !!(active & IEVENT_ERR_MASK); + + DPRINTF("%s IRQ ievent=%"PRIx32" imask=%"PRIx32" %c%c%c", + __func__, ievent, imask, + tx ? 'T' : '_', + rx ? 'R' : '_', + err ? 'E' : '_'); + + qemu_set_irq(etsec->tx_irq, tx); + qemu_set_irq(etsec->rx_irq, rx); + qemu_set_irq(etsec->err_irq, err); +} + static uint64_t etsec_read(void *opaque, hwaddr addr, unsigned size) { eTSEC *etsec = opaque; @@ -139,31 +161,6 @@ static void write_rbasex(eTSEC *etsec, etsec->regs[RBPTR0 + (reg_index - RBASE0)].value = value & ~0x7; } -static void write_ievent(eTSEC *etsec, - eTSEC_Register *reg, - uint32_t reg_index, - uint32_t value) -{ - /* Write 1 to clear */ - reg->value &= ~value; - - if (!(reg->value & (IEVENT_TXF | IEVENT_TXF))) { - qemu_irq_lower(etsec->tx_irq); - } - if (!(reg->value & (IEVENT_RXF | IEVENT_RXF))) { - qemu_irq_lower(etsec->rx_irq); - } - - if (!(reg->value & (IEVENT_MAG | IEVENT_GTSC | IEVENT_GRSC | IEVENT_TXC | - IEVENT_RXC | IEVENT_BABR | IEVENT_BABT | IEVENT_LC | - IEVENT_CRL | IEVENT_FGPI | IEVENT_FIR | IEVENT_FIQ | - IEVENT_DPE | IEVENT_PERR | IEVENT_EBERR | IEVENT_TXE | - IEVENT_XFUN | IEVENT_BSY | IEVENT_MSRO | IEVENT_MMRD | - IEVENT_MMRW))) { - qemu_irq_lower(etsec->err_irq); - } -} - static void write_dmactrl(eTSEC *etsec, eTSEC_Register *reg, uint32_t reg_index, @@ -178,9 +175,7 @@ static void write_dmactrl(eTSEC *etsec, } else { /* Graceful receive stop now */ etsec->regs[IEVENT].value |= IEVENT_GRSC; - if (etsec->regs[IMASK].value & IMASK_GRSCEN) { - qemu_irq_raise(etsec->err_irq); - } + etsec_update_irq(etsec); } } @@ -191,9 +186,7 @@ static void write_dmactrl(eTSEC *etsec, } else { /* Graceful transmit stop now */ etsec->regs[IEVENT].value |= IEVENT_GTSC; - if (etsec->regs[IMASK].value & IMASK_GTSCEN) { - qemu_irq_raise(etsec->err_irq); - } + etsec_update_irq(etsec); } } @@ -222,7 +215,16 @@ static void etsec_write(void *opaque, switch (reg_index) { case IEVENT: - write_ievent(etsec, reg, reg_index, value); + /* Write 1 to clear */ + reg->value &= ~value; + + etsec_update_irq(etsec); + break; + + case IMASK: + reg->value = value; + + etsec_update_irq(etsec); break; case DMACTRL: @@ -337,6 +339,8 @@ static void etsec_reset(DeviceState *d) MII_SR_EXTENDED_STATUS | MII_SR_100T2_HD_CAPS | MII_SR_100T2_FD_CAPS | MII_SR_10T_HD_CAPS | MII_SR_10T_FD_CAPS | MII_SR_100X_HD_CAPS | MII_SR_100X_FD_CAPS | MII_SR_100T4_CAPS; + + etsec_update_irq(etsec); } static ssize_t etsec_receive(NetClientState *nc, diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h index 30c828e241..877988572e 100644 --- a/hw/net/fsl_etsec/etsec.h +++ b/hw/net/fsl_etsec/etsec.h @@ -163,6 +163,8 @@ DeviceState *etsec_create(hwaddr base, qemu_irq rx_irq, qemu_irq err_irq); +void etsec_update_irq(eTSEC *etsec); + void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr); void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr); ssize_t etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size); diff --git a/hw/net/fsl_etsec/registers.h b/hw/net/fsl_etsec/registers.h index c4ed2b9d62..f085537ecd 100644 --- a/hw/net/fsl_etsec/registers.h +++ b/hw/net/fsl_etsec/registers.h @@ -74,6 +74,16 @@ extern const eTSEC_Register_Definition eTSEC_registers_def[]; #define IEVENT_RXC (1 << 30) #define IEVENT_BABR (1 << 31) +/* Mapping between interrupt pin and interrupt flags */ +#define IEVENT_RX_MASK (IEVENT_RXF | IEVENT_RXB) +#define IEVENT_TX_MASK (IEVENT_TXF | IEVENT_TXB) +#define IEVENT_ERR_MASK (IEVENT_MAG | IEVENT_GTSC | IEVENT_GRSC | IEVENT_TXC | \ + IEVENT_RXC | IEVENT_BABR | IEVENT_BABT | IEVENT_LC | \ + IEVENT_CRL | IEVENT_FGPI | IEVENT_FIR | IEVENT_FIQ | \ + IEVENT_DPE | IEVENT_PERR | IEVENT_EBERR | IEVENT_TXE | \ + IEVENT_XFUN | IEVENT_BSY | IEVENT_MSRO | IEVENT_MMRD | \ + IEVENT_MMRW) + #define IMASK_RXFEN (1 << 7) #define IMASK_GRSCEN (1 << 8) #define IMASK_RXBEN (1 << 15) diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c index d0f93eebfc..337a55fc95 100644 --- a/hw/net/fsl_etsec/rings.c +++ b/hw/net/fsl_etsec/rings.c @@ -152,17 +152,7 @@ static void ievent_set(eTSEC *etsec, { etsec->regs[IEVENT].value |= flags; - if ((flags & IEVENT_TXB && etsec->regs[IMASK].value & IMASK_TXBEN) - || (flags & IEVENT_TXF && etsec->regs[IMASK].value & IMASK_TXFEN)) { - qemu_irq_raise(etsec->tx_irq); - RING_DEBUG("%s Raise Tx IRQ\n", __func__); - } - - if ((flags & IEVENT_RXB && etsec->regs[IMASK].value & IMASK_RXBEN) - || (flags & IEVENT_RXF && etsec->regs[IMASK].value & IMASK_RXFEN)) { - qemu_irq_raise(etsec->rx_irq); - RING_DEBUG("%s Raise Rx IRQ\n", __func__); - } + etsec_update_irq(etsec); } static void tx_padding_and_crc(eTSEC *etsec, uint32_t min_frame_len) -- cgit v1.2.3 From 3cc702d6aad603fdbe0c83db0bf803e450a6d0b8 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sun, 15 Jul 2018 22:47:26 +0200 Subject: sam460ex: Correct use after free error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 51b0d834c changed error handling to report file name in error message but forgot to move freeing it after usage. Noticed by Coverity. Fixes: CID 1394217 Reported-by: Paolo Bonzini Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/ppc/sam460ex.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index e2b7028843..0999efcc1e 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -269,11 +269,12 @@ static int sam460ex_load_device_tree(hwaddr addr, exit(1); } fdt = load_device_tree(filename, &fdt_size); - g_free(filename); if (!fdt) { error_report("Couldn't load dtb file `%s'", filename); + g_free(filename); exit(1); } + g_free(filename); /* Manipulate device tree in memory. */ -- cgit v1.2.3 From 6730df0514d3aec35e646ff9833fbe8b05fd0776 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sun, 15 Jul 2018 22:59:21 +0200 Subject: sm501: Fix warning about unreachable code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coverity warned that the false arm of conditional expression is unreachable when it is inside an if with the same condition. Remove the unreachable code to avoid the warning. Fixes: CID 1394215 Reported-by: Paolo Bonzini Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/display/sm501.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 9ab29d35dd..874260a143 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1024,7 +1024,7 @@ static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value, if (res) { SM501_DPRINTF("sm501 i2c : transfer failed" " i=%d, res=%d\n", i, res); - s->i2c_status |= (res ? SM501_I2C_STATUS_ERROR : 0); + s->i2c_status |= SM501_I2C_STATUS_ERROR; return; } } -- cgit v1.2.3