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);
|
*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) {
|
if (dev_st) {
|
||||||
VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
|
VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
|
||||||
object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
|
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),
|
SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
|
||||||
TYPE_SCSI_DEVICE);
|
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.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
|
||||||
ipl->iplb.blk0_len =
|
ipl->iplb.blk0_len =
|
||||||
cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_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.devno = cpu_to_be16(ccw_dev->sch->devno);
|
||||||
ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
|
ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
|
||||||
} else {
|
} 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)) {
|
if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
|
||||||
ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID;
|
ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +427,8 @@ unref_mr:
|
||||||
return img_size;
|
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 cssid;
|
||||||
uint8_t ssid;
|
uint8_t ssid;
|
||||||
|
@ -426,13 +448,23 @@ static bool is_virtio_net_device(IplParameterBlock *iplb)
|
||||||
sch = css_find_subch(1, cssid, ssid, schid);
|
sch = css_find_subch(1, cssid, ssid, schid);
|
||||||
|
|
||||||
if (sch && sch->devno == devno) {
|
if (sch && sch->devno == devno) {
|
||||||
return sch->id.cu_model == VIRTIO_ID_NET;
|
return sch->id.cu_model == virtio_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
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)
|
void s390_ipl_update_diag308(IplParameterBlock *iplb)
|
||||||
{
|
{
|
||||||
S390IPLState *ipl = get_ipl_device();
|
S390IPLState *ipl = get_ipl_device();
|
||||||
|
@ -457,6 +489,22 @@ void s390_reipl_request(void)
|
||||||
S390IPLState *ipl = get_ipl_device();
|
S390IPLState *ipl = get_ipl_device();
|
||||||
|
|
||||||
ipl->reipl_requested = true;
|
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);
|
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) {
|
if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) {
|
||||||
error_setg(&err, "vfio: subchannel %s has already been attached",
|
error_setg(&err, "vfio: subchannel %s has already been attached",
|
||||||
vcdev->vdev.name);
|
vcdev->vdev.name);
|
||||||
|
g_free(vcdev->vdev.name);
|
||||||
goto out_device_err;
|
goto out_device_err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, &err)) {
|
if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, &err)) {
|
||||||
|
g_free(vcdev->vdev.name);
|
||||||
goto out_device_err;
|
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 */
|
/* store the subsystem information _after_ the bootmap was loaded */
|
||||||
write_subsystem_identification();
|
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
|
* 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
|
* 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_CCW 0x02
|
||||||
#define S390_IPL_TYPE_QEMU_SCSI 0xff
|
#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 addr asm("0") = (unsigned long) iplb;
|
||||||
register unsigned long rc asm("1") = 0;
|
register unsigned long rc asm("1") = 0;
|
||||||
|
|
||||||
asm volatile ("diag %0,%2,0x308\n"
|
asm volatile ("diag %0,%2,0x308\n"
|
||||||
: "+d" (addr), "+d" (rc)
|
: "+d" (addr), "+d" (rc)
|
||||||
: "d" (6)
|
: "d" (store ? 6 : 5)
|
||||||
: "memory", "cc");
|
: "memory", "cc");
|
||||||
return rc == 0x01;
|
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 */
|
#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.addr = addr;
|
||||||
env->psw.mask = mask;
|
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) {
|
if ((old_mask ^ mask) & PSW_MASK_PER) {
|
||||||
s390_cpu_recompute_watchpoints(CPU(s390_env_get_cpu(env)));
|
s390_cpu_recompute_watchpoints(CPU(s390_env_get_cpu(env)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */
|
if (mask & PSW_MASK_WAIT) {
|
||||||
if (tcg_enabled() && (mask & PSW_MASK_WAIT)) {
|
|
||||||
s390_handle_wait(s390_env_get_cpu(env));
|
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();
|
qemu_mutex_lock_iothread();
|
||||||
|
|
||||||
|
cpu_synchronize_state(cs);
|
||||||
|
|
||||||
switch (run->exit_reason) {
|
switch (run->exit_reason) {
|
||||||
case KVM_EXIT_S390_SIEIC:
|
case KVM_EXIT_S390_SIEIC:
|
||||||
ret = handle_intercept(cpu);
|
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,
|
r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw,
|
||||||
exc);
|
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);
|
trigger_prot_fault(env, vaddr, asc, rw, exc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue