From 66fb2d5467cc93feecc12d3bbab860d7615b6616 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 22 Feb 2016 13:36:17 +0100 Subject: [PATCH 01/14] linux-headers: update against kvm/next Update against commit efef127c, but keep userfaultd.h. Signed-off-by: Cornelia Huck --- linux-headers/asm-arm/unistd.h | 2 ++ linux-headers/asm-powerpc/unistd.h | 13 +------------ linux-headers/asm-s390/kvm.h | 11 +++++++++-- linux-headers/asm-s390/unistd.h | 3 ++- linux-headers/asm-x86/unistd_32.h | 1 + linux-headers/asm-x86/unistd_64.h | 1 + linux-headers/asm-x86/unistd_x32.h | 1 + linux-headers/linux/kvm.h | 9 ++++++++- linux-headers/linux/vfio.h | 9 +++++++++ 9 files changed, 34 insertions(+), 16 deletions(-) diff --git a/linux-headers/asm-arm/unistd.h b/linux-headers/asm-arm/unistd.h index 0a1376c357..3f6f727929 100644 --- a/linux-headers/asm-arm/unistd.h +++ b/linux-headers/asm-arm/unistd.h @@ -416,6 +416,8 @@ #define __NR_execveat (__NR_SYSCALL_BASE+387) #define __NR_userfaultfd (__NR_SYSCALL_BASE+388) #define __NR_membarrier (__NR_SYSCALL_BASE+389) +#define __NR_mlock2 (__NR_SYSCALL_BASE+390) +#define __NR_copy_file_range (__NR_SYSCALL_BASE+391) /* * The following SWIs are ARM private. diff --git a/linux-headers/asm-powerpc/unistd.h b/linux-headers/asm-powerpc/unistd.h index 1bf7e36747..cd92d982f0 100644 --- a/linux-headers/asm-powerpc/unistd.h +++ b/linux-headers/asm-powerpc/unistd.h @@ -388,18 +388,7 @@ #define __NR_switch_endian 363 #define __NR_userfaultfd 364 #define __NR_membarrier 365 -#define __NR_semop 366 -#define __NR_semget 367 -#define __NR_semctl 368 -#define __NR_semtimedop 369 -#define __NR_msgsnd 370 -#define __NR_msgrcv 371 -#define __NR_msgget 372 -#define __NR_msgctl 373 -#define __NR_shmat 374 -#define __NR_shmdt 375 -#define __NR_shmget 376 -#define __NR_shmctl 377 #define __NR_mlock2 378 +#define __NR_copy_file_range 379 #endif /* _ASM_POWERPC_UNISTD_H_ */ diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h index ac213a153a..a59499be0a 100644 --- a/linux-headers/asm-s390/kvm.h +++ b/linux-headers/asm-s390/kvm.h @@ -153,6 +153,8 @@ struct kvm_guest_debug_arch { #define KVM_SYNC_ARCH0 (1UL << 4) #define KVM_SYNC_PFAULT (1UL << 5) #define KVM_SYNC_VRS (1UL << 6) +#define KVM_SYNC_RICCB (1UL << 7) +#define KVM_SYNC_FPRS (1UL << 8) /* definition of registers in kvm_run */ struct kvm_sync_regs { __u64 prefix; /* prefix register */ @@ -167,9 +169,14 @@ struct kvm_sync_regs { __u64 pft; /* pfault token [PFAULT] */ __u64 pfs; /* pfault select [PFAULT] */ __u64 pfc; /* pfault compare [PFAULT] */ - __u64 vrs[32][2]; /* vector registers */ + union { + __u64 vrs[32][2]; /* vector registers (KVM_SYNC_VRS) */ + __u64 fprs[16]; /* fp registers (KVM_SYNC_FPRS) */ + }; __u8 reserved[512]; /* for future vector expansion */ - __u32 fpc; /* only valid with vector registers */ + __u32 fpc; /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */ + __u8 padding[52]; /* riccb needs to be 64byte aligned */ + __u8 riccb[64]; /* runtime instrumentation controls block */ }; #define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1) diff --git a/linux-headers/asm-s390/unistd.h b/linux-headers/asm-s390/unistd.h index bccd002258..885837ed5e 100644 --- a/linux-headers/asm-s390/unistd.h +++ b/linux-headers/asm-s390/unistd.h @@ -310,7 +310,8 @@ #define __NR_recvmsg 372 #define __NR_shutdown 373 #define __NR_mlock2 374 -#define NR_syscalls 375 +#define __NR_copy_file_range 375 +#define NR_syscalls 376 /* * There are some system calls that are not present on 64 bit, some diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h index 30ff8fc56b..a1525426d8 100644 --- a/linux-headers/asm-x86/unistd_32.h +++ b/linux-headers/asm-x86/unistd_32.h @@ -374,5 +374,6 @@ #define __NR_userfaultfd 374 #define __NR_membarrier 375 #define __NR_mlock2 376 +#define __NR_copy_file_range 377 #endif /* _ASM_X86_UNISTD_32_H */ diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h index c8f7959390..4f67c5446a 100644 --- a/linux-headers/asm-x86/unistd_64.h +++ b/linux-headers/asm-x86/unistd_64.h @@ -327,5 +327,6 @@ #define __NR_userfaultfd 323 #define __NR_membarrier 324 #define __NR_mlock2 325 +#define __NR_copy_file_range 326 #endif /* _ASM_X86_UNISTD_64_H */ diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h index 27003f3049..8f77ee868a 100644 --- a/linux-headers/asm-x86/unistd_x32.h +++ b/linux-headers/asm-x86/unistd_x32.h @@ -282,6 +282,7 @@ #define __NR_userfaultfd (__X32_SYSCALL_BIT + 323) #define __NR_membarrier (__X32_SYSCALL_BIT + 324) #define __NR_mlock2 (__X32_SYSCALL_BIT + 325) +#define __NR_copy_file_range (__X32_SYSCALL_BIT + 326) #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512) #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513) #define __NR_ioctl (__X32_SYSCALL_BIT + 514) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 4e20262597..4a56b9ea76 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -541,7 +541,13 @@ struct kvm_s390_pgm_info { __u8 exc_access_id; __u8 per_access_id; __u8 op_access_id; - __u8 pad[3]; +#define KVM_S390_PGM_FLAGS_ILC_VALID 0x01 +#define KVM_S390_PGM_FLAGS_ILC_0 0x02 +#define KVM_S390_PGM_FLAGS_ILC_1 0x04 +#define KVM_S390_PGM_FLAGS_ILC_MASK 0x06 +#define KVM_S390_PGM_FLAGS_NO_REWIND 0x08 + __u8 flags; + __u8 pad[2]; }; struct kvm_s390_prefix_info { @@ -849,6 +855,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_SPLIT_IRQCHIP 121 #define KVM_CAP_IOEVENTFD_ANY_LENGTH 122 #define KVM_CAP_HYPERV_SYNIC 123 +#define KVM_CAP_S390_RI 124 #ifdef KVM_CAP_IRQ_ROUTING diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h index aa276bce39..15e096c43a 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -38,6 +38,13 @@ #define VFIO_SPAPR_TCE_v2_IOMMU 7 +/* + * The No-IOMMU IOMMU offers no translation or isolation for devices and + * supports no ioctls outside of VFIO_CHECK_EXTENSION. Use of VFIO's No-IOMMU + * code will taint the host kernel and should be used with extreme caution. + */ +#define VFIO_NOIOMMU_IOMMU 8 + /* * The IOCTL interface is designed for extensibility by embedding the * structure length (argsz) and flags into structures passed between @@ -568,8 +575,10 @@ struct vfio_iommu_spapr_tce_create { __u32 flags; /* in */ __u32 page_shift; + __u32 __resv1; __u64 window_size; __u32 levels; + __u32 __resv2; /* out */ __u64 start_addr; }; From 5ab0e547bf230a6128caf898ef7706bd226514d4 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Tue, 2 Feb 2016 09:08:58 +0100 Subject: [PATCH 02/14] s390x/kvm: sync fprs via kvm_run We can now also sync the fprs via kvm_run, avoiding one ioctl. Reviewed-by: Christian Borntraeger Signed-off-by: David Hildenbrand Signed-off-by: Cornelia Huck --- target-s390x/kvm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 9b21b96da5..67636567e1 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -342,6 +342,12 @@ int kvm_arch_put_registers(CPUState *cs, int level) } cs->kvm_run->s.regs.fpc = env->fpc; cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_VRS; + } else if (can_sync_regs(cs, KVM_SYNC_FPRS)) { + for (i = 0; i < 16; i++) { + cs->kvm_run->s.regs.fprs[i] = get_freg(env, i)->ll; + } + cs->kvm_run->s.regs.fpc = env->fpc; + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_FPRS; } else { /* Floating point */ for (i = 0; i < 16; i++) { @@ -482,6 +488,11 @@ int kvm_arch_get_registers(CPUState *cs) env->vregs[i][1].ll = cs->kvm_run->s.regs.vrs[i][1]; } env->fpc = cs->kvm_run->s.regs.fpc; + } else if (can_sync_regs(cs, KVM_SYNC_FPRS)) { + for (i = 0; i < 16; i++) { + get_freg(env, i)->ll = cs->kvm_run->s.regs.fprs[i]; + } + env->fpc = cs->kvm_run->s.regs.fpc; } else { r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu); if (r < 0) { From c5b2ee4c7a2fa573042344c9ec5f0f217a099d84 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Mon, 25 Jan 2016 09:03:57 +0100 Subject: [PATCH 03/14] s390x: fix debug statement in trigger_page_fault() When mmu_translate debugging output is enabled, code won't compile. Let's just use the same statement as in trigger_prot_fault(). Acked-by: Cornelia Huck Signed-off-by: David Hildenbrand Signed-off-by: Cornelia Huck --- target-s390x/mmu_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c index 5323c53541..b11a02706c 100644 --- a/target-s390x/mmu_helper.c +++ b/target-s390x/mmu_helper.c @@ -90,7 +90,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | asc >> 46; - DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits); + DPRINTF("%s: trans_exc_code=%016" PRIx64 "\n", __func__, tec); if (!exc) { return; From 8777f6abdbf7017b7aea38dcee2f389f61925ed8 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 27 Jan 2016 13:39:53 +0100 Subject: [PATCH 04/14] s390x: remove {kvm_}s390_virtio_irq() This interface was only used by the old virtio machine and therefore is not needed anymore. Reviewed-by: David Hildenbrand Reviewed-by: Halil Pasic Signed-off-by: Cornelia Huck --- target-s390x/cpu.h | 5 ----- target-s390x/interrupt.c | 11 ----------- target-s390x/kvm.c | 11 ----------- 3 files changed, 27 deletions(-) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 6ae5699e0b..49c84155be 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -470,10 +470,8 @@ 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_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); @@ -484,9 +482,6 @@ int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock); #else -static inline void kvm_s390_virtio_irq(int config_change, uint64_t token) -{ -} static inline void kvm_s390_service_interrupt(uint32_t parm) { } diff --git a/target-s390x/interrupt.c b/target-s390x/interrupt.c index 07d210acf7..bad60a7e13 100644 --- a/target-s390x/interrupt.c +++ b/target-s390x/interrupt.c @@ -28,17 +28,6 @@ void s390_sclp_extint(uint32_t parm) } } -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) { diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 67636567e1..e1859cae04 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -936,17 +936,6 @@ void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq) __kvm_s390_floating_interrupt(irq); } -void kvm_s390_virtio_irq(int config_change, uint64_t token) -{ - 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 = { From fe345a3d5d7ed4bc2965c65542832b1fa785ae9d Mon Sep 17 00:00:00 2001 From: Sascha Silbe Date: Fri, 29 Jan 2016 15:51:45 +0100 Subject: [PATCH 05/14] watchdog/diag288: avoid race condition on expired watchdog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When configured to inject an NMI, watchdog_perform_action() may cause the BQL to be temporarily relinquished (inject_nmi() → ... → s390_nmi() → s390_cpu_restart() → run_on_cpu()). When the guest issues diag 288 again in response to the NMI, the diag 288 operation will race against wdt_diag288_reset(). Depending on scheduler behaviour, wdt_diag288_reset() may be run after the guest issued a diag 288 Init. As a result, we will cancel the timer the guest just set up. The effect observed by the guest is that a second expiry does not trigger the watchdog action and diag 288 Change operations fail. Fix this by resetting the timer _before_ invoking the action. Signed-off-by: Sascha Silbe Acked-by: David Hildenbrand Signed-off-by: Cornelia Huck --- hw/watchdog/wdt_diag288.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c index 5eb5b94e43..1c3658e4a8 100644 --- a/hw/watchdog/wdt_diag288.c +++ b/hw/watchdog/wdt_diag288.c @@ -51,15 +51,19 @@ static void diag288_reset(void *opaque) static void diag288_timer_expired(void *dev) { qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n"); - watchdog_perform_action(); - /* Reset the watchdog only if the guest was notified about expiry. */ + /* Reset the watchdog only if the guest gets notified about + * expiry. watchdog_perform_action() may temporarily relinquish + * the BQL; reset before triggering the action to avoid races with + * diag288 instructions. */ switch (get_watchdog_action()) { case WDT_DEBUG: case WDT_NONE: case WDT_PAUSE: - return; + break; + default: + wdt_diag288_reset(dev); } - wdt_diag288_reset(dev); + watchdog_perform_action(); } static int wdt_diag288_handle_timer(DIAG288State *diag288, From 99abd0d6f75109b58dbd662134d8d013999e1e8f Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 10 Feb 2016 13:22:32 +0100 Subject: [PATCH 06/14] s390x/virtio: old machine leftovers Remove some now unused #defines. Reviewed-By: Sascha Silbe Reviewed-by: Halil Pasic Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index c320878024..8e533ae88a 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -54,8 +54,6 @@ #endif #define MAX_BLK_DEVS 10 -#define S390_MACHINE "s390-virtio" -#define TYPE_S390_MACHINE MACHINE_TYPE_NAME(S390_MACHINE) #define S390_TOD_CLOCK_VALUE_MISSING 0x00 #define S390_TOD_CLOCK_VALUE_PRESENT 0x01 From a28d8391e323ef586c44e9313826097f884eebc6 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Wed, 27 Jan 2016 16:05:26 +0800 Subject: [PATCH 07/14] s390x/css: introduce indicator refcounting interfaces Currently, virtio-ccw uses its own interfaces to keep indicators mapped just once even if the same address has been registered multiple times. These interfaces fit the PCI use case as well. Therefore, move them to css and make them generic interfaces. Signed-off-by: Yi Min Zhao Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 63 +++++++++++++++++++++++++++++++++++++++++++ hw/s390x/css.h | 14 ++++++++++ hw/s390x/virtio-ccw.c | 63 ------------------------------------------- hw/s390x/virtio-ccw.h | 11 ++------ 4 files changed, 79 insertions(+), 72 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index c29068b30d..c02f5bca8d 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -60,10 +60,72 @@ typedef struct ChannelSubSys { CssImage *css[MAX_CSSID + 1]; uint8_t default_cssid; QTAILQ_HEAD(, IoAdapter) io_adapters; + QTAILQ_HEAD(, IndAddr) indicator_addresses; } ChannelSubSys; static ChannelSubSys *channel_subsys; +IndAddr *get_indicator(hwaddr ind_addr, int len) +{ + IndAddr *indicator; + + QTAILQ_FOREACH(indicator, &channel_subsys->indicator_addresses, sibling) { + if (indicator->addr == ind_addr) { + indicator->refcnt++; + return indicator; + } + } + indicator = g_new0(IndAddr, 1); + indicator->addr = ind_addr; + indicator->len = len; + indicator->refcnt = 1; + QTAILQ_INSERT_TAIL(&channel_subsys->indicator_addresses, + indicator, sibling); + return indicator; +} + +static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr, + bool do_map) +{ + S390FLICState *fs = s390_get_flic(); + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); + + return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map); +} + +void release_indicator(AdapterInfo *adapter, IndAddr *indicator) +{ + assert(indicator->refcnt > 0); + indicator->refcnt--; + if (indicator->refcnt > 0) { + return; + } + QTAILQ_REMOVE(&channel_subsys->indicator_addresses, indicator, sibling); + if (indicator->map) { + s390_io_adapter_map(adapter, indicator->map, false); + } + g_free(indicator); +} + +int map_indicator(AdapterInfo *adapter, IndAddr *indicator) +{ + int ret; + + if (indicator->map) { + return 0; /* already mapped is not an error */ + } + indicator->map = indicator->addr; + ret = s390_io_adapter_map(adapter, indicator->map, true); + if ((ret != 0) && (ret != -ENOSYS)) { + goto out_err; + } + return 0; + +out_err: + indicator->map = 0; + return ret; +} + int css_create_css_image(uint8_t cssid, bool default_image) { trace_css_new_image(cssid, default_image ? "(default)" : ""); @@ -1524,6 +1586,7 @@ static void css_init(void) channel_subsys->crws_lost = false; channel_subsys->chnmon_active = false; QTAILQ_INIT(&channel_subsys->io_adapters); + QTAILQ_INIT(&channel_subsys->indicator_addresses); } machine_init(css_init); diff --git a/hw/s390x/css.h b/hw/s390x/css.h index a47937dee5..a320eea59c 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -12,6 +12,8 @@ #ifndef CSS_H #define CSS_H +#include "hw/s390x/adapter.h" +#include "hw/s390x/s390_flic.h" #include "ioinst.h" /* Channel subsystem constants. */ @@ -86,6 +88,18 @@ struct SubchDev { void *driver_data; }; +typedef struct IndAddr { + hwaddr addr; + uint64_t map; + unsigned long refcnt; + int len; + QTAILQ_ENTRY(IndAddr) sibling; +} IndAddr; + +IndAddr *get_indicator(hwaddr ind_addr, int len); +void release_indicator(AdapterInfo *adapter, IndAddr *indicator); +int map_indicator(AdapterInfo *adapter, IndAddr *indicator); + 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); diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 74b9e2e22b..cb887ba7e2 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -32,69 +32,6 @@ #include "virtio-ccw.h" #include "trace.h" -static QTAILQ_HEAD(, IndAddr) indicator_addresses = - QTAILQ_HEAD_INITIALIZER(indicator_addresses); - -static IndAddr *get_indicator(hwaddr ind_addr, int len) -{ - IndAddr *indicator; - - QTAILQ_FOREACH(indicator, &indicator_addresses, sibling) { - if (indicator->addr == ind_addr) { - indicator->refcnt++; - return indicator; - } - } - indicator = g_new0(IndAddr, 1); - indicator->addr = ind_addr; - indicator->len = len; - indicator->refcnt = 1; - QTAILQ_INSERT_TAIL(&indicator_addresses, indicator, sibling); - return indicator; -} - -static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr, - bool do_map) -{ - S390FLICState *fs = s390_get_flic(); - S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); - - return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map); -} - -static void release_indicator(AdapterInfo *adapter, IndAddr *indicator) -{ - assert(indicator->refcnt > 0); - indicator->refcnt--; - if (indicator->refcnt > 0) { - return; - } - QTAILQ_REMOVE(&indicator_addresses, indicator, sibling); - if (indicator->map) { - s390_io_adapter_map(adapter, indicator->map, false); - } - g_free(indicator); -} - -static int map_indicator(AdapterInfo *adapter, IndAddr *indicator) -{ - int ret; - - if (indicator->map) { - return 0; /* already mapped is not an error */ - } - indicator->map = indicator->addr; - ret = s390_io_adapter_map(adapter, indicator->map, true); - if ((ret != 0) && (ret != -ENOSYS)) { - goto out_err; - } - return 0; - -out_err: - indicator->map = 0; - return ret; -} - static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, VirtioCcwDevice *dev); diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index a526d2f2ae..66c831ba84 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -23,7 +23,8 @@ #include #include #include -#include + +#include "css.h" #define VIRTUAL_CSSID 0xfe @@ -75,14 +76,6 @@ typedef struct VirtIOCCWDeviceClass { #define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1 #define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT) -typedef struct IndAddr { - hwaddr addr; - uint64_t map; - unsigned long refcnt; - int len; - QTAILQ_ENTRY(IndAddr) sibling; -} IndAddr; - struct VirtioCcwDevice { DeviceState parent_obj; SubchDev *sch; From 8581c115d2b995e216223f9f9d29fb4810474dc4 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Thu, 28 Jan 2016 13:26:43 +0800 Subject: [PATCH 08/14] s390x/pci: fix reg/dereg irq functions Indicator refcounting interfaces are introduced. This patch fixes introducing unneeded indicator mappings and failure to release AISB mappings on deregistration. Signed-off-by: Yi Min Zhao Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-bus.h | 2 ++ hw/s390x/s390-pci-inst.c | 23 +++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index d8ddb77281..59fd5c9583 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -233,6 +233,8 @@ typedef struct S390PCIBusDevice { AddressSpace as; MemoryRegion mr; MemoryRegion iommu_mr; + IndAddr *summary_ind; + IndAddr *indicator; } S390PCIBusDevice; typedef struct S390pciState { diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index fe73ca8819..506147d670 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -621,19 +621,19 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib) { - int ret; - S390FLICState *fs = s390_get_flic(); - S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); + int ret, len; ret = css_register_io_adapter(S390_PCIPT_ADAPTER, FIB_DATA_ISC(ldl_p(&fib.data)), true, false, &pbdev->routes.adapter.adapter_id); assert(ret == 0); - fsc->io_adapter_map(fs, pbdev->routes.adapter.adapter_id, - ldq_p(&fib.aisb), true); - fsc->io_adapter_map(fs, pbdev->routes.adapter.adapter_id, - ldq_p(&fib.aibv), true); + pbdev->summary_ind = get_indicator(ldq_p(&fib.aisb), sizeof(uint64_t)); + len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long); + pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len); + + map_indicator(&pbdev->routes.adapter, pbdev->summary_ind); + map_indicator(&pbdev->routes.adapter, pbdev->indicator); pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb); pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data)); @@ -649,12 +649,11 @@ static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib) static int dereg_irqs(S390PCIBusDevice *pbdev) { - S390FLICState *fs = s390_get_flic(); - S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); - - fsc->io_adapter_map(fs, pbdev->routes.adapter.adapter_id, - pbdev->routes.adapter.ind_addr, false); + release_indicator(&pbdev->routes.adapter, pbdev->summary_ind); + release_indicator(&pbdev->routes.adapter, pbdev->indicator); + pbdev->summary_ind = NULL; + pbdev->indicator = NULL; pbdev->routes.adapter.summary_addr = 0; pbdev->routes.adapter.summary_offset = 0; pbdev->routes.adapter.ind_addr = 0; From 562f5e0b97bf36bec6c22f41f94975a20036edec Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Tue, 16 Feb 2016 18:59:05 -0200 Subject: [PATCH 09/14] s390x/css: Allocate channel_subsys statically There's no need to use g_malloc0() to allocate the channel_subsys struct, just use a static variable. Cc: Cornelia Huck Cc: Christian Borntraeger Cc: Richard Henderson Cc: Alexander Graf Signed-off-by: Eduardo Habkost Message-Id: <1455656347-29033-3-git-send-email-ehabkost@redhat.com> Reviewed-by: Cornelia Huck [adapted on top of indicator changes] Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 185 ++++++++++++++++++++++++------------------------- 1 file changed, 92 insertions(+), 93 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index c02f5bca8d..3b16c82862 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -63,13 +63,13 @@ typedef struct ChannelSubSys { QTAILQ_HEAD(, IndAddr) indicator_addresses; } ChannelSubSys; -static ChannelSubSys *channel_subsys; +static ChannelSubSys channel_subsys; IndAddr *get_indicator(hwaddr ind_addr, int len) { IndAddr *indicator; - QTAILQ_FOREACH(indicator, &channel_subsys->indicator_addresses, sibling) { + QTAILQ_FOREACH(indicator, &channel_subsys.indicator_addresses, sibling) { if (indicator->addr == ind_addr) { indicator->refcnt++; return indicator; @@ -79,7 +79,7 @@ IndAddr *get_indicator(hwaddr ind_addr, int len) indicator->addr = ind_addr; indicator->len = len; indicator->refcnt = 1; - QTAILQ_INSERT_TAIL(&channel_subsys->indicator_addresses, + QTAILQ_INSERT_TAIL(&channel_subsys.indicator_addresses, indicator, sibling); return indicator; } @@ -100,7 +100,7 @@ void release_indicator(AdapterInfo *adapter, IndAddr *indicator) if (indicator->refcnt > 0) { return; } - QTAILQ_REMOVE(&channel_subsys->indicator_addresses, indicator, sibling); + QTAILQ_REMOVE(&channel_subsys.indicator_addresses, indicator, sibling); if (indicator->map) { s390_io_adapter_map(adapter, indicator->map, false); } @@ -132,12 +132,12 @@ int css_create_css_image(uint8_t cssid, bool default_image) if (cssid > MAX_CSSID) { return -EINVAL; } - if (channel_subsys->css[cssid]) { + if (channel_subsys.css[cssid]) { return -EBUSY; } - channel_subsys->css[cssid] = g_malloc0(sizeof(CssImage)); + channel_subsys.css[cssid] = g_malloc0(sizeof(CssImage)); if (default_image) { - channel_subsys->default_cssid = cssid; + channel_subsys.default_cssid = cssid; } return 0; } @@ -152,7 +152,7 @@ int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap, S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); *id = 0; - QTAILQ_FOREACH(adapter, &channel_subsys->io_adapters, sibling) { + QTAILQ_FOREACH(adapter, &channel_subsys.io_adapters, sibling) { if ((adapter->type == type) && (adapter->isc == isc)) { *id = adapter->id; found = true; @@ -172,7 +172,7 @@ int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap, adapter->id = *id; adapter->isc = isc; adapter->type = type; - QTAILQ_INSERT_TAIL(&channel_subsys->io_adapters, adapter, sibling); + QTAILQ_INSERT_TAIL(&channel_subsys.io_adapters, adapter, sibling); } else { g_free(adapter); fprintf(stderr, "Unexpected error %d when registering adapter %d\n", @@ -184,7 +184,7 @@ out: uint16_t css_build_subchannel_id(SubchDev *sch) { - if (channel_subsys->max_cssid > 0) { + if (channel_subsys.max_cssid > 0) { return (sch->cssid << 8) | (1 << 3) | (sch->ssid << 1) | 1; } return (sch->ssid << 1) | 1; @@ -840,12 +840,12 @@ static void css_update_chnmon(SubchDev *sch) offset = sch->curr_status.pmcw.mbi << 5; count = address_space_lduw(&address_space_memory, - channel_subsys->chnmon_area + offset, + channel_subsys.chnmon_area + offset, MEMTXATTRS_UNSPECIFIED, NULL); count++; address_space_stw(&address_space_memory, - channel_subsys->chnmon_area + offset, count, + channel_subsys.chnmon_area + offset, count, MEMTXATTRS_UNSPECIFIED, NULL); } } @@ -874,7 +874,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb) } /* If monitoring is active, update counter. */ - if (channel_subsys->chnmon_active) { + if (channel_subsys.chnmon_active) { css_update_chnmon(sch); } sch->channel_prog = orb->cpa; @@ -1033,16 +1033,16 @@ int css_do_stcrw(CRW *crw) CrwContainer *crw_cont; int ret; - crw_cont = QTAILQ_FIRST(&channel_subsys->pending_crws); + crw_cont = QTAILQ_FIRST(&channel_subsys.pending_crws); if (crw_cont) { - QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling); + QTAILQ_REMOVE(&channel_subsys.pending_crws, crw_cont, sibling); copy_crw_to_guest(crw, &crw_cont->crw); g_free(crw_cont); ret = 0; } else { /* List was empty, turn crw machine checks on again. */ memset(crw, 0, sizeof(*crw)); - channel_subsys->do_crw_mchk = true; + channel_subsys.do_crw_mchk = true; ret = 1; } @@ -1061,12 +1061,12 @@ void css_undo_stcrw(CRW *crw) crw_cont = g_try_malloc0(sizeof(CrwContainer)); if (!crw_cont) { - channel_subsys->crws_lost = true; + channel_subsys.crws_lost = true; return; } copy_crw_from_guest(&crw_cont->crw, crw); - QTAILQ_INSERT_HEAD(&channel_subsys->pending_crws, crw_cont, sibling); + QTAILQ_INSERT_HEAD(&channel_subsys.pending_crws, crw_cont, sibling); } int css_do_tpi(IOIntCode *int_code, int lowcore) @@ -1084,9 +1084,9 @@ int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid, CssImage *css; if (!m && !cssid) { - css = channel_subsys->css[channel_subsys->default_cssid]; + css = channel_subsys.css[channel_subsys.default_cssid]; } else { - css = channel_subsys->css[cssid]; + css = channel_subsys.css[cssid]; } if (!css) { return 0; @@ -1121,15 +1121,15 @@ void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo) { /* dct is currently ignored (not really meaningful for our devices) */ /* TODO: Don't ignore mbk. */ - if (update && !channel_subsys->chnmon_active) { + if (update && !channel_subsys.chnmon_active) { /* Enable measuring. */ - channel_subsys->chnmon_area = mbo; - channel_subsys->chnmon_active = true; + channel_subsys.chnmon_area = mbo; + channel_subsys.chnmon_active = true; } - if (!update && channel_subsys->chnmon_active) { + if (!update && channel_subsys.chnmon_active) { /* Disable measuring. */ - channel_subsys->chnmon_area = 0; - channel_subsys->chnmon_active = false; + channel_subsys.chnmon_area = 0; + channel_subsys.chnmon_active = false; } } @@ -1157,7 +1157,7 @@ int css_do_rsch(SubchDev *sch) } /* If monitoring is active, update counter. */ - if (channel_subsys->chnmon_active) { + if (channel_subsys.chnmon_active) { css_update_chnmon(sch); } @@ -1173,23 +1173,23 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid) { uint8_t real_cssid; - if (cssid > channel_subsys->max_cssid) { + if (cssid > channel_subsys.max_cssid) { return -EINVAL; } - if (channel_subsys->max_cssid == 0) { - real_cssid = channel_subsys->default_cssid; + if (channel_subsys.max_cssid == 0) { + real_cssid = channel_subsys.default_cssid; } else { real_cssid = cssid; } - if (!channel_subsys->css[real_cssid]) { + if (!channel_subsys.css[real_cssid]) { return -EINVAL; } - if (!channel_subsys->css[real_cssid]->chpids[chpid].in_use) { + if (!channel_subsys.css[real_cssid]->chpids[chpid].in_use) { return -ENODEV; } - if (!channel_subsys->css[real_cssid]->chpids[chpid].is_virtual) { + if (!channel_subsys.css[real_cssid]->chpids[chpid].is_virtual) { fprintf(stderr, "rchp unsupported for non-virtual chpid %x.%02x!\n", real_cssid, chpid); @@ -1198,8 +1198,8 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid) /* We don't really use a channel path, so we're done here. */ css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, - channel_subsys->max_cssid > 0 ? 1 : 0, chpid); - if (channel_subsys->max_cssid > 0) { + channel_subsys.max_cssid > 0 ? 1 : 0, chpid); + if (channel_subsys.max_cssid > 0) { css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 0, real_cssid << 8); } return 0; @@ -1210,13 +1210,13 @@ bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid) SubchSet *set; uint8_t real_cssid; - real_cssid = (!m && (cssid == 0)) ? channel_subsys->default_cssid : cssid; + real_cssid = (!m && (cssid == 0)) ? channel_subsys.default_cssid : cssid; if (real_cssid > MAX_CSSID || ssid > MAX_SSID || - !channel_subsys->css[real_cssid] || - !channel_subsys->css[real_cssid]->sch_set[ssid]) { + !channel_subsys.css[real_cssid] || + !channel_subsys.css[real_cssid]->sch_set[ssid]) { return true; } - set = channel_subsys->css[real_cssid]->sch_set[ssid]; + set = channel_subsys.css[real_cssid]->sch_set[ssid]; return schid > find_last_bit(set->schids_used, (MAX_SCHID + 1) / sizeof(unsigned long)); } @@ -1229,7 +1229,7 @@ static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type) if (cssid > MAX_CSSID) { return -EINVAL; } - css = channel_subsys->css[cssid]; + css = channel_subsys.css[cssid]; if (!css) { return -EINVAL; } @@ -1250,7 +1250,7 @@ void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type) PMCW *p = &sch->curr_status.pmcw; SCSW *s = &sch->curr_status.scsw; int i; - CssImage *css = channel_subsys->css[sch->cssid]; + CssImage *css = channel_subsys.css[sch->cssid]; assert(css != NULL); memset(p, 0, sizeof(PMCW)); @@ -1276,27 +1276,27 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, uint16_t schid) { uint8_t real_cssid; - real_cssid = (!m && (cssid == 0)) ? channel_subsys->default_cssid : cssid; + real_cssid = (!m && (cssid == 0)) ? channel_subsys.default_cssid : cssid; - if (!channel_subsys->css[real_cssid]) { + if (!channel_subsys.css[real_cssid]) { return NULL; } - if (!channel_subsys->css[real_cssid]->sch_set[ssid]) { + if (!channel_subsys.css[real_cssid]->sch_set[ssid]) { return NULL; } - return channel_subsys->css[real_cssid]->sch_set[ssid]->sch[schid]; + return channel_subsys.css[real_cssid]->sch_set[ssid]->sch[schid]; } bool css_subch_visible(SubchDev *sch) { - if (sch->ssid > channel_subsys->max_ssid) { + if (sch->ssid > channel_subsys.max_ssid) { return false; } - if (sch->cssid != channel_subsys->default_cssid) { - return (channel_subsys->max_cssid > 0); + if (sch->cssid != channel_subsys.default_cssid) { + return (channel_subsys.max_cssid > 0); } return true; @@ -1304,20 +1304,20 @@ bool css_subch_visible(SubchDev *sch) bool css_present(uint8_t cssid) { - return (channel_subsys->css[cssid] != NULL); + return (channel_subsys.css[cssid] != NULL); } bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno) { - if (!channel_subsys->css[cssid]) { + if (!channel_subsys.css[cssid]) { return false; } - if (!channel_subsys->css[cssid]->sch_set[ssid]) { + if (!channel_subsys.css[cssid]->sch_set[ssid]) { return false; } return !!test_bit(devno, - channel_subsys->css[cssid]->sch_set[ssid]->devnos_used); + channel_subsys.css[cssid]->sch_set[ssid]->devnos_used); } void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid, @@ -1328,13 +1328,13 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid, trace_css_assign_subch(sch ? "assign" : "deassign", cssid, ssid, schid, devno); - if (!channel_subsys->css[cssid]) { + if (!channel_subsys.css[cssid]) { fprintf(stderr, "Suspicious call to %s (%x.%x.%04x) for non-existing css!\n", __func__, cssid, ssid, schid); return; } - css = channel_subsys->css[cssid]; + css = channel_subsys.css[cssid]; if (!css->sch_set[ssid]) { css->sch_set[ssid] = g_malloc0(sizeof(SubchSet)); @@ -1359,7 +1359,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid) /* TODO: Maybe use a static crw pool? */ crw_cont = g_try_malloc0(sizeof(CrwContainer)); if (!crw_cont) { - channel_subsys->crws_lost = true; + channel_subsys.crws_lost = true; return; } crw_cont->crw.flags = (rsc << 8) | erc; @@ -1367,15 +1367,15 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid) crw_cont->crw.flags |= CRW_FLAGS_MASK_C; } crw_cont->crw.rsid = rsid; - if (channel_subsys->crws_lost) { + if (channel_subsys.crws_lost) { crw_cont->crw.flags |= CRW_FLAGS_MASK_R; - channel_subsys->crws_lost = false; + channel_subsys.crws_lost = false; } - QTAILQ_INSERT_TAIL(&channel_subsys->pending_crws, crw_cont, sibling); + QTAILQ_INSERT_TAIL(&channel_subsys.pending_crws, crw_cont, sibling); - if (channel_subsys->do_crw_mchk) { - channel_subsys->do_crw_mchk = false; + if (channel_subsys.do_crw_mchk) { + channel_subsys.do_crw_mchk = false; /* Inject crw pending machine check. */ s390_crw_mchk(); } @@ -1390,9 +1390,9 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, if (add && !hotplugged) { return; } - if (channel_subsys->max_cssid == 0) { + if (channel_subsys.max_cssid == 0) { /* Default cssid shows up as 0. */ - guest_cssid = (cssid == channel_subsys->default_cssid) ? 0 : cssid; + guest_cssid = (cssid == channel_subsys.default_cssid) ? 0 : cssid; } else { /* Show real cssid to the guest. */ guest_cssid = cssid; @@ -1401,14 +1401,14 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, * Only notify for higher subchannel sets/channel subsystems if the * guest has enabled it. */ - if ((ssid > channel_subsys->max_ssid) || - (guest_cssid > channel_subsys->max_cssid) || - ((channel_subsys->max_cssid == 0) && - (cssid != channel_subsys->default_cssid))) { + if ((ssid > channel_subsys.max_ssid) || + (guest_cssid > channel_subsys.max_cssid) || + ((channel_subsys.max_cssid == 0) && + (cssid != channel_subsys.default_cssid))) { return; } - chain_crw = (channel_subsys->max_ssid > 0) || - (channel_subsys->max_cssid > 0); + chain_crw = (channel_subsys.max_ssid > 0) || + (channel_subsys.max_cssid > 0); css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, chain_crw ? 1 : 0, schid); if (chain_crw) { css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0, @@ -1423,28 +1423,28 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid) void css_generate_css_crws(uint8_t cssid) { - if (!channel_subsys->sei_pending) { + if (!channel_subsys.sei_pending) { css_queue_crw(CRW_RSC_CSS, 0, 0, cssid); } - channel_subsys->sei_pending = true; + channel_subsys.sei_pending = true; } void css_clear_sei_pending(void) { - channel_subsys->sei_pending = false; + channel_subsys.sei_pending = false; } int css_enable_mcsse(void) { trace_css_enable_facility("mcsse"); - channel_subsys->max_cssid = MAX_CSSID; + channel_subsys.max_cssid = MAX_CSSID; return 0; } int css_enable_mss(void) { trace_css_enable_facility("mss"); - channel_subsys->max_ssid = MAX_SSID; + channel_subsys.max_ssid = MAX_SSID; return 0; } @@ -1567,10 +1567,10 @@ int subch_device_load(SubchDev *s, QEMUFile *f) */ if (s->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA) { if (s->ssid) { - channel_subsys->max_ssid = MAX_SSID; + channel_subsys.max_ssid = MAX_SSID; } - if (s->cssid != channel_subsys->default_cssid) { - channel_subsys->max_cssid = MAX_CSSID; + if (s->cssid != channel_subsys.default_cssid) { + channel_subsys.max_cssid = MAX_CSSID; } } return 0; @@ -1579,14 +1579,13 @@ int subch_device_load(SubchDev *s, QEMUFile *f) static void css_init(void) { - channel_subsys = g_malloc0(sizeof(*channel_subsys)); - QTAILQ_INIT(&channel_subsys->pending_crws); - channel_subsys->sei_pending = false; - channel_subsys->do_crw_mchk = true; - channel_subsys->crws_lost = false; - channel_subsys->chnmon_active = false; - QTAILQ_INIT(&channel_subsys->io_adapters); - QTAILQ_INIT(&channel_subsys->indicator_addresses); + QTAILQ_INIT(&channel_subsys.pending_crws); + channel_subsys.sei_pending = false; + channel_subsys.do_crw_mchk = true; + channel_subsys.crws_lost = false; + channel_subsys.chnmon_active = false; + QTAILQ_INIT(&channel_subsys.io_adapters); + QTAILQ_INIT(&channel_subsys.indicator_addresses); } machine_init(css_init); @@ -1627,19 +1626,19 @@ void css_reset(void) CrwContainer *crw_cont; /* Clean up monitoring. */ - channel_subsys->chnmon_active = false; - channel_subsys->chnmon_area = 0; + channel_subsys.chnmon_active = false; + channel_subsys.chnmon_area = 0; /* Clear pending CRWs. */ - while ((crw_cont = QTAILQ_FIRST(&channel_subsys->pending_crws))) { - QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling); + while ((crw_cont = QTAILQ_FIRST(&channel_subsys.pending_crws))) { + QTAILQ_REMOVE(&channel_subsys.pending_crws, crw_cont, sibling); g_free(crw_cont); } - channel_subsys->sei_pending = false; - channel_subsys->do_crw_mchk = true; - channel_subsys->crws_lost = false; + channel_subsys.sei_pending = false; + channel_subsys.do_crw_mchk = true; + channel_subsys.crws_lost = false; /* Reset maximum ids. */ - channel_subsys->max_cssid = 0; - channel_subsys->max_ssid = 0; + channel_subsys.max_cssid = 0; + channel_subsys.max_ssid = 0; } From bc994b74ea38579e18f9d9144021c6f8de597a34 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Tue, 16 Feb 2016 18:59:06 -0200 Subject: [PATCH 10/14] s390x/css: Use static initialization for channel_subsys fields machine_init() will be gone, but we don't need it if we just initialize the channel_subsys fields statically. Cc: Cornelia Huck Cc: Christian Borntraeger Cc: Richard Henderson Cc: Alexander Graf Signed-off-by: Eduardo Habkost Message-Id: <1455656347-29033-4-git-send-email-ehabkost@redhat.com> Reviewed-by: Cornelia Huck [adapted on top of indicator changes] Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 3b16c82862..55cb26a7fe 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -63,7 +63,17 @@ typedef struct ChannelSubSys { QTAILQ_HEAD(, IndAddr) indicator_addresses; } ChannelSubSys; -static ChannelSubSys channel_subsys; +static ChannelSubSys channel_subsys = { + .pending_crws = QTAILQ_HEAD_INITIALIZER(channel_subsys.pending_crws), + .do_crw_mchk = true, + .sei_pending = false, + .do_crw_mchk = true, + .crws_lost = false, + .chnmon_active = false, + .io_adapters = QTAILQ_HEAD_INITIALIZER(channel_subsys.io_adapters), + .indicator_addresses = + QTAILQ_HEAD_INITIALIZER(channel_subsys.indicator_addresses), +}; IndAddr *get_indicator(hwaddr ind_addr, int len) { @@ -1576,19 +1586,6 @@ int subch_device_load(SubchDev *s, QEMUFile *f) return 0; } - -static void css_init(void) -{ - QTAILQ_INIT(&channel_subsys.pending_crws); - channel_subsys.sei_pending = false; - channel_subsys.do_crw_mchk = true; - channel_subsys.crws_lost = false; - channel_subsys.chnmon_active = false; - QTAILQ_INIT(&channel_subsys.io_adapters); - QTAILQ_INIT(&channel_subsys.indicator_addresses); -} -machine_init(css_init); - void css_reset_sch(SubchDev *sch) { PMCW *p = &sch->curr_status.pmcw; From ce1307e180cae11660847581b1927599c1ab8657 Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Fri, 19 Feb 2016 15:18:11 +0000 Subject: [PATCH 11/14] s390x/pci: use PCI_MSIX_FLAGS on retrieving the MSIX entries Even PCI_CAP_FLAGS has the same value as PCI_MSIX_FLAGS, the later one is the more proper on retrieving MSIX entries. This patch uses PCI_MSIX_FLAGS to retrieve the MSIX entries. Signed-off-by: Wei Yang CC: Cornelia Huck CC: Christian Borntraeger Message-Id: <1455895091-7589-3-git-send-email-richard.weiyang@gmail.com> Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 5d6cebb6e8..dba0202b70 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -524,7 +524,7 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev) return 0; } - ctrl = pci_host_config_read_common(pbdev->pdev, pos + PCI_CAP_FLAGS, + ctrl = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_FLAGS, pci_config_size(pbdev->pdev), sizeof(ctrl)); table = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_TABLE, pci_config_size(pbdev->pdev), sizeof(table)); From 6aaa681c9b158bb5116a1de7b474d5997905473e Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 25 Feb 2016 10:57:54 +0100 Subject: [PATCH 12/14] MAINTAINERS: Remove the old s390-virtio machine The old s390-virtio machine has been removed last year, so we don't need the corresponding section in the MAINTAINERS file anymore. Signed-off-by: Thomas Huth Message-Id: <1456394274-21082-1-git-send-email-thuth@redhat.com> Signed-off-by: Cornelia Huck --- MAINTAINERS | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a5853cd7b6..2774f31e85 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -656,12 +656,6 @@ F: hw/*/grlib* S390 Machines ------------- -S390 Virtio -M: Alexander Graf -S: Maintained -F: hw/s390x/s390-*.c -X: hw/s390x/*pci*.[hc] - S390 Virtio-ccw M: Cornelia Huck M: Christian Borntraeger From d90527178c424b2634faf6aed4d940b95e03bb57 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 25 Feb 2016 11:45:00 +0100 Subject: [PATCH 13/14] MAINTAINERS: Remove entry for hw/s390x/s390-virtio-bus.[ch] The files have been deleted recently, no need to keep these entries anymore. Signed-off-by: Thomas Huth Message-Id: <1456397100-22746-1-git-send-email-thuth@redhat.com> Signed-off-by: Cornelia Huck --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2774f31e85..13d1b4d81a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -663,7 +663,6 @@ M: Alexander Graf S: Supported F: hw/char/sclp*.[hc] F: hw/s390x/ -X: hw/s390x/s390-virtio-bus.[ch] F: include/hw/s390x/ F: pc-bios/s390-ccw/ F: hw/watchdog/wdt_diag288.c From ce350f32e4bb9638085f585329fb5d751676d2d2 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 22 Feb 2016 16:43:04 +0100 Subject: [PATCH 14/14] s390x/css: only suspend when enabled by orb We must not allow a channel program to suspend if the suspend control bit in the orb had not been specified. Reviewed-by: Halil Pasic Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 55cb26a7fe..3a1d919580 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -342,7 +342,8 @@ static CCW1 copy_ccw_from_guest(hwaddr addr, bool fmt1) return ret; } -static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr) +static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr, + bool suspend_allowed) { int ret; bool check_len; @@ -370,7 +371,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr) } if (ccw.flags & CCW_FLAG_SUSPEND) { - return -EINPROGRESS; + return suspend_allowed ? -EINPROGRESS : -EINVAL; } check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC)); @@ -468,6 +469,7 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb) SCSW *s = &sch->curr_status.scsw; int path; int ret; + bool suspend_allowed; /* Path management: In our simple css, we always choose the only path. */ path = 0x80; @@ -487,12 +489,15 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb) } sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT); sch->ccw_no_data_cnt = 0; + suspend_allowed = !!(orb->ctrl0 & ORB_CTRL0_MASK_SPND); } else { s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND); + /* The channel program had been suspended before. */ + suspend_allowed = true; } sch->last_cmd_valid = false; do { - ret = css_interpret_ccw(sch, sch->channel_prog); + ret = css_interpret_ccw(sch, sch->channel_prog, suspend_allowed); switch (ret) { case -EAGAIN: /* ccw chain, continue processing */