qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20180409' into staging

Fixes for s390x: kvm, vfio-ccw, ipl code, bios. Includes a rebuild
of s390-ccw.img and s390-netboot.img.

# gpg: Signature made Mon 09 Apr 2018 16:08:19 BST
# gpg: using RSA key DECF6B93C6F02FAF
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>"
# gpg: aka "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>"
# gpg: aka "Cornelia Huck <cohuck@kernel.org>"
# gpg: aka "Cornelia Huck <cohuck@redhat.com>"
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0 18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20180409:
s390x: load_psw() should only exchange the PSW for KVM
s390x/mmu: don't overwrite pending exception in mmu translate
vfio-ccw: fix memory leaks in vfio_ccw_realize()
pc-bios/s390: update images
s390: Do not pass inofficial IPL type to the guest
s390: Ensure IPL from SCSI works as expected
s390: Refactor IPL parameter block generation
s390x/kvm: call cpu_synchronize_state() on every kvm_arch_handle_exit()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+110 -38
+79 -31
hw/s390x/ipl.c
··· 279 279 *timeout = cpu_to_be32(splash_time); 280 280 } 281 281 282 - static bool s390_gen_initial_iplb(S390IPLState *ipl) 282 + static CcwDevice *s390_get_ccw_device(DeviceState *dev_st) 283 283 { 284 - DeviceState *dev_st; 284 + CcwDevice *ccw_dev = NULL; 285 285 286 - dev_st = get_boot_device(0); 287 286 if (dev_st) { 288 287 VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *) 289 288 object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent), 290 - TYPE_VIRTIO_CCW_DEVICE); 291 - SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st), 292 - TYPE_SCSI_DEVICE); 293 - VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st), 294 - TYPE_VIRTIO_NET); 289 + TYPE_VIRTIO_CCW_DEVICE); 290 + if (virtio_ccw_dev) { 291 + ccw_dev = CCW_DEVICE(virtio_ccw_dev); 292 + } else { 293 + SCSIDevice *sd = (SCSIDevice *) 294 + object_dynamic_cast(OBJECT(dev_st), 295 + TYPE_SCSI_DEVICE); 296 + if (sd) { 297 + SCSIBus *bus = scsi_bus_from_device(sd); 298 + VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus); 299 + VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, 300 + vdev); 295 301 296 - if (vn) { 297 - ipl->netboot = true; 302 + ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw), 303 + TYPE_CCW_DEVICE); 304 + } 298 305 } 299 - if (virtio_ccw_dev) { 300 - CcwDevice *ccw_dev = CCW_DEVICE(virtio_ccw_dev); 306 + } 307 + return ccw_dev; 308 + } 301 309 302 - ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); 303 - ipl->iplb.blk0_len = 304 - cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); 305 - ipl->iplb.pbt = S390_IPL_TYPE_CCW; 306 - ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); 307 - ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; 308 - } else if (sd) { 309 - SCSIBus *bus = scsi_bus_from_device(sd); 310 - VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus); 311 - VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev); 312 - CcwDevice *ccw_dev; 310 + static bool s390_gen_initial_iplb(S390IPLState *ipl) 311 + { 312 + DeviceState *dev_st; 313 + CcwDevice *ccw_dev = NULL; 313 314 314 - ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw), 315 - TYPE_CCW_DEVICE); 316 - if (!ccw_dev) { /* It might be a PCI device instead */ 317 - return false; 318 - } 315 + dev_st = get_boot_device(0); 316 + if (dev_st) { 317 + ccw_dev = s390_get_ccw_device(dev_st); 318 + } 319 319 320 + /* 321 + * Currently allow IPL only from CCW devices. 322 + */ 323 + if (ccw_dev) { 324 + SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st), 325 + TYPE_SCSI_DEVICE); 326 + 327 + if (sd) { 320 328 ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN); 321 329 ipl->iplb.blk0_len = 322 330 cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN); ··· 327 335 ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno); 328 336 ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3; 329 337 } else { 330 - return false; /* unknown device */ 338 + VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st), 339 + TYPE_VIRTIO_NET); 340 + 341 + ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); 342 + ipl->iplb.blk0_len = 343 + cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); 344 + ipl->iplb.pbt = S390_IPL_TYPE_CCW; 345 + ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); 346 + ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; 347 + 348 + if (vn) { 349 + ipl->netboot = true; 350 + } 331 351 } 332 352 333 353 if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) { 334 354 ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID; 335 355 } 356 + 336 357 return true; 337 358 } 338 359 ··· 406 427 return img_size; 407 428 } 408 429 409 - static bool is_virtio_net_device(IplParameterBlock *iplb) 430 + static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb, 431 + int virtio_id) 410 432 { 411 433 uint8_t cssid; 412 434 uint8_t ssid; ··· 426 448 sch = css_find_subch(1, cssid, ssid, schid); 427 449 428 450 if (sch && sch->devno == devno) { 429 - return sch->id.cu_model == VIRTIO_ID_NET; 451 + return sch->id.cu_model == virtio_id; 430 452 } 431 453 } 432 454 } 433 455 return false; 456 + } 457 + 458 + static bool is_virtio_net_device(IplParameterBlock *iplb) 459 + { 460 + return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_NET); 461 + } 462 + 463 + static bool is_virtio_scsi_device(IplParameterBlock *iplb) 464 + { 465 + return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_SCSI); 434 466 } 435 467 436 468 void s390_ipl_update_diag308(IplParameterBlock *iplb) ··· 457 489 S390IPLState *ipl = get_ipl_device(); 458 490 459 491 ipl->reipl_requested = true; 492 + if (ipl->iplb_valid && 493 + !ipl->netboot && 494 + ipl->iplb.pbt == S390_IPL_TYPE_CCW && 495 + is_virtio_scsi_device(&ipl->iplb)) { 496 + CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0)); 497 + 498 + if (ccw_dev && 499 + cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno && 500 + (ccw_dev->sch->ssid & 3) == ipl->iplb.ccw.ssid) { 501 + /* 502 + * this is the original boot device's SCSI 503 + * so restore IPL parameter info from it 504 + */ 505 + ipl->iplb_valid = s390_gen_initial_iplb(ipl); 506 + } 507 + } 460 508 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 461 509 } 462 510
+2
hw/vfio/ccw.c
··· 357 357 if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) { 358 358 error_setg(&err, "vfio: subchannel %s has already been attached", 359 359 vcdev->vdev.name); 360 + g_free(vcdev->vdev.name); 360 361 goto out_device_err; 361 362 } 362 363 } 363 364 364 365 if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, &err)) { 366 + g_free(vcdev->vdev.name); 365 367 goto out_device_err; 366 368 } 367 369
pc-bios/s390-ccw.img

This is a binary file and will not be displayed.

+7
pc-bios/s390-ccw/bootmap.c
··· 70 70 { 71 71 /* store the subsystem information _after_ the bootmap was loaded */ 72 72 write_subsystem_identification(); 73 + 74 + /* prevent unknown IPL types in the guest */ 75 + if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) { 76 + iplb.pbt = S390_IPL_TYPE_CCW; 77 + set_iplb(&iplb); 78 + } 79 + 73 80 /* 74 81 * The IPL PSW is at address 0. We also must not overwrite the 75 82 * content of non-BIOS memory after we loaded the guest, so we
+13 -2
pc-bios/s390-ccw/iplb.h
··· 97 97 #define S390_IPL_TYPE_CCW 0x02 98 98 #define S390_IPL_TYPE_QEMU_SCSI 0xff 99 99 100 - static inline bool store_iplb(IplParameterBlock *iplb) 100 + static inline bool manage_iplb(IplParameterBlock *iplb, bool store) 101 101 { 102 102 register unsigned long addr asm("0") = (unsigned long) iplb; 103 103 register unsigned long rc asm("1") = 0; 104 104 105 105 asm volatile ("diag %0,%2,0x308\n" 106 106 : "+d" (addr), "+d" (rc) 107 - : "d" (6) 107 + : "d" (store ? 6 : 5) 108 108 : "memory", "cc"); 109 109 return rc == 0x01; 110 + } 111 + 112 + 113 + static inline bool store_iplb(IplParameterBlock *iplb) 114 + { 115 + return manage_iplb(iplb, true); 116 + } 117 + 118 + static inline bool set_iplb(IplParameterBlock *iplb) 119 + { 120 + return manage_iplb(iplb, false); 110 121 } 111 122 112 123 #endif /* IPLB_H */
pc-bios/s390-netboot.img

This is a binary file and will not be displayed.

+6 -4
target/s390x/helper.c
··· 103 103 104 104 env->psw.addr = addr; 105 105 env->psw.mask = mask; 106 - if (tcg_enabled()) { 107 - env->cc_op = (mask >> 44) & 3; 106 + 107 + /* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */ 108 + if (!tcg_enabled()) { 109 + return; 108 110 } 111 + env->cc_op = (mask >> 44) & 3; 109 112 110 113 if ((old_mask ^ mask) & PSW_MASK_PER) { 111 114 s390_cpu_recompute_watchpoints(CPU(s390_env_get_cpu(env))); 112 115 } 113 116 114 - /* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */ 115 - if (tcg_enabled() && (mask & PSW_MASK_WAIT)) { 117 + if (mask & PSW_MASK_WAIT) { 116 118 s390_handle_wait(s390_env_get_cpu(env)); 117 119 } 118 120 }
+2
target/s390x/kvm.c
··· 1778 1778 1779 1779 qemu_mutex_lock_iothread(); 1780 1780 1781 + cpu_synchronize_state(cs); 1782 + 1781 1783 switch (run->exit_reason) { 1782 1784 case KVM_EXIT_S390_SIEIC: 1783 1785 ret = handle_intercept(cpu);
+1 -1
target/s390x/mmu_helper.c
··· 325 325 326 326 r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw, 327 327 exc); 328 - if (rw == MMU_DATA_STORE && !(*flags & PAGE_WRITE)) { 328 + if (!r && rw == MMU_DATA_STORE && !(*flags & PAGE_WRITE)) { 329 329 trigger_prot_fault(env, vaddr, asc, rw, exc); 330 330 return -1; 331 331 }