From: Nico Boehr <nrb@linux.ibm.com>
To: thuth@redhat.com, pbonzini@redhat.com, andrew.jones@linux.dev
Cc: kvm@vger.kernel.org, frankja@linux.ibm.com, imbrenda@linux.ibm.com
Subject: [kvm-unit-tests GIT PULL 05/26] lib: s390x: sclp: Add line mode input handling
Date: Fri, 10 Nov 2023 14:52:14 +0100 [thread overview]
Message-ID: <20231110135348.245156-6-nrb@linux.ibm.com> (raw)
In-Reply-To: <20231110135348.245156-1-nrb@linux.ibm.com>
From: Janosch Frank <frankja@linux.ibm.com>
Time to add line-mode input so we can use input handling under LPAR if
there's no access to a ASCII console.
Line-mode IO is pretty wild and the documentation could be improved a
lot. Hence I've copied the input parsing functions from Linux.
For some reason output is a type 2 event but input is a type 1
event. This also means that the input and output structures are
different from each other.
The input can consist of multiple structures which don't contain text
data before the input text data is reached. Hence we need a bunch of
search functions to retrieve a pointer to the text data.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Link: https://lore.kernel.org/r/20231031095519.73311-4-frankja@linux.ibm.com
Signed-off-by: Nico Boehr <nrb@linux.ibm.com>
---
lib/s390x/sclp.h | 26 +++++-
lib/s390x/sclp-console.c | 181 ++++++++++++++++++++++++++++++++++-----
2 files changed, 186 insertions(+), 21 deletions(-)
diff --git a/lib/s390x/sclp.h b/lib/s390x/sclp.h
index 6a611bc..22f120d 100644
--- a/lib/s390x/sclp.h
+++ b/lib/s390x/sclp.h
@@ -226,6 +226,7 @@ typedef struct SCCB {
} __attribute__((packed)) SCCB;
/* SCLP event types */
+#define SCLP_EVENT_OP_CMD 0x01
#define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a
#define SCLP_EVENT_SIGNAL_QUIESCE 0x1d
@@ -233,6 +234,7 @@ typedef struct SCCB {
#define SCLP_EVENT_MASK_SIGNAL_QUIESCE 0x00000008
#define SCLP_EVENT_MASK_MSG_ASCII 0x00000040
#define SCLP_EVENT_MASK_MSG 0x40000000
+#define SCLP_EVENT_MASK_OPCMD 0x80000000
#define SCLP_UNCONDITIONAL_READ 0x00
#define SCLP_SELECTIVE_READ 0x01
@@ -296,6 +298,23 @@ struct mdb {
struct mto mto;
} __attribute__((packed));
+/* vector keys and ids */
+#define GDS_ID_MDSMU 0x1310
+#define GDS_ID_CPMSU 0x1212
+#define GDS_ID_TEXTCMD 0x1320
+#define GDS_KEY_SELFDEFTEXTMSG 0x31
+#define EBC_MDB 0xd4c4c240
+
+struct gds_vector {
+ uint16_t length;
+ uint16_t gds_id;
+} __attribute__((packed));
+
+struct gds_subvector {
+ uint8_t length;
+ uint8_t key;
+} __attribute__((packed));
+
typedef struct EventBufferHeader {
uint16_t length;
uint8_t type;
@@ -320,12 +339,17 @@ typedef struct ReadEventData {
#define SCLP_EVENT_ASCII_TYPE_DATA_STREAM_FOLLOWS 0
typedef struct ReadEventDataAsciiConsole {
- SCCBHeader h;
EventBufferHeader ebh;
uint8_t type;
char data[];
} __attribute__((packed)) ReadEventDataAsciiConsole;
+struct ReadEventDataLMConsole {
+ SCCBHeader h;
+ EventBufferHeader ebh;
+ struct gds_vector v[];
+};
+
extern char _sccb[];
void sclp_setup_int(void);
void sclp_handle_ext(void);
diff --git a/lib/s390x/sclp-console.c b/lib/s390x/sclp-console.c
index 6c965b6..5de3325 100644
--- a/lib/s390x/sclp-console.c
+++ b/lib/s390x/sclp-console.c
@@ -1,8 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * SCLP ASCII access driver
+ * SCLP line mode and ASCII console driver
+ * Some parts taken from the Linux kernel.
*
* Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * Copyright IBM Corp. 1999
+ * Author(s): Martin Peschke <mpeschke@de.ibm.com>
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <libcflat.h>
@@ -86,6 +91,41 @@ static uint8_t _ascebc[256] = {
0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
};
+static const uint8_t _ebcasc[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+ 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+ 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+ 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+ 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+ 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+ 0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
+ 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+ 0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+ 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+ 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+ 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+ 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+ 0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+ 0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+ 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07,
+};
+
static bool lpar_ascii_compat;
static char lm_buff[120];
@@ -226,7 +266,8 @@ static void sclp_write_event_mask(int receive_mask, int send_mask)
static void sclp_console_enable_read(void)
{
- sclp_write_event_mask(SCLP_EVENT_MASK_MSG_ASCII, SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG);
+ sclp_write_event_mask(SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_OPCMD,
+ SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG);
}
static void sclp_console_disable_read(void)
@@ -264,37 +305,137 @@ void sclp_print(const char *str)
sclp_print_lm(str);
}
-static int console_refill_read_buffer(void)
+static char *console_read_ascii(struct EventBufferHeader *ebh, int *len)
{
+ struct ReadEventDataAsciiConsole *evdata = (void *)ebh;
const int max_event_buffer_len = SCCB_SIZE - offsetof(ReadEventDataAsciiConsole, ebh);
- ReadEventDataAsciiConsole *sccb = (void *)_sccb;
- const int event_buffer_ascii_recv_header_len = sizeof(sccb->ebh) + sizeof(sccb->type);
- int ret = -1;
+ const int event_buffer_ascii_recv_header_len = offsetof(ReadEventDataAsciiConsole, data);
+
+ assert(ebh->length <= max_event_buffer_len);
+ assert(ebh->length > event_buffer_ascii_recv_header_len);
+
+ *len = ebh->length - event_buffer_ascii_recv_header_len;
+ return evdata->data;
+}
+
+
+static struct gds_vector *sclp_find_gds_vector(void *start, void *end, uint16_t id)
+{
+ struct gds_vector *v;
+
+ for (v = start; (void *)v < end; v = (void *)v + v->length)
+ if (v->gds_id == id)
+ return v;
+ return NULL;
+}
+
+static struct gds_subvector *sclp_eval_selfdeftextmsg(struct gds_subvector *sv)
+{
+ void *end;
+
+ end = (void *)sv + sv->length;
+ for (sv = sv + 1; (void *)sv < end; sv = (void *)sv + sv->length)
+ if (sv->key == 0x30)
+ return sv;
+ return NULL;
+}
+
+static struct gds_subvector *sclp_eval_textcmd(struct gds_vector *v)
+{
+ struct gds_subvector *sv;
+ void *end;
+
+ end = (void *)v + v->length;
+ for (sv = (struct gds_subvector *)(v + 1); (void *)sv < end;
+ sv = (void *)sv + sv->length)
+ if (sv->key == GDS_KEY_SELFDEFTEXTMSG)
+ return sclp_eval_selfdeftextmsg(sv);
+ return NULL;
+}
+
+static struct gds_subvector *sclp_eval_cpmsu(struct gds_vector *v)
+{
+ void *end;
+
+ end = (void *)v + v->length;
+ for (v = v + 1; (void *)v < end; v = (void *)v + v->length)
+ if (v->gds_id == GDS_ID_TEXTCMD)
+ return sclp_eval_textcmd(v);
+ return NULL;
+}
+
+static struct gds_subvector *sclp_eval_mdsmu(struct gds_vector *v)
+{
+ v = sclp_find_gds_vector(v + 1, (void *)v + v->length, GDS_ID_CPMSU);
+ if (v)
+ return sclp_eval_cpmsu(v);
+ return NULL;
+}
+
+static char *console_read_lm(struct EventBufferHeader *ebh, int *len)
+{
+ struct gds_vector *v = (void *)ebh + sizeof(*ebh);
+ struct gds_subvector *sv;
+
+ v = sclp_find_gds_vector(v, (void *)ebh + ebh->length,
+ GDS_ID_MDSMU);
+ if (!v)
+ return NULL;
+
+ sv = sclp_eval_mdsmu(v);
+ if (!sv)
+ return NULL;
+
+ *len = sv->length - (sizeof(*sv));
+ return (char *)(sv + 1);
+}
+
+static void ebc_to_asc(char *data, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ data[i] = _ebcasc[(uint8_t)data[i]];
+}
+
+static int console_refill_read_buffer(void)
+{
+ struct SCCBHeader *sccb = (struct SCCBHeader *)_sccb;
+ struct EventBufferHeader *ebh = (void *)_sccb + sizeof(struct SCCBHeader);
+ char *data;
+ int ret = -1, len;
sclp_console_enable_read();
sclp_mark_busy();
- memset(sccb, 0, SCCB_SIZE);
- sccb->h.length = PAGE_SIZE;
- sccb->h.function_code = SCLP_UNCONDITIONAL_READ;
- sccb->h.control_mask[2] = SCLP_CM2_VARIABLE_LENGTH_RESPONSE;
+ memset(_sccb, 0, SCCB_SIZE);
+ sccb->length = PAGE_SIZE;
+ sccb->function_code = SCLP_UNCONDITIONAL_READ;
+ sccb->control_mask[2] = SCLP_CM2_VARIABLE_LENGTH_RESPONSE;
sclp_service_call(SCLP_CMD_READ_EVENT_DATA, sccb);
- if (sccb->h.response_code == SCLP_RC_NO_EVENT_BUFFERS_STORED ||
- sccb->ebh.type != SCLP_EVENT_ASCII_CONSOLE_DATA ||
- sccb->type != SCLP_EVENT_ASCII_TYPE_DATA_STREAM_FOLLOWS) {
- ret = -1;
+ if (sccb->response_code == SCLP_RC_NO_EVENT_BUFFERS_STORED)
goto out;
- }
- assert(sccb->ebh.length <= max_event_buffer_len);
- assert(sccb->ebh.length > event_buffer_ascii_recv_header_len);
+ switch (ebh->type) {
+ case SCLP_EVENT_OP_CMD:
+ data = console_read_lm(ebh, &len);
+ if (data)
+ ebc_to_asc(data, len);
+ break;
+ case SCLP_EVENT_ASCII_CONSOLE_DATA:
+ data = console_read_ascii(ebh, &len);
+ break;
+ default:
+ goto out;
+ }
- read_buf_length = sccb->ebh.length - event_buffer_ascii_recv_header_len;
+ if (!data)
+ goto out;
- assert(read_buf_length <= sizeof(read_buf));
- memcpy(read_buf, sccb->data, read_buf_length);
+ assert(len <= sizeof(read_buf));
+ memcpy(read_buf, data, len);
read_index = 0;
ret = 0;
--
2.41.0
next prev parent reply other threads:[~2023-11-10 13:54 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-10 13:52 [kvm-unit-tests GIT PULL 00/26] s390x: multiline unittests.cfg, sclp enhancements, topology fixes and improvements, sie without MSO/MSL, 2G guest alignment, bug fixes Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 01/26] s390x: spec_ex: load full register Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 02/26] s390x: run PV guests with confidential guest enabled Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 03/26] lib: s390x: hw: rework do_detect_host so we don't need allocation Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 04/26] lib: s390x: sclp: Add compat handling for HMC ASCII consoles Nico Boehr
2023-11-10 13:52 ` Nico Boehr [this message]
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 06/26] s390x: spec_ex-sie: refactor to use snippet API Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 07/26] s390x: sie: ensure guests are aligned to 2GB Nico Boehr
2023-11-22 11:06 ` Thomas Huth
2023-11-23 9:24 ` Nina Schoetterl-Glausch
2023-11-23 13:03 ` Thomas Huth
2023-11-23 14:16 ` Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 08/26] s390x: mvpg-sie: fix virtual-physical address confusion Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 09/26] s390x: topology: Introduce enums for polarization & cpu type Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 10/26] s390x: topology: Fix report message Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 11/26] s390x: topology: Use function parameter in stsi_get_sysib Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 12/26] s390x: topology: Fix parsing loop Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 13/26] s390x: topology: Make some report messages unique Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 14/26] s390x: topology: Refine stsi header test Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 15/26] s390x: topology: Rename topology_core to topology_cpu Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 16/26] s390x: topology: Rewrite topology list test Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 17/26] scripts: Implement multiline strings for extra_params Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 18/26] s390x: topology: Add complex topology test Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 19/26] lib: s390x: introduce bitfield for PSW mask Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 20/26] s390x: add function to set DAT mode for all interrupts Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 21/26] s390x: sie: switch to home space mode before entering SIE Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 22/26] s390x: lib: don't forward PSW when handling exception in SIE Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 23/26] s390x: lib: sie: don't reenter SIE on pgm int Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 24/26] s390x: add test source dir to include paths Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 25/26] s390x: add a test for SIE without MSO/MSL Nico Boehr
2023-11-10 13:52 ` [kvm-unit-tests GIT PULL 26/26] lib: s390x: interrupt: remove TEID_ASCE defines Nico Boehr
2023-11-10 15:25 ` [kvm-unit-tests GIT PULL 00/26] s390x: multiline unittests.cfg, sclp enhancements, topology fixes and improvements, sie without MSO/MSL, 2G guest alignment, bug fixes Thomas Huth
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231110135348.245156-6-nrb@linux.ibm.com \
--to=nrb@linux.ibm.com \
--cc=andrew.jones@linux.dev \
--cc=frankja@linux.ibm.com \
--cc=imbrenda@linux.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox