From: Janosch Frank <frankja@linux.ibm.com>
To: kvm@vger.kernel.org
Cc: linux-s390@vger.kernel.org, david@redhat.com, thuth@redhat.com
Subject: [kvm-unit-tests PATCH 2/6] s390x: Add linemode console
Date: Thu, 29 Aug 2019 14:14:55 +0200 [thread overview]
Message-ID: <20190829121459.1708-3-frankja@linux.ibm.com> (raw)
In-Reply-To: <20190829121459.1708-1-frankja@linux.ibm.com>
z/VM isn't fond of vt220, so we need line mode when running under
z/VM.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Acked-by: David Hildenbrand <david@redhat.com>
---
lib/s390x/sclp-console.c | 181 +++++++++++++++++++++++++++++++++++----
lib/s390x/sclp.h | 55 +++++++++++-
2 files changed, 218 insertions(+), 18 deletions(-)
diff --git a/lib/s390x/sclp-console.c b/lib/s390x/sclp-console.c
index a5ef45f..19416b5 100644
--- a/lib/s390x/sclp-console.c
+++ b/lib/s390x/sclp-console.c
@@ -11,21 +11,165 @@
#include <libcflat.h>
#include <string.h>
#include <asm/page.h>
+#include <asm/arch_def.h>
+#include <asm/io.h>
#include "sclp.h"
+/*
+ * ASCII (IBM PC 437) -> EBCDIC 037
+ */
+static uint8_t _ascebc[256] = {
+ /*00 NUL SOH STX ETX EOT ENQ ACK BEL */
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ /*08 BS HT LF VT FF CR SO SI */
+ /* ->NL */
+ 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /*10 DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
+ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+ /*18 CAN EM SUB ESC FS GS RS US */
+ /* ->IGS ->IRS ->IUS */
+ 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+ /*20 SP ! " # $ % & ' */
+ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ /*28 ( ) * + , - . / */
+ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ /*30 0 1 2 3 4 5 6 7 */
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ /*38 8 9 : ; < = > ? */
+ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ /*40 @ A B C D E F G */
+ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ /*48 H I J K L M N O */
+ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ /*50 P Q R S T U V W */
+ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ /*58 X Y Z [ \ ] ^ _ */
+ 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
+ /*60 ` a b c d e f g */
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ /*68 h i j k l m n o */
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ /*70 p q r s t u v w */
+ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ /*78 x y z { | } ~ DL */
+ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+ /*80*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*88*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*90*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*98*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A0*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A8*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B0*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B8*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C0*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C8*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D0*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D8*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E0 sz */
+ 0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E8*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F0*/
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F8*/
+ 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+static void sclp_print_ascii(const char *str)
+{
+ int len = strlen(str);
+ WriteEventData *sccb = (void *)_sccb;
+
+ sclp_mark_busy();
+ memset(sccb, 0, sizeof(*sccb));
+ sccb->h.length = offsetof(WriteEventData, msg) + len;
+ sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
+ sccb->ebh.length = sizeof(EventBufferHeader) + len;
+ sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
+ memcpy(&sccb->msg, str, len);
+
+ sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
+}
+
+static void sclp_print_lm(const char *str)
+{
+ unsigned char *ptr, *end, ch;
+ unsigned int count, offset, len;
+ struct WriteEventData *sccb;
+ struct mdb *mdb;
+ struct mto *mto;
+ struct go *go;
+
+ sclp_mark_busy();
+ sccb = (struct WriteEventData *) _sccb;
+ end = (unsigned char *) sccb + 4096 - 1;
+ memset(sccb, 0, sizeof(*sccb));
+ ptr = (unsigned char *) &sccb->msg.mdb.mto;
+ len = strlen(str);
+ offset = 0;
+ do {
+ for (count = sizeof(*mto); offset < len; count++) {
+ ch = str[offset++];
+ if (ch == 0x0a || ptr + count > end)
+ break;
+ ptr[count] = _ascebc[ch];
+ }
+ mto = (struct mto *) ptr;
+ mto->length = count;
+ mto->type = 4;
+ mto->line_type_flags = LNTPFLGS_ENDTEXT;
+ ptr += count;
+ } while (offset < len && ptr + sizeof(*mto) <= end);
+ len = ptr - (unsigned char *) sccb;
+ sccb->h.length = len - offsetof(struct WriteEventData, h);
+ sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
+ sccb->ebh.type = EVTYP_MSG;
+ sccb->ebh.length = len - offsetof(struct WriteEventData, ebh);
+ mdb = &sccb->msg.mdb;
+ mdb->header.type = 1;
+ mdb->header.tag = 0xD4C4C240;
+ mdb->header.revision_code = 1;
+ mdb->header.length = len - offsetof(struct WriteEventData, msg.mdb.header);
+ go = &mdb->go;
+ go->length = sizeof(*go);
+ go->type = 1;
+ sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
+}
+
+/*
+ * SCLP needs to be initialized by setting a send and receive mask,
+ * indicating which messages the control program (we) want(s) to
+ * send/receive.
+ */
static void sclp_set_write_mask(void)
{
WriteEventMask *sccb = (void *)_sccb;
sclp_mark_busy();
+ memset(_sccb, 0, sizeof(*sccb));
sccb->h.length = sizeof(WriteEventMask);
- sccb->mask_length = sizeof(unsigned int);
- sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
- sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
- sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
- sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+ sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
+ sccb->mask_length = sizeof(sccb_mask_t);
+
+ /* For now we don't process sclp input. */
+ sccb->cp_receive_mask = 0;
+ /* We send ASCII and line mode. */
+ sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG;
sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
+ assert(sccb->h.response_code == SCLP_RC_NORMAL_COMPLETION);
}
void sclp_console_setup(void)
@@ -35,16 +179,19 @@ void sclp_console_setup(void)
void sclp_print(const char *str)
{
- int len = strlen(str);
- WriteEventData *sccb = (void *)_sccb;
-
- sclp_mark_busy();
- sccb->h.length = sizeof(WriteEventData) + len;
- sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
- sccb->ebh.length = sizeof(EventBufferHeader) + len;
- sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
- sccb->ebh.flags = 0;
- memcpy(sccb->data, str, len);
-
- sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
+ /*
+ * z/VM advertises a vt220 console which is not functional:
+ * (response code 05F0, "not active because of the state of
+ * the machine"). Hence testing the masks would only work if
+ * we also use stsi data to distinguish z/VM.
+ *
+ * Let's rather print on all available consoles.
+ */
+ if (strlen(str) > (PAGE_SIZE / 2)) {
+ sclp_print_ascii("Warning: Printing is limited to 2KB of data.");
+ sclp_print_lm("Warning: Printing is limited to 2KB of data.");
+ return;
+ }
+ sclp_print_ascii(str);
+ sclp_print_lm(str);
}
diff --git a/lib/s390x/sclp.h b/lib/s390x/sclp.h
index 63cf609..98c482a 100644
--- a/lib/s390x/sclp.h
+++ b/lib/s390x/sclp.h
@@ -179,6 +179,7 @@ typedef struct SCCB {
/* SCLP event masks */
#define SCLP_EVENT_MASK_SIGNAL_QUIESCE 0x00000008
#define SCLP_EVENT_MASK_MSG_ASCII 0x00000040
+#define SCLP_EVENT_MASK_MSG 0x40000000
#define SCLP_UNCONDITIONAL_READ 0x00
#define SCLP_SELECTIVE_READ 0x01
@@ -193,6 +194,55 @@ typedef struct WriteEventMask {
uint32_t receive_mask;
} __attribute__((packed)) WriteEventMask;
+#define MDBTYP_GO 0x0001
+#define MDBTYP_MTO 0x0004
+#define EVTYP_MSG 0x02
+#define LNTPFLGS_CNTLTEXT 0x8000
+#define LNTPFLGS_LABELTEXT 0x4000
+#define LNTPFLGS_DATATEXT 0x2000
+#define LNTPFLGS_ENDTEXT 0x1000
+#define LNTPFLGS_PROMPTTEXT 0x0800
+
+typedef uint32_t sccb_mask_t;
+
+/* SCLP line mode console related structures. */
+
+struct mto {
+ u16 length;
+ u16 type;
+ u16 line_type_flags;
+ u8 alarm_control;
+ u8 _reserved[3];
+} __attribute__((packed));
+
+struct go {
+ u16 length;
+ u16 type;
+ u32 domid;
+ u8 hhmmss_time[8];
+ u8 th_time[3];
+ u8 reserved_0;
+ u8 dddyyyy_date[7];
+ u8 _reserved_1;
+ u16 general_msg_flags;
+ u8 _reserved_2[10];
+ u8 originating_system_name[8];
+ u8 job_guest_name[8];
+} __attribute__((packed));
+
+struct mdb_header {
+ u16 length;
+ u16 type;
+ u32 tag;
+ u32 revision_code;
+} __attribute__((packed));
+
+struct mdb {
+ struct mdb_header header;
+ struct go go;
+ struct mto mto;
+} __attribute__((packed));
+
typedef struct EventBufferHeader {
uint16_t length;
uint8_t type;
@@ -203,7 +253,10 @@ typedef struct EventBufferHeader {
typedef struct WriteEventData {
SCCBHeader h;
EventBufferHeader ebh;
- char data[0];
+ union {
+ char data[0];
+ struct mdb mdb;
+ } msg;
} __attribute__((packed)) WriteEventData;
typedef struct ReadEventData {
--
2.17.0
next prev parent reply other threads:[~2019-08-29 12:15 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-29 12:14 [kvm-unit-tests PATCH 0/6] s390x: Add multiboot and smp Janosch Frank
2019-08-29 12:14 ` [kvm-unit-tests PATCH 1/6] s390x: Use interrupts in SCLP and add locking Janosch Frank
2019-08-30 12:21 ` David Hildenbrand
2019-09-02 11:42 ` Thomas Huth
2019-09-03 7:53 ` Janosch Frank
2019-09-03 8:52 ` David Hildenbrand
2019-08-29 12:14 ` Janosch Frank [this message]
2019-09-02 11:59 ` [kvm-unit-tests PATCH 2/6] s390x: Add linemode console Thomas Huth
2019-08-29 12:14 ` [kvm-unit-tests PATCH 3/6] s390x: Add linemode buffer to fix newline on every print Janosch Frank
2019-08-29 12:14 ` [kvm-unit-tests PATCH 4/6] s390x: Add initial smp code Janosch Frank
2019-09-02 13:21 ` Thomas Huth
2019-09-03 8:10 ` Janosch Frank
2019-08-29 12:14 ` [kvm-unit-tests PATCH 5/6] s390x: Prepare for external calls Janosch Frank
2019-09-02 13:58 ` Thomas Huth
2019-09-02 14:17 ` Janosch Frank
2019-08-29 12:14 ` [kvm-unit-tests PATCH 6/6] s390x: SMP test Janosch Frank
2019-09-02 15:40 ` Thomas Huth
2019-09-03 8:44 ` Janosch Frank
2019-09-03 8:56 ` 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=20190829121459.1708-3-frankja@linux.ibm.com \
--to=frankja@linux.ibm.com \
--cc=david@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.