diff options
37 files changed, 611 insertions, 296 deletions
diff --git a/arch_init.c b/arch_init.c index 9f1a174d3a..23044c1d12 100644 --- a/arch_init.c +++ b/arch_init.c @@ -739,7 +739,6 @@ static void migration_end(void) XBZRLE_cache_lock(); if (XBZRLE.cache) { cache_fini(XBZRLE.cache); - g_free(XBZRLE.cache); g_free(XBZRLE.encoded_buf); g_free(XBZRLE.current_buf); XBZRLE.cache = NULL; diff --git a/block/vdi.c b/block/vdi.c index 27737af555..1b2be1af7b 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -239,7 +239,6 @@ static void vdi_header_to_le(VdiHeader *header) cpu_to_le32s(&header->block_extra); cpu_to_le32s(&header->blocks_in_image); cpu_to_le32s(&header->blocks_allocated); - cpu_to_le32s(&header->blocks_allocated); uuid_convert(header->uuid_image); uuid_convert(header->uuid_last_snap); uuid_convert(header->uuid_link); diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 9ba47e6c63..ab54b6fc58 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -863,7 +863,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address) break; case SVGA_REG_CURSOR_Y: - ret = s->cursor.x; + ret = s->cursor.y; break; case SVGA_REG_CURSOR_ON: diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index cc90eb5110..ee60d3ff39 100644 --- a/hw/dma/xilinx_axidma.c +++ b/hw/dma/xilinx_axidma.c @@ -157,11 +157,6 @@ static inline int stream_running(struct Stream *s) return s->regs[R_DMACR] & DMACR_RUNSTOP; } -static inline int stream_halted(struct Stream *s) -{ - return s->regs[R_DMASR] & DMASR_HALTED; -} - static inline int stream_idle(struct Stream *s) { return !!(s->regs[R_DMASR] & DMASR_IDLE); diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e6369d5be6..32d163288c 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -922,9 +922,6 @@ static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 }; static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 }; -static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc }; -static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; - void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd) { static int nb_ne2k = 0; diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index b3bedde8b9..e3fa1b2fc1 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -745,11 +745,6 @@ void smbios_set_cpuid(uint32_t version, uint32_t features) field = value; \ } -#define G_FREE_UNLESS_NULL(ptr) \ - if (ptr != NULL) { \ - g_free(ptr); \ - } - void smbios_set_defaults(const char *manufacturer, const char *product, const char *version, bool legacy_mode) { @@ -758,7 +753,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product, /* drop unwanted version of command-line file blob(s) */ if (smbios_legacy) { - G_FREE_UNLESS_NULL(smbios_tables); + g_free(smbios_tables); /* in legacy mode, also complain if fields were given for types > 1 */ if (find_next_bit(have_fields_bitmap, SMBIOS_MAX_TYPE+1, 2) < SMBIOS_MAX_TYPE+1) { @@ -767,7 +762,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product, exit(1); } } else { - G_FREE_UNLESS_NULL(smbios_entries); + g_free(smbios_entries); } SMBIOS_SET_DEFAULT(type1.manufacturer, manufacturer); diff --git a/hw/input/milkymist-softusb.c b/hw/input/milkymist-softusb.c index 53ba71410d..1b4b8d441a 100644 --- a/hw/input/milkymist-softusb.c +++ b/hw/input/milkymist-softusb.c @@ -156,31 +156,6 @@ static inline void softusb_write_dmem(MilkymistSoftUsbState *s, memcpy(s->dmem_ptr + offset, buf, len); } -static inline void softusb_read_pmem(MilkymistSoftUsbState *s, - uint32_t offset, uint8_t *buf, uint32_t len) -{ - if (offset + len >= s->pmem_size) { - error_report("milkymist_softusb: read pmem out of bounds " - "at offset 0x%x, len %d", offset, len); - memset(buf, 0, len); - return; - } - - memcpy(buf, s->pmem_ptr + offset, len); -} - -static inline void softusb_write_pmem(MilkymistSoftUsbState *s, - uint32_t offset, uint8_t *buf, uint32_t len) -{ - if (offset + len >= s->pmem_size) { - error_report("milkymist_softusb: write pmem out of bounds " - "at offset 0x%x, len %d", offset, len); - return; - } - - memcpy(s->pmem_ptr + offset, buf, len); -} - static void softusb_mouse_changed(MilkymistSoftUsbState *s) { uint8_t m; diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c index 17136c9333..08e0e19c59 100644 --- a/hw/intc/openpic.c +++ b/hw/intc/openpic.c @@ -311,11 +311,6 @@ static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ) clear_bit(n_IRQ, q->queue); } -static inline int IRQ_testbit(IRQQueue *q, int n_IRQ) -{ - return test_bit(n_IRQ, q->queue); -} - static void IRQ_check(OpenPICState *opp, IRQQueue *q) { int irq = -1; diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index 46c9e612d1..b471e7a41e 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -117,6 +117,16 @@ static int flic_enqueue_irqs(void *buf, uint64_t len, return rc ? -errno : 0; } +int kvm_s390_inject_flic(struct kvm_s390_irq *irq) +{ + static KVMS390FLICState *flic; + + if (unlikely(!flic)) { + flic = KVM_S390_FLIC(s390_get_flic()); + } + return flic_enqueue_irqs(irq, sizeof(*irq), flic); +} + /** * __get_all_irqs - store all pending irqs in buffer * @flic: pointer to flic device state @@ -170,7 +180,8 @@ static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id, }; if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) { - return -ENOSYS; + /* nothing to do */ + return 0; } r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); @@ -195,7 +206,8 @@ static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id, int r; if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) { - return -ENOSYS; + /* nothing to do */ + return 0; } r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c index b352b491ac..9327c53132 100644 --- a/hw/isa/pc87312.c +++ b/hw/isa/pc87312.c @@ -86,11 +86,6 @@ static inline uint32_t get_parallel_irq(PC87312State *s) } } -static inline bool is_parallel_epp(PC87312State *s) -{ - return s->regs[REG_PTR] & PTR_EPP_MODE; -} - /* UARTs */ diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index a26861e2ae..de26609c9d 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -50,7 +50,7 @@ #define GEM_IER (0x00000028/4) /* Interrupt Enable reg */ #define GEM_IDR (0x0000002C/4) /* Interrupt Disable reg */ #define GEM_IMR (0x00000030/4) /* Interrupt Mask reg */ -#define GEM_PHYMNTNC (0x00000034/4) /* Phy Maintaince reg */ +#define GEM_PHYMNTNC (0x00000034/4) /* Phy Maintenance reg */ #define GEM_RXPAUSE (0x00000038/4) /* RX Pause Time reg */ #define GEM_TXPAUSE (0x0000003C/4) /* TX Pause Time reg */ #define GEM_TXPARTIALSF (0x00000040/4) /* TX Partial Store and Forward */ @@ -150,7 +150,7 @@ #define GEM_NWCTRL_LOCALLOOP 0x00000002 /* Local Loopback */ #define GEM_NWCFG_STRIP_FCS 0x00020000 /* Strip FCS field */ -#define GEM_NWCFG_LERR_DISC 0x00010000 /* Discard RX frames with lenth err */ +#define GEM_NWCFG_LERR_DISC 0x00010000 /* Discard RX frames with len err */ #define GEM_NWCFG_BUFF_OFST_M 0x0000C000 /* Receive buffer offset mask */ #define GEM_NWCFG_BUFF_OFST_S 14 /* Receive buffer offset shift */ #define GEM_NWCFG_UCAST_HASH 0x00000080 /* accept unicast if hash match */ @@ -397,7 +397,7 @@ static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; */ static void gem_init_register_masks(GemState *s) { - /* Mask of register bits which are read only*/ + /* Mask of register bits which are read only */ memset(&s->regs_ro[0], 0, sizeof(s->regs_ro)); s->regs_ro[GEM_NWCTRL] = 0xFFF80000; s->regs_ro[GEM_NWSTATUS] = 0xFFFFFFFF; @@ -719,7 +719,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) unsigned crc_val; /* The application wants the FCS field, which QEMU does not provide. - * We must try and caclculate one. + * We must try and calculate one. */ memcpy(rxbuf, buf, size); @@ -871,7 +871,7 @@ static void gem_transmit(GemState *s) DB_PRINT("\n"); - /* The packet we will hand off to qemu. + /* The packet we will hand off to QEMU. * Packets scattered across multiple descriptors are gathered to this * one contiguous buffer first. */ @@ -880,8 +880,10 @@ static void gem_transmit(GemState *s) /* read current descriptor */ packet_desc_addr = s->tx_desc_addr; + + DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr); cpu_physical_memory_read(packet_desc_addr, - (uint8_t *)&desc[0], sizeof(desc)); + (uint8_t *)desc, sizeof(desc)); /* Handle all descriptors owned by hardware */ while (tx_desc_get_used(desc) == 0) { @@ -911,15 +913,17 @@ static void gem_transmit(GemState *s) /* Last descriptor for this packet; hand the whole thing off */ if (tx_desc_get_last(desc)) { + unsigned desc_first[2]; + /* Modify the 1st descriptor of this packet to be owned by * the processor. */ - cpu_physical_memory_read(s->tx_desc_addr, - (uint8_t *)&desc[0], sizeof(desc)); - tx_desc_set_used(desc); - cpu_physical_memory_write(s->tx_desc_addr, - (uint8_t *)&desc[0], sizeof(desc)); - /* Advance the hardare current descriptor past this packet */ + cpu_physical_memory_read(s->tx_desc_addr, (uint8_t *)desc_first, + sizeof(desc_first)); + tx_desc_set_used(desc_first); + cpu_physical_memory_write(s->tx_desc_addr, (uint8_t *)desc_first, + sizeof(desc_first)); + /* Advance the hardware current descriptor past this packet */ if (tx_desc_get_wrap(desc)) { s->tx_desc_addr = s->regs[GEM_TXQBASE]; } else { @@ -960,8 +964,9 @@ static void gem_transmit(GemState *s) } else { packet_desc_addr += 8; } + DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr); cpu_physical_memory_read(packet_desc_addr, - (uint8_t *)&desc[0], sizeof(desc)); + (uint8_t *)desc, sizeof(desc)); } if (tx_desc_get_used(desc)) { diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c index c660e58335..0a14f6d1cd 100644 --- a/hw/net/ne2000-isa.c +++ b/hw/net/ne2000-isa.c @@ -98,6 +98,7 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data) dc->realize = isa_ne2000_realizefn; dc->props = ne2000_isa_properties; + dc->vmsd = &vmstate_isa_ne2000; set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); } diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 1497008258..6fa2723449 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -99,8 +99,8 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0) #define IOMMU_TTE_DATA_SIZE (1ULL << 61) #define IOMMU_TTE_DATA_W (1ULL << 1) -#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000 -#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000 +#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000ULL +#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL #define IOMMU_TSB_8K_OFFSET_MASK_8M 0x00000000007fe000ULL #define IOMMU_TSB_8K_OFFSET_MASK_16M 0x0000000000ffe000ULL diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 2678e4432c..e758890dcd 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -128,13 +128,11 @@ uint16_t css_build_subchannel_id(SubchDev *sch) static void css_inject_io_interrupt(SubchDev *sch) { - S390CPU *cpu = s390_cpu_addr2state(0); uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11; trace_css_io_interrupt(sch->cssid, sch->ssid, sch->schid, sch->curr_status.pmcw.intparm, isc, ""); - s390_io_interrupt(cpu, - css_build_subchannel_id(sch), + s390_io_interrupt(css_build_subchannel_id(sch), sch->schid, sch->curr_status.pmcw.intparm, isc << 27); @@ -147,7 +145,6 @@ void css_conditional_io_interrupt(SubchDev *sch) * with alert status. */ if (!(sch->curr_status.scsw.ctrl & SCSW_STCTL_STATUS_PEND)) { - S390CPU *cpu = s390_cpu_addr2state(0); uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11; trace_css_io_interrupt(sch->cssid, sch->ssid, sch->schid, @@ -157,8 +154,7 @@ void css_conditional_io_interrupt(SubchDev *sch) sch->curr_status.scsw.ctrl |= SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND; /* Inject an I/O interrupt. */ - s390_io_interrupt(cpu, - css_build_subchannel_id(sch), + s390_io_interrupt(css_build_subchannel_id(sch), sch->schid, sch->curr_status.pmcw.intparm, isc << 27); @@ -167,11 +163,10 @@ void css_conditional_io_interrupt(SubchDev *sch) void css_adapter_interrupt(uint8_t isc) { - S390CPU *cpu = s390_cpu_addr2state(0); uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI; trace_css_adapter_interrupt(isc); - s390_io_interrupt(cpu, 0, 0, 0, io_int_word); + s390_io_interrupt(0, 0, 0, io_int_word); } static void sch_handle_clear_func(SubchDev *sch) @@ -779,9 +774,11 @@ out: return ret; } -static void copy_irb_to_guest(IRB *dest, const IRB *src) +static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw) { int i; + uint16_t stctl = src->scsw.ctrl & SCSW_CTRL_MASK_STCTL; + uint16_t actl = src->scsw.ctrl & SCSW_CTRL_MASK_ACTL; copy_scsw_to_guest(&dest->scsw, &src->scsw); @@ -791,8 +788,22 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src) for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) { dest->ecw[i] = cpu_to_be32(src->ecw[i]); } - for (i = 0; i < ARRAY_SIZE(dest->emw); i++) { - dest->emw[i] = cpu_to_be32(src->emw[i]); + /* extended measurements enabled? */ + if ((src->scsw.flags & SCSW_FLAGS_MASK_ESWF) || + !(pmcw->flags & PMCW_FLAGS_MASK_TF) || + !(pmcw->chars & PMCW_CHARS_MASK_XMWME)) { + return; + } + /* extended measurements pending? */ + if (!(stctl & SCSW_STCTL_STATUS_PEND)) { + return; + } + if ((stctl & SCSW_STCTL_PRIMARY) || + (stctl == SCSW_STCTL_SECONDARY) || + ((stctl & SCSW_STCTL_INTERMEDIATE) && (actl & SCSW_ACTL_SUSP))) { + for (i = 0; i < ARRAY_SIZE(dest->emw); i++) { + dest->emw[i] = cpu_to_be32(src->emw[i]); + } } } @@ -838,7 +849,7 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb) } } /* Store the irb to the guest. */ - copy_irb_to_guest(target_irb, &irb); + copy_irb_to_guest(target_irb, &irb, p); /* Clear conditions on subchannel, if applicable. */ if (stctl & SCSW_STCTL_STATUS_PEND) { @@ -1215,11 +1226,9 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid) QTAILQ_INSERT_TAIL(&channel_subsys->pending_crws, crw_cont, sibling); if (channel_subsys->do_crw_mchk) { - S390CPU *cpu = s390_cpu_addr2state(0); - channel_subsys->do_crw_mchk = false; /* Inject crw pending machine check. */ - s390_crw_mchk(cpu); + s390_crw_mchk(); } } @@ -1277,6 +1286,117 @@ int css_enable_mss(void) return 0; } +void subch_device_save(SubchDev *s, QEMUFile *f) +{ + int i; + + qemu_put_byte(f, s->cssid); + qemu_put_byte(f, s->ssid); + qemu_put_be16(f, s->schid); + qemu_put_be16(f, s->devno); + qemu_put_byte(f, s->thinint_active); + /* SCHIB */ + /* PMCW */ + qemu_put_be32(f, s->curr_status.pmcw.intparm); + qemu_put_be16(f, s->curr_status.pmcw.flags); + qemu_put_be16(f, s->curr_status.pmcw.devno); + qemu_put_byte(f, s->curr_status.pmcw.lpm); + qemu_put_byte(f, s->curr_status.pmcw.pnom); + qemu_put_byte(f, s->curr_status.pmcw.lpum); + qemu_put_byte(f, s->curr_status.pmcw.pim); + qemu_put_be16(f, s->curr_status.pmcw.mbi); + qemu_put_byte(f, s->curr_status.pmcw.pom); + qemu_put_byte(f, s->curr_status.pmcw.pam); + qemu_put_buffer(f, s->curr_status.pmcw.chpid, 8); + qemu_put_be32(f, s->curr_status.pmcw.chars); + /* SCSW */ + qemu_put_be16(f, s->curr_status.scsw.flags); + qemu_put_be16(f, s->curr_status.scsw.ctrl); + qemu_put_be32(f, s->curr_status.scsw.cpa); + qemu_put_byte(f, s->curr_status.scsw.dstat); + qemu_put_byte(f, s->curr_status.scsw.cstat); + qemu_put_be16(f, s->curr_status.scsw.count); + qemu_put_be64(f, s->curr_status.mba); + qemu_put_buffer(f, s->curr_status.mda, 4); + /* end SCHIB */ + qemu_put_buffer(f, s->sense_data, 32); + qemu_put_be64(f, s->channel_prog); + /* last cmd */ + qemu_put_byte(f, s->last_cmd.cmd_code); + qemu_put_byte(f, s->last_cmd.flags); + qemu_put_be16(f, s->last_cmd.count); + qemu_put_be32(f, s->last_cmd.cda); + qemu_put_byte(f, s->last_cmd_valid); + qemu_put_byte(f, s->id.reserved); + qemu_put_be16(f, s->id.cu_type); + qemu_put_byte(f, s->id.cu_model); + qemu_put_be16(f, s->id.dev_type); + qemu_put_byte(f, s->id.dev_model); + qemu_put_byte(f, s->id.unused); + for (i = 0; i < ARRAY_SIZE(s->id.ciw); i++) { + qemu_put_byte(f, s->id.ciw[i].type); + qemu_put_byte(f, s->id.ciw[i].command); + qemu_put_be16(f, s->id.ciw[i].count); + } + return; +} + +int subch_device_load(SubchDev *s, QEMUFile *f) +{ + int i; + + s->cssid = qemu_get_byte(f); + s->ssid = qemu_get_byte(f); + s->schid = qemu_get_be16(f); + s->devno = qemu_get_be16(f); + s->thinint_active = qemu_get_byte(f); + /* SCHIB */ + /* PMCW */ + s->curr_status.pmcw.intparm = qemu_get_be32(f); + s->curr_status.pmcw.flags = qemu_get_be16(f); + s->curr_status.pmcw.devno = qemu_get_be16(f); + s->curr_status.pmcw.lpm = qemu_get_byte(f); + s->curr_status.pmcw.pnom = qemu_get_byte(f); + s->curr_status.pmcw.lpum = qemu_get_byte(f); + s->curr_status.pmcw.pim = qemu_get_byte(f); + s->curr_status.pmcw.mbi = qemu_get_be16(f); + s->curr_status.pmcw.pom = qemu_get_byte(f); + s->curr_status.pmcw.pam = qemu_get_byte(f); + qemu_get_buffer(f, s->curr_status.pmcw.chpid, 8); + s->curr_status.pmcw.chars = qemu_get_be32(f); + /* SCSW */ + s->curr_status.scsw.flags = qemu_get_be16(f); + s->curr_status.scsw.ctrl = qemu_get_be16(f); + s->curr_status.scsw.cpa = qemu_get_be32(f); + s->curr_status.scsw.dstat = qemu_get_byte(f); + s->curr_status.scsw.cstat = qemu_get_byte(f); + s->curr_status.scsw.count = qemu_get_be16(f); + s->curr_status.mba = qemu_get_be64(f); + qemu_get_buffer(f, s->curr_status.mda, 4); + /* end SCHIB */ + qemu_get_buffer(f, s->sense_data, 32); + s->channel_prog = qemu_get_be64(f); + /* last cmd */ + s->last_cmd.cmd_code = qemu_get_byte(f); + s->last_cmd.flags = qemu_get_byte(f); + s->last_cmd.count = qemu_get_be16(f); + s->last_cmd.cda = qemu_get_be32(f); + s->last_cmd_valid = qemu_get_byte(f); + s->id.reserved = qemu_get_byte(f); + s->id.cu_type = qemu_get_be16(f); + s->id.cu_model = qemu_get_byte(f); + s->id.dev_type = qemu_get_be16(f); + s->id.dev_model = qemu_get_byte(f); + s->id.unused = qemu_get_byte(f); + for (i = 0; i < ARRAY_SIZE(s->id.ciw); i++) { + s->id.ciw[i].type = qemu_get_byte(f); + s->id.ciw[i].command = qemu_get_byte(f); + s->id.ciw[i].count = qemu_get_be16(f); + } + return 0; +} + + static void css_init(void) { channel_subsys = g_malloc0(sizeof(*channel_subsys)); diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 6586106fa7..c864ea765b 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -85,6 +85,8 @@ struct SubchDev { typedef SubchDev *(*css_subch_cb_func)(uint8_t m, uint8_t cssid, uint8_t ssid, uint16_t schid); +void subch_device_save(SubchDev *s, QEMUFile *f); +int subch_device_load(SubchDev *s, QEMUFile *f); int css_create_css_image(uint8_t cssid, bool default_image); bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno); void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid, diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 9c71afa031..7c8c81b0cc 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -45,8 +45,6 @@ do { } while (0) #endif -#define VIRTIO_EXT_CODE 0x2603 - static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size, VirtIOS390Device *dev); @@ -113,15 +111,6 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) return bus; } -static void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token) -{ - if (kvm_enabled()) { - kvm_s390_virtio_irq(cpu, config_change, token); - } else { - cpu_inject_ext(cpu, VIRTIO_EXT_CODE, config_change, token); - } -} - static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) { VirtIOS390Bus *bus; @@ -144,8 +133,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) s390_virtio_device_sync(dev); s390_virtio_reset_idx(dev); if (dev->qdev.hotplugged) { - S390CPU *cpu = s390_cpu_addr2state(0); - s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs); + s390_virtio_irq(VIRTIO_PARAM_DEV_ADD, dev->dev_offs); } return 0; @@ -489,9 +477,8 @@ static void virtio_s390_notify(DeviceState *d, uint16_t vector) { VirtIOS390Device *dev = to_virtio_s390_device_fast(d); uint64_t token = s390_virtio_device_vq_token(dev, vector); - S390CPU *cpu = s390_cpu_addr2state(0); - s390_virtio_irq(cpu, 0, token); + s390_virtio_irq(0, token); } static unsigned virtio_s390_get_features(DeviceState *d) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index c4f21d3816..05656a2887 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1275,6 +1275,97 @@ irqroute_error: return r; } +static void virtio_ccw_save_queue(DeviceState *d, int n, QEMUFile *f) +{ + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); + VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); + + qemu_put_be16(f, virtio_queue_vector(vdev, n)); +} + +static int virtio_ccw_load_queue(DeviceState *d, int n, QEMUFile *f) +{ + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); + VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); + uint16_t vector; + + qemu_get_be16s(f, &vector); + virtio_queue_set_vector(vdev, n , vector); + + return 0; +} + +static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f) +{ + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); + SubchDev *s = dev->sch; + + subch_device_save(s, f); + if (dev->indicators != NULL) { + qemu_put_be32(f, dev->indicators->len); + qemu_put_be64(f, dev->indicators->addr); + } else { + qemu_put_be32(f, 0); + qemu_put_be64(f, 0UL); + } + if (dev->indicators2 != NULL) { + qemu_put_be32(f, dev->indicators2->len); + qemu_put_be64(f, dev->indicators2->addr); + } else { + qemu_put_be32(f, 0); + qemu_put_be64(f, 0UL); + } + if (dev->summary_indicator != NULL) { + qemu_put_be32(f, dev->summary_indicator->len); + qemu_put_be64(f, dev->summary_indicator->addr); + } else { + qemu_put_be32(f, 0); + qemu_put_be64(f, 0UL); + } + qemu_put_be64(f, dev->routes.adapter.ind_offset); + qemu_put_byte(f, dev->thinint_isc); +} + +static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f) +{ + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); + SubchDev *s = dev->sch; + int len; + + s->driver_data = dev; + subch_device_load(s, f); + len = qemu_get_be32(f); + if (len != 0) { + dev->indicators = get_indicator(qemu_get_be64(f), len); + } else { + qemu_get_be64(f); + dev->indicators = NULL; + } + len = qemu_get_be32(f); + if (len != 0) { + dev->indicators2 = get_indicator(qemu_get_be64(f), len); + } else { + qemu_get_be64(f); + dev->indicators2 = NULL; + } + len = qemu_get_be32(f); + if (len != 0) { + dev->summary_indicator = get_indicator(qemu_get_be64(f), len); + } else { + qemu_get_be64(f); + dev->summary_indicator = NULL; + } + dev->routes.adapter.ind_offset = qemu_get_be64(f); + dev->thinint_isc = qemu_get_byte(f); + if (s->thinint_active) { + return css_register_io_adapter(CSS_IO_ADAPTER_VIRTIO, + dev->thinint_isc, true, false, + &dev->routes.adapter.adapter_id); + } + + return 0; +} + /**************** Virtio-ccw Bus Device Descriptions *******************/ static Property virtio_ccw_net_properties[] = { @@ -1597,6 +1688,10 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data) k->query_guest_notifiers = virtio_ccw_query_guest_notifiers; k->set_host_notifier = virtio_ccw_set_host_notifier; k->set_guest_notifiers = virtio_ccw_set_guest_notifiers; + k->save_queue = virtio_ccw_save_queue; + k->load_queue = virtio_ccw_load_queue; + k->save_config = virtio_ccw_save_config; + k->load_config = virtio_ccw_load_config; } static const TypeInfo virtio_ccw_bus_info = { diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 4502ad143d..5efe8c1af7 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -151,17 +151,6 @@ static const sd_cmd_type_t sd_cmd_type[64] = { sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, }; -static const sd_cmd_type_t sd_acmd_type[64] = { - sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac, sd_none, - sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none, - sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_ac, - sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, - sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, - sd_none, sd_bcr, sd_ac, sd_none, sd_none, sd_none, sd_none, sd_none, - sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none, sd_none, sd_none, - sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, -}; - static const int sd_cmd_class[64] = { 0, 0, 0, 0, 0, 9, 10, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 3557c178f1..a07ae8ad91 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -440,7 +440,7 @@ void virtqueue_map_sg(struct iovec *sg, hwaddr *addr, len = sg[i].iov_len; sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write); if (sg[i].iov_base == NULL || len != sg[i].iov_len) { - error_report("virtio: trying to map MMIO memory"); + error_report("virtio: error trying to map MMIO memory"); exit(1); } } diff --git a/libcacard/cac.c b/libcacard/cac.c index 0a0163d3eb..ae8c3784b9 100644 --- a/libcacard/cac.c +++ b/libcacard/cac.c @@ -100,10 +100,8 @@ cac_applet_pki_reset(VCard *card, int channel) pki_applet = &(applet_private->u.pki_data); pki_applet->cert_buffer = NULL; - if (pki_applet->sign_buffer) { - g_free(pki_applet->sign_buffer); - pki_applet->sign_buffer = NULL; - } + g_free(pki_applet->sign_buffer); + pki_applet->sign_buffer = NULL; pki_applet->cert_buffer_len = 0; pki_applet->sign_buffer_len = 0; return VCARD_DONE; @@ -285,12 +283,8 @@ cac_delete_pki_applet_private(VCardAppletPrivate *applet_private) return; } pki_applet_data = &(applet_private->u.pki_data); - if (pki_applet_data->cert != NULL) { - g_free(pki_applet_data->cert); - } - if (pki_applet_data->sign_buffer != NULL) { - g_free(pki_applet_data->sign_buffer); - } + g_free(pki_applet_data->cert); + g_free(pki_applet_data->sign_buffer); if (pki_applet_data->key != NULL) { vcard_emul_delete_key(pki_applet_data->key); } diff --git a/libcacard/card_7816.c b/libcacard/card_7816.c index a54f880390..814fa1662f 100644 --- a/libcacard/card_7816.c +++ b/libcacard/card_7816.c @@ -172,16 +172,12 @@ vcard_response_delete(VCardResponse *response) switch (response->b_type) { case VCARD_MALLOC: /* everything was malloc'ed */ - if (response->b_data) { - g_free(response->b_data); - } + g_free(response->b_data); g_free(response); break; case VCARD_MALLOC_DATA: /* only the data buffer was malloc'ed */ - if (response->b_data) { - g_free(response->b_data); - } + g_free(response->b_data); break; case VCARD_MALLOC_STRUCT: /* only the structure was malloc'ed */ @@ -358,9 +354,7 @@ vcard_apdu_delete(VCardAPDU *apdu) if (apdu == NULL) { return; } - if (apdu->a_data) { - g_free(apdu->a_data); - } + g_free(apdu->a_data); g_free(apdu); } diff --git a/libcacard/vcard.c b/libcacard/vcard.c index 6aaf085ecc..87ad5166a8 100644 --- a/libcacard/vcard.c +++ b/libcacard/vcard.c @@ -51,9 +51,7 @@ vcard_buffer_response_delete(VCardBufferResponse *buffer_response) if (buffer_response == NULL) { return; } - if (buffer_response->buffer) { - g_free(buffer_response->buffer); - } + g_free(buffer_response->buffer); g_free(buffer_response); } @@ -119,12 +117,8 @@ vcard_delete_applet(VCardApplet *applet) } if (applet->applet_private_free) { applet->applet_private_free(applet->applet_private); - applet->applet_private = NULL; - } - if (applet->aid) { - g_free(applet->aid); - applet->aid = NULL; } + g_free(applet->aid); g_free(applet); } @@ -178,8 +172,6 @@ vcard_free(VCard *vcard) } if (vcard->vcard_private_free) { (*vcard->vcard_private_free)(vcard->vcard_private); - vcard->vcard_private_free = 0; - vcard->vcard_private = 0; } for (current_applet = vcard->applet_list; current_applet; current_applet = next_applet) { diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c index cefc38333f..f1bba57c2f 100644 --- a/libcacard/vcard_emul_nss.c +++ b/libcacard/vcard_emul_nss.c @@ -471,9 +471,7 @@ vreader_emul_delete(VReaderEmul *vreader_emul) if (vreader_emul->slot) { PK11_FreeSlot(vreader_emul->slot); } - if (vreader_emul->type_params) { - g_free(vreader_emul->type_params); - } + g_free(vreader_emul->type_params); g_free(vreader_emul); } diff --git a/libcacard/vreader.c b/libcacard/vreader.c index f0c57e6db7..0315dd8920 100644 --- a/libcacard/vreader.c +++ b/libcacard/vreader.c @@ -154,9 +154,7 @@ vreader_free(VReader *reader) if (reader->card) { vcard_free(reader->card); } - if (reader->name) { - g_free(reader->name); - } + g_free(reader->name); if (reader->reader_private_free) { reader->reader_private_free(reader->reader_private); } @@ -344,8 +342,6 @@ vreader_list_delete(VReaderList *list) next_entry = vreader_list_get_next(current_entry); vreader_list_entry_delete(current_entry); } - list->head = NULL; - list->tail = NULL; g_free(list); } diff --git a/page_cache.c b/page_cache.c index b033681a93..89bb1ec3a0 100644 --- a/page_cache.c +++ b/page_cache.c @@ -109,6 +109,7 @@ void cache_fini(PageCache *cache) g_free(cache->page_cache); cache->page_cache = NULL; + g_free(cache); } static size_t cache_get_cache_pos(const PageCache *cache, diff --git a/qtest.c b/qtest.c index f9695a8ff6..04a6dc1f0f 100644 --- a/qtest.c +++ b/qtest.c @@ -148,7 +148,7 @@ static int hex2nib(char ch) } else if (ch >= 'a' && ch <= 'f') { return 10 + (ch - 'a'); } else if (ch >= 'A' && ch <= 'F') { - return 10 + (ch - 'a'); + return 10 + (ch - 'A'); } else { return -1; } diff --git a/slirp/slirp.c b/slirp/slirp.c index 60280361e6..35f819afb7 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -37,8 +37,6 @@ static const uint8_t special_ethaddr[ETH_ALEN] = { 0x52, 0x55, 0x00, 0x00, 0x00, 0x00 }; -static const uint8_t zero_ethaddr[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - u_int curtime; static QTAILQ_HEAD(slirp_instances, Slirp) slirp_instances = diff --git a/target-i386/cpu.c b/target-i386/cpu.c index dde052cc42..8983457e23 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1688,8 +1688,8 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, numvalue = strtoul(val, &err, 0); if (!*val || *err) { - error_setg(&local_err, "bad numerical value %s", val); - goto out; + error_setg(errp, "bad numerical value %s", val); + return; } if (numvalue < 0x80000000) { error_report("xlevel value shall always be >= 0x80000000" @@ -1706,8 +1706,8 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, tsc_freq = strtosz_suffix_unit(val, &err, STRTOSZ_DEFSUFFIX_B, 1000); if (tsc_freq < 0 || *err) { - error_setg(&local_err, "bad numerical value %s", val); - goto out; + error_setg(errp, "bad numerical value %s", val); + return; } snprintf(num, sizeof(num), "%" PRId64, tsc_freq); object_property_parse(OBJECT(cpu), num, "tsc-frequency", @@ -1718,8 +1718,8 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, char num[32]; numvalue = strtoul(val, &err, 0); if (!*val || *err) { - error_setg(&local_err, "bad numerical value %s", val); - goto out; + error_setg(errp, "bad numerical value %s", val); + return; } if (numvalue < min) { error_report("hv-spinlocks value shall always be >= 0x%x" @@ -1738,7 +1738,7 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, } if (local_err) { error_propagate(errp, local_err); - goto out; + return; } featurestr = strtok(NULL, ","); } @@ -1758,9 +1758,6 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, env->features[FEAT_KVM] &= ~minus_features[FEAT_KVM]; env->features[FEAT_SVM] &= ~minus_features[FEAT_SVM]; env->features[FEAT_7_0_EBX] &= ~minus_features[FEAT_7_0_EBX]; - -out: - return; } /* generate a composite string into buf of all cpuid names in featureset diff --git a/target-i386/translate.c b/target-i386/translate.c index 2359787b42..6fcd8245d2 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -1506,14 +1506,6 @@ static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2, } } -static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2) -{ - if (arg2 >= 0) - tcg_gen_shli_tl(ret, arg1, arg2); - else - tcg_gen_shri_tl(ret, arg1, -arg2); -} - static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right) { target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f); diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index c422bdc718..03ea15803b 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -99,19 +99,6 @@ static const char *special_regnames[] = "sr16", "sr17", "sr18" }; -/* Sign extend at translation time. */ -static inline int sign_extend(unsigned int val, unsigned int width) -{ - int sval; - - /* LSL. */ - val <<= 31 - width; - sval = val; - /* ASR. */ - sval >>= 31 - width; - return sval; -} - static inline void t_sync_flags(DisasContext *dc) { /* Synch the tb dependent flags between translator and runtime. */ diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 06454d6da5..b13761d925 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -357,30 +357,23 @@ void s390x_tod_timer(void *opaque); void s390x_cpu_timer(void *opaque); int s390_virtio_hypercall(CPUS390XState *env); +void s390_virtio_irq(int config_change, uint64_t token); #ifdef CONFIG_KVM void kvm_s390_reset_vcpu(S390CPU *cpu); -void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code); -void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token); -void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm, - uint64_t parm64, int vm); +void kvm_s390_virtio_irq(int config_change, uint64_t token); +void kvm_s390_service_interrupt(uint32_t parm); +void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq); +void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq); +int kvm_s390_inject_flic(struct kvm_s390_irq *irq); #else static inline void kvm_s390_reset_vcpu(S390CPU *cpu) { } - -static inline void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code) +static inline void kvm_s390_virtio_irq(int config_change, uint64_t token) { } - -static inline void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, - uint64_t token) -{ -} - -static inline void kvm_s390_interrupt_internal(S390CPU *cpu, int type, - uint32_t parm, uint64_t parm64, - int vm) +static inline void kvm_s390_service_interrupt(uint32_t parm) { } #endif @@ -1066,23 +1059,23 @@ void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, uintptr_t retaddr); #ifdef CONFIG_KVM -void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id, +void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_parm, uint32_t io_int_word); -void kvm_s390_crw_mchk(S390CPU *cpu); +void kvm_s390_crw_mchk(void); void kvm_s390_enable_css_support(S390CPU *cpu); int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int vq, bool assign); int kvm_s390_cpu_restart(S390CPU *cpu); +void kvm_s390_clear_cmma_callback(void *opaque); #else -static inline void kvm_s390_io_interrupt(S390CPU *cpu, - uint16_t subchannel_id, +static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_parm, uint32_t io_int_word) { } -static inline void kvm_s390_crw_mchk(S390CPU *cpu) +static inline void kvm_s390_crw_mchk(void) { } static inline void kvm_s390_enable_css_support(S390CPU *cpu) @@ -1098,40 +1091,31 @@ static inline int kvm_s390_cpu_restart(S390CPU *cpu) { return -ENOSYS; } -#endif - -static inline int s390_cpu_restart(S390CPU *cpu) +static inline void kvm_s390_clear_cmma_callback(void *opaque) { - if (kvm_enabled()) { - return kvm_s390_cpu_restart(cpu); - } - return -ENOSYS; } +#endif -static inline void s390_io_interrupt(S390CPU *cpu, - uint16_t subchannel_id, - uint16_t subchannel_nr, - uint32_t io_int_parm, - uint32_t io_int_word) +static inline void cmma_reset(S390CPU *cpu) { if (kvm_enabled()) { - kvm_s390_io_interrupt(cpu, subchannel_id, subchannel_nr, io_int_parm, - io_int_word); - } else { - cpu_inject_io(cpu, subchannel_id, subchannel_nr, io_int_parm, - io_int_word); + CPUState *cs = CPU(cpu); + kvm_s390_clear_cmma_callback(cs->kvm_state); } } -static inline void s390_crw_mchk(S390CPU *cpu) +static inline int s390_cpu_restart(S390CPU *cpu) { if (kvm_enabled()) { - kvm_s390_crw_mchk(cpu); - } else { - cpu_inject_crw_mchk(cpu); + return kvm_s390_cpu_restart(cpu); } + return -ENOSYS; } +void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, + uint32_t io_int_parm, uint32_t io_int_word); +void s390_crw_mchk(void); + static inline int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id, int vq, bool assign) diff --git a/target-s390x/interrupt.c b/target-s390x/interrupt.c index 6d6580de3a..23a9114f5a 100644 --- a/target-s390x/interrupt.c +++ b/target-s390x/interrupt.c @@ -1,7 +1,7 @@ /* * QEMU S/390 Interrupt support * - * Copyright IBM, Corp. 2012 + * Copyright IBM Corp. 2012, 2014 * * This work is licensed under the terms of the GNU GPL, version 2 or (at your * option) any later version. See the COPYING file in the top-level directory. @@ -10,21 +10,59 @@ #include "cpu.h" #include "sysemu/kvm.h" +/* + * All of the following interrupts are floating, i.e. not per-vcpu. + * We just need a dummy cpustate in order to be able to inject in the + * non-kvm case. + */ #if !defined(CONFIG_USER_ONLY) -/* service interrupts are floating therefore we must not pass an cpustate */ void s390_sclp_extint(uint32_t parm) { - S390CPU *dummy_cpu = s390_cpu_addr2state(0); - CPUS390XState *env = &dummy_cpu->env; - if (kvm_enabled()) { -#ifdef CONFIG_KVM - kvm_s390_interrupt_internal(dummy_cpu, KVM_S390_INT_SERVICE, parm, - 0, 1); -#endif + kvm_s390_service_interrupt(parm); } else { + S390CPU *dummy_cpu = s390_cpu_addr2state(0); + CPUS390XState *env = &dummy_cpu->env; + env->psw.addr += 4; cpu_inject_ext(dummy_cpu, EXT_SERVICE, parm, 0); } } + +void s390_virtio_irq(int config_change, uint64_t token) +{ + if (kvm_enabled()) { + kvm_s390_virtio_irq(config_change, token); + } else { + S390CPU *dummy_cpu = s390_cpu_addr2state(0); + + cpu_inject_ext(dummy_cpu, EXT_VIRTIO, config_change, token); + } +} + +void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, + uint32_t io_int_parm, uint32_t io_int_word) +{ + if (kvm_enabled()) { + kvm_s390_io_interrupt(subchannel_id, subchannel_nr, io_int_parm, + io_int_word); + } else { + S390CPU *dummy_cpu = s390_cpu_addr2state(0); + + cpu_inject_io(dummy_cpu, subchannel_id, subchannel_nr, io_int_parm, + io_int_word); + } +} + +void s390_crw_mchk(void) +{ + if (kvm_enabled()) { + kvm_s390_crw_mchk(); + } else { + S390CPU *dummy_cpu = s390_cpu_addr2state(0); + + cpu_inject_crw_mchk(dummy_cpu); + } +} + #endif diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 7a07f9d753..a1a4cc2cab 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -32,6 +32,7 @@ #include "qemu/timer.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" +#include "hw/hw.h" #include "cpu.h" #include "sysemu/device_tree.h" #include "qapi/qmp/qjson.h" @@ -82,6 +83,8 @@ #define DIAG_KVM_BREAKPOINT 0x501 #define ICPT_INSTRUCTION 0x04 +#define ICPT_PROGRAM 0x08 +#define ICPT_EXT_INT 0x14 #define ICPT_WAITPSW 0x1c #define ICPT_SOFT_INTERCEPT 0x24 #define ICPT_CPU_STOP 0x28 @@ -104,10 +107,67 @@ static int cap_async_pf; static void *legacy_s390_alloc(size_t size); +static int kvm_s390_check_clear_cmma(KVMState *s) +{ + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_CLR_CMMA, + }; + + return kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attr); +} + +static int kvm_s390_check_enable_cmma(KVMState *s) +{ + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_ENABLE_CMMA, + }; + + return kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attr); +} + +void kvm_s390_clear_cmma_callback(void *opaque) +{ + int rc; + KVMState *s = opaque; + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_CLR_CMMA, + }; + + rc = kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr); + trace_kvm_clear_cmma(rc); +} + +static void kvm_s390_enable_cmma(KVMState *s) +{ + int rc; + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_ENABLE_CMMA, + }; + + if (kvm_s390_check_enable_cmma(s) || kvm_s390_check_clear_cmma(s)) { + return; + } + + rc = kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr); + if (!rc) { + qemu_register_reset(kvm_s390_clear_cmma_callback, s); + } + trace_kvm_enable_cmma(rc); +} + int kvm_arch_init(KVMState *s) { cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS); cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF); + + if (kvm_check_extension(s, KVM_CAP_VM_ATTRIBUTES)) { + kvm_s390_enable_cmma(s); + } + if (!kvm_check_extension(s, KVM_CAP_S390_GMAP) || !kvm_check_extension(s, KVM_CAP_S390_COW)) { phys_mem_set_alloc(legacy_s390_alloc); @@ -495,47 +555,138 @@ int kvm_arch_process_async_events(CPUState *cs) return cs->halted; } -void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm, - uint64_t parm64, int vm) +static int s390_kvm_irq_to_interrupt(struct kvm_s390_irq *irq, + struct kvm_s390_interrupt *interrupt) { + int r = 0; + + interrupt->type = irq->type; + switch (irq->type) { + case KVM_S390_INT_VIRTIO: + interrupt->parm = irq->u.ext.ext_params; + /* fall through */ + case KVM_S390_INT_PFAULT_INIT: + case KVM_S390_INT_PFAULT_DONE: + interrupt->parm64 = irq->u.ext.ext_params2; + break; + case KVM_S390_PROGRAM_INT: + interrupt->parm = irq->u.pgm.code; + break; + case KVM_S390_SIGP_SET_PREFIX: + interrupt->parm = irq->u.prefix.address; + break; + case KVM_S390_INT_SERVICE: + interrupt->parm = irq->u.ext.ext_params; + break; + case KVM_S390_MCHK: + interrupt->parm = irq->u.mchk.cr14; + interrupt->parm64 = irq->u.mchk.mcic; + break; + case KVM_S390_INT_EXTERNAL_CALL: + interrupt->parm = irq->u.extcall.code; + break; + case KVM_S390_INT_EMERGENCY: + interrupt->parm = irq->u.emerg.code; + break; + case KVM_S390_SIGP_STOP: + case KVM_S390_RESTART: + break; /* These types have no parameters */ + case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: + interrupt->parm = irq->u.io.subchannel_id << 16; + interrupt->parm |= irq->u.io.subchannel_nr; + interrupt->parm64 = (uint64_t)irq->u.io.io_int_parm << 32; + interrupt->parm64 |= irq->u.io.io_int_word; + break; + default: + r = -EINVAL; + break; + } + return r; +} + +void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq) +{ + struct kvm_s390_interrupt kvmint = {}; CPUState *cs = CPU(cpu); - struct kvm_s390_interrupt kvmint; int r; - if (!cs->kvm_state) { - return; + r = s390_kvm_irq_to_interrupt(irq, &kvmint); + if (r < 0) { + fprintf(stderr, "%s called with bogus interrupt\n", __func__); + exit(1); + } + + r = kvm_vcpu_ioctl(cs, KVM_S390_INTERRUPT, &kvmint); + if (r < 0) { + fprintf(stderr, "KVM failed to inject interrupt\n"); + exit(1); } +} - kvmint.type = type; - kvmint.parm = parm; - kvmint.parm64 = parm64; +static void __kvm_s390_floating_interrupt(struct kvm_s390_irq *irq) +{ + struct kvm_s390_interrupt kvmint = {}; + int r; - if (vm) { - r = kvm_vm_ioctl(cs->kvm_state, KVM_S390_INTERRUPT, &kvmint); - } else { - r = kvm_vcpu_ioctl(cs, KVM_S390_INTERRUPT, &kvmint); + r = s390_kvm_irq_to_interrupt(irq, &kvmint); + if (r < 0) { + fprintf(stderr, "%s called with bogus interrupt\n", __func__); + exit(1); } + r = kvm_vm_ioctl(kvm_state, KVM_S390_INTERRUPT, &kvmint); if (r < 0) { fprintf(stderr, "KVM failed to inject interrupt\n"); exit(1); } } -void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token) +void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq) { - kvm_s390_interrupt_internal(cpu, KVM_S390_INT_VIRTIO, config_change, - token, 1); + static bool use_flic = true; + int r; + + if (use_flic) { + r = kvm_s390_inject_flic(irq); + if (r == -ENOSYS) { + use_flic = false; + } + if (!r) { + return; + } + } + __kvm_s390_floating_interrupt(irq); } -void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code) +void kvm_s390_virtio_irq(int config_change, uint64_t token) { - kvm_s390_interrupt_internal(cpu, type, code, 0, 0); + struct kvm_s390_irq irq = { + .type = KVM_S390_INT_VIRTIO, + .u.ext.ext_params = config_change, + .u.ext.ext_params2 = token, + }; + + kvm_s390_floating_interrupt(&irq); +} + +void kvm_s390_service_interrupt(uint32_t parm) +{ + struct kvm_s390_irq irq = { + .type = KVM_S390_INT_SERVICE, + .u.ext.ext_params = parm, + }; + + kvm_s390_floating_interrupt(&irq); } static void enter_pgmcheck(S390CPU *cpu, uint16_t code) { - kvm_s390_interrupt(cpu, KVM_S390_PROGRAM_INT, code); + struct kvm_s390_irq irq = { + .type = KVM_S390_PROGRAM_INT, + .u.pgm.code = code, + }; + + kvm_s390_vcpu_interrupt(cpu, &irq); } static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, @@ -751,7 +902,11 @@ static int kvm_s390_cpu_start(S390CPU *cpu) int kvm_s390_cpu_restart(S390CPU *cpu) { - kvm_s390_interrupt(cpu, KVM_S390_RESTART, 0); + struct kvm_s390_irq irq = { + .type = KVM_S390_RESTART, + }; + + kvm_s390_vcpu_interrupt(cpu, &irq); s390_add_running_cpu(cpu); qemu_cpu_kick(CPU(cpu)); DPRINTF("DONE: KVM cpu restart: %p\n", &cpu->env); @@ -872,6 +1027,28 @@ static bool is_special_wait_psw(CPUState *cs) return cs->kvm_run->psw_addr == 0xfffUL; } +static void guest_panicked(void) +{ + QObject *data; + + data = qobject_from_jsonf("{ 'action': %s }", "pause"); + monitor_protocol_event(QEVENT_GUEST_PANICKED, data); + qobject_decref(data); + + vm_stop(RUN_STATE_GUEST_PANICKED); +} + +static void unmanageable_intercept(S390CPU *cpu, const char *str, int pswoffset) +{ + CPUState *cs = CPU(cpu); + + error_report("Unmanageable %s! CPU%i new PSW: 0x%016lx:%016lx", + str, cs->cpu_index, ldq_phys(cs->as, cpu->env.psa + pswoffset), + ldq_phys(cs->as, cpu->env.psa + pswoffset + 8)); + s390_del_running_cpu(cpu); + guest_panicked(); +} + static int handle_intercept(S390CPU *cpu) { CPUState *cs = CPU(cpu); @@ -885,18 +1062,23 @@ static int handle_intercept(S390CPU *cpu) case ICPT_INSTRUCTION: r = handle_instruction(cpu, run); break; + case ICPT_PROGRAM: + unmanageable_intercept(cpu, "program interrupt", + offsetof(LowCore, program_new_psw)); + r = EXCP_HALTED; + break; + case ICPT_EXT_INT: + unmanageable_intercept(cpu, "external interrupt", + offsetof(LowCore, external_new_psw)); + r = EXCP_HALTED; + break; case ICPT_WAITPSW: /* disabled wait, since enabled wait is handled in kernel */ if (s390_del_running_cpu(cpu) == 0) { if (is_special_wait_psw(cs)) { qemu_system_shutdown_request(); } else { - QObject *data; - - data = qobject_from_jsonf("{ 'action': %s }", "pause"); - monitor_protocol_event(QEVENT_GUEST_PANICKED, data); - qobject_decref(data); - vm_stop(RUN_STATE_GUEST_PANICKED); + guest_panicked(); } } r = EXCP_HALTED; @@ -944,18 +1126,10 @@ static int handle_tsch(S390CPU *cpu) * If an I/O interrupt had been dequeued, we have to reinject it. */ if (run->s390_tsch.dequeued) { - uint16_t subchannel_id = run->s390_tsch.subchannel_id; - uint16_t subchannel_nr = run->s390_tsch.subchannel_nr; - uint32_t io_int_parm = run->s390_tsch.io_int_parm; - uint32_t io_int_word = run->s390_tsch.io_int_word; - uint32_t type = ((subchannel_id & 0xff00) << 24) | - ((subchannel_id & 0x00060) << 22) | (subchannel_nr << 16); - - kvm_s390_interrupt_internal(cpu, type, - ((uint32_t)subchannel_id << 16) - | subchannel_nr, - ((uint64_t)io_int_parm << 32) - | io_int_word, 1); + kvm_s390_io_interrupt(run->s390_tsch.subchannel_id, + run->s390_tsch.subchannel_nr, + run->s390_tsch.io_int_parm, + run->s390_tsch.io_int_word); } ret = 0; } @@ -1040,27 +1214,34 @@ int kvm_arch_on_sigbus(int code, void *addr) return 1; } -void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id, +void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_parm, uint32_t io_int_word) { - uint32_t type; + struct kvm_s390_irq irq = { + .u.io.subchannel_id = subchannel_id, + .u.io.subchannel_nr = subchannel_nr, + .u.io.io_int_parm = io_int_parm, + .u.io.io_int_word = io_int_word, + }; if (io_int_word & IO_INT_WORD_AI) { - type = KVM_S390_INT_IO(1, 0, 0, 0); + irq.type = KVM_S390_INT_IO(1, 0, 0, 0); } else { - type = ((subchannel_id & 0xff00) << 24) | + irq.type = ((subchannel_id & 0xff00) << 24) | ((subchannel_id & 0x00060) << 22) | (subchannel_nr << 16); } - kvm_s390_interrupt_internal(cpu, type, - ((uint32_t)subchannel_id << 16) | subchannel_nr, - ((uint64_t)io_int_parm << 32) | io_int_word, 1); + kvm_s390_floating_interrupt(&irq); } -void kvm_s390_crw_mchk(S390CPU *cpu) +void kvm_s390_crw_mchk(void) { - kvm_s390_interrupt_internal(cpu, KVM_S390_MCHK, 1 << 28, - 0x00400f1d40330000, 1); + struct kvm_s390_irq irq = { + .type = KVM_S390_MCHK, + .u.mchk.cr14 = 1 << 28, + .u.mchk.mcic = 0x00400f1d40330000, + }; + kvm_s390_floating_interrupt(&irq); } void kvm_s390_enable_css_support(S390CPU *cpu) diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 9dae0256fa..0b625826ef 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -85,7 +85,12 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilen) if (kvm_enabled()) { #ifdef CONFIG_KVM - kvm_s390_interrupt(cpu, KVM_S390_PROGRAM_INT, code); + struct kvm_s390_irq irq = { + .type = KVM_S390_PROGRAM_INT, + .u.pgm.code = code, + }; + + kvm_s390_vcpu_interrupt(cpu, &irq); #endif } else { CPUState *cs = CPU(cpu); @@ -136,6 +141,7 @@ static int modified_clear_reset(S390CPU *cpu) pause_all_vcpus(); cpu_synchronize_all_states(); cpu_full_reset_all(); + cmma_reset(cpu); io_subsystem_reset(); scc->load_normal(CPU(cpu)); cpu_synchronize_all_post_reset(); @@ -150,6 +156,7 @@ static int load_normal_reset(S390CPU *cpu) pause_all_vcpus(); cpu_synchronize_all_states(); cpu_reset_all(); + cmma_reset(cpu); io_subsystem_reset(); scc->initial_cpu_reset(CPU(cpu)); scc->load_normal(CPU(cpu)); diff --git a/trace-events b/trace-events index ffe6e62031..e984e762cf 100644 --- a/trace-events +++ b/trace-events @@ -1258,3 +1258,7 @@ xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (ad # hw/pci/pci_host.c pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x -> 0x%x" pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x <- 0x%x" + +# target-s390x/kvm.c +kvm_enable_cmma(int rc) "CMMA: enabling with result code %d" +kvm_clear_cmma(int rc) "CMMA: clearing with result code %d" diff --git a/ui/console.c b/ui/console.c index 2ce55a69d0..7dc4c1414c 100644 --- a/ui/console.c +++ b/ui/console.c @@ -30,7 +30,6 @@ #include "trace.h" #define DEFAULT_BACKSCROLL 512 -#define MAX_CONSOLES 12 #define CONSOLE_CURSOR_PERIOD 500 typedef struct TextAttributes { @@ -173,7 +172,7 @@ struct DisplayState { static DisplayState *display_state; static QemuConsole *active_console; -static QemuConsole *consoles[MAX_CONSOLES]; +static QemuConsole **consoles; static int nb_consoles = 0; static bool cursor_visible_phase; static QEMUTimer *cursor_timer; @@ -983,9 +982,6 @@ void console_select(unsigned int index) DisplayChangeListener *dcl; QemuConsole *s; - if (index >= MAX_CONSOLES) - return; - trace_console_select(index); s = qemu_console_lookup_by_index(index); if (s) { @@ -1191,9 +1187,6 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, QemuConsole *s; int i; - if (nb_consoles >= MAX_CONSOLES) - return NULL; - obj = object_new(TYPE_QEMU_CONSOLE); s = QEMU_CONSOLE(obj); s->head = head; @@ -1211,6 +1204,8 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, } s->ds = ds; s->console_type = console_type; + + consoles = g_realloc(consoles, sizeof(*consoles) * (nb_consoles+1)); if (console_type != GRAPHIC_CONSOLE) { s->index = nb_consoles; consoles[nb_consoles++] = s; @@ -1585,10 +1580,7 @@ DisplayState *init_displaystate(void) gchar *name; int i; - if (!display_state) { - display_state = g_new0(DisplayState, 1); - } - + get_alloc_displaystate(); for (i = 0; i < nb_consoles; i++) { if (consoles[i]->console_type != GRAPHIC_CONSOLE && consoles[i]->ds == NULL) { @@ -1634,7 +1626,7 @@ QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head, QemuConsole *qemu_console_lookup_by_index(unsigned int index) { - if (index >= MAX_CONSOLES) { + if (index >= nb_consoles) { return NULL; } return consoles[index]; diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 627e60931a..e3d29eebb8 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -30,8 +30,6 @@ # define AI_ADDRCONFIG 0 #endif -static const int on=1, off=0; - /* used temporarily until all users are converted to QemuOpts */ QemuOptsList socket_optslist = { .name = "socket", @@ -159,6 +157,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) #ifdef IPV6_V6ONLY if (e->ai_family == PF_INET6) { /* listen on both ipv4 and ipv6 */ + const int off = 0; qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)); } |