aboutsummaryrefslogtreecommitdiff
path: root/hw/s390x/css.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/s390x/css.c')
-rw-r--r--hw/s390x/css.c173
1 files changed, 50 insertions, 123 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 35683d7..f6b5c80 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -488,7 +488,7 @@ int css_create_css_image(uint8_t cssid, bool default_image)
if (channel_subsys.css[cssid]) {
return -EBUSY;
}
- channel_subsys.css[cssid] = g_malloc0(sizeof(CssImage));
+ channel_subsys.css[cssid] = g_new0(CssImage, 1);
if (default_image) {
channel_subsys.default_cssid = cssid;
}
@@ -1181,12 +1181,11 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
}
-static int sch_handle_start_func_passthrough(SubchDev *sch)
+static IOInstEnding sch_handle_start_func_passthrough(SubchDev *sch)
{
PMCW *p = &sch->curr_status.pmcw;
SCSW *s = &sch->curr_status.scsw;
- int ret;
ORB *orb = &sch->orb;
if (!(s->ctrl & SCSW_ACTL_SUSP)) {
@@ -1200,31 +1199,12 @@ static int sch_handle_start_func_passthrough(SubchDev *sch)
*/
if (!(orb->ctrl0 & ORB_CTRL0_MASK_PFCH) ||
!(orb->ctrl0 & ORB_CTRL0_MASK_C64)) {
- return -EINVAL;
+ warn_report("vfio-ccw requires PFCH and C64 flags set");
+ sch_gen_unit_exception(sch);
+ css_inject_io_interrupt(sch);
+ return IOINST_CC_EXPECTED;
}
-
- ret = s390_ccw_cmd_request(orb, s, sch->driver_data);
- switch (ret) {
- /* Currently we don't update control block and just return the cc code. */
- case 0:
- break;
- case -EBUSY:
- break;
- case -ENODEV:
- break;
- case -EACCES:
- /* Let's reflect an inaccessible host device by cc 3. */
- ret = -ENODEV;
- break;
- default:
- /*
- * All other return codes will trigger a program check,
- * or set cc to 1.
- */
- break;
- };
-
- return ret;
+ return s390_ccw_cmd_request(sch);
}
/*
@@ -1233,7 +1213,7 @@ static int sch_handle_start_func_passthrough(SubchDev *sch)
* read/writes) asynchronous later on if we start supporting more than
* our current very simple devices.
*/
-int do_subchannel_work_virtual(SubchDev *sch)
+IOInstEnding do_subchannel_work_virtual(SubchDev *sch)
{
SCSW *s = &sch->curr_status.scsw;
@@ -1245,44 +1225,35 @@ int do_subchannel_work_virtual(SubchDev *sch)
} else if (s->ctrl & SCSW_FCTL_START_FUNC) {
/* Triggered by both ssch and rsch. */
sch_handle_start_func_virtual(sch);
- } else {
- /* Cannot happen. */
- return 0;
}
css_inject_io_interrupt(sch);
- return 0;
+ /* inst must succeed if this func is called */
+ return IOINST_CC_EXPECTED;
}
-int do_subchannel_work_passthrough(SubchDev *sch)
+IOInstEnding do_subchannel_work_passthrough(SubchDev *sch)
{
- int ret;
SCSW *s = &sch->curr_status.scsw;
if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {
/* TODO: Clear handling */
sch_handle_clear_func(sch);
- ret = 0;
} else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {
/* TODO: Halt handling */
sch_handle_halt_func(sch);
- ret = 0;
} else if (s->ctrl & SCSW_FCTL_START_FUNC) {
- ret = sch_handle_start_func_passthrough(sch);
- } else {
- /* Cannot happen. */
- return -ENODEV;
+ return sch_handle_start_func_passthrough(sch);
}
-
- return ret;
+ return IOINST_CC_EXPECTED;
}
-static int do_subchannel_work(SubchDev *sch)
+static IOInstEnding do_subchannel_work(SubchDev *sch)
{
- if (sch->do_subchannel_work) {
- return sch->do_subchannel_work(sch);
- } else {
- return -EINVAL;
+ if (!sch->do_subchannel_work) {
+ return IOINST_CC_STATUS_PRESENT;
}
+ g_assert(sch->curr_status.scsw.ctrl & SCSW_CTRL_MASK_FCTL);
+ return sch->do_subchannel_work(sch);
}
static void copy_pmcw_to_guest(PMCW *dest, const PMCW *src)
@@ -1376,28 +1347,24 @@ static void copy_schib_from_guest(SCHIB *dest, const SCHIB *src)
}
}
-int css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
+IOInstEnding 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;
if (!(sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_DNV)) {
- ret = 0;
- goto out;
+ return IOINST_CC_EXPECTED;
}
if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
- ret = -EINPROGRESS;
- goto out;
+ return IOINST_CC_STATUS_PRESENT;
}
if (s->ctrl &
(SCSW_FCTL_START_FUNC|SCSW_FCTL_HALT_FUNC|SCSW_FCTL_CLEAR_FUNC)) {
- ret = -EBUSY;
- goto out;
+ return IOINST_CC_BUSY;
}
copy_schib_from_guest(&schib, orig_schib);
@@ -1424,27 +1391,20 @@ int css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
&& (p->flags & PMCW_FLAGS_MASK_ENA) == 0) {
sch->disable_cb(sch);
}
-
- ret = 0;
-
-out:
- return ret;
+ return IOINST_CC_EXPECTED;
}
-int css_do_xsch(SubchDev *sch)
+IOInstEnding css_do_xsch(SubchDev *sch)
{
SCSW *s = &sch->curr_status.scsw;
PMCW *p = &sch->curr_status.pmcw;
- int ret;
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
- ret = -ENODEV;
- goto out;
+ return IOINST_CC_NOT_OPERATIONAL;
}
if (s->ctrl & SCSW_CTRL_MASK_STCTL) {
- ret = -EINPROGRESS;
- goto out;
+ return IOINST_CC_STATUS_PRESENT;
}
if (!(s->ctrl & SCSW_CTRL_MASK_FCTL) ||
@@ -1452,8 +1412,7 @@ int css_do_xsch(SubchDev *sch)
(!(s->ctrl &
(SCSW_ACTL_RESUME_PEND | SCSW_ACTL_START_PEND | SCSW_ACTL_SUSP))) ||
(s->ctrl & SCSW_ACTL_SUBCH_ACTIVE)) {
- ret = -EBUSY;
- goto out;
+ return IOINST_CC_BUSY;
}
/* Cancel the current operation. */
@@ -1465,56 +1424,43 @@ int css_do_xsch(SubchDev *sch)
sch->last_cmd_valid = false;
s->dstat = 0;
s->cstat = 0;
- ret = 0;
-
-out:
- return ret;
+ return IOINST_CC_EXPECTED;
}
-int css_do_csch(SubchDev *sch)
+IOInstEnding css_do_csch(SubchDev *sch)
{
SCSW *s = &sch->curr_status.scsw;
PMCW *p = &sch->curr_status.pmcw;
- int ret;
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
- ret = -ENODEV;
- goto out;
+ return IOINST_CC_NOT_OPERATIONAL;
}
/* Trigger the clear function. */
s->ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL);
s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND;
- do_subchannel_work(sch);
- ret = 0;
-
-out:
- return ret;
+ return do_subchannel_work(sch);
}
-int css_do_hsch(SubchDev *sch)
+IOInstEnding css_do_hsch(SubchDev *sch)
{
SCSW *s = &sch->curr_status.scsw;
PMCW *p = &sch->curr_status.pmcw;
- int ret;
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
- ret = -ENODEV;
- goto out;
+ return IOINST_CC_NOT_OPERATIONAL;
}
if (((s->ctrl & SCSW_CTRL_MASK_STCTL) == SCSW_STCTL_STATUS_PEND) ||
(s->ctrl & (SCSW_STCTL_PRIMARY |
SCSW_STCTL_SECONDARY |
SCSW_STCTL_ALERT))) {
- ret = -EINPROGRESS;
- goto out;
+ return IOINST_CC_STATUS_PRESENT;
}
if (s->ctrl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
- ret = -EBUSY;
- goto out;
+ return IOINST_CC_BUSY;
}
/* Trigger the halt function. */
@@ -1527,11 +1473,7 @@ int css_do_hsch(SubchDev *sch)
}
s->ctrl |= SCSW_ACTL_HALT_PEND;
- do_subchannel_work(sch);
- ret = 0;
-
-out:
- return ret;
+ return do_subchannel_work(sch);
}
static void css_update_chnmon(SubchDev *sch)
@@ -1569,27 +1511,23 @@ static void css_update_chnmon(SubchDev *sch)
}
}
-int css_do_ssch(SubchDev *sch, ORB *orb)
+IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb)
{
SCSW *s = &sch->curr_status.scsw;
PMCW *p = &sch->curr_status.pmcw;
- int ret;
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
- ret = -ENODEV;
- goto out;
+ return IOINST_CC_NOT_OPERATIONAL;
}
if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
- ret = -EINPROGRESS;
- goto out;
+ return IOINST_CC_STATUS_PRESENT;
}
if (s->ctrl & (SCSW_FCTL_START_FUNC |
SCSW_FCTL_HALT_FUNC |
SCSW_FCTL_CLEAR_FUNC)) {
- ret = -EBUSY;
- goto out;
+ return IOINST_CC_BUSY;
}
/* If monitoring is active, update counter. */
@@ -1602,10 +1540,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb)
s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND);
s->flags &= ~SCSW_FLAGS_MASK_PNO;
- ret = do_subchannel_work(sch);
-
-out:
- return ret;
+ return do_subchannel_work(sch);
}
static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw,
@@ -1778,7 +1713,7 @@ void css_undo_stcrw(CRW *crw)
{
CrwContainer *crw_cont;
- crw_cont = g_try_malloc0(sizeof(CrwContainer));
+ crw_cont = g_try_new0(CrwContainer, 1);
if (!crw_cont) {
channel_subsys.crws_lost = true;
return;
@@ -1852,27 +1787,23 @@ void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo)
}
}
-int css_do_rsch(SubchDev *sch)
+IOInstEnding css_do_rsch(SubchDev *sch)
{
SCSW *s = &sch->curr_status.scsw;
PMCW *p = &sch->curr_status.pmcw;
- int ret;
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
- ret = -ENODEV;
- goto out;
+ return IOINST_CC_NOT_OPERATIONAL;
}
if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
- ret = -EINPROGRESS;
- goto out;
+ return IOINST_CC_STATUS_PRESENT;
}
if (((s->ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
(s->ctrl & SCSW_ACTL_RESUME_PEND) ||
(!(s->ctrl & SCSW_ACTL_SUSP))) {
- ret = -EINVAL;
- goto out;
+ return IOINST_CC_BUSY;
}
/* If monitoring is active, update counter. */
@@ -1881,11 +1812,7 @@ int css_do_rsch(SubchDev *sch)
}
s->ctrl |= SCSW_ACTL_RESUME_PEND;
- do_subchannel_work(sch);
- ret = 0;
-
-out:
- return ret;
+ return do_subchannel_work(sch);
}
int css_do_rchp(uint8_t cssid, uint8_t chpid)
@@ -2185,7 +2112,7 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
css = channel_subsys.css[cssid];
if (!css->sch_set[ssid]) {
- css->sch_set[ssid] = g_malloc0(sizeof(SubchSet));
+ css->sch_set[ssid] = g_new0(SubchSet, 1);
}
s_set = css->sch_set[ssid];
@@ -2206,7 +2133,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited,
trace_css_crw(rsc, erc, rsid, chain ? "(chained)" : "");
/* TODO: Maybe use a static crw pool? */
- crw_cont = g_try_malloc0(sizeof(CrwContainer));
+ crw_cont = g_try_new0(CrwContainer, 1);
if (!crw_cont) {
channel_subsys.crws_lost = true;
return;
@@ -2498,7 +2425,7 @@ SubchDev *css_create_sch(CssDevId bus_id, bool is_virtual, bool squash_mcss,
}
}
- sch = g_malloc0(sizeof(*sch));
+ sch = g_new0(SubchDev, 1);
sch->cssid = bus_id.cssid;
sch->ssid = bus_id.ssid;
sch->devno = bus_id.devid;