aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Silbe <silbe@linux.vnet.ibm.com>2015-11-24 10:28:55 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-11-27 03:24:17 -0500
commit3f975df69dba78834471b7133dcb8c8ddf7f986a (patch)
tree572cdf72e9c514bfd5c6f89e69fee55b0be929d5
parent561e103002696a17907ac5bbccec551e32de3b7f (diff)
s390/sclp: Add VT220 support to early sclp console
When running under qemu with the default configuration (-nographic), there is only a VT220 SCLP console, no line-mode SCLP console. Add VT220 support to the early SCLP console so the user has a chance to see critical error messages during early boot. None of the existing users of _sclp_print_early() check the return code. Instead of trying to come up with return code semantics when printing to multiple consoles (any or all of which may fail), we just drop the return code entirely. Tested on z/VM (line mode console) and LPAR (VT220 and line mode console). Tested on qemu/KVM with VT220 console and / or line mode console. Signed-off-by: Sascha Silbe <silbe@linux.vnet.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/sclp.h2
-rw-r--r--arch/s390/kernel/sclp.c65
2 files changed, 51 insertions, 16 deletions
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index 2ca9c7bc50db..cb691602f295 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -80,6 +80,6 @@ int sclp_pci_deconfigure(u32 fid);
80int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count); 80int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count);
81int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count); 81int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count);
82void sclp_early_detect(void); 82void sclp_early_detect(void);
83int _sclp_print_early(const char *); 83void _sclp_print_early(const char *);
84 84
85#endif /* _ASM_S390_SCLP_H */ 85#endif /* _ASM_S390_SCLP_H */
diff --git a/arch/s390/kernel/sclp.c b/arch/s390/kernel/sclp.c
index 9fe7781a45cd..d88db40bdf15 100644
--- a/arch/s390/kernel/sclp.c
+++ b/arch/s390/kernel/sclp.c
@@ -9,7 +9,11 @@
9#include <asm/processor.h> 9#include <asm/processor.h>
10#include <asm/sclp.h> 10#include <asm/sclp.h>
11 11
12#define EVTYP_VT220MSG_MASK 0x00000040
13#define EVTYP_MSG_MASK 0x40000000
14
12static char _sclp_work_area[4096] __aligned(PAGE_SIZE); 15static char _sclp_work_area[4096] __aligned(PAGE_SIZE);
16static bool have_vt220, have_linemode;
13 17
14static void _sclp_wait_int(void) 18static void _sclp_wait_int(void)
15{ 19{
@@ -68,7 +72,7 @@ static int _sclp_setup(int disable)
68 0x00, 0x1c, 72 0x00, 0x1c,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x04, 74 0x00, 0x04,
71 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 75 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
73 }; 77 };
74 unsigned int *masks; 78 unsigned int *masks;
@@ -82,13 +86,13 @@ static int _sclp_setup(int disable)
82 rc = _sclp_servc(0x00780005, _sclp_work_area); 86 rc = _sclp_servc(0x00780005, _sclp_work_area);
83 if (rc) 87 if (rc)
84 return rc; 88 return rc;
85 if ((masks[0] & masks[3]) != masks[0] || 89 have_vt220 = masks[2] & EVTYP_VT220MSG_MASK;
86 (masks[1] & masks[2]) != masks[1]) 90 have_linemode = masks[2] & EVTYP_MSG_MASK;
87 return -EIO;
88 return 0; 91 return 0;
89} 92}
90 93
91static int _sclp_print(const char *str) 94/* Output multi-line text using SCLP Message interface. */
95static void _sclp_print_lm(const char *str)
92{ 96{
93 static unsigned char write_head[] = { 97 static unsigned char write_head[] = {
94 /* sccb header */ 98 /* sccb header */
@@ -143,18 +147,49 @@ static int _sclp_print(const char *str)
143 } while (ch != 0); 147 } while (ch != 0);
144 148
145 /* SCLP write data */ 149 /* SCLP write data */
146 return _sclp_servc(0x00760005, _sclp_work_area); 150 _sclp_servc(0x00760005, _sclp_work_area);
147} 151}
148 152
149int _sclp_print_early(const char *str) 153/* Output multi-line text (plus a newline) using SCLP VT220
154 * interface.
155 */
156static void _sclp_print_vt220(const char *str)
150{ 157{
151 int rc; 158 static unsigned char const write_head[] = {
159 /* sccb header */
160 0x00, 0x0e,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 /* evbuf header */
163 0x00, 0x06,
164 0x1a, 0x00, 0x00, 0x00,
165 };
166 size_t len = strlen(str);
152 167
153 rc = _sclp_setup(0); 168 if (sizeof(write_head) + len >= sizeof(_sclp_work_area))
154 if (rc) 169 len = sizeof(_sclp_work_area) - sizeof(write_head) - 1;
155 return rc; 170
156 rc = _sclp_print(str); 171 memcpy(_sclp_work_area, write_head, sizeof(write_head));
157 if (rc) 172 memcpy(_sclp_work_area + sizeof(write_head), str, len);
158 return rc; 173 _sclp_work_area[sizeof(write_head) + len] = '\n';
159 return _sclp_setup(1); 174
175 /* Update length fields in evbuf and sccb headers */
176 *(unsigned short *)(_sclp_work_area + 8) += len + 1;
177 *(unsigned short *)(_sclp_work_area + 0) += len + 1;
178
179 /* SCLP write data */
180 (void)_sclp_servc(0x00760005, _sclp_work_area);
181}
182
183/* Output one or more lines of text on the SCLP console (VT220 and /
184 * or line-mode). All lines get terminated; no need for a trailing LF.
185 */
186void _sclp_print_early(const char *str)
187{
188 if (_sclp_setup(0) != 0)
189 return;
190 if (have_linemode)
191 _sclp_print_lm(str);
192 if (have_vt220)
193 _sclp_print_vt220(str);
194 _sclp_setup(1);
160} 195}