From ff804f15a120dee62bdcf17a8db84bf59d83d6eb Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 7 Jun 2016 15:11:44 +0200 Subject: [PATCH 1/7] linux-headers: update Update to 4.7-rc2. Signed-off-by: Cornelia Huck --- include/standard-headers/linux/pci_regs.h | 20 ++++++++++++++++++- .../standard-headers/linux/virtio_config.h | 2 ++ linux-headers/asm-arm/unistd.h | 2 ++ linux-headers/asm-arm64/unistd.h | 3 +++ linux-headers/asm-powerpc/unistd.h | 2 ++ linux-headers/asm-s390/kvm.h | 1 + linux-headers/asm-s390/unistd.h | 4 +++- linux-headers/asm-x86/kvm.h | 6 +++--- linux-headers/asm-x86/unistd_x32.h | 2 ++ linux-headers/linux/kvm.h | 1 + 10 files changed, 38 insertions(+), 5 deletions(-) diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h index 1becea86c7..404095124a 100644 --- a/include/standard-headers/linux/pci_regs.h +++ b/include/standard-headers/linux/pci_regs.h @@ -670,7 +670,8 @@ #define PCI_EXT_CAP_ID_SECPCI 0x19 /* Secondary PCIe Capability */ #define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ #define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ -#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PASID +#define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */ +#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DPC #define PCI_EXT_CAP_DSN_SIZEOF 12 #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 @@ -946,4 +947,21 @@ #define PCI_TPH_CAP_ST_SHIFT 16 /* st table shift */ #define PCI_TPH_BASE_SIZEOF 12 /* size with no st table */ +/* Downstream Port Containment */ +#define PCI_EXP_DPC_CAP 4 /* DPC Capability */ +#define PCI_EXP_DPC_CAP_RP_EXT 0x20 /* Root Port Extensions for DPC */ +#define PCI_EXP_DPC_CAP_POISONED_TLP 0x40 /* Poisoned TLP Egress Blocking Supported */ +#define PCI_EXP_DPC_CAP_SW_TRIGGER 0x80 /* Software Triggering Supported */ +#define PCI_EXP_DPC_CAP_DL_ACTIVE 0x1000 /* ERR_COR signal on DL_Active supported */ + +#define PCI_EXP_DPC_CTL 6 /* DPC control */ +#define PCI_EXP_DPC_CTL_EN_NONFATAL 0x02 /* Enable trigger on ERR_NONFATAL message */ +#define PCI_EXP_DPC_CTL_INT_EN 0x08 /* DPC Interrupt Enable */ + +#define PCI_EXP_DPC_STATUS 8 /* DPC Status */ +#define PCI_EXP_DPC_STATUS_TRIGGER 0x01 /* Trigger Status */ +#define PCI_EXP_DPC_STATUS_INTERRUPT 0x08 /* Interrupt Status */ + +#define PCI_EXP_DPC_SOURCE_ID 10 /* DPC Source Identifier */ + #endif /* LINUX_PCI_REGS_H */ diff --git a/include/standard-headers/linux/virtio_config.h b/include/standard-headers/linux/virtio_config.h index bcc445b3d8..b30d0cb0c1 100644 --- a/include/standard-headers/linux/virtio_config.h +++ b/include/standard-headers/linux/virtio_config.h @@ -40,6 +40,8 @@ #define VIRTIO_CONFIG_S_DRIVER_OK 4 /* Driver has finished configuring features */ #define VIRTIO_CONFIG_S_FEATURES_OK 8 +/* Device entered invalid state, driver must reset it */ +#define VIRTIO_CONFIG_S_NEEDS_RESET 0x40 /* We've given up on this device. */ #define VIRTIO_CONFIG_S_FAILED 0x80 diff --git a/linux-headers/asm-arm/unistd.h b/linux-headers/asm-arm/unistd.h index 3f6f727929..ceb5450c81 100644 --- a/linux-headers/asm-arm/unistd.h +++ b/linux-headers/asm-arm/unistd.h @@ -418,6 +418,8 @@ #define __NR_membarrier (__NR_SYSCALL_BASE+389) #define __NR_mlock2 (__NR_SYSCALL_BASE+390) #define __NR_copy_file_range (__NR_SYSCALL_BASE+391) +#define __NR_preadv2 (__NR_SYSCALL_BASE+392) +#define __NR_pwritev2 (__NR_SYSCALL_BASE+393) /* * The following SWIs are ARM private. diff --git a/linux-headers/asm-arm64/unistd.h b/linux-headers/asm-arm64/unistd.h index 1caadc24e3..043d17a213 100644 --- a/linux-headers/asm-arm64/unistd.h +++ b/linux-headers/asm-arm64/unistd.h @@ -13,4 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +#define __ARCH_WANT_RENAMEAT + #include diff --git a/linux-headers/asm-powerpc/unistd.h b/linux-headers/asm-powerpc/unistd.h index cd92d982f0..1e66eba4c6 100644 --- a/linux-headers/asm-powerpc/unistd.h +++ b/linux-headers/asm-powerpc/unistd.h @@ -390,5 +390,7 @@ #define __NR_membarrier 365 #define __NR_mlock2 378 #define __NR_copy_file_range 379 +#define __NR_preadv2 380 +#define __NR_pwritev2 381 #endif /* _ASM_POWERPC_UNISTD_H_ */ diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h index a59499be0a..09ae5dc2e9 100644 --- a/linux-headers/asm-s390/kvm.h +++ b/linux-headers/asm-s390/kvm.h @@ -25,6 +25,7 @@ #define KVM_DEV_FLIC_APF_DISABLE_WAIT 5 #define KVM_DEV_FLIC_ADAPTER_REGISTER 6 #define KVM_DEV_FLIC_ADAPTER_MODIFY 7 +#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8 /* * We can have up to 4*64k pending subchannels + 8 adapter interrupts, * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. diff --git a/linux-headers/asm-s390/unistd.h b/linux-headers/asm-s390/unistd.h index 885837ed5e..8a404fd3a1 100644 --- a/linux-headers/asm-s390/unistd.h +++ b/linux-headers/asm-s390/unistd.h @@ -311,7 +311,9 @@ #define __NR_shutdown 373 #define __NR_mlock2 374 #define __NR_copy_file_range 375 -#define NR_syscalls 376 +#define __NR_preadv2 376 +#define __NR_pwritev2 377 +#define NR_syscalls 378 /* * There are some system calls that are not present on 64 bit, some diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h index cd54147cb3..739c0c5940 100644 --- a/linux-headers/asm-x86/kvm.h +++ b/linux-headers/asm-x86/kvm.h @@ -216,9 +216,9 @@ struct kvm_cpuid_entry2 { __u32 padding[3]; }; -#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0) -#define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1) -#define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2) +#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX (1 << 0) +#define KVM_CPUID_FLAG_STATEFUL_FUNC (1 << 1) +#define KVM_CPUID_FLAG_STATE_READ_NEXT (1 << 2) /* for KVM_SET_CPUID2 */ struct kvm_cpuid2 { diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h index 8f77ee868a..0230779a84 100644 --- a/linux-headers/asm-x86/unistd_x32.h +++ b/linux-headers/asm-x86/unistd_x32.h @@ -306,7 +306,9 @@ #define __NR_vmsplice (__X32_SYSCALL_BIT + 532) #define __NR_move_pages (__X32_SYSCALL_BIT + 533) #define __NR_preadv (__X32_SYSCALL_BIT + 534) +#define __NR_preadv2 (__X32_SYSCALL_BIT + 534) #define __NR_pwritev (__X32_SYSCALL_BIT + 535) +#define __NR_pwritev2 (__X32_SYSCALL_BIT + 535) #define __NR_rt_tgsigqueueinfo (__X32_SYSCALL_BIT + 536) #define __NR_recvmmsg (__X32_SYSCALL_BIT + 537) #define __NR_sendmmsg (__X32_SYSCALL_BIT + 538) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 3bae71a874..e60e21ba22 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -865,6 +865,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_SPAPR_TCE_64 125 #define KVM_CAP_ARM_PMU_V3 126 #define KVM_CAP_VCPU_ATTRIBUTES 127 +#define KVM_CAP_MAX_VCPU_ID 128 #ifdef KVM_CAP_IRQ_ROUTING From 9eccb8622c4dd9702d3bd3a7f1a60d744fe71a0b Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Wed, 27 Jan 2016 13:03:44 +0100 Subject: [PATCH 2/7] s390x/kvm: add interface for clearing IO irqs According to the platform specification, under certain conditions, pending IO interruptions have to be cleared. Let's add an interface for that. Signed-off-by: Halil Pasic Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- hw/intc/s390_flic.c | 8 ++++++++ hw/intc/s390_flic_kvm.c | 26 ++++++++++++++++++++++++++ include/hw/s390x/s390_flic.h | 2 ++ 3 files changed, 36 insertions(+) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index bc75fa7d95..6ab29efc65 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -67,6 +67,13 @@ static void qemu_s390_release_adapter_routes(S390FLICState *fs, { } +static int qemu_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr) +{ + /* Fixme TCG */ + return -ENOSYS; +} + static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) { S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); @@ -75,6 +82,7 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) fsc->io_adapter_map = qemu_s390_io_adapter_map; fsc->add_adapter_routes = qemu_s390_add_adapter_routes; fsc->release_adapter_routes = qemu_s390_release_adapter_routes; + fsc->clear_io_irq = qemu_s390_clear_io_flic; } static const TypeInfo qemu_s390_flic_info = { diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index eed6325cde..680857f0c7 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -30,6 +30,7 @@ typedef struct KVMS390FLICState { S390FLICState parent_obj; uint32_t fd; + bool clear_io_supported; } KVMS390FLICState; DeviceState *s390_flic_kvm_create(void) @@ -130,6 +131,24 @@ int kvm_s390_inject_flic(struct kvm_s390_irq *irq) return flic_enqueue_irqs(irq, sizeof(*irq), flic); } +static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr) +{ + KVMS390FLICState *flic = KVM_S390_FLIC(fs); + int rc; + uint32_t sid = subchannel_id << 16 | subchannel_nr; + struct kvm_device_attr attr = { + .group = KVM_DEV_FLIC_CLEAR_IO_IRQ, + .addr = (uint64_t) &sid, + .attr = sizeof(sid), + }; + if (unlikely(!flic->clear_io_supported)) { + return -ENOSYS; + } + rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); + return rc ? -errno : 0; +} + /** * __get_all_irqs - store all pending irqs in buffer * @flic: pointer to flic device state @@ -358,6 +377,7 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) { KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); struct kvm_create_device cd = {0}; + struct kvm_device_attr test_attr = {0}; int ret; flic_state->fd = -1; @@ -374,6 +394,11 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) } flic_state->fd = cd.fd; + /* Check clear_io_irq support */ + test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ; + flic_state->clear_io_supported = !ioctl(flic_state->fd, + KVM_HAS_DEVICE_ATTR, test_attr); + /* Register savevm handler for floating interrupts */ register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save, kvm_flic_load, (void *) flic_state); @@ -420,6 +445,7 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data) fsc->io_adapter_map = kvm_s390_io_adapter_map; fsc->add_adapter_routes = kvm_s390_add_adapter_routes; fsc->release_adapter_routes = kvm_s390_release_adapter_routes; + fsc->clear_io_irq = kvm_s390_clear_io_flic; } static const TypeInfo kvm_s390_flic_info = { diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index 200e7e93fa..1dac2ee48d 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -49,6 +49,8 @@ typedef struct S390FLICStateClass { bool do_map); int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); + int (*clear_io_irq)(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr); } S390FLICStateClass; #define TYPE_KVM_S390_FLIC "s390-flic-kvm" From c1755b14fade16f02d3e10a487a03741a2f317ce Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Wed, 27 Jan 2016 13:24:17 +0100 Subject: [PATCH 3/7] s390x/css: clear IO irqs when generating IPI CRW According to the Principles of Operation (more precisely the subsection 'Channel-Report Word'), a subchannel put into the installed parameters initialized state is in the same state as after an I/O system reset (just parameters possibly changed). This implies that any I/O interrupts for that subchannel are no longer pending (as I/O system resets clear I/O interrupts). Therefore, we need an interface to clear pending I/O interrupts. Make css_generate_sch_crws clear the pending IO interrupts for the subchannel. Signed-off-by: Halil Pasic Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 1675a19ac2..aceb1c0ee1 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -10,6 +10,7 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include #include "qemu/bitops.h" #include "exec/address-spaces.h" @@ -192,12 +193,46 @@ out: return ret; } -uint16_t css_build_subchannel_id(SubchDev *sch) +static void css_clear_io_interrupt(uint16_t subchannel_id, + uint16_t subchannel_nr) +{ + Error *err = NULL; + static bool no_clear_irq; + S390FLICState *fs = s390_get_flic(); + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); + int r; + + if (unlikely(no_clear_irq)) { + return; + } + r = fsc->clear_io_irq(fs, subchannel_id, subchannel_nr); + switch (r) { + case 0: + break; + case -ENOSYS: + no_clear_irq = true; + /* + * Ignore unavailability, as the user can't do anything + * about it anyway. + */ + break; + default: + error_setg_errno(&err, -r, "unexpected error condition"); + error_propagate(&error_abort, err); + } +} + +static inline uint16_t css_do_build_subchannel_id(uint8_t cssid, uint8_t ssid) { if (channel_subsys.max_cssid > 0) { - return (sch->cssid << 8) | (1 << 3) | (sch->ssid << 1) | 1; + return (cssid << 8) | (1 << 3) | (ssid << 1) | 1; } - return (sch->ssid << 1) | 1; + return (ssid << 1) | 1; +} + +uint16_t css_build_subchannel_id(SubchDev *sch) +{ + return css_do_build_subchannel_id(sch->cssid, sch->ssid); } static void css_inject_io_interrupt(SubchDev *sch) @@ -1429,6 +1464,8 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0, (guest_cssid << 8) | (ssid << 4)); } + /* RW_ERC_IPI --> clear pending interrupts */ + css_clear_io_interrupt(css_do_build_subchannel_id(cssid, ssid), schid); } void css_generate_chp_crws(uint8_t cssid, uint8_t chpid) From 06e686eaab344b1d38125e49abeb31a416428201 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 1 Apr 2016 13:42:04 +0200 Subject: [PATCH 4/7] s390x/css: introduce property type for device ids Let's introduce a CssDevId to handle device ids of the xx.x.xxxx type used for channel devices. This has some benefits: - We can use them in virtio-ccw and split the validity checks for a channel device id in general from the constraint checking within the virtio-ccw scope. - We can reuse the device id type for future non-virtio channel devices. While we're at it, improve the validity checks and disallow e.g. trailing characters. Suggested-by: Dong Jia Shi Acked-by: David Hildenbrand Reviewed-by: Dong Jia Shi Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 81 ++++++++++++++++++++++++++++++++++++++++++ hw/s390x/virtio-ccw.c | 81 +++++++++++++++++------------------------- hw/s390x/virtio-ccw.h | 2 +- include/hw/s390x/css.h | 17 +++++++++ 4 files changed, 132 insertions(+), 49 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index aceb1c0ee1..76668814da 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -11,6 +11,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qapi/visitor.h" #include #include "qemu/bitops.h" #include "exec/address-spaces.h" @@ -1681,3 +1682,83 @@ void css_reset(void) channel_subsys.max_cssid = 0; channel_subsys.max_ssid = 0; } + +static void get_css_devid(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + CssDevId *dev_id = qdev_get_prop_ptr(dev, prop); + char buffer[] = "xx.x.xxxx"; + char *p = buffer; + int r; + + if (dev_id->valid) { + + r = snprintf(buffer, sizeof(buffer), "%02x.%1x.%04x", dev_id->cssid, + dev_id->ssid, dev_id->devid); + assert(r == sizeof(buffer) - 1); + + /* drop leading zero */ + if (dev_id->cssid <= 0xf) { + p++; + } + } else { + snprintf(buffer, sizeof(buffer), ""); + } + + visit_type_str(v, name, &p, errp); +} + +/* + * parse .. and assert valid range for cssid/ssid + */ +static void set_css_devid(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + CssDevId *dev_id = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + char *str; + int num, n1, n2; + unsigned int cssid, ssid, devid; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_str(v, name, &str, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + num = sscanf(str, "%2x.%1x%n.%4x%n", &cssid, &ssid, &n1, &devid, &n2); + if (num != 3 || (n2 - n1) != 5 || strlen(str) != n2) { + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); + goto out; + } + if ((cssid > MAX_CSSID) || (ssid > MAX_SSID)) { + error_setg(errp, "Invalid cssid or ssid: cssid %x, ssid %x", + cssid, ssid); + goto out; + } + + dev_id->cssid = cssid; + dev_id->ssid = ssid; + dev_id->devid = devid; + dev_id->valid = true; + +out: + g_free(str); +} + +PropertyInfo css_devid_propinfo = { + .name = "str", + .description = "Identifier of an I/O device in the channel " + "subsystem, example: fe.1.23ab", + .get = get_css_devid, + .set = set_css_devid, +}; diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 2b68e5e87d..e62a3a344e 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -737,14 +737,9 @@ static void virtio_sch_disable_cb(SubchDev *sch) static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp) { - unsigned int cssid = 0; - unsigned int ssid = 0; unsigned int schid; - unsigned int devno; - bool have_devno = false; bool found = false; SubchDev *sch; - int num; Error *err = NULL; VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev); @@ -763,54 +758,44 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp) * Use a device number if provided. Otherwise, fall back to subchannel * number. */ - if (dev->bus_id) { - num = sscanf(dev->bus_id, "%x.%x.%04x", &cssid, &ssid, &devno); - if (num == 3) { - if ((cssid > MAX_CSSID) || (ssid > MAX_SSID)) { - error_setg(errp, "Invalid cssid or ssid: cssid %x, ssid %x", - cssid, ssid); - goto out_err; - } - /* Enforce use of virtual cssid. */ - if (cssid != VIRTUAL_CSSID) { - error_setg(errp, "cssid %x not valid for virtio devices", - cssid); - goto out_err; - } - if (css_devno_used(cssid, ssid, devno)) { - error_setg(errp, "Device %x.%x.%04x already exists", - cssid, ssid, devno); - goto out_err; - } - sch->cssid = cssid; - sch->ssid = ssid; - sch->devno = devno; - have_devno = true; - } else { - error_setg(errp, "Malformed devno parameter '%s'", dev->bus_id); + if (dev->bus_id.valid) { + /* Enforce use of virtual cssid. */ + if (dev->bus_id.cssid != VIRTUAL_CSSID) { + error_setg(errp, "cssid %x not valid for virtio devices", + dev->bus_id.cssid); goto out_err; } - } + if (css_devno_used(dev->bus_id.cssid, dev->bus_id.ssid, + dev->bus_id.devid)) { + error_setg(errp, "Device %x.%x.%04x already exists", + dev->bus_id.cssid, dev->bus_id.ssid, + dev->bus_id.devid); + goto out_err; + } + sch->cssid = dev->bus_id.cssid; + sch->ssid = dev->bus_id.ssid; + sch->devno = dev->bus_id.devid; - /* Find the next free id. */ - if (have_devno) { + /* Find the next free id. */ for (schid = 0; schid <= MAX_SCHID; schid++) { - if (!css_find_subch(1, cssid, ssid, schid)) { + if (!css_find_subch(1, sch->cssid, sch->ssid, schid)) { sch->schid = schid; - css_subch_assign(cssid, ssid, schid, devno, sch); + css_subch_assign(sch->cssid, sch->ssid, sch->schid, + sch->devno, sch); found = true; break; } } if (!found) { error_setg(errp, "No free subchannel found for %x.%x.%04x", - cssid, ssid, devno); + sch->cssid, sch->ssid, sch->devno); goto out_err; } - trace_virtio_ccw_new_device(cssid, ssid, schid, devno, - "user-configured"); + trace_virtio_ccw_new_device(sch->cssid, sch->ssid, sch->schid, + sch->devno, "user-configured"); } else { - cssid = VIRTUAL_CSSID; + unsigned int cssid = VIRTUAL_CSSID, ssid, devno; + for (ssid = 0; ssid <= MAX_SSID; ssid++) { for (schid = 0; schid <= MAX_SCHID; schid++) { if (!css_find_subch(1, cssid, ssid, schid)) { @@ -868,7 +853,7 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp) } if (err) { error_propagate(errp, err); - css_subch_assign(cssid, ssid, schid, devno, NULL); + css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL); goto out_err; } @@ -1516,7 +1501,7 @@ static void virtio_ccw_device_unplugged(DeviceState *d) /**************** Virtio-ccw Bus Device Descriptions *******************/ static Property virtio_ccw_net_properties[] = { - DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1545,7 +1530,7 @@ static const TypeInfo virtio_ccw_net = { }; static Property virtio_ccw_blk_properties[] = { - DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1574,7 +1559,7 @@ static const TypeInfo virtio_ccw_blk = { }; static Property virtio_ccw_serial_properties[] = { - DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1603,7 +1588,7 @@ static const TypeInfo virtio_ccw_serial = { }; static Property virtio_ccw_balloon_properties[] = { - DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1632,7 +1617,7 @@ static const TypeInfo virtio_ccw_balloon = { }; static Property virtio_ccw_scsi_properties[] = { - DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1662,7 +1647,7 @@ static const TypeInfo virtio_ccw_scsi = { #ifdef CONFIG_VHOST_SCSI static Property vhost_ccw_scsi_properties[] = { - DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, VIRTIO_CCW_MAX_REV), DEFINE_PROP_END_OF_LIST(), @@ -1700,7 +1685,7 @@ static void virtio_ccw_rng_instance_init(Object *obj) } static Property virtio_ccw_rng_properties[] = { - DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, @@ -1856,7 +1841,7 @@ static const TypeInfo virtio_ccw_bus_info = { #ifdef CONFIG_VIRTFS static Property virtio_ccw_9p_properties[] = { - DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 86b9edb18f..0bfb5d93c6 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -80,7 +80,7 @@ typedef struct VirtIOCCWDeviceClass { struct VirtioCcwDevice { DeviceState parent_obj; SubchDev *sch; - char *bus_id; + CssDevId bus_id; int revision; uint32_t max_rev; VirtioBusState bus; diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index 98b2e2cc79..38f4d77779 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -151,5 +151,22 @@ int css_do_rsch(SubchDev *sch); int css_do_rchp(uint8_t cssid, uint8_t chpid); bool css_present(uint8_t cssid); #endif +/* + * Identify a device within the channel subsystem. + * Note that this can be used to identify either the subchannel or + * the attached I/O device, as there's always one I/O device per + * subchannel. + */ +typedef struct CssDevId { + uint8_t cssid; + uint8_t ssid; + uint16_t devid; + bool valid; +} CssDevId; + +extern PropertyInfo css_devid_propinfo; + +#define DEFINE_PROP_CSS_DEV_ID(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, css_devid_propinfo, CssDevId) #endif From 06409bd91b0a40f30d2e41159627a6eb8f5ac322 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 2 Jun 2016 10:57:37 +0200 Subject: [PATCH 5/7] virtio-ccw: Provide traces for indicator changes This allows to trace changes in the summary and queue indicators for the non-irqfd case. For irqfd, kernel traces are needed instead. Signed-off-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- hw/s390x/virtio-ccw.c | 1 + trace-events | 1 + 2 files changed, 2 insertions(+) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index e62a3a344e..2192be8774 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1091,6 +1091,7 @@ static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc, ind_old = *ind_addr; ind_new = ind_old | to_be_set; } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old); + trace_virtio_ccw_set_ind(ind_loc, ind_old, ind_new); cpu_physical_memory_unmap(ind_addr, len, 1, len); return ind_old; diff --git a/trace-events b/trace-events index 421d89f476..2f14205de0 100644 --- a/trace-events +++ b/trace-events @@ -1475,6 +1475,7 @@ css_adapter_interrupt(uint8_t isc) "CSS: adapter I/O interrupt (isc %x)" # hw/s390x/virtio-ccw.c virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) "VIRTIO-CCW: %x.%x.%04x: interpret command %x" virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char *devno_mode) "VIRTIO-CCW: add subchannel %x.%x.%04x, devno %04x (%s)" +virtio_ccw_set_ind(uint64_t ind_loc, uint8_t ind_old, uint8_t ind_new) "VIRTIO-CCW: indicator at %" PRIu64 ": %x->%x" # hw/intc/s390_flic_kvm.c flic_create_device(int err) "flic: create device failed %d" From dcddc75e4756eac166bb002f71dfb09aca9b59fc Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 2 Jun 2016 14:06:10 +0200 Subject: [PATCH 6/7] s390x: Limit s390-ccw machines to 248 CPUs The sclp scp read info call fills in a buffer with information about the system. With more than 248 CPUs we overflow the 4k buffer of the SCCB, leading to random data corruption. Basically ALL guest operating systems call scp read info, so let's limit the machines to 248 CPUs to make it obvious that >=249 does not work. As KVM also limits itself to 248 and TCG on s390 does not support SMP, this should cause no regression for any user as no VMs with more than 248 VCPUs were ever possible. Signed-off-by: Christian Borntraeger Reviewed-by: David Hildenbrand Reviewed-by: Boris Fiuczynski Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-ccw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 95ff5e35ae..e257ca5ab0 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -204,7 +204,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) mc->no_parallel = 1; mc->no_sdcard = 1; mc->use_sclp = 1; - mc->max_cpus = 255; + mc->max_cpus = 248; mc->get_hotplug_handler = s390_get_hotplug_handler; hc->plug = s390_machine_device_plug; nc->nmi_monitor_handler = s390_nmi; From 393ad2a4a15db3836698de0e11249b4ec9dafb11 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 6 Jun 2016 16:57:50 +0200 Subject: [PATCH 7/7] s390x/kvm: Fixup interrupt type for non-adapter I/O interrupts The current algorithm for I/O interrupts would result in a wrong interrupt type for subchannel numbers fffe and ffff. In addition a non adapter interrupt might look like an adapter interrupt for any subchannel number that has the 0x0400 bit set. No kernel has ever used the type outside logging - and the logging was wrong all the time. For everything else the kernel used the interrupt parameters. Let's use the KVM_S390_INT_IO macro as for adapter interrupts. Signed-off-by: Christian Borntraeger Reviewed-by: David Hildenbrand Acked-by: Cornelia Huck Signed-off-by: Cornelia Huck --- target-s390x/kvm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 8f46fd0f10..f108cd3875 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -2071,8 +2071,9 @@ void kvm_s390_io_interrupt(uint16_t subchannel_id, if (io_int_word & IO_INT_WORD_AI) { irq.type = KVM_S390_INT_IO(1, 0, 0, 0); } else { - irq.type = ((subchannel_id & 0xff00) << 24) | - ((subchannel_id & 0x00060) << 22) | (subchannel_nr << 16); + irq.type = KVM_S390_INT_IO(0, (subchannel_id & 0xff00) >> 8, + (subchannel_id & 0x0006), + subchannel_nr); } kvm_s390_floating_interrupt(&irq); }