1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright IBM Corp. 2015
4 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 #include <linux/kernel.h>
8 #include <asm/processor.h>
9 #include <asm/lowcore.h>
10 #include <asm/ctlreg.h>
11 #include <asm/ebcdic.h>
13 #include <asm/sections.h>
14 #include <asm/physmem_info.h>
15 #include <asm/facility.h>
19 static struct read_info_sccb
__bootdata(sclp_info_sccb
);
20 static int __bootdata(sclp_info_sccb_valid
);
21 char *__bootdata_preserved(sclp_early_sccb
);
22 int sclp_init_state
= sclp_init_state_uninitialized
;
24 * Used to keep track of the size of the event masks. Qemu until version 2.11
25 * only supports 4 and needs a workaround.
27 bool sclp_mask_compat_mode
;
29 void sclp_early_wait_irq(void)
31 unsigned long psw_mask
, addr
;
32 psw_t psw_ext_save
, psw_wait
;
33 union ctlreg0 cr0
, cr0_new
;
35 local_ctl_store(0, &cr0
.reg
);
36 cr0_new
.val
= cr0
.val
& ~CR0_IRQ_SUBCLASS_MASK
;
39 local_ctl_load(0, &cr0_new
.reg
);
41 psw_ext_save
= get_lowcore()->external_new_psw
;
42 psw_mask
= __extract_psw();
43 get_lowcore()->external_new_psw
.mask
= psw_mask
;
44 psw_wait
.mask
= psw_mask
| PSW_MASK_EXT
| PSW_MASK_WAIT
;
45 get_lowcore()->ext_int_code
= 0;
50 " stg %[addr],%[psw_wait_addr]\n"
51 " stg %[addr],%[psw_ext_addr]\n"
52 " lpswe %[psw_wait]\n"
54 : [addr
] "=&d" (addr
),
55 [psw_wait_addr
] "=Q" (psw_wait
.addr
),
56 [psw_ext_addr
] "=Q" (get_lowcore()->external_new_psw
.addr
)
57 : [psw_wait
] "Q" (psw_wait
)
59 } while (get_lowcore()->ext_int_code
!= EXT_IRQ_SERVICE_SIG
);
61 get_lowcore()->external_new_psw
= psw_ext_save
;
62 local_ctl_load(0, &cr0
.reg
);
65 int sclp_early_cmd(sclp_cmdw_t cmd
, void *sccb
)
70 flags
= arch_local_irq_save();
71 rc
= sclp_service_call(cmd
, sccb
);
74 sclp_early_wait_irq();
76 arch_local_irq_restore(flags
);
81 struct sccb_header header
;
85 /* Output multi-line text using SCLP Message interface. */
86 static void sclp_early_print_lm(const char *str
, unsigned int len
)
88 unsigned char *ptr
, *end
, ch
;
89 unsigned int count
, offset
;
90 struct write_sccb
*sccb
;
96 sccb
= (struct write_sccb
*) sclp_early_sccb
;
97 end
= (unsigned char *) sccb
+ EARLY_SCCB_SIZE
- 1;
98 memset(sccb
, 0, sizeof(*sccb
));
99 ptr
= (unsigned char *) &sccb
->msg
.mdb
.mto
;
102 for (count
= sizeof(*mto
); offset
< len
; count
++) {
104 if ((ch
== 0x0a) || (ptr
+ count
> end
))
106 ptr
[count
] = _ascebc
[ch
];
108 mto
= (struct mto
*) ptr
;
109 memset(mto
, 0, sizeof(*mto
));
112 mto
->line_type_flags
= LNTPFLGS_ENDTEXT
;
114 } while ((offset
< len
) && (ptr
+ sizeof(*mto
) <= end
));
115 len
= ptr
- (unsigned char *) sccb
;
116 sccb
->header
.length
= len
- offsetof(struct write_sccb
, header
);
118 msg
->header
.type
= EVTYP_MSG
;
119 msg
->header
.length
= len
- offsetof(struct write_sccb
, msg
.header
);
121 mdb
->header
.type
= 1;
122 mdb
->header
.tag
= 0xD4C4C240;
123 mdb
->header
.revision_code
= 1;
124 mdb
->header
.length
= len
- offsetof(struct write_sccb
, msg
.mdb
.header
);
126 go
->length
= sizeof(*go
);
128 sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA
, sccb
);
132 struct sccb_header header
;
134 struct evbuf_header header
;
139 /* Output multi-line text using SCLP VT220 interface. */
140 static void sclp_early_print_vt220(const char *str
, unsigned int len
)
142 struct vt220_sccb
*sccb
;
144 sccb
= (struct vt220_sccb
*) sclp_early_sccb
;
145 if (sizeof(*sccb
) + len
>= EARLY_SCCB_SIZE
)
146 len
= EARLY_SCCB_SIZE
- sizeof(*sccb
);
147 memset(sccb
, 0, sizeof(*sccb
));
148 memcpy(&sccb
->msg
.data
, str
, len
);
149 sccb
->header
.length
= sizeof(*sccb
) + len
;
150 sccb
->msg
.header
.length
= sizeof(sccb
->msg
) + len
;
151 sccb
->msg
.header
.type
= EVTYP_VT220MSG
;
152 sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA
, sccb
);
155 int sclp_early_set_event_mask(struct init_sccb
*sccb
,
156 sccb_mask_t receive_mask
,
157 sccb_mask_t send_mask
)
160 memset(sccb
, 0, sizeof(*sccb
));
161 sccb
->header
.length
= sizeof(*sccb
);
162 if (sclp_mask_compat_mode
)
163 sccb
->mask_length
= SCLP_MASK_SIZE_COMPAT
;
165 sccb
->mask_length
= sizeof(sccb_mask_t
);
166 sccb_set_recv_mask(sccb
, receive_mask
);
167 sccb_set_send_mask(sccb
, send_mask
);
168 if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_MASK
, sccb
))
170 if ((sccb
->header
.response_code
== 0x74f0) && !sclp_mask_compat_mode
) {
171 sclp_mask_compat_mode
= true;
174 if (sccb
->header
.response_code
!= 0x20)
179 unsigned int sclp_early_con_check_linemode(struct init_sccb
*sccb
)
181 if (!(sccb_get_sclp_send_mask(sccb
) & EVTYP_OPCMD_MASK
))
183 if (!(sccb_get_sclp_recv_mask(sccb
) & (EVTYP_MSG_MASK
| EVTYP_PMSGCMD_MASK
)))
188 unsigned int sclp_early_con_check_vt220(struct init_sccb
*sccb
)
190 if (sccb_get_sclp_send_mask(sccb
) & EVTYP_VT220MSG_MASK
)
195 static int sclp_early_setup(int disable
, int *have_linemode
, int *have_vt220
)
197 unsigned long receive_mask
, send_mask
;
198 struct init_sccb
*sccb
;
201 BUILD_BUG_ON(sizeof(struct init_sccb
) > PAGE_SIZE
);
203 *have_linemode
= *have_vt220
= 0;
204 sccb
= (struct init_sccb
*) sclp_early_sccb
;
205 receive_mask
= disable
? 0 : EVTYP_OPCMD_MASK
;
206 send_mask
= disable
? 0 : EVTYP_VT220MSG_MASK
| EVTYP_MSG_MASK
;
207 rc
= sclp_early_set_event_mask(sccb
, receive_mask
, send_mask
);
210 *have_linemode
= sclp_early_con_check_linemode(sccb
);
211 *have_vt220
= !!(sccb_get_send_mask(sccb
) & EVTYP_VT220MSG_MASK
);
215 void sclp_early_set_buffer(void *sccb
)
217 sclp_early_sccb
= sccb
;
221 * Output one or more lines of text on the SCLP console (VT220 and /
224 void __sclp_early_printk(const char *str
, unsigned int len
)
226 int have_linemode
, have_vt220
;
228 if (sclp_init_state
!= sclp_init_state_uninitialized
)
230 if (sclp_early_setup(0, &have_linemode
, &have_vt220
) != 0)
233 sclp_early_print_lm(str
, len
);
235 sclp_early_print_vt220(str
, len
);
236 sclp_early_setup(1, &have_linemode
, &have_vt220
);
239 void sclp_early_printk(const char *str
)
241 __sclp_early_printk(str
, strlen(str
));
245 * Use sclp_emergency_printk() to print a string when the system is in a
246 * state where regular console drivers cannot be assumed to work anymore.
248 * Callers must make sure that no concurrent SCLP requests are outstanding
249 * and all other CPUs are stopped, or at least disabled for external
252 void sclp_emergency_printk(const char *str
)
254 int have_linemode
, have_vt220
;
259 * Don't care about return values; if requests fail, just ignore and
260 * continue to have a rather high chance that anything is printed.
262 sclp_early_setup(0, &have_linemode
, &have_vt220
);
263 sclp_early_print_lm(str
, len
);
264 sclp_early_print_vt220(str
, len
);
265 sclp_early_setup(1, &have_linemode
, &have_vt220
);
269 * We can't pass sclp_info_sccb to sclp_early_cmd() here directly,
270 * because it might not fulfil the requiremets for a SCLP communication buffer:
271 * - lie below 2G in memory
273 * Therefore, we use the buffer sclp_early_sccb (which fulfils all those
274 * requirements) temporarily for communication and copy a received response
275 * back into the buffer sclp_info_sccb upon successful completion.
277 int __init
sclp_early_read_info(void)
280 int length
= test_facility(140) ? EXT_SCCB_READ_SCP
: PAGE_SIZE
;
281 struct read_info_sccb
*sccb
= (struct read_info_sccb
*)sclp_early_sccb
;
282 sclp_cmdw_t commands
[] = {SCLP_CMDW_READ_SCP_INFO_FORCED
,
283 SCLP_CMDW_READ_SCP_INFO
};
285 for (i
= 0; i
< ARRAY_SIZE(commands
); i
++) {
286 memset(sccb
, 0, length
);
287 sccb
->header
.length
= length
;
288 sccb
->header
.function_code
= 0x80;
289 sccb
->header
.control_mask
[2] = 0x80;
290 if (sclp_early_cmd(commands
[i
], sccb
))
292 if (sccb
->header
.response_code
== 0x10) {
293 memcpy(&sclp_info_sccb
, sccb
, length
);
294 sclp_info_sccb_valid
= 1;
297 if (sccb
->header
.response_code
!= 0x1f0)
303 struct read_info_sccb
* __init
sclp_early_get_info(void)
305 if (!sclp_info_sccb_valid
)
308 return &sclp_info_sccb
;
311 int __init
sclp_early_get_memsize(unsigned long *mem
)
314 unsigned long rnsize
;
315 struct read_info_sccb
*sccb
= &sclp_info_sccb
;
317 if (!sclp_info_sccb_valid
)
320 rnmax
= sccb
->rnmax
? sccb
->rnmax
: sccb
->rnmax2
;
321 rnsize
= sccb
->rnsize
? sccb
->rnsize
: sccb
->rnsize2
;
323 *mem
= rnsize
* rnmax
;
327 int __init
sclp_early_get_hsa_size(unsigned long *hsa_size
)
329 if (!sclp_info_sccb_valid
)
333 if (sclp_info_sccb
.hsa_size
)
334 *hsa_size
= (sclp_info_sccb
.hsa_size
- 1) * PAGE_SIZE
;
338 #define SCLP_STORAGE_INFO_FACILITY 0x0000400000000000UL
340 void __weak __init
add_physmem_online_range(u64 start
, u64 end
) {}
341 int __init
sclp_early_read_storage_info(void)
343 struct read_storage_sccb
*sccb
= (struct read_storage_sccb
*)sclp_early_sccb
;
344 int rc
, id
, max_id
= 0;
345 unsigned long rn
, rzm
;
349 if (!sclp_info_sccb_valid
)
352 if (!(sclp_info_sccb
.facilities
& SCLP_STORAGE_INFO_FACILITY
))
355 rzm
= sclp_info_sccb
.rnsize
?: sclp_info_sccb
.rnsize2
;
358 for (id
= 0; id
<= max_id
; id
++) {
359 memset(sclp_early_sccb
, 0, EARLY_SCCB_SIZE
);
360 sccb
->header
.length
= EARLY_SCCB_SIZE
;
361 command
= SCLP_CMDW_READ_STORAGE_INFO
| (id
<< 8);
362 rc
= sclp_early_cmd(command
, sccb
);
366 max_id
= sccb
->max_id
;
367 switch (sccb
->header
.response_code
) {
369 for (sn
= 0; sn
< sccb
->assigned
; sn
++) {
370 if (!sccb
->entries
[sn
])
372 rn
= sccb
->entries
[sn
] >> 16;
373 add_physmem_online_range((rn
- 1) * rzm
, rn
* rzm
);
386 physmem_info
.range_count
= 0;