Fixes for s390x: kvm, vfio-ccw, ipl code, bios. Includes a rebuild

of s390-ccw.img and s390-netboot.img.
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEw9DWbcNiT/aowBjO3s9rk8bwL68FAlrLgeMSHGNvaHVja0By
 ZWRoYXQuY29tAAoJEN7Pa5PG8C+vnSMP/25JBDDWCOHbZGqtzDN4Su6rrExziRqI
 D9dqTIeplDOJhgpJ9320UjZYwFwJtgIuZelludo6J6Mi9RJiX5/FUUUn8mBkFTaL
 KX6VOZF08oM0pxkHc3cVqDAm8W58hxZZa4ndtvKi/ZBxcW5JaGxokkDP0k+7mJQx
 qydKzgaZ9RaXsewSDBEUUmEkxMFyqbaFeRLej5Ra4V75TdL7fam4N0VOBL/uFRXy
 aBYQUEL9ZkIiwYAuuQ6w/KwqY/FIRvFCZkmq+exJ94ylqwgTCJXPhS957IhDEJdt
 VQEHPKR5W0io2yYyctp/il++EjUsy5jd+1Yu7rrKpk+JqRb/eP2t8PQJjUzOS0As
 s+HCJ08jaTboAXJbJ8Ya2b3/a5lY+iVt7WTB1ykc44KGJIfjwX4C4NZ6orH4DuOd
 /zoFIxcogGnvuAJRKSmgAY2EWIw0skXe9m0KgzSm/wWVxk2MB2ORgiflm9YfT1mt
 0ZVjT8rsrbTUEP1+TqPJctP4EgcIweVXlZQ5oeESNyUkWsQSUe6EwRfCKFo8BTZY
 0zOfBZRpT5KEYEUCAUrRw44fuSIU6v7+bJ7vl49jycLRfXr2ESl1+NAKjiaeqHhO
 zzEZ8+hP99DOeP66Gkz0iqbGvY7JCR5yBIMa3ELUersBi/0odJmpBLiUF9q9gA5/
 5zBm9iBU8ZvJ
 =Hx/l
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2018-04-09 18:21:22 +01:00
commit 1e7e92e2ef
9 changed files with 112 additions and 40 deletions

View file

@ -279,44 +279,52 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
*timeout = cpu_to_be32(splash_time);
}
static bool s390_gen_initial_iplb(S390IPLState *ipl)
static CcwDevice *s390_get_ccw_device(DeviceState *dev_st)
{
DeviceState *dev_st;
CcwDevice *ccw_dev = NULL;
dev_st = get_boot_device(0);
if (dev_st) {
VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
TYPE_VIRTIO_CCW_DEVICE);
TYPE_VIRTIO_CCW_DEVICE);
if (virtio_ccw_dev) {
ccw_dev = CCW_DEVICE(virtio_ccw_dev);
} else {
SCSIDevice *sd = (SCSIDevice *)
object_dynamic_cast(OBJECT(dev_st),
TYPE_SCSI_DEVICE);
if (sd) {
SCSIBus *bus = scsi_bus_from_device(sd);
VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw,
vdev);
ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw),
TYPE_CCW_DEVICE);
}
}
}
return ccw_dev;
}
static bool s390_gen_initial_iplb(S390IPLState *ipl)
{
DeviceState *dev_st;
CcwDevice *ccw_dev = NULL;
dev_st = get_boot_device(0);
if (dev_st) {
ccw_dev = s390_get_ccw_device(dev_st);
}
/*
* Currently allow IPL only from CCW devices.
*/
if (ccw_dev) {
SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
TYPE_SCSI_DEVICE);
VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st),
TYPE_VIRTIO_NET);
if (vn) {
ipl->netboot = true;
}
if (virtio_ccw_dev) {
CcwDevice *ccw_dev = CCW_DEVICE(virtio_ccw_dev);
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
ipl->iplb.blk0_len =
cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
ipl->iplb.pbt = S390_IPL_TYPE_CCW;
ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
} else if (sd) {
SCSIBus *bus = scsi_bus_from_device(sd);
VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev);
CcwDevice *ccw_dev;
ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw),
TYPE_CCW_DEVICE);
if (!ccw_dev) { /* It might be a PCI device instead */
return false;
}
if (sd) {
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
ipl->iplb.blk0_len =
cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN);
@ -327,12 +335,25 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
} else {
return false; /* unknown device */
VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st),
TYPE_VIRTIO_NET);
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
ipl->iplb.blk0_len =
cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
ipl->iplb.pbt = S390_IPL_TYPE_CCW;
ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
if (vn) {
ipl->netboot = true;
}
}
if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID;
}
return true;
}
@ -406,7 +427,8 @@ unref_mr:
return img_size;
}
static bool is_virtio_net_device(IplParameterBlock *iplb)
static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb,
int virtio_id)
{
uint8_t cssid;
uint8_t ssid;
@ -426,13 +448,23 @@ static bool is_virtio_net_device(IplParameterBlock *iplb)
sch = css_find_subch(1, cssid, ssid, schid);
if (sch && sch->devno == devno) {
return sch->id.cu_model == VIRTIO_ID_NET;
return sch->id.cu_model == virtio_id;
}
}
}
return false;
}
static bool is_virtio_net_device(IplParameterBlock *iplb)
{
return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_NET);
}
static bool is_virtio_scsi_device(IplParameterBlock *iplb)
{
return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_SCSI);
}
void s390_ipl_update_diag308(IplParameterBlock *iplb)
{
S390IPLState *ipl = get_ipl_device();
@ -457,6 +489,22 @@ void s390_reipl_request(void)
S390IPLState *ipl = get_ipl_device();
ipl->reipl_requested = true;
if (ipl->iplb_valid &&
!ipl->netboot &&
ipl->iplb.pbt == S390_IPL_TYPE_CCW &&
is_virtio_scsi_device(&ipl->iplb)) {
CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0));
if (ccw_dev &&
cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno &&
(ccw_dev->sch->ssid & 3) == ipl->iplb.ccw.ssid) {
/*
* this is the original boot device's SCSI
* so restore IPL parameter info from it
*/
ipl->iplb_valid = s390_gen_initial_iplb(ipl);
}
}
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}

View file

@ -357,11 +357,13 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) {
error_setg(&err, "vfio: subchannel %s has already been attached",
vcdev->vdev.name);
g_free(vcdev->vdev.name);
goto out_device_err;
}
}
if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, &err)) {
g_free(vcdev->vdev.name);
goto out_device_err;
}

Binary file not shown.

View file

@ -70,6 +70,13 @@ static void jump_to_IPL_code(uint64_t address)
{
/* store the subsystem information _after_ the bootmap was loaded */
write_subsystem_identification();
/* prevent unknown IPL types in the guest */
if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) {
iplb.pbt = S390_IPL_TYPE_CCW;
set_iplb(&iplb);
}
/*
* The IPL PSW is at address 0. We also must not overwrite the
* content of non-BIOS memory after we loaded the guest, so we

View file

@ -97,16 +97,27 @@ extern QemuIplParameters qipl;
#define S390_IPL_TYPE_CCW 0x02
#define S390_IPL_TYPE_QEMU_SCSI 0xff
static inline bool store_iplb(IplParameterBlock *iplb)
static inline bool manage_iplb(IplParameterBlock *iplb, bool store)
{
register unsigned long addr asm("0") = (unsigned long) iplb;
register unsigned long rc asm("1") = 0;
asm volatile ("diag %0,%2,0x308\n"
: "+d" (addr), "+d" (rc)
: "d" (6)
: "d" (store ? 6 : 5)
: "memory", "cc");
return rc == 0x01;
}
static inline bool store_iplb(IplParameterBlock *iplb)
{
return manage_iplb(iplb, true);
}
static inline bool set_iplb(IplParameterBlock *iplb)
{
return manage_iplb(iplb, false);
}
#endif /* IPLB_H */

Binary file not shown.

View file

@ -103,16 +103,18 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
env->psw.addr = addr;
env->psw.mask = mask;
if (tcg_enabled()) {
env->cc_op = (mask >> 44) & 3;
/* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */
if (!tcg_enabled()) {
return;
}
env->cc_op = (mask >> 44) & 3;
if ((old_mask ^ mask) & PSW_MASK_PER) {
s390_cpu_recompute_watchpoints(CPU(s390_env_get_cpu(env)));
}
/* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */
if (tcg_enabled() && (mask & PSW_MASK_WAIT)) {
if (mask & PSW_MASK_WAIT) {
s390_handle_wait(s390_env_get_cpu(env));
}
}

View file

@ -1778,6 +1778,8 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
qemu_mutex_lock_iothread();
cpu_synchronize_state(cs);
switch (run->exit_reason) {
case KVM_EXIT_S390_SIEIC:
ret = handle_intercept(cpu);

View file

@ -325,7 +325,7 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw,
exc);
if (rw == MMU_DATA_STORE && !(*flags & PAGE_WRITE)) {
if (!r && rw == MMU_DATA_STORE && !(*flags & PAGE_WRITE)) {
trigger_prot_fault(env, vaddr, asc, rw, exc);
return -1;
}