diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-05-04 11:53:58 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-05-04 11:53:58 +0100 |
commit | 46e04dacd3a6e7e453fb0b76b144b5fc67f52349 (patch) | |
tree | f2a825c7fcb022c67951a1cb120d9622bcd7c559 /hw | |
parent | 2e4bd4a286ccfadc41165aea413f0abc28beed3e (diff) | |
parent | 532cd4b067d37b96496dbacbfab6c990c063d33d (diff) |
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20180504' into staging
First s390x pull request for 2.13.
- new machine type
- extend SCLP event masks
- support configuration of consoles via -serial
- firmware improvements: non-sequential entries in boot menu, support
for indirect loading via .INS files in s390-netboot
- bugfixes and cleanups
# gpg: Signature made Fri 04 May 2018 08:19:57 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-20180504:
pc-bios/s390: Update firmware images
s390-ccw: force diag 308 subcode to unsigned long
pc-bios/s390-ccw/net: Add support for .INS config files
pc-bios/s390-ccw/net: Use diag308 to reset machine before jumping to the OS
pc-bios/s390-ccw/net: Split up net_load() into init, load and release parts
pc-bios/s390-ccw: fix non-sequential boot entries (enum)
pc-bios/s390-ccw: fix non-sequential boot entries (eckd)
pc-bios/s390-ccw: fix loadparm initialization and int conversion
pc-bios/s390-ccw: rename MAX_TABLE_ENTRIES to MAX_BOOT_ENTRIES
pc-bios/s390-ccw: size_t should be unsigned
hw/s390x: Allow to configure the consoles with the "-serial" parameter
s390x/kvm: cleanup calls to cpu_synchronize_state()
vfio-ccw: introduce vfio_ccw_get_device()
s390x/sclp: extend SCLP event masks to 64 bits
s390x: introduce 2.13 compat machine
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/s390x/event-facility.c | 64 | ||||
-rw-r--r-- | hw/s390x/ipl.c | 4 | ||||
-rw-r--r-- | hw/s390x/s390-pci-inst.c | 8 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 36 | ||||
-rw-r--r-- | hw/vfio/ccw.c | 56 |
5 files changed, 128 insertions, 40 deletions
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index 9c24bc6f7c..ee5b83448b 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -26,11 +26,23 @@ typedef struct SCLPEventsBus { BusState qbus; } SCLPEventsBus; +/* we need to save 32 bit chunks for compatibility */ +#ifdef HOST_WORDS_BIGENDIAN +#define RECV_MASK_LOWER 1 +#define RECV_MASK_UPPER 0 +#else /* little endian host */ +#define RECV_MASK_LOWER 0 +#define RECV_MASK_UPPER 1 +#endif + struct SCLPEventFacility { SysBusDevice parent_obj; SCLPEventsBus sbus; /* guest's receive mask */ - sccb_mask_t receive_mask; + union { + uint32_t receive_mask_pieces[2]; + sccb_mask_t receive_mask; + }; /* * when false, we keep the same broken, backwards compatible behaviour as * before, allowing only masks of size exactly 4; when true, we implement @@ -262,7 +274,7 @@ static void read_event_data(SCLPEventFacility *ef, SCCB *sccb) case SCLP_SELECTIVE_READ: copy_mask((uint8_t *)&sclp_active_selection_mask, (uint8_t *)&red->mask, sizeof(sclp_active_selection_mask), ef->mask_length); - sclp_active_selection_mask = be32_to_cpu(sclp_active_selection_mask); + sclp_active_selection_mask = be64_to_cpu(sclp_active_selection_mask); if (!sclp_cp_receive_mask || (sclp_active_selection_mask & ~sclp_cp_receive_mask)) { sccb->h.response_code = @@ -294,21 +306,22 @@ static void write_event_mask(SCLPEventFacility *ef, SCCB *sccb) } /* - * Note: We currently only support masks up to 4 byte length; - * the remainder is filled up with zeroes. Linux uses - * a 4 byte mask length. + * Note: We currently only support masks up to 8 byte length; + * the remainder is filled up with zeroes. Older Linux + * kernels use a 4 byte mask length, newer ones can use both + * 8 or 4 depending on what is available on the host. */ /* keep track of the guest's capability masks */ copy_mask((uint8_t *)&tmp_mask, WEM_CP_RECEIVE_MASK(we_mask, mask_length), sizeof(tmp_mask), mask_length); - ef->receive_mask = be32_to_cpu(tmp_mask); + ef->receive_mask = be64_to_cpu(tmp_mask); /* return the SCLP's capability masks to the guest */ - tmp_mask = cpu_to_be32(get_host_receive_mask(ef)); + tmp_mask = cpu_to_be64(get_host_receive_mask(ef)); copy_mask(WEM_RECEIVE_MASK(we_mask, mask_length), (uint8_t *)&tmp_mask, mask_length, sizeof(tmp_mask)); - tmp_mask = cpu_to_be32(get_host_send_mask(ef)); + tmp_mask = cpu_to_be64(get_host_send_mask(ef)); copy_mask(WEM_SEND_MASK(we_mask, mask_length), (uint8_t *)&tmp_mask, mask_length, sizeof(tmp_mask)); @@ -369,6 +382,13 @@ static void command_handler(SCLPEventFacility *ef, SCCB *sccb, uint64_t code) } } +static bool vmstate_event_facility_mask64_needed(void *opaque) +{ + SCLPEventFacility *ef = opaque; + + return (ef->receive_mask & 0xFFFFFFFF) != 0; +} + static bool vmstate_event_facility_mask_length_needed(void *opaque) { SCLPEventFacility *ef = opaque; @@ -376,6 +396,17 @@ static bool vmstate_event_facility_mask_length_needed(void *opaque) return ef->allow_all_mask_sizes; } +static const VMStateDescription vmstate_event_facility_mask64 = { + .name = "vmstate-event-facility/mask64", + .version_id = 0, + .minimum_version_id = 0, + .needed = vmstate_event_facility_mask64_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT32(receive_mask_pieces[RECV_MASK_LOWER], SCLPEventFacility), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_event_facility_mask_length = { .name = "vmstate-event-facility/mask_length", .version_id = 0, @@ -392,10 +423,11 @@ static const VMStateDescription vmstate_event_facility = { .version_id = 0, .minimum_version_id = 0, .fields = (VMStateField[]) { - VMSTATE_UINT32(receive_mask, SCLPEventFacility), + VMSTATE_UINT32(receive_mask_pieces[RECV_MASK_UPPER], SCLPEventFacility), VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription * []) { + &vmstate_event_facility_mask64, &vmstate_event_facility_mask_length, NULL } @@ -511,3 +543,17 @@ static void register_types(void) } type_init(register_types) + +BusState *sclp_get_event_facility_bus(void) +{ + Object *busobj; + SCLPEventsBus *sbus; + + busobj = object_resolve_path_type("", TYPE_SCLP_EVENTS_BUS, NULL); + sbus = OBJECT_CHECK(SCLPEventsBus, busobj, TYPE_SCLP_EVENTS_BUS); + if (!sbus) { + return NULL; + } + + return &sbus->qbus; +} diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index fb554ab156..150f6c0582 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -373,6 +373,10 @@ int s390_ipl_set_loadparm(uint8_t *loadparm) loadparm[i] = ascii2ebcdic[(uint8_t) lp[i]]; } + if (i < 8) { + memset(loadparm + i, 0x40, 8 - i); /* fill with EBCDIC spaces */ + } + g_free(lp); return 0; } diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 3fcc330fe3..02a815fd31 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -155,8 +155,6 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra) S390pciState *s = s390_get_phb(); int i; - cpu_synchronize_state(CPU(cpu)); - if (env->psw.mask & PSW_MASK_PSTATE) { s390_program_interrupt(env, PGM_PRIVILEGED, 4, ra); return 0; @@ -389,8 +387,6 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) uint32_t fh; uint8_t pcias; - cpu_synchronize_state(CPU(cpu)); - if (env->psw.mask & PSW_MASK_PSTATE) { s390_program_interrupt(env, PGM_PRIVILEGED, 4, ra); return 0; @@ -487,8 +483,6 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) uint32_t fh; uint8_t pcias; - cpu_synchronize_state(CPU(cpu)); - if (env->psw.mask & PSW_MASK_PSTATE) { s390_program_interrupt(env, PGM_PRIVILEGED, 4, ra); return 0; @@ -620,8 +614,6 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) S390IOTLBEntry entry; hwaddr start, end; - cpu_synchronize_state(CPU(cpu)); - if (env->psw.mask & PSW_MASK_PSTATE) { s390_program_interrupt(env, PGM_PRIVILEGED, 4, ra); return 0; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 435f7c99e7..100dfdc96d 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -288,6 +288,15 @@ static void s390_create_virtio_net(BusState *bus, const char *name) } } +static void s390_create_sclpconsole(const char *type, Chardev *chardev) +{ + DeviceState *dev; + + dev = qdev_create(sclp_get_event_facility_bus(), type); + qdev_prop_set_chr(dev, "chardev", chardev); + qdev_init_nofail(dev); +} + static void ccw_init(MachineState *machine) { int ret; @@ -346,6 +355,14 @@ static void ccw_init(MachineState *machine) /* Create VirtIO network adapters */ s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw"); + /* init consoles */ + if (serial_hd(0)) { + s390_create_sclpconsole("sclpconsole", serial_hd(0)); + } + if (serial_hd(1)) { + s390_create_sclpconsole("sclplmconsole", serial_hd(1)); + } + /* Register savevm handler for guest TOD clock */ register_savevm_live(NULL, "todclock", 0, 1, &savevm_gtod, NULL); } @@ -470,10 +487,8 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_VIRTIO; mc->no_cdrom = 1; mc->no_floppy = 1; - mc->no_serial = 1; mc->no_parallel = 1; mc->no_sdcard = 1; - mc->use_sclp = 1; mc->max_cpus = S390_MAX_CPUS; mc->has_hotpluggable_cpus = true; mc->get_hotplug_handler = s390_get_hotplug_handler; @@ -671,6 +686,9 @@ bool css_migration_enabled(void) } \ type_init(ccw_machine_register_##suffix) +#define CCW_COMPAT_2_12 \ + HW_COMPAT_2_12 + #define CCW_COMPAT_2_11 \ HW_COMPAT_2_11 \ {\ @@ -756,14 +774,26 @@ bool css_migration_enabled(void) .value = "0",\ }, +static void ccw_machine_2_13_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_2_13_class_options(MachineClass *mc) +{ +} +DEFINE_CCW_MACHINE(2_13, "2.13", true); + static void ccw_machine_2_12_instance_options(MachineState *machine) { + ccw_machine_2_13_instance_options(machine); } static void ccw_machine_2_12_class_options(MachineClass *mc) { + ccw_machine_2_13_class_options(mc); + SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_12); } -DEFINE_CCW_MACHINE(2_12, "2.12", true); +DEFINE_CCW_MACHINE(2_12, "2.12", false); static void ccw_machine_2_11_instance_options(MachineState *machine) { diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index fe34b50769..e67392c5f9 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -292,12 +292,43 @@ static void vfio_ccw_put_region(VFIOCCWDevice *vcdev) g_free(vcdev->io_region); } -static void vfio_put_device(VFIOCCWDevice *vcdev) +static void vfio_ccw_put_device(VFIOCCWDevice *vcdev) { g_free(vcdev->vdev.name); vfio_put_base_device(&vcdev->vdev); } +static void vfio_ccw_get_device(VFIOGroup *group, VFIOCCWDevice *vcdev, + Error **errp) +{ + char *name = g_strdup_printf("%x.%x.%04x", vcdev->cdev.hostid.cssid, + vcdev->cdev.hostid.ssid, + vcdev->cdev.hostid.devid); + VFIODevice *vbasedev; + + QLIST_FOREACH(vbasedev, &group->device_list, next) { + if (strcmp(vbasedev->name, name) == 0) { + error_setg(errp, "vfio: subchannel %s has already been attached", + name); + goto out_err; + } + } + + if (vfio_get_device(group, vcdev->cdev.mdevid, &vcdev->vdev, errp)) { + goto out_err; + } + + vcdev->vdev.ops = &vfio_ccw_ops; + vcdev->vdev.type = VFIO_DEVICE_TYPE_CCW; + vcdev->vdev.name = name; + vcdev->vdev.dev = &vcdev->cdev.parent_obj.parent_obj; + + return; + +out_err: + g_free(name); +} + static VFIOGroup *vfio_ccw_get_group(S390CCWDevice *cdev, Error **errp) { char *tmp, group_path[PATH_MAX]; @@ -327,7 +358,6 @@ static VFIOGroup *vfio_ccw_get_group(S390CCWDevice *cdev, Error **errp) static void vfio_ccw_realize(DeviceState *dev, Error **errp) { - VFIODevice *vbasedev; VFIOGroup *group; CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev); S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev); @@ -348,22 +378,8 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) goto out_group_err; } - vcdev->vdev.ops = &vfio_ccw_ops; - vcdev->vdev.type = VFIO_DEVICE_TYPE_CCW; - vcdev->vdev.name = g_strdup_printf("%x.%x.%04x", cdev->hostid.cssid, - cdev->hostid.ssid, cdev->hostid.devid); - vcdev->vdev.dev = dev; - QLIST_FOREACH(vbasedev, &group->device_list, next) { - 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); + vfio_ccw_get_device(group, vcdev, &err); + if (err) { goto out_device_err; } @@ -382,7 +398,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) out_notifier_err: vfio_ccw_put_region(vcdev); out_region_err: - vfio_put_device(vcdev); + vfio_ccw_put_device(vcdev); out_device_err: vfio_put_group(group); out_group_err: @@ -403,7 +419,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp) vfio_ccw_unregister_io_notifier(vcdev); vfio_ccw_put_region(vcdev); - vfio_put_device(vcdev); + vfio_ccw_put_device(vcdev); vfio_put_group(group); if (cdc->unrealize) { |