1/*
2 * SCLP early driver
3 *
4 * Copyright IBM Corp. 2013
5 */
6
7#define KMSG_COMPONENT "sclp_early"
8#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
9
10#include <linux/errno.h>
11#include <asm/ctl_reg.h>
12#include <asm/sclp.h>
13#include <asm/ipl.h>
14#include "sclp_sdias.h"
15#include "sclp.h"
16
17#define SCLP_CMDW_READ_SCP_INFO		0x00020001
18#define SCLP_CMDW_READ_SCP_INFO_FORCED	0x00120001
19
20struct read_info_sccb {
21	struct	sccb_header header;	/* 0-7 */
22	u16	rnmax;			/* 8-9 */
23	u8	rnsize;			/* 10 */
24	u8	_pad_11[16 - 11];	/* 11-15 */
25	u16	ncpurl;			/* 16-17 */
26	u16	cpuoff;			/* 18-19 */
27	u8	_pad_20[24 - 20];	/* 20-23 */
28	u8	loadparm[8];		/* 24-31 */
29	u8	_pad_32[42 - 32];	/* 32-41 */
30	u8	fac42;			/* 42 */
31	u8	fac43;			/* 43 */
32	u8	_pad_44[48 - 44];	/* 44-47 */
33	u64	facilities;		/* 48-55 */
34	u8	_pad_56[66 - 56];	/* 56-65 */
35	u8	fac66;			/* 66 */
36	u8	_pad_67[76 - 67];	/* 67-83 */
37	u32	ibc;			/* 76-79 */
38	u8	_pad80[84 - 80];	/* 80-83 */
39	u8	fac84;			/* 84 */
40	u8	fac85;			/* 85 */
41	u8	_pad_86[91 - 86];	/* 86-90 */
42	u8	flags;			/* 91 */
43	u8	_pad_92[100 - 92];	/* 92-99 */
44	u32	rnsize2;		/* 100-103 */
45	u64	rnmax2;			/* 104-111 */
46	u8	_pad_112[120 - 112];	/* 112-119 */
47	u16	hcpua;			/* 120-121 */
48	u8	_pad_122[4096 - 122];	/* 122-4095 */
49} __packed __aligned(PAGE_SIZE);
50
51static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata;
52static unsigned int sclp_con_has_vt220 __initdata;
53static unsigned int sclp_con_has_linemode __initdata;
54static unsigned long sclp_hsa_size;
55static unsigned int sclp_max_cpu;
56static struct sclp_ipl_info sclp_ipl_info;
57static unsigned char sclp_siif;
58static unsigned char sclp_sigpif;
59static u32 sclp_ibc;
60static unsigned int sclp_mtid;
61static unsigned int sclp_mtid_cp;
62static unsigned int sclp_mtid_max;
63static unsigned int sclp_mtid_prev;
64
65u64 sclp_facilities;
66u8 sclp_fac84;
67unsigned long long sclp_rzm;
68unsigned long long sclp_rnmax;
69
70static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
71{
72	int rc;
73
74	__ctl_set_bit(0, 9);
75	rc = sclp_service_call(cmd, sccb);
76	if (rc)
77		goto out;
78	__load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA |
79			PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT);
80	local_irq_disable();
81out:
82	/* Contents of the sccb might have changed. */
83	barrier();
84	__ctl_clear_bit(0, 9);
85	return rc;
86}
87
88static int __init sclp_read_info_early(struct read_info_sccb *sccb)
89{
90	int rc, i;
91	sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
92				  SCLP_CMDW_READ_SCP_INFO};
93
94	for (i = 0; i < ARRAY_SIZE(commands); i++) {
95		do {
96			memset(sccb, 0, sizeof(*sccb));
97			sccb->header.length = sizeof(*sccb);
98			sccb->header.function_code = 0x80;
99			sccb->header.control_mask[2] = 0x80;
100			rc = sclp_cmd_sync_early(commands[i], sccb);
101		} while (rc == -EBUSY);
102
103		if (rc)
104			break;
105		if (sccb->header.response_code == 0x10)
106			return 0;
107		if (sccb->header.response_code != 0x1f0)
108			break;
109	}
110	return -EIO;
111}
112
113static void __init sclp_facilities_detect(struct read_info_sccb *sccb)
114{
115	struct sclp_cpu_entry *cpue;
116	u16 boot_cpu_address, cpu;
117
118	if (sclp_read_info_early(sccb))
119		return;
120
121	sclp_facilities = sccb->facilities;
122	sclp_fac84 = sccb->fac84;
123	if (sccb->fac85 & 0x02)
124		S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
125	sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
126	sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
127	sclp_rzm <<= 20;
128	sclp_ibc = sccb->ibc;
129
130	if (!sccb->hcpua) {
131		if (MACHINE_IS_VM)
132			sclp_max_cpu = 64;
133		else
134			sclp_max_cpu = sccb->ncpurl;
135	} else {
136		sclp_max_cpu = sccb->hcpua + 1;
137	}
138
139	boot_cpu_address = stap();
140	cpue = (void *)sccb + sccb->cpuoff;
141	for (cpu = 0; cpu < sccb->ncpurl; cpue++, cpu++) {
142		if (boot_cpu_address != cpue->core_id)
143			continue;
144		sclp_siif = cpue->siif;
145		sclp_sigpif = cpue->sigpif;
146		break;
147	}
148
149	/* Save IPL information */
150	sclp_ipl_info.is_valid = 1;
151	if (sccb->flags & 0x2)
152		sclp_ipl_info.has_dump = 1;
153	memcpy(&sclp_ipl_info.loadparm, &sccb->loadparm, LOADPARM_LEN);
154
155	sclp_mtid = (sccb->fac42 & 0x80) ? (sccb->fac42 & 31) : 0;
156	sclp_mtid_cp = (sccb->fac42 & 0x80) ? (sccb->fac43 & 31) : 0;
157	sclp_mtid_max = max(sclp_mtid, sclp_mtid_cp);
158	sclp_mtid_prev = (sccb->fac42 & 0x80) ? (sccb->fac66 & 31) : 0;
159}
160
161bool __init sclp_has_linemode(void)
162{
163	return !!sclp_con_has_linemode;
164}
165
166bool __init sclp_has_vt220(void)
167{
168	return !!sclp_con_has_vt220;
169}
170
171unsigned long long sclp_get_rnmax(void)
172{
173	return sclp_rnmax;
174}
175
176unsigned long long sclp_get_rzm(void)
177{
178	return sclp_rzm;
179}
180
181unsigned int sclp_get_max_cpu(void)
182{
183	return sclp_max_cpu;
184}
185
186int sclp_has_siif(void)
187{
188	return sclp_siif;
189}
190EXPORT_SYMBOL(sclp_has_siif);
191
192int sclp_has_sigpif(void)
193{
194	return sclp_sigpif;
195}
196EXPORT_SYMBOL(sclp_has_sigpif);
197
198unsigned int sclp_get_ibc(void)
199{
200	return sclp_ibc;
201}
202EXPORT_SYMBOL(sclp_get_ibc);
203
204unsigned int sclp_get_mtid(u8 cpu_type)
205{
206	return cpu_type ? sclp_mtid : sclp_mtid_cp;
207}
208
209unsigned int sclp_get_mtid_max(void)
210{
211	return sclp_mtid_max;
212}
213
214unsigned int sclp_get_mtid_prev(void)
215{
216	return sclp_mtid_prev;
217}
218
219/*
220 * This function will be called after sclp_facilities_detect(), which gets
221 * called from early.c code. The sclp_facilities_detect() function retrieves
222 * and saves the IPL information.
223 */
224void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
225{
226	*info = sclp_ipl_info;
227}
228
229static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb)
230{
231	int rc;
232
233	do {
234		rc = sclp_cmd_sync_early(cmd, sccb);
235	} while (rc == -EBUSY);
236
237	if (rc)
238		return -EIO;
239	if (((struct sccb_header *) sccb)->response_code != 0x0020)
240		return -EIO;
241	return 0;
242}
243
244static void __init sccb_init_eq_size(struct sdias_sccb *sccb)
245{
246	memset(sccb, 0, sizeof(*sccb));
247
248	sccb->hdr.length = sizeof(*sccb);
249	sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf);
250	sccb->evbuf.hdr.type = EVTYP_SDIAS;
251	sccb->evbuf.event_qual = SDIAS_EQ_SIZE;
252	sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP;
253	sccb->evbuf.event_id = 4712;
254	sccb->evbuf.dbs = 1;
255}
256
257static int __init sclp_set_event_mask(struct init_sccb *sccb,
258				      unsigned long receive_mask,
259				      unsigned long send_mask)
260{
261	memset(sccb, 0, sizeof(*sccb));
262	sccb->header.length = sizeof(*sccb);
263	sccb->mask_length = sizeof(sccb_mask_t);
264	sccb->receive_mask = receive_mask;
265	sccb->send_mask = send_mask;
266	return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb);
267}
268
269static long __init sclp_hsa_size_init(struct sdias_sccb *sccb)
270{
271	sccb_init_eq_size(sccb);
272	if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb))
273		return -EIO;
274	if (sccb->evbuf.blk_cnt == 0)
275		return 0;
276	return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE;
277}
278
279static long __init sclp_hsa_copy_wait(struct sccb_header *sccb)
280{
281	memset(sccb, 0, PAGE_SIZE);
282	sccb->length = PAGE_SIZE;
283	if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb))
284		return -EIO;
285	if (((struct sdias_sccb *) sccb)->evbuf.blk_cnt == 0)
286		return 0;
287	return (((struct sdias_sccb *) sccb)->evbuf.blk_cnt - 1) * PAGE_SIZE;
288}
289
290unsigned long sclp_get_hsa_size(void)
291{
292	return sclp_hsa_size;
293}
294
295static void __init sclp_hsa_size_detect(void *sccb)
296{
297	long size;
298
299	/* First try synchronous interface (LPAR) */
300	if (sclp_set_event_mask(sccb, 0, 0x40000010))
301		return;
302	size = sclp_hsa_size_init(sccb);
303	if (size < 0)
304		return;
305	if (size != 0)
306		goto out;
307	/* Then try asynchronous interface (z/VM) */
308	if (sclp_set_event_mask(sccb, 0x00000010, 0x40000010))
309		return;
310	size = sclp_hsa_size_init(sccb);
311	if (size < 0)
312		return;
313	size = sclp_hsa_copy_wait(sccb);
314	if (size < 0)
315		return;
316out:
317	sclp_hsa_size = size;
318}
319
320static unsigned int __init sclp_con_check_linemode(struct init_sccb *sccb)
321{
322	if (!(sccb->sclp_send_mask & EVTYP_OPCMD_MASK))
323		return 0;
324	if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
325		return 0;
326	return 1;
327}
328
329static void __init sclp_console_detect(struct init_sccb *sccb)
330{
331	if (sccb->header.response_code != 0x20)
332		return;
333
334	if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK)
335		sclp_con_has_vt220 = 1;
336
337	if (sclp_con_check_linemode(sccb))
338		sclp_con_has_linemode = 1;
339}
340
341void __init sclp_early_detect(void)
342{
343	void *sccb = &sccb_early;
344
345	sclp_facilities_detect(sccb);
346	sclp_hsa_size_detect(sccb);
347
348	/* Turn off SCLP event notifications.  Also save remote masks in the
349	 * sccb.  These are sufficient to detect sclp console capabilities.
350	 */
351	sclp_set_event_mask(sccb, 0, 0);
352	sclp_console_detect(sccb);
353}
354