mirror of https://github.com/xemu-project/xemu.git
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:
commit
1e7e92e2ef
114
hw/s390x/ipl.c
114
hw/s390x/ipl.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
@ -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
|
||||
|
|
|
@ -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.
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue