| .. | .. |
|---|
| 9 | 9 | #include <asm/lowcore.h> |
|---|
| 10 | 10 | #include <asm/ebcdic.h> |
|---|
| 11 | 11 | #include <asm/irq.h> |
|---|
| 12 | +#include <asm/sections.h> |
|---|
| 13 | +#include <asm/mem_detect.h> |
|---|
| 12 | 14 | #include "sclp.h" |
|---|
| 13 | 15 | #include "sclp_rw.h" |
|---|
| 14 | 16 | |
|---|
| 15 | | -char sclp_early_sccb[PAGE_SIZE] __aligned(PAGE_SIZE) __section(.data); |
|---|
| 16 | | -int sclp_init_state __section(.data) = sclp_init_state_uninitialized; |
|---|
| 17 | +static struct read_info_sccb __bootdata(sclp_info_sccb); |
|---|
| 18 | +static int __bootdata(sclp_info_sccb_valid); |
|---|
| 19 | +char *sclp_early_sccb = (char *) EARLY_SCCB_OFFSET; |
|---|
| 20 | +int sclp_init_state = sclp_init_state_uninitialized; |
|---|
| 17 | 21 | /* |
|---|
| 18 | 22 | * Used to keep track of the size of the event masks. Qemu until version 2.11 |
|---|
| 19 | 23 | * only supports 4 and needs a workaround. |
|---|
| 20 | 24 | */ |
|---|
| 21 | | -bool sclp_mask_compat_mode __section(.data); |
|---|
| 25 | +bool sclp_mask_compat_mode; |
|---|
| 22 | 26 | |
|---|
| 23 | 27 | void sclp_early_wait_irq(void) |
|---|
| 24 | 28 | { |
|---|
| .. | .. |
|---|
| 87 | 91 | struct mto *mto; |
|---|
| 88 | 92 | struct go *go; |
|---|
| 89 | 93 | |
|---|
| 90 | | - sccb = (struct write_sccb *) &sclp_early_sccb; |
|---|
| 91 | | - end = (unsigned char *) sccb + sizeof(sclp_early_sccb) - 1; |
|---|
| 94 | + sccb = (struct write_sccb *) sclp_early_sccb; |
|---|
| 95 | + end = (unsigned char *) sccb + EARLY_SCCB_SIZE - 1; |
|---|
| 92 | 96 | memset(sccb, 0, sizeof(*sccb)); |
|---|
| 93 | 97 | ptr = (unsigned char *) &sccb->msg.mdb.mto; |
|---|
| 94 | 98 | offset = 0; |
|---|
| .. | .. |
|---|
| 135 | 139 | { |
|---|
| 136 | 140 | struct vt220_sccb *sccb; |
|---|
| 137 | 141 | |
|---|
| 138 | | - sccb = (struct vt220_sccb *) &sclp_early_sccb; |
|---|
| 139 | | - if (sizeof(*sccb) + len >= sizeof(sclp_early_sccb)) |
|---|
| 140 | | - len = sizeof(sclp_early_sccb) - sizeof(*sccb); |
|---|
| 142 | + sccb = (struct vt220_sccb *) sclp_early_sccb; |
|---|
| 143 | + if (sizeof(*sccb) + len >= EARLY_SCCB_SIZE) |
|---|
| 144 | + len = EARLY_SCCB_SIZE - sizeof(*sccb); |
|---|
| 141 | 145 | memset(sccb, 0, sizeof(*sccb)); |
|---|
| 142 | 146 | memcpy(&sccb->msg.data, str, len); |
|---|
| 143 | 147 | sccb->header.length = sizeof(*sccb) + len; |
|---|
| .. | .. |
|---|
| 195 | 199 | BUILD_BUG_ON(sizeof(struct init_sccb) > PAGE_SIZE); |
|---|
| 196 | 200 | |
|---|
| 197 | 201 | *have_linemode = *have_vt220 = 0; |
|---|
| 198 | | - sccb = (struct init_sccb *) &sclp_early_sccb; |
|---|
| 202 | + sccb = (struct init_sccb *) sclp_early_sccb; |
|---|
| 199 | 203 | receive_mask = disable ? 0 : EVTYP_OPCMD_MASK; |
|---|
| 200 | 204 | send_mask = disable ? 0 : EVTYP_VT220MSG_MASK | EVTYP_MSG_MASK; |
|---|
| 201 | 205 | rc = sclp_early_set_event_mask(sccb, receive_mask, send_mask); |
|---|
| .. | .. |
|---|
| 210 | 214 | * Output one or more lines of text on the SCLP console (VT220 and / |
|---|
| 211 | 215 | * or line-mode). |
|---|
| 212 | 216 | */ |
|---|
| 213 | | -void __sclp_early_printk(const char *str, unsigned int len, unsigned int force) |
|---|
| 217 | +void __sclp_early_printk(const char *str, unsigned int len) |
|---|
| 214 | 218 | { |
|---|
| 215 | 219 | int have_linemode, have_vt220; |
|---|
| 216 | 220 | |
|---|
| 217 | | - if (!force && sclp_init_state != sclp_init_state_uninitialized) |
|---|
| 221 | + if (sclp_init_state != sclp_init_state_uninitialized) |
|---|
| 218 | 222 | return; |
|---|
| 219 | 223 | if (sclp_early_setup(0, &have_linemode, &have_vt220) != 0) |
|---|
| 220 | 224 | return; |
|---|
| .. | .. |
|---|
| 227 | 231 | |
|---|
| 228 | 232 | void sclp_early_printk(const char *str) |
|---|
| 229 | 233 | { |
|---|
| 230 | | - __sclp_early_printk(str, strlen(str), 0); |
|---|
| 234 | + __sclp_early_printk(str, strlen(str)); |
|---|
| 231 | 235 | } |
|---|
| 232 | 236 | |
|---|
| 233 | | -void sclp_early_printk_force(const char *str) |
|---|
| 237 | +int __init sclp_early_read_info(void) |
|---|
| 234 | 238 | { |
|---|
| 235 | | - __sclp_early_printk(str, strlen(str), 1); |
|---|
| 239 | + int i; |
|---|
| 240 | + struct read_info_sccb *sccb = &sclp_info_sccb; |
|---|
| 241 | + sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, |
|---|
| 242 | + SCLP_CMDW_READ_SCP_INFO}; |
|---|
| 243 | + |
|---|
| 244 | + for (i = 0; i < ARRAY_SIZE(commands); i++) { |
|---|
| 245 | + memset(sccb, 0, sizeof(*sccb)); |
|---|
| 246 | + sccb->header.length = sizeof(*sccb); |
|---|
| 247 | + sccb->header.function_code = 0x80; |
|---|
| 248 | + sccb->header.control_mask[2] = 0x80; |
|---|
| 249 | + if (sclp_early_cmd(commands[i], sccb)) |
|---|
| 250 | + break; |
|---|
| 251 | + if (sccb->header.response_code == 0x10) { |
|---|
| 252 | + sclp_info_sccb_valid = 1; |
|---|
| 253 | + return 0; |
|---|
| 254 | + } |
|---|
| 255 | + if (sccb->header.response_code != 0x1f0) |
|---|
| 256 | + break; |
|---|
| 257 | + } |
|---|
| 258 | + return -EIO; |
|---|
| 259 | +} |
|---|
| 260 | + |
|---|
| 261 | +int __init sclp_early_get_info(struct read_info_sccb *info) |
|---|
| 262 | +{ |
|---|
| 263 | + if (!sclp_info_sccb_valid) |
|---|
| 264 | + return -EIO; |
|---|
| 265 | + |
|---|
| 266 | + *info = sclp_info_sccb; |
|---|
| 267 | + return 0; |
|---|
| 268 | +} |
|---|
| 269 | + |
|---|
| 270 | +int __init sclp_early_get_memsize(unsigned long *mem) |
|---|
| 271 | +{ |
|---|
| 272 | + unsigned long rnmax; |
|---|
| 273 | + unsigned long rnsize; |
|---|
| 274 | + struct read_info_sccb *sccb = &sclp_info_sccb; |
|---|
| 275 | + |
|---|
| 276 | + if (!sclp_info_sccb_valid) |
|---|
| 277 | + return -EIO; |
|---|
| 278 | + |
|---|
| 279 | + rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; |
|---|
| 280 | + rnsize = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; |
|---|
| 281 | + rnsize <<= 20; |
|---|
| 282 | + *mem = rnsize * rnmax; |
|---|
| 283 | + return 0; |
|---|
| 284 | +} |
|---|
| 285 | + |
|---|
| 286 | +int __init sclp_early_get_hsa_size(unsigned long *hsa_size) |
|---|
| 287 | +{ |
|---|
| 288 | + if (!sclp_info_sccb_valid) |
|---|
| 289 | + return -EIO; |
|---|
| 290 | + |
|---|
| 291 | + *hsa_size = 0; |
|---|
| 292 | + if (sclp_info_sccb.hsa_size) |
|---|
| 293 | + *hsa_size = (sclp_info_sccb.hsa_size - 1) * PAGE_SIZE; |
|---|
| 294 | + return 0; |
|---|
| 295 | +} |
|---|
| 296 | + |
|---|
| 297 | +#define SCLP_STORAGE_INFO_FACILITY 0x0000400000000000UL |
|---|
| 298 | + |
|---|
| 299 | +void __weak __init add_mem_detect_block(u64 start, u64 end) {} |
|---|
| 300 | +int __init sclp_early_read_storage_info(void) |
|---|
| 301 | +{ |
|---|
| 302 | + struct read_storage_sccb *sccb = (struct read_storage_sccb *)sclp_early_sccb; |
|---|
| 303 | + int rc, id, max_id = 0; |
|---|
| 304 | + unsigned long rn, rzm; |
|---|
| 305 | + sclp_cmdw_t command; |
|---|
| 306 | + u16 sn; |
|---|
| 307 | + |
|---|
| 308 | + if (!sclp_info_sccb_valid) |
|---|
| 309 | + return -EIO; |
|---|
| 310 | + |
|---|
| 311 | + if (!(sclp_info_sccb.facilities & SCLP_STORAGE_INFO_FACILITY)) |
|---|
| 312 | + return -EOPNOTSUPP; |
|---|
| 313 | + |
|---|
| 314 | + rzm = sclp_info_sccb.rnsize ?: sclp_info_sccb.rnsize2; |
|---|
| 315 | + rzm <<= 20; |
|---|
| 316 | + |
|---|
| 317 | + for (id = 0; id <= max_id; id++) { |
|---|
| 318 | + memset(sclp_early_sccb, 0, EARLY_SCCB_SIZE); |
|---|
| 319 | + sccb->header.length = EARLY_SCCB_SIZE; |
|---|
| 320 | + command = SCLP_CMDW_READ_STORAGE_INFO | (id << 8); |
|---|
| 321 | + rc = sclp_early_cmd(command, sccb); |
|---|
| 322 | + if (rc) |
|---|
| 323 | + goto fail; |
|---|
| 324 | + |
|---|
| 325 | + max_id = sccb->max_id; |
|---|
| 326 | + switch (sccb->header.response_code) { |
|---|
| 327 | + case 0x0010: |
|---|
| 328 | + for (sn = 0; sn < sccb->assigned; sn++) { |
|---|
| 329 | + if (!sccb->entries[sn]) |
|---|
| 330 | + continue; |
|---|
| 331 | + rn = sccb->entries[sn] >> 16; |
|---|
| 332 | + add_mem_detect_block((rn - 1) * rzm, rn * rzm); |
|---|
| 333 | + } |
|---|
| 334 | + break; |
|---|
| 335 | + case 0x0310: |
|---|
| 336 | + case 0x0410: |
|---|
| 337 | + break; |
|---|
| 338 | + default: |
|---|
| 339 | + goto fail; |
|---|
| 340 | + } |
|---|
| 341 | + } |
|---|
| 342 | + |
|---|
| 343 | + return 0; |
|---|
| 344 | +fail: |
|---|
| 345 | + mem_detect.count = 0; |
|---|
| 346 | + return -EIO; |
|---|
| 236 | 347 | } |
|---|