Several s390x patches including:
- missing virtio-1 related code for virtio-ccw - bugfixes in ipl device, gdb, virtio-ccw - bugfix in s390-ccw bios + rebuild - introduce versioned machines for s390-ccw-virtio -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJVlUUuAAoJEN7Pa5PG8C+vLQgP/0HMDJCbUtmH7L47jRKAnoAQ RsXqmdnIqMaMAuf9PJwVy6Gx/akvo2qR3cu9J3H19uBhZvXj4WyfBZkeSBO/uqfn r23f3EEGmeym0uHaC3Xi8j0MGUJbu+K41mXwA5/pZXwEe//EsvV1uFoo7Euff2/u 2cuGLdte6E9iJg2n/sbRoZuODOoEKQv1xyc7Z7uB1AnLiiUwwPcw2h2Q57rVNuhM 8J8fc9kFRGIjmh/vXYT0nLImboyVdIz2whYT/AXm+Q0gDBf4vGUo0pLjN0I/DMSe 6lxBBVNA+4qFF3EFkbQU32gc/HnIzqKhtLno9l6+wDjETEsCKabESRRnmRrlPWYw hJsJf/DxoObob7z7tEvA0EKFR+cDVxyv0u68aha7AykY7CrMiZy7QS18BsSTp6gX OP0u1JQU9v+hOq1X4LGOoHuJMT9f83UDsjHoXYHPRxlNVf9YHznrexRBJXVp2Nkr 1yRusXrazBajdyJ0Mp1CXIaOfICBOLSIpJpExteqBZcRJBSBd4usCBCO+EbdDAHc rr/DmhpFNqyvlFysg4ILQ5ua0yyqV3ViRpHK+CNODi11ZzkZ7B6ROrdBeRzYNgz8 sYMd0leFHWHCzfRYf/P6GipdeCr9fUw5GCGpm5KGQ+q9kejFj1WipFtesLcZPeiZ jopOuL787iuRxl/SvIj8 =kh9m -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20150702-v3' into staging Several s390x patches including: - missing virtio-1 related code for virtio-ccw - bugfixes in ipl device, gdb, virtio-ccw - bugfix in s390-ccw bios + rebuild - introduce versioned machines for s390-ccw-virtio # gpg: Signature made Thu Jul 2 15:05:34 2015 BST using RSA key ID C6F02FAF # gpg: Good signature from "Cornelia Huck <huckc@linux.vnet.ibm.com>" # gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>" * remotes/cohuck/tags/s390x-20150702-v3: s390x/migration: Introduce 2.4 machine s390x/gdb: synchronize cpu state after modifying acrs s390x/ipl: Fix boot if no bootindex was specified virtio-ccw: migrate ->revision s390x/virtio-ccw: support virtio-1 set_vq format s390x/virtio-ccw: add virtio set-revision call s390x/css: Add a callback for when subchannel gets disabled s390-ccw.img: update s390-ccw.img: Consume service interrupts css: mss/mcss-e vs. migration virtio-ccw: complete handling of guest-initiated resets Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5317b0f6d4
@ -588,6 +588,7 @@ int css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
uint16_t oldflags;
|
||||
int ret;
|
||||
SCHIB schib;
|
||||
|
||||
@ -610,6 +611,7 @@ int css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
|
||||
copy_schib_from_guest(&schib, orig_schib);
|
||||
/* Only update the program-modifiable fields. */
|
||||
p->intparm = schib.pmcw.intparm;
|
||||
oldflags = p->flags;
|
||||
p->flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
|
||||
PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME |
|
||||
PMCW_FLAGS_MASK_MP);
|
||||
@ -625,6 +627,12 @@ int css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
|
||||
(PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_CSENSE);
|
||||
sch->curr_status.mba = schib.mba;
|
||||
|
||||
/* Has the channel been disabled? */
|
||||
if (sch->disable_cb && (oldflags & PMCW_FLAGS_MASK_ENA) != 0
|
||||
&& (p->flags & PMCW_FLAGS_MASK_ENA) == 0) {
|
||||
sch->disable_cb(sch);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
@ -1464,6 +1472,21 @@ int subch_device_load(SubchDev *s, QEMUFile *f)
|
||||
}
|
||||
s->ccw_fmt_1 = qemu_get_byte(f);
|
||||
s->ccw_no_data_cnt = qemu_get_byte(f);
|
||||
/*
|
||||
* Hack alert. We don't migrate the channel subsystem status (no
|
||||
* device!), but we need to find out if the guest enabled mss/mcss-e.
|
||||
* If the subchannel is enabled, it certainly was able to access it,
|
||||
* so adjust the max_ssid/max_cssid values for relevant ssid/cssid
|
||||
* values. This is not watertight, but better than nothing.
|
||||
*/
|
||||
if (s->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA) {
|
||||
if (s->ssid) {
|
||||
channel_subsys->max_ssid = MAX_SSID;
|
||||
}
|
||||
if (s->cssid != channel_subsys->default_cssid) {
|
||||
channel_subsys->max_cssid = MAX_CSSID;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1483,6 +1506,10 @@ void css_reset_sch(SubchDev *sch)
|
||||
{
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
|
||||
if ((p->flags & PMCW_FLAGS_MASK_ENA) != 0 && sch->disable_cb) {
|
||||
sch->disable_cb(sch);
|
||||
}
|
||||
|
||||
p->intparm = 0;
|
||||
p->flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
|
||||
PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME |
|
||||
|
@ -81,6 +81,7 @@ struct SubchDev {
|
||||
uint8_t ccw_no_data_cnt;
|
||||
/* transport-provided data: */
|
||||
int (*ccw_cb) (SubchDev *, CCW1);
|
||||
void (*disable_cb)(SubchDev *);
|
||||
SenseId id;
|
||||
void *driver_data;
|
||||
};
|
||||
|
@ -218,7 +218,7 @@ static Property s390_ipl_properties[] = {
|
||||
* - -1 if no valid boot device was found
|
||||
* - ccw id of the boot device otherwise
|
||||
*/
|
||||
static uint32_t s390_update_iplstate(CPUS390XState *env, S390IPLState *ipl)
|
||||
static uint64_t s390_update_iplstate(CPUS390XState *env, S390IPLState *ipl)
|
||||
{
|
||||
DeviceState *dev_st;
|
||||
|
||||
@ -248,7 +248,7 @@ static uint32_t s390_update_iplstate(CPUS390XState *env, S390IPLState *ipl)
|
||||
|
||||
return -1;
|
||||
out:
|
||||
return ipl->cssid << 24 | ipl->ssid << 16 | ipl->devno;
|
||||
return (uint32_t) (ipl->cssid << 24 | ipl->ssid << 16 | ipl->devno);
|
||||
}
|
||||
|
||||
int s390_ipl_update_diag308(IplParameterBlock *iplb)
|
||||
|
@ -204,9 +204,6 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
NMIClass *nc = NMI_CLASS(oc);
|
||||
|
||||
mc->name = "s390-ccw-virtio";
|
||||
mc->alias = "s390-ccw";
|
||||
mc->desc = "VirtIO-ccw based S390 machine";
|
||||
mc->init = ccw_init;
|
||||
mc->block_default_type = IF_VIRTIO;
|
||||
mc->no_cdrom = 1;
|
||||
@ -216,7 +213,6 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->no_sdcard = 1;
|
||||
mc->use_sclp = 1;
|
||||
mc->max_cpus = 255;
|
||||
mc->is_default = 1;
|
||||
nc->nmi_monitor_handler = s390_nmi;
|
||||
}
|
||||
|
||||
@ -272,6 +268,7 @@ static inline void s390_machine_initfn(Object *obj)
|
||||
static const TypeInfo ccw_machine_info = {
|
||||
.name = TYPE_S390_CCW_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.abstract = true,
|
||||
.instance_size = sizeof(S390CcwMachineState),
|
||||
.instance_init = s390_machine_initfn,
|
||||
.class_init = ccw_machine_class_init,
|
||||
@ -281,9 +278,26 @@ static const TypeInfo ccw_machine_info = {
|
||||
},
|
||||
};
|
||||
|
||||
static void ccw_machine_2_4_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->name = "s390-ccw-virtio-2.4";
|
||||
mc->alias = "s390-ccw-virtio";
|
||||
mc->desc = "VirtIO-ccw based S390 machine v2.4";
|
||||
mc->is_default = 1;
|
||||
}
|
||||
|
||||
static const TypeInfo ccw_machine_2_4_info = {
|
||||
.name = TYPE_S390_CCW_MACHINE "2.4",
|
||||
.parent = TYPE_S390_CCW_MACHINE,
|
||||
.class_init = ccw_machine_2_4_class_init,
|
||||
};
|
||||
|
||||
static void ccw_machine_register_types(void)
|
||||
{
|
||||
type_register_static(&ccw_machine_info);
|
||||
type_register_static(&ccw_machine_2_4_info);
|
||||
}
|
||||
|
||||
type_init(ccw_machine_register_types)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "hw/sysbus.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "hw/s390x/adapter.h"
|
||||
#include "hw/s390x/s390_flic.h"
|
||||
@ -237,11 +238,20 @@ VirtualCssBus *virtual_css_bus_init(void)
|
||||
}
|
||||
|
||||
/* Communication blocks used by several channel commands. */
|
||||
typedef struct VqInfoBlock {
|
||||
typedef struct VqInfoBlockLegacy {
|
||||
uint64_t queue;
|
||||
uint32_t align;
|
||||
uint16_t index;
|
||||
uint16_t num;
|
||||
} QEMU_PACKED VqInfoBlockLegacy;
|
||||
|
||||
typedef struct VqInfoBlock {
|
||||
uint64_t desc;
|
||||
uint32_t res0;
|
||||
uint16_t index;
|
||||
uint16_t num;
|
||||
uint64_t avail;
|
||||
uint64_t used;
|
||||
} QEMU_PACKED VqInfoBlock;
|
||||
|
||||
typedef struct VqConfigBlock {
|
||||
@ -261,18 +271,27 @@ typedef struct VirtioThinintInfo {
|
||||
uint8_t isc;
|
||||
} QEMU_PACKED VirtioThinintInfo;
|
||||
|
||||
typedef struct VirtioRevInfo {
|
||||
uint16_t revision;
|
||||
uint16_t length;
|
||||
uint8_t data[0];
|
||||
} QEMU_PACKED VirtioRevInfo;
|
||||
|
||||
/* Specify where the virtqueues for the subchannel are in guest memory. */
|
||||
static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
|
||||
uint16_t index, uint16_t num)
|
||||
static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
|
||||
VqInfoBlockLegacy *linfo)
|
||||
{
|
||||
VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
|
||||
uint16_t index = info ? info->index : linfo->index;
|
||||
uint16_t num = info ? info->num : linfo->num;
|
||||
uint64_t desc = info ? info->desc : linfo->queue;
|
||||
|
||||
if (index >= VIRTIO_CCW_QUEUE_MAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Current code in virtio.c relies on 4K alignment. */
|
||||
if (addr && (align != 4096)) {
|
||||
if (linfo && desc && (linfo->align != 4096)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -280,8 +299,12 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
virtio_queue_set_addr(vdev, index, addr);
|
||||
if (!addr) {
|
||||
if (info) {
|
||||
virtio_queue_set_rings(vdev, index, desc, info->avail, info->used);
|
||||
} else {
|
||||
virtio_queue_set_addr(vdev, index, desc);
|
||||
}
|
||||
if (!desc) {
|
||||
virtio_queue_set_vector(vdev, index, VIRTIO_NO_VECTOR);
|
||||
} else {
|
||||
/* Fail if we don't have a big enough queue. */
|
||||
@ -296,10 +319,98 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
|
||||
{
|
||||
virtio_ccw_stop_ioeventfd(dev);
|
||||
virtio_reset(vdev);
|
||||
if (dev->indicators) {
|
||||
release_indicator(&dev->routes.adapter, dev->indicators);
|
||||
dev->indicators = NULL;
|
||||
}
|
||||
if (dev->indicators2) {
|
||||
release_indicator(&dev->routes.adapter, dev->indicators2);
|
||||
dev->indicators2 = NULL;
|
||||
}
|
||||
if (dev->summary_indicator) {
|
||||
release_indicator(&dev->routes.adapter, dev->summary_indicator);
|
||||
dev->summary_indicator = NULL;
|
||||
}
|
||||
dev->sch->thinint_active = false;
|
||||
}
|
||||
|
||||
static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
|
||||
bool is_legacy)
|
||||
{
|
||||
int ret;
|
||||
VqInfoBlock info;
|
||||
VqInfoBlockLegacy linfo;
|
||||
size_t info_len = is_legacy ? sizeof(linfo) : sizeof(info);
|
||||
|
||||
if (check_len) {
|
||||
if (ccw.count != info_len) {
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (ccw.count < info_len) {
|
||||
/* Can't execute command. */
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!ccw.cda) {
|
||||
return -EFAULT;
|
||||
}
|
||||
if (is_legacy) {
|
||||
linfo.queue = address_space_ldq_be(&address_space_memory, ccw.cda,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
linfo.align = address_space_ldl_be(&address_space_memory,
|
||||
ccw.cda + sizeof(linfo.queue),
|
||||
MEMTXATTRS_UNSPECIFIED,
|
||||
NULL);
|
||||
linfo.index = address_space_lduw_be(&address_space_memory,
|
||||
ccw.cda + sizeof(linfo.queue)
|
||||
+ sizeof(linfo.align),
|
||||
MEMTXATTRS_UNSPECIFIED,
|
||||
NULL);
|
||||
linfo.num = address_space_lduw_be(&address_space_memory,
|
||||
ccw.cda + sizeof(linfo.queue)
|
||||
+ sizeof(linfo.align)
|
||||
+ sizeof(linfo.index),
|
||||
MEMTXATTRS_UNSPECIFIED,
|
||||
NULL);
|
||||
ret = virtio_ccw_set_vqs(sch, NULL, &linfo);
|
||||
} else {
|
||||
info.desc = address_space_ldq_be(&address_space_memory, ccw.cda,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
info.index = address_space_lduw_be(&address_space_memory,
|
||||
ccw.cda + sizeof(info.desc)
|
||||
+ sizeof(info.res0),
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
info.num = address_space_lduw_be(&address_space_memory,
|
||||
ccw.cda + sizeof(info.desc)
|
||||
+ sizeof(info.res0)
|
||||
+ sizeof(info.index),
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
info.avail = address_space_ldq_be(&address_space_memory,
|
||||
ccw.cda + sizeof(info.desc)
|
||||
+ sizeof(info.res0)
|
||||
+ sizeof(info.index)
|
||||
+ sizeof(info.num),
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
info.used = address_space_ldq_be(&address_space_memory,
|
||||
ccw.cda + sizeof(info.desc)
|
||||
+ sizeof(info.res0)
|
||||
+ sizeof(info.index)
|
||||
+ sizeof(info.num)
|
||||
+ sizeof(info.avail),
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
ret = virtio_ccw_set_vqs(sch, &info, NULL);
|
||||
}
|
||||
sch->curr_status.scsw.count = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
{
|
||||
int ret;
|
||||
VirtioRevInfo revinfo;
|
||||
uint8_t status;
|
||||
VirtioFeatDesc features;
|
||||
void *config;
|
||||
@ -323,44 +434,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
/* Look at the command. */
|
||||
switch (ccw.cmd_code) {
|
||||
case CCW_CMD_SET_VQ:
|
||||
if (check_len) {
|
||||
if (ccw.count != sizeof(info)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
} else if (ccw.count < sizeof(info)) {
|
||||
/* Can't execute command. */
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (!ccw.cda) {
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
info.queue = address_space_ldq(&address_space_memory, ccw.cda,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
info.align = address_space_ldl(&address_space_memory,
|
||||
ccw.cda + sizeof(info.queue),
|
||||
MEMTXATTRS_UNSPECIFIED,
|
||||
NULL);
|
||||
info.index = address_space_lduw(&address_space_memory,
|
||||
ccw.cda + sizeof(info.queue)
|
||||
+ sizeof(info.align),
|
||||
MEMTXATTRS_UNSPECIFIED,
|
||||
NULL);
|
||||
info.num = address_space_lduw(&address_space_memory,
|
||||
ccw.cda + sizeof(info.queue)
|
||||
+ sizeof(info.align)
|
||||
+ sizeof(info.index),
|
||||
MEMTXATTRS_UNSPECIFIED,
|
||||
NULL);
|
||||
ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index,
|
||||
info.num);
|
||||
sch->curr_status.scsw.count = 0;
|
||||
}
|
||||
ret = virtio_ccw_handle_set_vq(sch, ccw, check_len, dev->revision < 1);
|
||||
break;
|
||||
case CCW_CMD_VDEV_RESET:
|
||||
virtio_ccw_stop_ioeventfd(dev);
|
||||
virtio_reset(vdev);
|
||||
virtio_ccw_reset_virtio(dev, vdev);
|
||||
ret = 0;
|
||||
break;
|
||||
case CCW_CMD_READ_FEAT:
|
||||
@ -383,7 +460,16 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
MEMTXATTRS_UNSPECIFIED,
|
||||
NULL);
|
||||
if (features.index == 0) {
|
||||
features.features = vdev->host_features;
|
||||
features.features = (uint32_t)vdev->host_features;
|
||||
} else if (features.index == 1) {
|
||||
features.features = (uint32_t)(vdev->host_features >> 32);
|
||||
/*
|
||||
* Don't offer version 1 to the guest if it did not
|
||||
* negotiate at least revision 1.
|
||||
*/
|
||||
if (dev->revision <= 0) {
|
||||
features.features &= ~(1 << (VIRTIO_F_VERSION_1 - 32));
|
||||
}
|
||||
} else {
|
||||
/* Return zeroes if the guest supports more feature bits. */
|
||||
features.features = 0;
|
||||
@ -419,7 +505,20 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
MEMTXATTRS_UNSPECIFIED,
|
||||
NULL);
|
||||
if (features.index == 0) {
|
||||
virtio_set_features(vdev, features.features);
|
||||
virtio_set_features(vdev,
|
||||
(vdev->guest_features & 0xffffffff00000000ULL) |
|
||||
features.features);
|
||||
} else if (features.index == 1) {
|
||||
/*
|
||||
* The guest should not set version 1 if it didn't
|
||||
* negotiate a revision >= 1.
|
||||
*/
|
||||
if (dev->revision <= 0) {
|
||||
features.features &= ~(1 << (VIRTIO_F_VERSION_1 - 32));
|
||||
}
|
||||
virtio_set_features(vdev,
|
||||
(vdev->guest_features & 0x00000000ffffffffULL) |
|
||||
((uint64_t)features.features << 32));
|
||||
} else {
|
||||
/*
|
||||
* If the guest supports more feature bits, assert that it
|
||||
@ -500,7 +599,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
}
|
||||
if (virtio_set_status(vdev, status) == 0) {
|
||||
if (vdev->status == 0) {
|
||||
virtio_reset(vdev);
|
||||
virtio_ccw_reset_virtio(dev, vdev);
|
||||
}
|
||||
if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
|
||||
virtio_ccw_start_ioeventfd(dev);
|
||||
@ -640,6 +739,40 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CCW_CMD_SET_VIRTIO_REV:
|
||||
len = sizeof(revinfo);
|
||||
if (ccw.count < len) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (!ccw.cda) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
revinfo.revision =
|
||||
address_space_lduw_be(&address_space_memory, ccw.cda,
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
revinfo.length =
|
||||
address_space_lduw_be(&address_space_memory,
|
||||
ccw.cda + sizeof(revinfo.revision),
|
||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||
if (ccw.count < len + revinfo.length ||
|
||||
(check_len && ccw.count > len + revinfo.length)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Once we start to support revisions with additional data, we'll
|
||||
* need to fetch it here. Nothing to do for now, though.
|
||||
*/
|
||||
if (dev->revision >= 0 ||
|
||||
revinfo.revision > virtio_ccw_rev_max(vdev)) {
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
ret = 0;
|
||||
dev->revision = revinfo.revision;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
@ -647,6 +780,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void virtio_sch_disable_cb(SubchDev *sch)
|
||||
{
|
||||
VirtioCcwDevice *dev = sch->driver_data;
|
||||
|
||||
dev->revision = -1;
|
||||
}
|
||||
|
||||
static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
|
||||
{
|
||||
unsigned int cssid = 0;
|
||||
@ -766,12 +906,15 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
|
||||
css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE);
|
||||
|
||||
sch->ccw_cb = virtio_ccw_cb;
|
||||
sch->disable_cb = virtio_sch_disable_cb;
|
||||
|
||||
/* Build senseid data. */
|
||||
memset(&sch->id, 0, sizeof(SenseId));
|
||||
sch->id.reserved = 0xff;
|
||||
sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
|
||||
|
||||
dev->revision = -1;
|
||||
|
||||
if (k->realize) {
|
||||
k->realize(dev, &err);
|
||||
}
|
||||
@ -1081,21 +1224,8 @@ static void virtio_ccw_reset(DeviceState *d)
|
||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
||||
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
|
||||
|
||||
virtio_ccw_stop_ioeventfd(dev);
|
||||
virtio_reset(vdev);
|
||||
virtio_ccw_reset_virtio(dev, vdev);
|
||||
css_reset_sch(dev->sch);
|
||||
if (dev->indicators) {
|
||||
release_indicator(&dev->routes.adapter, dev->indicators);
|
||||
dev->indicators = NULL;
|
||||
}
|
||||
if (dev->indicators2) {
|
||||
release_indicator(&dev->routes.adapter, dev->indicators2);
|
||||
dev->indicators2 = NULL;
|
||||
}
|
||||
if (dev->summary_indicator) {
|
||||
release_indicator(&dev->routes.adapter, dev->summary_indicator);
|
||||
dev->summary_indicator = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
|
||||
@ -1342,6 +1472,7 @@ static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
|
||||
qemu_put_be16(f, vdev->config_vector);
|
||||
qemu_put_be64(f, dev->routes.adapter.ind_offset);
|
||||
qemu_put_byte(f, dev->thinint_isc);
|
||||
qemu_put_be32(f, dev->revision);
|
||||
}
|
||||
|
||||
static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
|
||||
@ -1382,6 +1513,7 @@ static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
|
||||
dev->thinint_isc, true, false,
|
||||
&dev->routes.adapter.adapter_id);
|
||||
}
|
||||
dev->revision = qemu_get_be32(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#define CCW_CMD_SET_CONF_IND 0x53
|
||||
#define CCW_CMD_READ_VQ_CONF 0x32
|
||||
#define CCW_CMD_SET_IND_ADAPTER 0x73
|
||||
#define CCW_CMD_SET_VIRTIO_REV 0x83
|
||||
|
||||
#define TYPE_VIRTIO_CCW_DEVICE "virtio-ccw-device"
|
||||
#define VIRTIO_CCW_DEVICE(obj) \
|
||||
@ -86,6 +87,7 @@ struct VirtioCcwDevice {
|
||||
DeviceState parent_obj;
|
||||
SubchDev *sch;
|
||||
char *bus_id;
|
||||
int revision;
|
||||
VirtioBusState bus;
|
||||
bool ioeventfd_started;
|
||||
bool ioeventfd_disabled;
|
||||
@ -99,6 +101,12 @@ struct VirtioCcwDevice {
|
||||
uint64_t ind_bit;
|
||||
};
|
||||
|
||||
/* The maximum virtio revision we support. */
|
||||
static inline int virtio_ccw_rev_max(VirtIODevice *vdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* virtual css bus type */
|
||||
typedef struct VirtualCssBus {
|
||||
BusState parent_obj;
|
||||
|
Binary file not shown.
@ -47,6 +47,7 @@ typedef unsigned long long __u64;
|
||||
|
||||
/* start.s */
|
||||
void disabled_wait(void);
|
||||
void consume_sclp_int(void);
|
||||
|
||||
/* main.c */
|
||||
void virtio_panic(const char *string);
|
||||
|
@ -24,6 +24,7 @@ static int sclp_service_call(unsigned int command, void *sccb)
|
||||
" srl %0,28"
|
||||
: "=&d" (cc) : "d" (command), "a" (__pa(sccb))
|
||||
: "cc", "memory");
|
||||
consume_sclp_int();
|
||||
if (cc == 3)
|
||||
return -EIO;
|
||||
if (cc == 2)
|
||||
|
@ -28,6 +28,38 @@ disabled_wait:
|
||||
larl %r1,disabled_wait_psw
|
||||
lpswe 0(%r1)
|
||||
|
||||
|
||||
/*
|
||||
* void consume_sclp_int(void)
|
||||
*
|
||||
* eats one sclp interrupt
|
||||
*/
|
||||
.globl consume_sclp_int
|
||||
consume_sclp_int:
|
||||
/* enable service interrupts in cr0 */
|
||||
stctg 0,0,0(15)
|
||||
oi 6(15), 0x2
|
||||
lctlg 0,0,0(15)
|
||||
/* prepare external call handler */
|
||||
larl %r1, external_new_code
|
||||
stg %r1, 0x1b8
|
||||
larl %r1, external_new_mask
|
||||
mvc 0x1b0(8),0(%r1)
|
||||
/* load enabled wait PSW */
|
||||
larl %r1, enabled_wait_psw
|
||||
lpswe 0(%r1)
|
||||
|
||||
external_new_code:
|
||||
/* disable service interrupts in cr0 */
|
||||
stctg 0,0,0(15)
|
||||
ni 6(15), 0xfd
|
||||
lctlg 0,0,0(15)
|
||||
br 14
|
||||
|
||||
.align 8
|
||||
disabled_wait_psw:
|
||||
.quad 0x0002000180000000,0x0000000000000000
|
||||
enabled_wait_psw:
|
||||
.quad 0x0302000180000000,0x0000000000000000
|
||||
external_new_mask:
|
||||
.quad 0x0000000180000000
|
||||
|
@ -92,6 +92,7 @@ static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
|
||||
switch (n) {
|
||||
case S390_A0_REGNUM ... S390_A15_REGNUM:
|
||||
env->aregs[n] = ldl_p(mem_buf);
|
||||
cpu_synchronize_post_init(ENV_GET_CPU(env));
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user