sclp_early_core.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright IBM Corp. 2015
  4. * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  5. */
  6. #include <linux/kernel.h>
  7. #include <asm/processor.h>
  8. #include <asm/lowcore.h>
  9. #include <asm/ebcdic.h>
  10. #include <asm/irq.h>
  11. #include <asm/sections.h>
  12. #include <asm/mem_detect.h>
  13. #include "sclp.h"
  14. #include "sclp_rw.h"
  15. static struct read_info_sccb __bootdata(sclp_info_sccb);
  16. static int __bootdata(sclp_info_sccb_valid);
  17. char sclp_early_sccb[PAGE_SIZE] __aligned(PAGE_SIZE) __section(.data);
  18. int sclp_init_state __section(.data) = sclp_init_state_uninitialized;
  19. /*
  20. * Used to keep track of the size of the event masks. Qemu until version 2.11
  21. * only supports 4 and needs a workaround.
  22. */
  23. bool sclp_mask_compat_mode __section(.data);
  24. void sclp_early_wait_irq(void)
  25. {
  26. unsigned long psw_mask, addr;
  27. psw_t psw_ext_save, psw_wait;
  28. union ctlreg0 cr0, cr0_new;
  29. __ctl_store(cr0.val, 0, 0);
  30. cr0_new.val = cr0.val & ~CR0_IRQ_SUBCLASS_MASK;
  31. cr0_new.lap = 0;
  32. cr0_new.sssm = 1;
  33. __ctl_load(cr0_new.val, 0, 0);
  34. psw_ext_save = S390_lowcore.external_new_psw;
  35. psw_mask = __extract_psw();
  36. S390_lowcore.external_new_psw.mask = psw_mask;
  37. psw_wait.mask = psw_mask | PSW_MASK_EXT | PSW_MASK_WAIT;
  38. S390_lowcore.ext_int_code = 0;
  39. do {
  40. asm volatile(
  41. " larl %[addr],0f\n"
  42. " stg %[addr],%[psw_wait_addr]\n"
  43. " stg %[addr],%[psw_ext_addr]\n"
  44. " lpswe %[psw_wait]\n"
  45. "0:\n"
  46. : [addr] "=&d" (addr),
  47. [psw_wait_addr] "=Q" (psw_wait.addr),
  48. [psw_ext_addr] "=Q" (S390_lowcore.external_new_psw.addr)
  49. : [psw_wait] "Q" (psw_wait)
  50. : "cc", "memory");
  51. } while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG);
  52. S390_lowcore.external_new_psw = psw_ext_save;
  53. __ctl_load(cr0.val, 0, 0);
  54. }
  55. int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb)
  56. {
  57. unsigned long flags;
  58. int rc;
  59. raw_local_irq_save(flags);
  60. rc = sclp_service_call(cmd, sccb);
  61. if (rc)
  62. goto out;
  63. sclp_early_wait_irq();
  64. out:
  65. raw_local_irq_restore(flags);
  66. return rc;
  67. }
  68. struct write_sccb {
  69. struct sccb_header header;
  70. struct msg_buf msg;
  71. } __packed;
  72. /* Output multi-line text using SCLP Message interface. */
  73. static void sclp_early_print_lm(const char *str, unsigned int len)
  74. {
  75. unsigned char *ptr, *end, ch;
  76. unsigned int count, offset;
  77. struct write_sccb *sccb;
  78. struct msg_buf *msg;
  79. struct mdb *mdb;
  80. struct mto *mto;
  81. struct go *go;
  82. sccb = (struct write_sccb *) &sclp_early_sccb;
  83. end = (unsigned char *) sccb + sizeof(sclp_early_sccb) - 1;
  84. memset(sccb, 0, sizeof(*sccb));
  85. ptr = (unsigned char *) &sccb->msg.mdb.mto;
  86. offset = 0;
  87. do {
  88. for (count = sizeof(*mto); offset < len; count++) {
  89. ch = str[offset++];
  90. if ((ch == 0x0a) || (ptr + count > end))
  91. break;
  92. ptr[count] = _ascebc[ch];
  93. }
  94. mto = (struct mto *) ptr;
  95. memset(mto, 0, sizeof(*mto));
  96. mto->length = count;
  97. mto->type = 4;
  98. mto->line_type_flags = LNTPFLGS_ENDTEXT;
  99. ptr += count;
  100. } while ((offset < len) && (ptr + sizeof(*mto) <= end));
  101. len = ptr - (unsigned char *) sccb;
  102. sccb->header.length = len - offsetof(struct write_sccb, header);
  103. msg = &sccb->msg;
  104. msg->header.type = EVTYP_MSG;
  105. msg->header.length = len - offsetof(struct write_sccb, msg.header);
  106. mdb = &msg->mdb;
  107. mdb->header.type = 1;
  108. mdb->header.tag = 0xD4C4C240;
  109. mdb->header.revision_code = 1;
  110. mdb->header.length = len - offsetof(struct write_sccb, msg.mdb.header);
  111. go = &mdb->go;
  112. go->length = sizeof(*go);
  113. go->type = 1;
  114. sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA, sccb);
  115. }
  116. struct vt220_sccb {
  117. struct sccb_header header;
  118. struct {
  119. struct evbuf_header header;
  120. char data[];
  121. } msg;
  122. } __packed;
  123. /* Output multi-line text using SCLP VT220 interface. */
  124. static void sclp_early_print_vt220(const char *str, unsigned int len)
  125. {
  126. struct vt220_sccb *sccb;
  127. sccb = (struct vt220_sccb *) &sclp_early_sccb;
  128. if (sizeof(*sccb) + len >= sizeof(sclp_early_sccb))
  129. len = sizeof(sclp_early_sccb) - sizeof(*sccb);
  130. memset(sccb, 0, sizeof(*sccb));
  131. memcpy(&sccb->msg.data, str, len);
  132. sccb->header.length = sizeof(*sccb) + len;
  133. sccb->msg.header.length = sizeof(sccb->msg) + len;
  134. sccb->msg.header.type = EVTYP_VT220MSG;
  135. sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_DATA, sccb);
  136. }
  137. int sclp_early_set_event_mask(struct init_sccb *sccb,
  138. sccb_mask_t receive_mask,
  139. sccb_mask_t send_mask)
  140. {
  141. retry:
  142. memset(sccb, 0, sizeof(*sccb));
  143. sccb->header.length = sizeof(*sccb);
  144. if (sclp_mask_compat_mode)
  145. sccb->mask_length = SCLP_MASK_SIZE_COMPAT;
  146. else
  147. sccb->mask_length = sizeof(sccb_mask_t);
  148. sccb_set_recv_mask(sccb, receive_mask);
  149. sccb_set_send_mask(sccb, send_mask);
  150. if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_MASK, sccb))
  151. return -EIO;
  152. if ((sccb->header.response_code == 0x74f0) && !sclp_mask_compat_mode) {
  153. sclp_mask_compat_mode = true;
  154. goto retry;
  155. }
  156. if (sccb->header.response_code != 0x20)
  157. return -EIO;
  158. return 0;
  159. }
  160. unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb)
  161. {
  162. if (!(sccb_get_sclp_send_mask(sccb) & EVTYP_OPCMD_MASK))
  163. return 0;
  164. if (!(sccb_get_sclp_recv_mask(sccb) & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
  165. return 0;
  166. return 1;
  167. }
  168. unsigned int sclp_early_con_check_vt220(struct init_sccb *sccb)
  169. {
  170. if (sccb_get_sclp_send_mask(sccb) & EVTYP_VT220MSG_MASK)
  171. return 1;
  172. return 0;
  173. }
  174. static int sclp_early_setup(int disable, int *have_linemode, int *have_vt220)
  175. {
  176. unsigned long receive_mask, send_mask;
  177. struct init_sccb *sccb;
  178. int rc;
  179. BUILD_BUG_ON(sizeof(struct init_sccb) > PAGE_SIZE);
  180. *have_linemode = *have_vt220 = 0;
  181. sccb = (struct init_sccb *) &sclp_early_sccb;
  182. receive_mask = disable ? 0 : EVTYP_OPCMD_MASK;
  183. send_mask = disable ? 0 : EVTYP_VT220MSG_MASK | EVTYP_MSG_MASK;
  184. rc = sclp_early_set_event_mask(sccb, receive_mask, send_mask);
  185. if (rc)
  186. return rc;
  187. *have_linemode = sclp_early_con_check_linemode(sccb);
  188. *have_vt220 = !!(sccb_get_send_mask(sccb) & EVTYP_VT220MSG_MASK);
  189. return rc;
  190. }
  191. /*
  192. * Output one or more lines of text on the SCLP console (VT220 and /
  193. * or line-mode).
  194. */
  195. void __sclp_early_printk(const char *str, unsigned int len, unsigned int force)
  196. {
  197. int have_linemode, have_vt220;
  198. if (!force && sclp_init_state != sclp_init_state_uninitialized)
  199. return;
  200. if (sclp_early_setup(0, &have_linemode, &have_vt220) != 0)
  201. return;
  202. if (have_linemode)
  203. sclp_early_print_lm(str, len);
  204. if (have_vt220)
  205. sclp_early_print_vt220(str, len);
  206. sclp_early_setup(1, &have_linemode, &have_vt220);
  207. }
  208. void sclp_early_printk(const char *str)
  209. {
  210. __sclp_early_printk(str, strlen(str), 0);
  211. }
  212. void sclp_early_printk_force(const char *str)
  213. {
  214. __sclp_early_printk(str, strlen(str), 1);
  215. }
  216. int __init sclp_early_read_info(void)
  217. {
  218. int i;
  219. struct read_info_sccb *sccb = &sclp_info_sccb;
  220. sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
  221. SCLP_CMDW_READ_SCP_INFO};
  222. for (i = 0; i < ARRAY_SIZE(commands); i++) {
  223. memset(sccb, 0, sizeof(*sccb));
  224. sccb->header.length = sizeof(*sccb);
  225. sccb->header.function_code = 0x80;
  226. sccb->header.control_mask[2] = 0x80;
  227. if (sclp_early_cmd(commands[i], sccb))
  228. break;
  229. if (sccb->header.response_code == 0x10) {
  230. sclp_info_sccb_valid = 1;
  231. return 0;
  232. }
  233. if (sccb->header.response_code != 0x1f0)
  234. break;
  235. }
  236. return -EIO;
  237. }
  238. int __init sclp_early_get_info(struct read_info_sccb *info)
  239. {
  240. if (!sclp_info_sccb_valid)
  241. return -EIO;
  242. *info = sclp_info_sccb;
  243. return 0;
  244. }
  245. int __init sclp_early_get_memsize(unsigned long *mem)
  246. {
  247. unsigned long rnmax;
  248. unsigned long rnsize;
  249. struct read_info_sccb *sccb = &sclp_info_sccb;
  250. if (!sclp_info_sccb_valid)
  251. return -EIO;
  252. rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
  253. rnsize = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
  254. rnsize <<= 20;
  255. *mem = rnsize * rnmax;
  256. return 0;
  257. }
  258. int __init sclp_early_get_hsa_size(unsigned long *hsa_size)
  259. {
  260. if (!sclp_info_sccb_valid)
  261. return -EIO;
  262. *hsa_size = 0;
  263. if (sclp_info_sccb.hsa_size)
  264. *hsa_size = (sclp_info_sccb.hsa_size - 1) * PAGE_SIZE;
  265. return 0;
  266. }
  267. #define SCLP_STORAGE_INFO_FACILITY 0x0000400000000000UL
  268. void __weak __init add_mem_detect_block(u64 start, u64 end) {}
  269. int __init sclp_early_read_storage_info(void)
  270. {
  271. struct read_storage_sccb *sccb = (struct read_storage_sccb *)&sclp_early_sccb;
  272. int rc, id, max_id = 0;
  273. unsigned long rn, rzm;
  274. sclp_cmdw_t command;
  275. u16 sn;
  276. if (!sclp_info_sccb_valid)
  277. return -EIO;
  278. if (!(sclp_info_sccb.facilities & SCLP_STORAGE_INFO_FACILITY))
  279. return -EOPNOTSUPP;
  280. rzm = sclp_info_sccb.rnsize ?: sclp_info_sccb.rnsize2;
  281. rzm <<= 20;
  282. for (id = 0; id <= max_id; id++) {
  283. memset(sclp_early_sccb, 0, sizeof(sclp_early_sccb));
  284. sccb->header.length = sizeof(sclp_early_sccb);
  285. command = SCLP_CMDW_READ_STORAGE_INFO | (id << 8);
  286. rc = sclp_early_cmd(command, sccb);
  287. if (rc)
  288. goto fail;
  289. max_id = sccb->max_id;
  290. switch (sccb->header.response_code) {
  291. case 0x0010:
  292. for (sn = 0; sn < sccb->assigned; sn++) {
  293. if (!sccb->entries[sn])
  294. continue;
  295. rn = sccb->entries[sn] >> 16;
  296. add_mem_detect_block((rn - 1) * rzm, rn * rzm);
  297. }
  298. break;
  299. case 0x0310:
  300. case 0x0410:
  301. break;
  302. default:
  303. goto fail;
  304. }
  305. }
  306. return 0;
  307. fail:
  308. mem_detect.count = 0;
  309. return -EIO;
  310. }