From nobody Mon Oct 13 23:47:35 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linux.ibm.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1552318884237169.0172012954297; Mon, 11 Mar 2019 08:41:24 -0700 (PDT) Received: from localhost ([127.0.0.1]:35436 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h3N3F-0004Kp-1S for importer@patchew.org; Mon, 11 Mar 2019 11:41:17 -0400 Received: from eggs.gnu.org ([209.51.188.92]:42203) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h3Mw0-0005vg-LX for qemu-devel@nongnu.org; Mon, 11 Mar 2019 11:33:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h3MnN-0007sx-Qg for qemu-devel@nongnu.org; Mon, 11 Mar 2019 11:24:55 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:58048) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1h3MnN-0007sS-4h for qemu-devel@nongnu.org; Mon, 11 Mar 2019 11:24:53 -0400 Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2BFOYMf043397 for ; Mon, 11 Mar 2019 11:24:51 -0400 Received: from e14.ny.us.ibm.com (e14.ny.us.ibm.com [129.33.205.204]) by mx0a-001b2d01.pphosted.com with ESMTP id 2r5s57urgk-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 11 Mar 2019 11:24:47 -0400 Received: from localhost by e14.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 11 Mar 2019 15:21:52 -0000 Received: from b01cxnp23034.gho.pok.ibm.com (9.57.198.29) by e14.ny.us.ibm.com (146.89.104.201) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Mon, 11 Mar 2019 15:21:49 -0000 Received: from b01ledav004.gho.pok.ibm.com (b01ledav004.gho.pok.ibm.com [9.57.199.109]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x2BFLlT121102794 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 11 Mar 2019 15:21:47 GMT Received: from b01ledav004.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0EB1F112061; Mon, 11 Mar 2019 15:21:47 +0000 (GMT) Received: from b01ledav004.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C99AA112067; Mon, 11 Mar 2019 15:21:46 +0000 (GMT) Received: from jason-laptop.endicott.ibm.com (unknown [9.60.75.251]) by b01ledav004.gho.pok.ibm.com (Postfix) with ESMTP; Mon, 11 Mar 2019 15:21:46 +0000 (GMT) From: "Jason J. Herne" To: qemu-devel@nongnu.org, qemu-s390x@nongnu.org, cohuck@redhat.com, thuth@redhat.com, pasic@linux.ibm.com, alifm@linux.ibm.com, borntraeger@de.ibm.com Date: Mon, 11 Mar 2019 11:21:28 -0400 X-Mailer: git-send-email 2.7.4 In-Reply-To: <1552317693-21979-1-git-send-email-jjherne@linux.ibm.com> References: <1552317693-21979-1-git-send-email-jjherne@linux.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 19031115-0052-0000-0000-0000039914E2 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00010739; HX=3.00000242; KW=3.00000007; PH=3.00000004; SC=3.00000281; SDB=6.01172861; UDB=6.00613172; IPR=6.00953516; MB=3.00025928; MTD=3.00000008; XFM=3.00000015; UTC=2019-03-11 15:21:51 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 19031115-0053-0000-0000-0000601E92B7 Message-Id: <1552317693-21979-11-git-send-email-jjherne@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-11_12:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1903110110 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PATCH v4 10/15] s390-bios: Support for running format-0/1 channel programs X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Introduce a library function for executing format-0 and format-1 channel programs and waiting for their completion before continuing execution. Add cu_type() to channel io library. This will be used to query control unit type which is used to determine if we are booting a virtio device or a real dasd device. Signed-off-by: Jason J. Herne Reviewed-by: Cornelia Huck --- pc-bios/s390-ccw/cio.c | 144 ++++++++++++++++++++++++++++++++++++++++= ++++ pc-bios/s390-ccw/cio.h | 130 ++++++++++++++++++++++++++++++++++++++- pc-bios/s390-ccw/s390-ccw.h | 1 + pc-bios/s390-ccw/start.S | 29 +++++++++ 4 files changed, 301 insertions(+), 3 deletions(-) diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c index 87c6b34..58f63e4 100644 --- a/pc-bios/s390-ccw/cio.c +++ b/pc-bios/s390-ccw/cio.c @@ -13,10 +13,14 @@ =20 #include "libc.h" #include "s390-ccw.h" +#include "s390-arch.h" +#include "helper.h" #include "cio.h" =20 static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); =20 +static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *i= rb); + int enable_mss_facility(void) { int ret; @@ -42,3 +46,143 @@ void enable_subchannel(SubChannelId schid) schib.pmcw.ena =3D 1; msch(schid, &schib); } + +uint16_t cu_type(SubChannelId schid) +{ + Ccw1 sense_id_ccw; + SenseId sense_data; + + sense_id_ccw.cmd_code =3D CCW_CMD_SENSE_ID; + sense_id_ccw.cda =3D ptr2u32(&sense_data); + sense_id_ccw.count =3D sizeof(sense_data); + sense_id_ccw.flags |=3D CCW_FLAG_SLI; + + if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) { + panic("Failed to run SenseID CCw\n"); + } + + return sense_data.cu_type; +} + +int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data, + uint16_t data_size) +{ + Ccw1 senseCcw; + Irb irb; + + senseCcw.cmd_code =3D CCW_CMD_BASIC_SENSE; + senseCcw.cda =3D ptr2u32(sense_data); + senseCcw.count =3D data_size; + + return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb); +} + +static bool irb_error(Irb *irb) +{ + if (irb->scsw.cstat) { + return true; + } + return irb->scsw.dstat !=3D (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND); +} + +/* + * Handles executing ssch, tsch and returns the irb obtained from tsch. + * Returns 0 on success, -1 if unexpected status pending and we need to re= try, + * otherwise returns condition code from ssch/tsch for error cases. + */ +static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *i= rb) +{ + CmdOrb orb =3D {}; + int rc; + + IPL_assert(fmt =3D=3D 0 || fmt =3D=3D 1, "Invalid ccw format"); + + /* ccw_addr must be <=3D 24 bits and point to at least one whole ccw. = */ + if (fmt =3D=3D 0) { + IPL_assert(ccw_addr <=3D 0xFFFFFF - 8, "Invalid ccw address"); + } + + orb.fmt =3D fmt; + orb.pfch =3D 1; /* QEMU's cio implementation requires prefetch */ + orb.c64 =3D 1; /* QEMU's cio implementation requires 64-bit idaws */ + orb.lpm =3D 0xFF; /* All paths allowed */ + orb.cpa =3D ccw_addr; + + rc =3D ssch(schid, &orb); + if (rc =3D=3D 1 || rc =3D=3D 2) { + /* Subchannel status pending or busy. Eat status and ask for retry= . */ + tsch(schid, irb); + return -1; + } + if (rc) { + print_int("ssch failed with cc=3D", rc); + return rc; + } + + consume_io_int(); + + /* collect status */ + rc =3D tsch(schid, irb); + if (rc) { + print_int("tsch failed with cc=3D", rc); + } + + return rc; +} + +/* + * Executes a channel program at a given subchannel. The request to run the + * channel program is sent to the subchannel, we then wait for the interru= pt + * signaling completion of the I/O operation(s) performed by the channel + * program. Lastly we verify that the i/o operation completed without erro= r and + * that the interrupt we received was for the subchannel used to run the + * channel program. + * + * Note: This function assumes it is running in an environment where no ot= her + * cpus are generating or receiving I/O interrupts. So either run it in a + * single-cpu environment or make sure all other cpus are not doing I/O and + * have I/O interrupts masked off. We also assume that only one device is + * active (generating i/o interrupts).=20 + * + * Returns non-zero on error. + */ +int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt) +{ + Irb irb =3D {}; + SenseDataEckdDasd sd; + int rc, retries =3D 0; + + while (true) { + rc =3D __do_cio(schid, ccw_addr, fmt, &irb); + + if (rc =3D=3D -1) { + retries++; + continue; + } + if (rc) { + /* ssch/tsch error. Message already reported by __do_cio */ + break; + } + + if (!irb_error(&irb)) { + break; + } + + /* + * Unexpected unit check, or interface-control-check. Use sense to + * clear (unit check only) then retry. + */ + if ((unit_check(&irb) || iface_ctrl_check(&irb)) && retries <=3D 2= ) { + if (unit_check(&irb)) { + basic_sense(schid, cutype, &sd, sizeof(sd)); + } + retries++; + continue; + } + + rc =3D -1; + break; + } + + return rc; +} diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h index 218fd96..1637e32 100644 --- a/pc-bios/s390-ccw/cio.h +++ b/pc-bios/s390-ccw/cio.h @@ -70,9 +70,46 @@ struct scsw { __u16 count; } __attribute__ ((packed)); =20 -#define SCSW_FCTL_CLEAR_FUNC 0x1000 -#define SCSW_FCTL_HALT_FUNC 0x2000 +/* Function Control */ #define SCSW_FCTL_START_FUNC 0x4000 +#define SCSW_FCTL_HALT_FUNC 0x2000 +#define SCSW_FCTL_CLEAR_FUNC 0x1000 + +/* Activity Control */ +#define SCSW_ACTL_RESUME_PEND 0x0800 +#define SCSW_ACTL_START_PEND 0x0400 +#define SCSW_ACTL_HALT_PEND 0x0200 +#define SCSW_ACTL_CLEAR_PEND 0x0100 +#define SCSW_ACTL_CH_ACTIVE 0x0080 +#define SCSW_ACTL_DEV_ACTIVE 0x0040 +#define SCSW_ACTL_SUSPENDED 0x0020 + +/* Status Control */ +#define SCSW_SCTL_ALERT 0x0010 +#define SCSW_SCTL_INTERMED 0x0008 +#define SCSW_SCTL_PRIMARY 0x0004 +#define SCSW_SCTL_SECONDARY 0x0002 +#define SCSW_SCTL_STATUS_PEND 0x0001 + +/* SCSW Device Status Flags */ +#define SCSW_DSTAT_ATTN 0x80 +#define SCSW_DSTAT_STATMOD 0x40 +#define SCSW_DSTAT_CUEND 0x20 +#define SCSW_DSTAT_BUSY 0x10 +#define SCSW_DSTAT_CHEND 0x08 +#define SCSW_DSTAT_DEVEND 0x04 +#define SCSW_DSTAT_UCHK 0x02 +#define SCSW_DSTAT_UEXCP 0x01 + +/* SCSW Subchannel Status Flags */ +#define SCSW_CSTAT_PCINT 0x80 +#define SCSW_CSTAT_BADLEN 0x40 +#define SCSW_CSTAT_PROGCHK 0x20 +#define SCSW_CSTAT_PROTCHK 0x10 +#define SCSW_CSTAT_CHDCHK 0x08 +#define SCSW_CSTAT_CHCCHK 0x04 +#define SCSW_CSTAT_ICCHK 0x02 +#define SCSW_CSTAT_CHAINCHK 0x01 =20 /* * subchannel information block @@ -127,7 +164,23 @@ struct tpi_info { __u32 reserved4:12; } __attribute__ ((packed, aligned(4))); =20 -/* channel command word (type 1) */ +/* channel command word (format 0) */ +typedef struct ccw0 { + __u8 cmd_code; + __u32 cda:24; + __u32 chainData:1; + __u32 chain:1; + __u32 sli:1; + __u32 skip:1; + __u32 pci:1; + __u32 ida:1; + __u32 suspend:1; + __u32 mida:1; + __u8 reserved; + __u16 count; +} __attribute__ ((packed, aligned(8))) Ccw0; + +/* channel command word (format 1) */ typedef struct ccw1 { __u8 cmd_code; __u8 flags; @@ -135,6 +188,10 @@ typedef struct ccw1 { __u32 cda; } __attribute__ ((packed, aligned(8))) Ccw1; =20 +/* do_cio() CCW formats */ +#define CCW_FMT0 0x00 +#define CCW_FMT1 0x01 + #define CCW_FLAG_DC 0x80 #define CCW_FLAG_CC 0x40 #define CCW_FLAG_SLI 0x20 @@ -190,6 +247,11 @@ struct ciw { __u16 count; }; =20 +#define CU_TYPE_UNKNOWN 0x0000 +#define CU_TYPE_DASD_2107 0x2107 +#define CU_TYPE_VIRTIO 0x3832 +#define CU_TYPE_DASD_3990 0x3990 + /* * sense-id response buffer layout */ @@ -205,6 +267,64 @@ typedef struct senseid { struct ciw ciw[62]; } __attribute__ ((packed, aligned(4))) SenseId; =20 +/* + * architected values for first sense byte - common_status. Bits 0-5 of th= is + * field are common to all device types. + */ +#define SNS_STAT0_CMD_REJECT 0x80 +#define SNS_STAT0_INTERVENTION_REQ 0x40 +#define SNS_STAT0_BUS_OUT_CHECK 0x20 +#define SNS_STAT0_EQUIPMENT_CHECK 0x10 +#define SNS_STAT0_DATA_CHECK 0x08 +#define SNS_STAT0_OVERRUN 0x04 +#define SNS_STAT0_INCOMPL_DOMAIN 0x01 + +/* ECKD DASD status[0] byte */ +#define SNS_STAT1_PERM_ERR 0x80 +#define SNS_STAT1_INV_TRACK_FORMAT 0x40 +#define SNS_STAT1_EOC 0x20 +#define SNS_STAT1_MESSAGE_TO_OPER 0x10 +#define SNS_STAT1_NO_REC_FOUND 0x08 +#define SNS_STAT1_FILE_PROTECTED 0x04 +#define SNS_STAT1_WRITE_INHIBITED 0x02 +#define SNS_STAT1_IMPRECISE_END 0x01 + +/* ECKD DASD status[1] byte */ +#define SNS_STAT2_REQ_INH_WRITE 0x80 +#define SNS_STAT2_CORRECTABLE 0x40 +#define SNS_STAT2_FIRST_LOG_ERR 0x20 +#define SNS_STAT2_ENV_DATA_PRESENT 0x10 +#define SNS_STAT2_IMPRECISE_END 0x04 + +/* ECKD DASD 24-byte Sense fmt_msg codes */ +#define SENSE24_FMT_PROG_SYS 0x0 +#define SENSE24_FMT_EQUIPMENT 0x2 +#define SENSE24_FMT_CONTROLLER 0x3 +#define SENSE24_FMT_MISC 0xF + +/* basic sense response buffer layout */ +typedef struct SenseDataEckdDasd { + uint8_t common_status; + uint8_t status[2]; + uint8_t res_count; + uint8_t phys_drive_id; + uint8_t low_cyl_addr; + uint8_t head_high_cyl_addr; + uint8_t fmt_msg; + uint64_t fmt_dependent_info[2]; + uint8_t reserved; + uint8_t program_action_code; + uint16_t config_info; + uint8_t mcode_hicyl; + uint8_t cyl_head_addr[3]; +} __attribute__ ((packed, aligned(4))) SenseDataEckdDasd; + +#define ECKD_SENSE24_GET_FMT(sd) (sd->fmt_msg & 0xF0 >> 4) +#define ECKD_SENSE24_GET_MSG(sd) (sd->fmt_msg & 0x0F) + +#define unit_check(irb) ((irb)->scsw.dstat & SCSW_DSTAT_UCHK) +#define iface_ctrl_check(irb) ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK) + /* interruption response block */ typedef struct irb { struct scsw scsw; @@ -215,6 +335,10 @@ typedef struct irb { =20 int enable_mss_facility(void); void enable_subchannel(SubChannelId schid); +uint16_t cu_type(SubChannelId schid); +int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data, + uint16_t data_size); +int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt= ); =20 /* * Some S390 specific IO instructions as inline diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h index b39ee5d..11bce7d 100644 --- a/pc-bios/s390-ccw/s390-ccw.h +++ b/pc-bios/s390-ccw/s390-ccw.h @@ -52,6 +52,7 @@ typedef unsigned long long __u64; /* start.s */ void disabled_wait(void); void consume_sclp_int(void); +void consume_io_int(void); =20 /* main.c */ void panic(const char *string); diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S index 5c22cb0..aa8fceb 100644 --- a/pc-bios/s390-ccw/start.S +++ b/pc-bios/s390-ccw/start.S @@ -71,6 +71,26 @@ consume_sclp_int: larl %r1, enabled_wait_psw lpswe 0(%r1) =20 +/* + * void consume_io_int(void) + * + * eats one I/O interrupt + */ + .globl consume_io_int +consume_io_int: + /* enable I/O interrupts in cr6 */ + stctg %c6,%c6,0(%r15) + oi 4(%r15), 0xff + lctlg %c6,%c6,0(%r15) + /* prepare i/o call handler */ + larl %r1, io_new_code + stg %r1, 0x1f8 + larl %r1, io_new_mask + mvc 0x1f0(8),0(%r1) + /* load enabled wait PSW */ + larl %r1, enabled_wait_psw + lpswe 0(%r1) + external_new_code: /* disable service interrupts in cr0 */ stctg %c0,%c0,0(%r15) @@ -78,6 +98,13 @@ external_new_code: lctlg %c0,%c0,0(%r15) br %r14 =20 +io_new_code: + /* disable I/O interrupts in cr6 */ + stctg %c6,%c6,0(%r15) + ni 4(%r15), 0x00 + lctlg %c6,%c6,0(%r15) + br %r14 + .align 8 disabled_wait_psw: .quad 0x0002000180000000,0x0000000000000000 @@ -85,3 +112,5 @@ enabled_wait_psw: .quad 0x0302000180000000,0x0000000000000000 external_new_mask: .quad 0x0000000180000000 +io_new_mask: + .quad 0x0000000180000000 --=20 2.7.4