Assorted fixes, cleanups and enhancements.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJW1YDIAAoJEN7Pa5PG8C+v2IYP/RsoJmh4au+JLB4Um+cDNlJD
 3r+E53W4mO3ItZhTomCNhAmBZg1T84u3VuJU7Ix0oZMuSeZGHllly3V37fCsZOG0
 mYDzLvSlWXlWA7gLYtr7hQFDvDr1PBi+zMMTBWYcae1TkdZlW+MIUFrh0EHTarc2
 bxT4GGPfAdcYCxlqj6AQf8kYZipKLiBoHXyCyHhVDtgDk087rGkVbUdZRoUUO7h1
 xXKinL+Z710GFzsLONd2hlEO+60EqzVDiYPeYK3dEYhj+Rr/ZKqUtd7lGCAffqki
 czoiVz5sQkM/PoSn+UPdFR8khXmRvTL2rH9W0Ho2xBibyW2ViSCmgMzAmDxnMDXj
 MPg0JD/zd+mY3y1APXacIx0rppJs3iQyDrrAwPk0sJolHz4mIKpyYkkUWfvxgBqj
 lDnpbdEuz0e2HOu0lG3dTeEhGQIrENo3Xxee252PnrrNVoE2Man9Gx4lC0TdW/rK
 GZufQTdTnH9EHf4kuNsWoRRaevqdguz2wichO+sDWdoKW28kP11o26s+TAMpUf1L
 oMBMPA7dFYpUWm5X8mHwP+w7Jdo3+rbahdj+1cKtf+0GQxsyHTbTvY8VvBAGFHD3
 uooooSDh7Tqly0zBMU1RsbdBpw85QG4KX6NFl1/IKcUvXq+8S+s/mldg5mxnFK8U
 Iwl324KNGrfdoZZ6u5d6
 =8wMZ
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20160301' into staging

Assorted fixes, cleanups and enhancements.

# gpg: Signature made Tue 01 Mar 2016 11:45:12 GMT 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-20160301:
  s390x/css: only suspend when enabled by orb
  MAINTAINERS: Remove entry for hw/s390x/s390-virtio-bus.[ch]
  MAINTAINERS: Remove the old s390-virtio machine
  s390x/pci: use PCI_MSIX_FLAGS on retrieving the MSIX entries
  s390x/css: Use static initialization for channel_subsys fields
  s390x/css: Allocate channel_subsys statically
  s390x/pci: fix reg/dereg irq functions
  s390x/css: introduce indicator refcounting interfaces
  s390x/virtio: old machine leftovers
  watchdog/diag288: avoid race condition on expired watchdog
  s390x: remove {kvm_}s390_virtio_irq()
  s390x: fix debug statement in trigger_page_fault()
  s390x/kvm: sync fprs via kvm_run
  linux-headers: update against kvm/next

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-03-01 13:09:55 +00:00
commit 9c279bec75
23 changed files with 246 additions and 240 deletions

View file

@ -656,12 +656,6 @@ F: hw/*/grlib*
S390 Machines
-------------
S390 Virtio
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: hw/s390x/s390-*.c
X: hw/s390x/*pci*.[hc]
S390 Virtio-ccw
M: Cornelia Huck <cornelia.huck@de.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
@ -669,7 +663,6 @@ M: Alexander Graf <agraf@suse.de>
S: Supported
F: hw/char/sclp*.[hc]
F: hw/s390x/
X: hw/s390x/s390-virtio-bus.[ch]
F: include/hw/s390x/
F: pc-bios/s390-ccw/
F: hw/watchdog/wdt_diag288.c

View file

@ -60,9 +60,81 @@ typedef struct ChannelSubSys {
CssImage *css[MAX_CSSID + 1];
uint8_t default_cssid;
QTAILQ_HEAD(, IoAdapter) io_adapters;
QTAILQ_HEAD(, IndAddr) indicator_addresses;
} ChannelSubSys;
static ChannelSubSys *channel_subsys;
static ChannelSubSys channel_subsys = {
.pending_crws = QTAILQ_HEAD_INITIALIZER(channel_subsys.pending_crws),
.do_crw_mchk = true,
.sei_pending = false,
.do_crw_mchk = true,
.crws_lost = false,
.chnmon_active = false,
.io_adapters = QTAILQ_HEAD_INITIALIZER(channel_subsys.io_adapters),
.indicator_addresses =
QTAILQ_HEAD_INITIALIZER(channel_subsys.indicator_addresses),
};
IndAddr *get_indicator(hwaddr ind_addr, int len)
{
IndAddr *indicator;
QTAILQ_FOREACH(indicator, &channel_subsys.indicator_addresses, sibling) {
if (indicator->addr == ind_addr) {
indicator->refcnt++;
return indicator;
}
}
indicator = g_new0(IndAddr, 1);
indicator->addr = ind_addr;
indicator->len = len;
indicator->refcnt = 1;
QTAILQ_INSERT_TAIL(&channel_subsys.indicator_addresses,
indicator, sibling);
return indicator;
}
static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr,
bool do_map)
{
S390FLICState *fs = s390_get_flic();
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map);
}
void release_indicator(AdapterInfo *adapter, IndAddr *indicator)
{
assert(indicator->refcnt > 0);
indicator->refcnt--;
if (indicator->refcnt > 0) {
return;
}
QTAILQ_REMOVE(&channel_subsys.indicator_addresses, indicator, sibling);
if (indicator->map) {
s390_io_adapter_map(adapter, indicator->map, false);
}
g_free(indicator);
}
int map_indicator(AdapterInfo *adapter, IndAddr *indicator)
{
int ret;
if (indicator->map) {
return 0; /* already mapped is not an error */
}
indicator->map = indicator->addr;
ret = s390_io_adapter_map(adapter, indicator->map, true);
if ((ret != 0) && (ret != -ENOSYS)) {
goto out_err;
}
return 0;
out_err:
indicator->map = 0;
return ret;
}
int css_create_css_image(uint8_t cssid, bool default_image)
{
@ -70,12 +142,12 @@ int css_create_css_image(uint8_t cssid, bool default_image)
if (cssid > MAX_CSSID) {
return -EINVAL;
}
if (channel_subsys->css[cssid]) {
if (channel_subsys.css[cssid]) {
return -EBUSY;
}
channel_subsys->css[cssid] = g_malloc0(sizeof(CssImage));
channel_subsys.css[cssid] = g_malloc0(sizeof(CssImage));
if (default_image) {
channel_subsys->default_cssid = cssid;
channel_subsys.default_cssid = cssid;
}
return 0;
}
@ -90,7 +162,7 @@ int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap,
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
*id = 0;
QTAILQ_FOREACH(adapter, &channel_subsys->io_adapters, sibling) {
QTAILQ_FOREACH(adapter, &channel_subsys.io_adapters, sibling) {
if ((adapter->type == type) && (adapter->isc == isc)) {
*id = adapter->id;
found = true;
@ -110,7 +182,7 @@ int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap,
adapter->id = *id;
adapter->isc = isc;
adapter->type = type;
QTAILQ_INSERT_TAIL(&channel_subsys->io_adapters, adapter, sibling);
QTAILQ_INSERT_TAIL(&channel_subsys.io_adapters, adapter, sibling);
} else {
g_free(adapter);
fprintf(stderr, "Unexpected error %d when registering adapter %d\n",
@ -122,7 +194,7 @@ out:
uint16_t css_build_subchannel_id(SubchDev *sch)
{
if (channel_subsys->max_cssid > 0) {
if (channel_subsys.max_cssid > 0) {
return (sch->cssid << 8) | (1 << 3) | (sch->ssid << 1) | 1;
}
return (sch->ssid << 1) | 1;
@ -270,7 +342,8 @@ static CCW1 copy_ccw_from_guest(hwaddr addr, bool fmt1)
return ret;
}
static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr)
static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
bool suspend_allowed)
{
int ret;
bool check_len;
@ -298,7 +371,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr)
}
if (ccw.flags & CCW_FLAG_SUSPEND) {
return -EINPROGRESS;
return suspend_allowed ? -EINPROGRESS : -EINVAL;
}
check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC));
@ -396,6 +469,7 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
SCSW *s = &sch->curr_status.scsw;
int path;
int ret;
bool suspend_allowed;
/* Path management: In our simple css, we always choose the only path. */
path = 0x80;
@ -415,12 +489,15 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
}
sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT);
sch->ccw_no_data_cnt = 0;
suspend_allowed = !!(orb->ctrl0 & ORB_CTRL0_MASK_SPND);
} else {
s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND);
/* The channel program had been suspended before. */
suspend_allowed = true;
}
sch->last_cmd_valid = false;
do {
ret = css_interpret_ccw(sch, sch->channel_prog);
ret = css_interpret_ccw(sch, sch->channel_prog, suspend_allowed);
switch (ret) {
case -EAGAIN:
/* ccw chain, continue processing */
@ -778,12 +855,12 @@ static void css_update_chnmon(SubchDev *sch)
offset = sch->curr_status.pmcw.mbi << 5;
count = address_space_lduw(&address_space_memory,
channel_subsys->chnmon_area + offset,
channel_subsys.chnmon_area + offset,
MEMTXATTRS_UNSPECIFIED,
NULL);
count++;
address_space_stw(&address_space_memory,
channel_subsys->chnmon_area + offset, count,
channel_subsys.chnmon_area + offset, count,
MEMTXATTRS_UNSPECIFIED, NULL);
}
}
@ -812,7 +889,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb)
}
/* If monitoring is active, update counter. */
if (channel_subsys->chnmon_active) {
if (channel_subsys.chnmon_active) {
css_update_chnmon(sch);
}
sch->channel_prog = orb->cpa;
@ -971,16 +1048,16 @@ int css_do_stcrw(CRW *crw)
CrwContainer *crw_cont;
int ret;
crw_cont = QTAILQ_FIRST(&channel_subsys->pending_crws);
crw_cont = QTAILQ_FIRST(&channel_subsys.pending_crws);
if (crw_cont) {
QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling);
QTAILQ_REMOVE(&channel_subsys.pending_crws, crw_cont, sibling);
copy_crw_to_guest(crw, &crw_cont->crw);
g_free(crw_cont);
ret = 0;
} else {
/* List was empty, turn crw machine checks on again. */
memset(crw, 0, sizeof(*crw));
channel_subsys->do_crw_mchk = true;
channel_subsys.do_crw_mchk = true;
ret = 1;
}
@ -999,12 +1076,12 @@ void css_undo_stcrw(CRW *crw)
crw_cont = g_try_malloc0(sizeof(CrwContainer));
if (!crw_cont) {
channel_subsys->crws_lost = true;
channel_subsys.crws_lost = true;
return;
}
copy_crw_from_guest(&crw_cont->crw, crw);
QTAILQ_INSERT_HEAD(&channel_subsys->pending_crws, crw_cont, sibling);
QTAILQ_INSERT_HEAD(&channel_subsys.pending_crws, crw_cont, sibling);
}
int css_do_tpi(IOIntCode *int_code, int lowcore)
@ -1022,9 +1099,9 @@ int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid,
CssImage *css;
if (!m && !cssid) {
css = channel_subsys->css[channel_subsys->default_cssid];
css = channel_subsys.css[channel_subsys.default_cssid];
} else {
css = channel_subsys->css[cssid];
css = channel_subsys.css[cssid];
}
if (!css) {
return 0;
@ -1059,15 +1136,15 @@ void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo)
{
/* dct is currently ignored (not really meaningful for our devices) */
/* TODO: Don't ignore mbk. */
if (update && !channel_subsys->chnmon_active) {
if (update && !channel_subsys.chnmon_active) {
/* Enable measuring. */
channel_subsys->chnmon_area = mbo;
channel_subsys->chnmon_active = true;
channel_subsys.chnmon_area = mbo;
channel_subsys.chnmon_active = true;
}
if (!update && channel_subsys->chnmon_active) {
if (!update && channel_subsys.chnmon_active) {
/* Disable measuring. */
channel_subsys->chnmon_area = 0;
channel_subsys->chnmon_active = false;
channel_subsys.chnmon_area = 0;
channel_subsys.chnmon_active = false;
}
}
@ -1095,7 +1172,7 @@ int css_do_rsch(SubchDev *sch)
}
/* If monitoring is active, update counter. */
if (channel_subsys->chnmon_active) {
if (channel_subsys.chnmon_active) {
css_update_chnmon(sch);
}
@ -1111,23 +1188,23 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid)
{
uint8_t real_cssid;
if (cssid > channel_subsys->max_cssid) {
if (cssid > channel_subsys.max_cssid) {
return -EINVAL;
}
if (channel_subsys->max_cssid == 0) {
real_cssid = channel_subsys->default_cssid;
if (channel_subsys.max_cssid == 0) {
real_cssid = channel_subsys.default_cssid;
} else {
real_cssid = cssid;
}
if (!channel_subsys->css[real_cssid]) {
if (!channel_subsys.css[real_cssid]) {
return -EINVAL;
}
if (!channel_subsys->css[real_cssid]->chpids[chpid].in_use) {
if (!channel_subsys.css[real_cssid]->chpids[chpid].in_use) {
return -ENODEV;
}
if (!channel_subsys->css[real_cssid]->chpids[chpid].is_virtual) {
if (!channel_subsys.css[real_cssid]->chpids[chpid].is_virtual) {
fprintf(stderr,
"rchp unsupported for non-virtual chpid %x.%02x!\n",
real_cssid, chpid);
@ -1136,8 +1213,8 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid)
/* We don't really use a channel path, so we're done here. */
css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT,
channel_subsys->max_cssid > 0 ? 1 : 0, chpid);
if (channel_subsys->max_cssid > 0) {
channel_subsys.max_cssid > 0 ? 1 : 0, chpid);
if (channel_subsys.max_cssid > 0) {
css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 0, real_cssid << 8);
}
return 0;
@ -1148,13 +1225,13 @@ bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid)
SubchSet *set;
uint8_t real_cssid;
real_cssid = (!m && (cssid == 0)) ? channel_subsys->default_cssid : cssid;
real_cssid = (!m && (cssid == 0)) ? channel_subsys.default_cssid : cssid;
if (real_cssid > MAX_CSSID || ssid > MAX_SSID ||
!channel_subsys->css[real_cssid] ||
!channel_subsys->css[real_cssid]->sch_set[ssid]) {
!channel_subsys.css[real_cssid] ||
!channel_subsys.css[real_cssid]->sch_set[ssid]) {
return true;
}
set = channel_subsys->css[real_cssid]->sch_set[ssid];
set = channel_subsys.css[real_cssid]->sch_set[ssid];
return schid > find_last_bit(set->schids_used,
(MAX_SCHID + 1) / sizeof(unsigned long));
}
@ -1167,7 +1244,7 @@ static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
if (cssid > MAX_CSSID) {
return -EINVAL;
}
css = channel_subsys->css[cssid];
css = channel_subsys.css[cssid];
if (!css) {
return -EINVAL;
}
@ -1188,7 +1265,7 @@ void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type)
PMCW *p = &sch->curr_status.pmcw;
SCSW *s = &sch->curr_status.scsw;
int i;
CssImage *css = channel_subsys->css[sch->cssid];
CssImage *css = channel_subsys.css[sch->cssid];
assert(css != NULL);
memset(p, 0, sizeof(PMCW));
@ -1214,27 +1291,27 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, uint16_t schid)
{
uint8_t real_cssid;
real_cssid = (!m && (cssid == 0)) ? channel_subsys->default_cssid : cssid;
real_cssid = (!m && (cssid == 0)) ? channel_subsys.default_cssid : cssid;
if (!channel_subsys->css[real_cssid]) {
if (!channel_subsys.css[real_cssid]) {
return NULL;
}
if (!channel_subsys->css[real_cssid]->sch_set[ssid]) {
if (!channel_subsys.css[real_cssid]->sch_set[ssid]) {
return NULL;
}
return channel_subsys->css[real_cssid]->sch_set[ssid]->sch[schid];
return channel_subsys.css[real_cssid]->sch_set[ssid]->sch[schid];
}
bool css_subch_visible(SubchDev *sch)
{
if (sch->ssid > channel_subsys->max_ssid) {
if (sch->ssid > channel_subsys.max_ssid) {
return false;
}
if (sch->cssid != channel_subsys->default_cssid) {
return (channel_subsys->max_cssid > 0);
if (sch->cssid != channel_subsys.default_cssid) {
return (channel_subsys.max_cssid > 0);
}
return true;
@ -1242,20 +1319,20 @@ bool css_subch_visible(SubchDev *sch)
bool css_present(uint8_t cssid)
{
return (channel_subsys->css[cssid] != NULL);
return (channel_subsys.css[cssid] != NULL);
}
bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno)
{
if (!channel_subsys->css[cssid]) {
if (!channel_subsys.css[cssid]) {
return false;
}
if (!channel_subsys->css[cssid]->sch_set[ssid]) {
if (!channel_subsys.css[cssid]->sch_set[ssid]) {
return false;
}
return !!test_bit(devno,
channel_subsys->css[cssid]->sch_set[ssid]->devnos_used);
channel_subsys.css[cssid]->sch_set[ssid]->devnos_used);
}
void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
@ -1266,13 +1343,13 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
trace_css_assign_subch(sch ? "assign" : "deassign", cssid, ssid, schid,
devno);
if (!channel_subsys->css[cssid]) {
if (!channel_subsys.css[cssid]) {
fprintf(stderr,
"Suspicious call to %s (%x.%x.%04x) for non-existing css!\n",
__func__, cssid, ssid, schid);
return;
}
css = channel_subsys->css[cssid];
css = channel_subsys.css[cssid];
if (!css->sch_set[ssid]) {
css->sch_set[ssid] = g_malloc0(sizeof(SubchSet));
@ -1297,7 +1374,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
/* TODO: Maybe use a static crw pool? */
crw_cont = g_try_malloc0(sizeof(CrwContainer));
if (!crw_cont) {
channel_subsys->crws_lost = true;
channel_subsys.crws_lost = true;
return;
}
crw_cont->crw.flags = (rsc << 8) | erc;
@ -1305,15 +1382,15 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
crw_cont->crw.flags |= CRW_FLAGS_MASK_C;
}
crw_cont->crw.rsid = rsid;
if (channel_subsys->crws_lost) {
if (channel_subsys.crws_lost) {
crw_cont->crw.flags |= CRW_FLAGS_MASK_R;
channel_subsys->crws_lost = false;
channel_subsys.crws_lost = false;
}
QTAILQ_INSERT_TAIL(&channel_subsys->pending_crws, crw_cont, sibling);
QTAILQ_INSERT_TAIL(&channel_subsys.pending_crws, crw_cont, sibling);
if (channel_subsys->do_crw_mchk) {
channel_subsys->do_crw_mchk = false;
if (channel_subsys.do_crw_mchk) {
channel_subsys.do_crw_mchk = false;
/* Inject crw pending machine check. */
s390_crw_mchk();
}
@ -1328,9 +1405,9 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
if (add && !hotplugged) {
return;
}
if (channel_subsys->max_cssid == 0) {
if (channel_subsys.max_cssid == 0) {
/* Default cssid shows up as 0. */
guest_cssid = (cssid == channel_subsys->default_cssid) ? 0 : cssid;
guest_cssid = (cssid == channel_subsys.default_cssid) ? 0 : cssid;
} else {
/* Show real cssid to the guest. */
guest_cssid = cssid;
@ -1339,14 +1416,14 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
* Only notify for higher subchannel sets/channel subsystems if the
* guest has enabled it.
*/
if ((ssid > channel_subsys->max_ssid) ||
(guest_cssid > channel_subsys->max_cssid) ||
((channel_subsys->max_cssid == 0) &&
(cssid != channel_subsys->default_cssid))) {
if ((ssid > channel_subsys.max_ssid) ||
(guest_cssid > channel_subsys.max_cssid) ||
((channel_subsys.max_cssid == 0) &&
(cssid != channel_subsys.default_cssid))) {
return;
}
chain_crw = (channel_subsys->max_ssid > 0) ||
(channel_subsys->max_cssid > 0);
chain_crw = (channel_subsys.max_ssid > 0) ||
(channel_subsys.max_cssid > 0);
css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, chain_crw ? 1 : 0, schid);
if (chain_crw) {
css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0,
@ -1361,28 +1438,28 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid)
void css_generate_css_crws(uint8_t cssid)
{
if (!channel_subsys->sei_pending) {
if (!channel_subsys.sei_pending) {
css_queue_crw(CRW_RSC_CSS, 0, 0, cssid);
}
channel_subsys->sei_pending = true;
channel_subsys.sei_pending = true;
}
void css_clear_sei_pending(void)
{
channel_subsys->sei_pending = false;
channel_subsys.sei_pending = false;
}
int css_enable_mcsse(void)
{
trace_css_enable_facility("mcsse");
channel_subsys->max_cssid = MAX_CSSID;
channel_subsys.max_cssid = MAX_CSSID;
return 0;
}
int css_enable_mss(void)
{
trace_css_enable_facility("mss");
channel_subsys->max_ssid = MAX_SSID;
channel_subsys.max_ssid = MAX_SSID;
return 0;
}
@ -1505,28 +1582,15 @@ int subch_device_load(SubchDev *s, QEMUFile *f)
*/
if (s->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA) {
if (s->ssid) {
channel_subsys->max_ssid = MAX_SSID;
channel_subsys.max_ssid = MAX_SSID;
}
if (s->cssid != channel_subsys->default_cssid) {
channel_subsys->max_cssid = MAX_CSSID;
if (s->cssid != channel_subsys.default_cssid) {
channel_subsys.max_cssid = MAX_CSSID;
}
}
return 0;
}
static void css_init(void)
{
channel_subsys = g_malloc0(sizeof(*channel_subsys));
QTAILQ_INIT(&channel_subsys->pending_crws);
channel_subsys->sei_pending = false;
channel_subsys->do_crw_mchk = true;
channel_subsys->crws_lost = false;
channel_subsys->chnmon_active = false;
QTAILQ_INIT(&channel_subsys->io_adapters);
}
machine_init(css_init);
void css_reset_sch(SubchDev *sch)
{
PMCW *p = &sch->curr_status.pmcw;
@ -1564,19 +1628,19 @@ void css_reset(void)
CrwContainer *crw_cont;
/* Clean up monitoring. */
channel_subsys->chnmon_active = false;
channel_subsys->chnmon_area = 0;
channel_subsys.chnmon_active = false;
channel_subsys.chnmon_area = 0;
/* Clear pending CRWs. */
while ((crw_cont = QTAILQ_FIRST(&channel_subsys->pending_crws))) {
QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling);
while ((crw_cont = QTAILQ_FIRST(&channel_subsys.pending_crws))) {
QTAILQ_REMOVE(&channel_subsys.pending_crws, crw_cont, sibling);
g_free(crw_cont);
}
channel_subsys->sei_pending = false;
channel_subsys->do_crw_mchk = true;
channel_subsys->crws_lost = false;
channel_subsys.sei_pending = false;
channel_subsys.do_crw_mchk = true;
channel_subsys.crws_lost = false;
/* Reset maximum ids. */
channel_subsys->max_cssid = 0;
channel_subsys->max_ssid = 0;
channel_subsys.max_cssid = 0;
channel_subsys.max_ssid = 0;
}

View file

@ -12,6 +12,8 @@
#ifndef CSS_H
#define CSS_H
#include "hw/s390x/adapter.h"
#include "hw/s390x/s390_flic.h"
#include "ioinst.h"
/* Channel subsystem constants. */
@ -86,6 +88,18 @@ struct SubchDev {
void *driver_data;
};
typedef struct IndAddr {
hwaddr addr;
uint64_t map;
unsigned long refcnt;
int len;
QTAILQ_ENTRY(IndAddr) sibling;
} IndAddr;
IndAddr *get_indicator(hwaddr ind_addr, int len);
void release_indicator(AdapterInfo *adapter, IndAddr *indicator);
int map_indicator(AdapterInfo *adapter, IndAddr *indicator);
typedef SubchDev *(*css_subch_cb_func)(uint8_t m, uint8_t cssid, uint8_t ssid,
uint16_t schid);
void subch_device_save(SubchDev *s, QEMUFile *f);

View file

@ -524,7 +524,7 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev)
return 0;
}
ctrl = pci_host_config_read_common(pbdev->pdev, pos + PCI_CAP_FLAGS,
ctrl = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_FLAGS,
pci_config_size(pbdev->pdev), sizeof(ctrl));
table = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_TABLE,
pci_config_size(pbdev->pdev), sizeof(table));

View file

@ -233,6 +233,8 @@ typedef struct S390PCIBusDevice {
AddressSpace as;
MemoryRegion mr;
MemoryRegion iommu_mr;
IndAddr *summary_ind;
IndAddr *indicator;
} S390PCIBusDevice;
typedef struct S390pciState {

View file

@ -621,19 +621,19 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
{
int ret;
S390FLICState *fs = s390_get_flic();
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
int ret, len;
ret = css_register_io_adapter(S390_PCIPT_ADAPTER,
FIB_DATA_ISC(ldl_p(&fib.data)), true, false,
&pbdev->routes.adapter.adapter_id);
assert(ret == 0);
fsc->io_adapter_map(fs, pbdev->routes.adapter.adapter_id,
ldq_p(&fib.aisb), true);
fsc->io_adapter_map(fs, pbdev->routes.adapter.adapter_id,
ldq_p(&fib.aibv), true);
pbdev->summary_ind = get_indicator(ldq_p(&fib.aisb), sizeof(uint64_t));
len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long);
pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len);
map_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
map_indicator(&pbdev->routes.adapter, pbdev->indicator);
pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb);
pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data));
@ -649,12 +649,11 @@ static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
static int dereg_irqs(S390PCIBusDevice *pbdev)
{
S390FLICState *fs = s390_get_flic();
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
fsc->io_adapter_map(fs, pbdev->routes.adapter.adapter_id,
pbdev->routes.adapter.ind_addr, false);
release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
release_indicator(&pbdev->routes.adapter, pbdev->indicator);
pbdev->summary_ind = NULL;
pbdev->indicator = NULL;
pbdev->routes.adapter.summary_addr = 0;
pbdev->routes.adapter.summary_offset = 0;
pbdev->routes.adapter.ind_addr = 0;

View file

@ -54,8 +54,6 @@
#endif
#define MAX_BLK_DEVS 10
#define S390_MACHINE "s390-virtio"
#define TYPE_S390_MACHINE MACHINE_TYPE_NAME(S390_MACHINE)
#define S390_TOD_CLOCK_VALUE_MISSING 0x00
#define S390_TOD_CLOCK_VALUE_PRESENT 0x01

View file

@ -32,69 +32,6 @@
#include "virtio-ccw.h"
#include "trace.h"
static QTAILQ_HEAD(, IndAddr) indicator_addresses =
QTAILQ_HEAD_INITIALIZER(indicator_addresses);
static IndAddr *get_indicator(hwaddr ind_addr, int len)
{
IndAddr *indicator;
QTAILQ_FOREACH(indicator, &indicator_addresses, sibling) {
if (indicator->addr == ind_addr) {
indicator->refcnt++;
return indicator;
}
}
indicator = g_new0(IndAddr, 1);
indicator->addr = ind_addr;
indicator->len = len;
indicator->refcnt = 1;
QTAILQ_INSERT_TAIL(&indicator_addresses, indicator, sibling);
return indicator;
}
static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr,
bool do_map)
{
S390FLICState *fs = s390_get_flic();
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map);
}
static void release_indicator(AdapterInfo *adapter, IndAddr *indicator)
{
assert(indicator->refcnt > 0);
indicator->refcnt--;
if (indicator->refcnt > 0) {
return;
}
QTAILQ_REMOVE(&indicator_addresses, indicator, sibling);
if (indicator->map) {
s390_io_adapter_map(adapter, indicator->map, false);
}
g_free(indicator);
}
static int map_indicator(AdapterInfo *adapter, IndAddr *indicator)
{
int ret;
if (indicator->map) {
return 0; /* already mapped is not an error */
}
indicator->map = indicator->addr;
ret = s390_io_adapter_map(adapter, indicator->map, true);
if ((ret != 0) && (ret != -ENOSYS)) {
goto out_err;
}
return 0;
out_err:
indicator->map = 0;
return ret;
}
static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
VirtioCcwDevice *dev);

View file

@ -23,7 +23,8 @@
#include <hw/virtio/virtio-balloon.h>
#include <hw/virtio/virtio-rng.h>
#include <hw/virtio/virtio-bus.h>
#include <hw/s390x/s390_flic.h>
#include "css.h"
#define VIRTUAL_CSSID 0xfe
@ -75,14 +76,6 @@ typedef struct VirtIOCCWDeviceClass {
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT)
typedef struct IndAddr {
hwaddr addr;
uint64_t map;
unsigned long refcnt;
int len;
QTAILQ_ENTRY(IndAddr) sibling;
} IndAddr;
struct VirtioCcwDevice {
DeviceState parent_obj;
SubchDev *sch;

View file

@ -51,15 +51,19 @@ static void diag288_reset(void *opaque)
static void diag288_timer_expired(void *dev)
{
qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
watchdog_perform_action();
/* Reset the watchdog only if the guest was notified about expiry. */
/* Reset the watchdog only if the guest gets notified about
* expiry. watchdog_perform_action() may temporarily relinquish
* the BQL; reset before triggering the action to avoid races with
* diag288 instructions. */
switch (get_watchdog_action()) {
case WDT_DEBUG:
case WDT_NONE:
case WDT_PAUSE:
return;
break;
default:
wdt_diag288_reset(dev);
}
wdt_diag288_reset(dev);
watchdog_perform_action();
}
static int wdt_diag288_handle_timer(DIAG288State *diag288,

View file

@ -416,6 +416,8 @@
#define __NR_execveat (__NR_SYSCALL_BASE+387)
#define __NR_userfaultfd (__NR_SYSCALL_BASE+388)
#define __NR_membarrier (__NR_SYSCALL_BASE+389)
#define __NR_mlock2 (__NR_SYSCALL_BASE+390)
#define __NR_copy_file_range (__NR_SYSCALL_BASE+391)
/*
* The following SWIs are ARM private.

View file

@ -388,18 +388,7 @@
#define __NR_switch_endian 363
#define __NR_userfaultfd 364
#define __NR_membarrier 365
#define __NR_semop 366
#define __NR_semget 367
#define __NR_semctl 368
#define __NR_semtimedop 369
#define __NR_msgsnd 370
#define __NR_msgrcv 371
#define __NR_msgget 372
#define __NR_msgctl 373
#define __NR_shmat 374
#define __NR_shmdt 375
#define __NR_shmget 376
#define __NR_shmctl 377
#define __NR_mlock2 378
#define __NR_copy_file_range 379
#endif /* _ASM_POWERPC_UNISTD_H_ */

View file

@ -153,6 +153,8 @@ struct kvm_guest_debug_arch {
#define KVM_SYNC_ARCH0 (1UL << 4)
#define KVM_SYNC_PFAULT (1UL << 5)
#define KVM_SYNC_VRS (1UL << 6)
#define KVM_SYNC_RICCB (1UL << 7)
#define KVM_SYNC_FPRS (1UL << 8)
/* definition of registers in kvm_run */
struct kvm_sync_regs {
__u64 prefix; /* prefix register */
@ -167,9 +169,14 @@ struct kvm_sync_regs {
__u64 pft; /* pfault token [PFAULT] */
__u64 pfs; /* pfault select [PFAULT] */
__u64 pfc; /* pfault compare [PFAULT] */
__u64 vrs[32][2]; /* vector registers */
union {
__u64 vrs[32][2]; /* vector registers (KVM_SYNC_VRS) */
__u64 fprs[16]; /* fp registers (KVM_SYNC_FPRS) */
};
__u8 reserved[512]; /* for future vector expansion */
__u32 fpc; /* only valid with vector registers */
__u32 fpc; /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */
__u8 padding[52]; /* riccb needs to be 64byte aligned */
__u8 riccb[64]; /* runtime instrumentation controls block */
};
#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)

View file

@ -310,7 +310,8 @@
#define __NR_recvmsg 372
#define __NR_shutdown 373
#define __NR_mlock2 374
#define NR_syscalls 375
#define __NR_copy_file_range 375
#define NR_syscalls 376
/*
* There are some system calls that are not present on 64 bit, some

View file

@ -374,5 +374,6 @@
#define __NR_userfaultfd 374
#define __NR_membarrier 375
#define __NR_mlock2 376
#define __NR_copy_file_range 377
#endif /* _ASM_X86_UNISTD_32_H */

View file

@ -327,5 +327,6 @@
#define __NR_userfaultfd 323
#define __NR_membarrier 324
#define __NR_mlock2 325
#define __NR_copy_file_range 326
#endif /* _ASM_X86_UNISTD_64_H */

View file

@ -282,6 +282,7 @@
#define __NR_userfaultfd (__X32_SYSCALL_BIT + 323)
#define __NR_membarrier (__X32_SYSCALL_BIT + 324)
#define __NR_mlock2 (__X32_SYSCALL_BIT + 325)
#define __NR_copy_file_range (__X32_SYSCALL_BIT + 326)
#define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512)
#define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513)
#define __NR_ioctl (__X32_SYSCALL_BIT + 514)

View file

@ -541,7 +541,13 @@ struct kvm_s390_pgm_info {
__u8 exc_access_id;
__u8 per_access_id;
__u8 op_access_id;
__u8 pad[3];
#define KVM_S390_PGM_FLAGS_ILC_VALID 0x01
#define KVM_S390_PGM_FLAGS_ILC_0 0x02
#define KVM_S390_PGM_FLAGS_ILC_1 0x04
#define KVM_S390_PGM_FLAGS_ILC_MASK 0x06
#define KVM_S390_PGM_FLAGS_NO_REWIND 0x08
__u8 flags;
__u8 pad[2];
};
struct kvm_s390_prefix_info {
@ -849,6 +855,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_SPLIT_IRQCHIP 121
#define KVM_CAP_IOEVENTFD_ANY_LENGTH 122
#define KVM_CAP_HYPERV_SYNIC 123
#define KVM_CAP_S390_RI 124
#ifdef KVM_CAP_IRQ_ROUTING

View file

@ -38,6 +38,13 @@
#define VFIO_SPAPR_TCE_v2_IOMMU 7
/*
* The No-IOMMU IOMMU offers no translation or isolation for devices and
* supports no ioctls outside of VFIO_CHECK_EXTENSION. Use of VFIO's No-IOMMU
* code will taint the host kernel and should be used with extreme caution.
*/
#define VFIO_NOIOMMU_IOMMU 8
/*
* The IOCTL interface is designed for extensibility by embedding the
* structure length (argsz) and flags into structures passed between
@ -568,8 +575,10 @@ struct vfio_iommu_spapr_tce_create {
__u32 flags;
/* in */
__u32 page_shift;
__u32 __resv1;
__u64 window_size;
__u32 levels;
__u32 __resv2;
/* out */
__u64 start_addr;
};

View file

@ -470,10 +470,8 @@ void s390x_tod_timer(void *opaque);
void s390x_cpu_timer(void *opaque);
int s390_virtio_hypercall(CPUS390XState *env);
void s390_virtio_irq(int config_change, uint64_t token);
#ifdef CONFIG_KVM
void kvm_s390_virtio_irq(int config_change, uint64_t token);
void kvm_s390_service_interrupt(uint32_t parm);
void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
@ -484,9 +482,6 @@ int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
#else
static inline void kvm_s390_virtio_irq(int config_change, uint64_t token)
{
}
static inline void kvm_s390_service_interrupt(uint32_t parm)
{
}

View file

@ -28,17 +28,6 @@ void s390_sclp_extint(uint32_t parm)
}
}
void s390_virtio_irq(int config_change, uint64_t token)
{
if (kvm_enabled()) {
kvm_s390_virtio_irq(config_change, token);
} else {
S390CPU *dummy_cpu = s390_cpu_addr2state(0);
cpu_inject_ext(dummy_cpu, EXT_VIRTIO, config_change, token);
}
}
void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
uint32_t io_int_parm, uint32_t io_int_word)
{

View file

@ -342,6 +342,12 @@ int kvm_arch_put_registers(CPUState *cs, int level)
}
cs->kvm_run->s.regs.fpc = env->fpc;
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_VRS;
} else if (can_sync_regs(cs, KVM_SYNC_FPRS)) {
for (i = 0; i < 16; i++) {
cs->kvm_run->s.regs.fprs[i] = get_freg(env, i)->ll;
}
cs->kvm_run->s.regs.fpc = env->fpc;
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_FPRS;
} else {
/* Floating point */
for (i = 0; i < 16; i++) {
@ -482,6 +488,11 @@ int kvm_arch_get_registers(CPUState *cs)
env->vregs[i][1].ll = cs->kvm_run->s.regs.vrs[i][1];
}
env->fpc = cs->kvm_run->s.regs.fpc;
} else if (can_sync_regs(cs, KVM_SYNC_FPRS)) {
for (i = 0; i < 16; i++) {
get_freg(env, i)->ll = cs->kvm_run->s.regs.fprs[i];
}
env->fpc = cs->kvm_run->s.regs.fpc;
} else {
r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
if (r < 0) {
@ -925,17 +936,6 @@ void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq)
__kvm_s390_floating_interrupt(irq);
}
void kvm_s390_virtio_irq(int config_change, uint64_t token)
{
struct kvm_s390_irq irq = {
.type = KVM_S390_INT_VIRTIO,
.u.ext.ext_params = config_change,
.u.ext.ext_params2 = token,
};
kvm_s390_floating_interrupt(&irq);
}
void kvm_s390_service_interrupt(uint32_t parm)
{
struct kvm_s390_irq irq = {

View file

@ -90,7 +90,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | asc >> 46;
DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
DPRINTF("%s: trans_exc_code=%016" PRIx64 "\n", __func__, tec);
if (!exc) {
return;