ipl.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  1. /*
  2. * arch/s390/kernel/ipl.c
  3. * ipl/reipl/dump support for Linux on s390.
  4. *
  5. * Copyright (C) IBM Corp. 2005,2006
  6. * Author(s): Michael Holzheu <holzheu@de.ibm.com>
  7. * Heiko Carstens <heiko.carstens@de.ibm.com>
  8. * Volker Sameske <sameske@de.ibm.com>
  9. */
  10. #include <linux/types.h>
  11. #include <linux/module.h>
  12. #include <linux/device.h>
  13. #include <linux/delay.h>
  14. #include <linux/reboot.h>
  15. #include <linux/ctype.h>
  16. #include <asm/ipl.h>
  17. #include <asm/smp.h>
  18. #include <asm/setup.h>
  19. #include <asm/cpcmd.h>
  20. #include <asm/cio.h>
  21. #include <asm/ebcdic.h>
  22. #include <asm/reset.h>
  23. #include <asm/sclp.h>
  24. #define IPL_PARM_BLOCK_VERSION 0
  25. #define IPL_UNKNOWN_STR "unknown"
  26. #define IPL_CCW_STR "ccw"
  27. #define IPL_FCP_STR "fcp"
  28. #define IPL_FCP_DUMP_STR "fcp_dump"
  29. #define IPL_NSS_STR "nss"
  30. static char *ipl_type_str(enum ipl_type type)
  31. {
  32. switch (type) {
  33. case IPL_TYPE_CCW:
  34. return IPL_CCW_STR;
  35. case IPL_TYPE_FCP:
  36. return IPL_FCP_STR;
  37. case IPL_TYPE_FCP_DUMP:
  38. return IPL_FCP_DUMP_STR;
  39. case IPL_TYPE_NSS:
  40. return IPL_NSS_STR;
  41. case IPL_TYPE_UNKNOWN:
  42. default:
  43. return IPL_UNKNOWN_STR;
  44. }
  45. }
  46. enum dump_type {
  47. DUMP_TYPE_NONE = 1,
  48. DUMP_TYPE_CCW = 2,
  49. DUMP_TYPE_FCP = 4,
  50. };
  51. #define DUMP_NONE_STR "none"
  52. #define DUMP_CCW_STR "ccw"
  53. #define DUMP_FCP_STR "fcp"
  54. static char *dump_type_str(enum dump_type type)
  55. {
  56. switch (type) {
  57. case DUMP_TYPE_NONE:
  58. return DUMP_NONE_STR;
  59. case DUMP_TYPE_CCW:
  60. return DUMP_CCW_STR;
  61. case DUMP_TYPE_FCP:
  62. return DUMP_FCP_STR;
  63. default:
  64. return NULL;
  65. }
  66. }
  67. /*
  68. * Must be in data section since the bss section
  69. * is not cleared when these are accessed.
  70. */
  71. static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
  72. u32 ipl_flags __attribute__((__section__(".data"))) = 0;
  73. enum ipl_method {
  74. REIPL_METHOD_CCW_CIO,
  75. REIPL_METHOD_CCW_DIAG,
  76. REIPL_METHOD_CCW_VM,
  77. REIPL_METHOD_FCP_RO_DIAG,
  78. REIPL_METHOD_FCP_RW_DIAG,
  79. REIPL_METHOD_FCP_RO_VM,
  80. REIPL_METHOD_FCP_DUMP,
  81. REIPL_METHOD_NSS,
  82. REIPL_METHOD_DEFAULT,
  83. };
  84. enum dump_method {
  85. DUMP_METHOD_NONE,
  86. DUMP_METHOD_CCW_CIO,
  87. DUMP_METHOD_CCW_DIAG,
  88. DUMP_METHOD_CCW_VM,
  89. DUMP_METHOD_FCP_DIAG,
  90. };
  91. enum shutdown_action {
  92. SHUTDOWN_REIPL,
  93. SHUTDOWN_DUMP,
  94. SHUTDOWN_STOP,
  95. };
  96. #define SHUTDOWN_REIPL_STR "reipl"
  97. #define SHUTDOWN_DUMP_STR "dump"
  98. #define SHUTDOWN_STOP_STR "stop"
  99. static char *shutdown_action_str(enum shutdown_action action)
  100. {
  101. switch (action) {
  102. case SHUTDOWN_REIPL:
  103. return SHUTDOWN_REIPL_STR;
  104. case SHUTDOWN_DUMP:
  105. return SHUTDOWN_DUMP_STR;
  106. case SHUTDOWN_STOP:
  107. return SHUTDOWN_STOP_STR;
  108. default:
  109. return NULL;
  110. }
  111. }
  112. static int diag308_set_works = 0;
  113. static int reipl_capabilities = IPL_TYPE_UNKNOWN;
  114. static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
  115. static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
  116. static struct ipl_parameter_block *reipl_block_fcp;
  117. static struct ipl_parameter_block *reipl_block_ccw;
  118. static char reipl_nss_name[NSS_NAME_SIZE + 1];
  119. static int dump_capabilities = DUMP_TYPE_NONE;
  120. static enum dump_type dump_type = DUMP_TYPE_NONE;
  121. static enum dump_method dump_method = DUMP_METHOD_NONE;
  122. static struct ipl_parameter_block *dump_block_fcp;
  123. static struct ipl_parameter_block *dump_block_ccw;
  124. static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
  125. static struct sclp_ipl_info sclp_ipl_info;
  126. int diag308(unsigned long subcode, void *addr)
  127. {
  128. register unsigned long _addr asm("0") = (unsigned long) addr;
  129. register unsigned long _rc asm("1") = 0;
  130. asm volatile(
  131. " diag %0,%2,0x308\n"
  132. "0:\n"
  133. EX_TABLE(0b,0b)
  134. : "+d" (_addr), "+d" (_rc)
  135. : "d" (subcode) : "cc", "memory");
  136. return _rc;
  137. }
  138. EXPORT_SYMBOL_GPL(diag308);
  139. /* SYSFS */
  140. #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
  141. static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \
  142. char *page) \
  143. { \
  144. return sprintf(page, _format, _value); \
  145. } \
  146. static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
  147. __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
  148. #define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
  149. static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \
  150. char *page) \
  151. { \
  152. return sprintf(page, _fmt_out, \
  153. (unsigned long long) _value); \
  154. } \
  155. static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \
  156. const char *buf, size_t len) \
  157. { \
  158. unsigned long long value; \
  159. if (sscanf(buf, _fmt_in, &value) != 1) \
  160. return -EINVAL; \
  161. _value = value; \
  162. return len; \
  163. } \
  164. static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
  165. __ATTR(_name,(S_IRUGO | S_IWUSR), \
  166. sys_##_prefix##_##_name##_show, \
  167. sys_##_prefix##_##_name##_store);
  168. #define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
  169. static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \
  170. char *page) \
  171. { \
  172. return sprintf(page, _fmt_out, _value); \
  173. } \
  174. static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \
  175. const char *buf, size_t len) \
  176. { \
  177. if (sscanf(buf, _fmt_in, _value) != 1) \
  178. return -EINVAL; \
  179. return len; \
  180. } \
  181. static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
  182. __ATTR(_name,(S_IRUGO | S_IWUSR), \
  183. sys_##_prefix##_##_name##_show, \
  184. sys_##_prefix##_##_name##_store);
  185. static void make_attrs_ro(struct attribute **attrs)
  186. {
  187. while (*attrs) {
  188. (*attrs)->mode = S_IRUGO;
  189. attrs++;
  190. }
  191. }
  192. /*
  193. * ipl section
  194. */
  195. static __init enum ipl_type get_ipl_type(void)
  196. {
  197. struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
  198. if (ipl_flags & IPL_NSS_VALID)
  199. return IPL_TYPE_NSS;
  200. if (!(ipl_flags & IPL_DEVNO_VALID))
  201. return IPL_TYPE_UNKNOWN;
  202. if (!(ipl_flags & IPL_PARMBLOCK_VALID))
  203. return IPL_TYPE_CCW;
  204. if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION)
  205. return IPL_TYPE_UNKNOWN;
  206. if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
  207. return IPL_TYPE_UNKNOWN;
  208. if (ipl->ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
  209. return IPL_TYPE_FCP_DUMP;
  210. return IPL_TYPE_FCP;
  211. }
  212. void __init setup_ipl_info(void)
  213. {
  214. ipl_info.type = get_ipl_type();
  215. switch (ipl_info.type) {
  216. case IPL_TYPE_CCW:
  217. ipl_info.data.ccw.dev_id.devno = ipl_devno;
  218. ipl_info.data.ccw.dev_id.ssid = 0;
  219. break;
  220. case IPL_TYPE_FCP:
  221. case IPL_TYPE_FCP_DUMP:
  222. ipl_info.data.fcp.dev_id.devno =
  223. IPL_PARMBLOCK_START->ipl_info.fcp.devno;
  224. ipl_info.data.fcp.dev_id.ssid = 0;
  225. ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
  226. ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
  227. break;
  228. case IPL_TYPE_NSS:
  229. strncpy(ipl_info.data.nss.name, kernel_nss_name,
  230. sizeof(ipl_info.data.nss.name));
  231. break;
  232. case IPL_TYPE_UNKNOWN:
  233. default:
  234. /* We have no info to copy */
  235. break;
  236. }
  237. }
  238. struct ipl_info ipl_info;
  239. EXPORT_SYMBOL_GPL(ipl_info);
  240. static ssize_t ipl_type_show(struct kset *kset, char *page)
  241. {
  242. return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
  243. }
  244. static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
  245. static ssize_t sys_ipl_device_show(struct kset *kset, char *page)
  246. {
  247. struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
  248. switch (ipl_info.type) {
  249. case IPL_TYPE_CCW:
  250. return sprintf(page, "0.0.%04x\n", ipl_devno);
  251. case IPL_TYPE_FCP:
  252. case IPL_TYPE_FCP_DUMP:
  253. return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
  254. default:
  255. return 0;
  256. }
  257. }
  258. static struct subsys_attribute sys_ipl_device_attr =
  259. __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
  260. static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr,
  261. char *buf, loff_t off, size_t count)
  262. {
  263. unsigned int size = IPL_PARMBLOCK_SIZE;
  264. if (off > size)
  265. return 0;
  266. if (off + count > size)
  267. count = size - off;
  268. memcpy(buf, (void *)IPL_PARMBLOCK_START + off, count);
  269. return count;
  270. }
  271. static struct bin_attribute ipl_parameter_attr = {
  272. .attr = {
  273. .name = "binary_parameter",
  274. .mode = S_IRUGO,
  275. },
  276. .size = PAGE_SIZE,
  277. .read = &ipl_parameter_read,
  278. };
  279. static ssize_t ipl_scp_data_read(struct kobject *kobj, struct bin_attribute *attr,
  280. char *buf, loff_t off, size_t count)
  281. {
  282. unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
  283. void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
  284. if (off > size)
  285. return 0;
  286. if (off + count > size)
  287. count = size - off;
  288. memcpy(buf, scp_data + off, count);
  289. return count;
  290. }
  291. static struct bin_attribute ipl_scp_data_attr = {
  292. .attr = {
  293. .name = "scp_data",
  294. .mode = S_IRUGO,
  295. },
  296. .size = PAGE_SIZE,
  297. .read = ipl_scp_data_read,
  298. };
  299. /* FCP ipl device attributes */
  300. DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long)
  301. IPL_PARMBLOCK_START->ipl_info.fcp.wwpn);
  302. DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long)
  303. IPL_PARMBLOCK_START->ipl_info.fcp.lun);
  304. DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
  305. IPL_PARMBLOCK_START->ipl_info.fcp.bootprog);
  306. DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
  307. IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
  308. static struct attribute *ipl_fcp_attrs[] = {
  309. &sys_ipl_type_attr.attr,
  310. &sys_ipl_device_attr.attr,
  311. &sys_ipl_fcp_wwpn_attr.attr,
  312. &sys_ipl_fcp_lun_attr.attr,
  313. &sys_ipl_fcp_bootprog_attr.attr,
  314. &sys_ipl_fcp_br_lba_attr.attr,
  315. NULL,
  316. };
  317. static struct attribute_group ipl_fcp_attr_group = {
  318. .attrs = ipl_fcp_attrs,
  319. };
  320. /* CCW ipl device attributes */
  321. static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page)
  322. {
  323. char loadparm[LOADPARM_LEN + 1] = {};
  324. if (!sclp_ipl_info.is_valid)
  325. return sprintf(page, "#unknown#\n");
  326. memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
  327. EBCASC(loadparm, LOADPARM_LEN);
  328. strstrip(loadparm);
  329. return sprintf(page, "%s\n", loadparm);
  330. }
  331. static struct subsys_attribute sys_ipl_ccw_loadparm_attr =
  332. __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
  333. static struct attribute *ipl_ccw_attrs[] = {
  334. &sys_ipl_type_attr.attr,
  335. &sys_ipl_device_attr.attr,
  336. &sys_ipl_ccw_loadparm_attr.attr,
  337. NULL,
  338. };
  339. static struct attribute_group ipl_ccw_attr_group = {
  340. .attrs = ipl_ccw_attrs,
  341. };
  342. /* NSS ipl device attributes */
  343. DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
  344. static struct attribute *ipl_nss_attrs[] = {
  345. &sys_ipl_type_attr.attr,
  346. &sys_ipl_nss_name_attr.attr,
  347. NULL,
  348. };
  349. static struct attribute_group ipl_nss_attr_group = {
  350. .attrs = ipl_nss_attrs,
  351. };
  352. /* UNKNOWN ipl device attributes */
  353. static struct attribute *ipl_unknown_attrs[] = {
  354. &sys_ipl_type_attr.attr,
  355. NULL,
  356. };
  357. static struct attribute_group ipl_unknown_attr_group = {
  358. .attrs = ipl_unknown_attrs,
  359. };
  360. static decl_subsys(ipl, NULL, NULL);
  361. /*
  362. * reipl section
  363. */
  364. /* FCP reipl device attributes */
  365. DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
  366. reipl_block_fcp->ipl_info.fcp.wwpn);
  367. DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n",
  368. reipl_block_fcp->ipl_info.fcp.lun);
  369. DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
  370. reipl_block_fcp->ipl_info.fcp.bootprog);
  371. DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
  372. reipl_block_fcp->ipl_info.fcp.br_lba);
  373. DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
  374. reipl_block_fcp->ipl_info.fcp.devno);
  375. static struct attribute *reipl_fcp_attrs[] = {
  376. &sys_reipl_fcp_device_attr.attr,
  377. &sys_reipl_fcp_wwpn_attr.attr,
  378. &sys_reipl_fcp_lun_attr.attr,
  379. &sys_reipl_fcp_bootprog_attr.attr,
  380. &sys_reipl_fcp_br_lba_attr.attr,
  381. NULL,
  382. };
  383. static struct attribute_group reipl_fcp_attr_group = {
  384. .name = IPL_FCP_STR,
  385. .attrs = reipl_fcp_attrs,
  386. };
  387. /* CCW reipl device attributes */
  388. DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
  389. reipl_block_ccw->ipl_info.ccw.devno);
  390. static void reipl_get_ascii_loadparm(char *loadparm)
  391. {
  392. memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param,
  393. LOADPARM_LEN);
  394. EBCASC(loadparm, LOADPARM_LEN);
  395. loadparm[LOADPARM_LEN] = 0;
  396. strstrip(loadparm);
  397. }
  398. static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page)
  399. {
  400. char buf[LOADPARM_LEN + 1];
  401. reipl_get_ascii_loadparm(buf);
  402. return sprintf(page, "%s\n", buf);
  403. }
  404. static ssize_t reipl_ccw_loadparm_store(struct kset *kset,
  405. const char *buf, size_t len)
  406. {
  407. int i, lp_len;
  408. /* ignore trailing newline */
  409. lp_len = len;
  410. if ((len > 0) && (buf[len - 1] == '\n'))
  411. lp_len--;
  412. /* loadparm can have max 8 characters and must not start with a blank */
  413. if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
  414. return -EINVAL;
  415. /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
  416. for (i = 0; i < lp_len; i++) {
  417. if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
  418. (buf[i] == '.'))
  419. continue;
  420. return -EINVAL;
  421. }
  422. /* initialize loadparm with blanks */
  423. memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN);
  424. /* copy and convert to ebcdic */
  425. memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len);
  426. ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN);
  427. return len;
  428. }
  429. static struct subsys_attribute sys_reipl_ccw_loadparm_attr =
  430. __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
  431. reipl_ccw_loadparm_store);
  432. static struct attribute *reipl_ccw_attrs[] = {
  433. &sys_reipl_ccw_device_attr.attr,
  434. &sys_reipl_ccw_loadparm_attr.attr,
  435. NULL,
  436. };
  437. static struct attribute_group reipl_ccw_attr_group = {
  438. .name = IPL_CCW_STR,
  439. .attrs = reipl_ccw_attrs,
  440. };
  441. /* NSS reipl device attributes */
  442. DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name);
  443. static struct attribute *reipl_nss_attrs[] = {
  444. &sys_reipl_nss_name_attr.attr,
  445. NULL,
  446. };
  447. static struct attribute_group reipl_nss_attr_group = {
  448. .name = IPL_NSS_STR,
  449. .attrs = reipl_nss_attrs,
  450. };
  451. /* reipl type */
  452. static int reipl_set_type(enum ipl_type type)
  453. {
  454. if (!(reipl_capabilities & type))
  455. return -EINVAL;
  456. switch(type) {
  457. case IPL_TYPE_CCW:
  458. if (MACHINE_IS_VM)
  459. reipl_method = REIPL_METHOD_CCW_VM;
  460. else
  461. reipl_method = REIPL_METHOD_CCW_CIO;
  462. break;
  463. case IPL_TYPE_FCP:
  464. if (diag308_set_works)
  465. reipl_method = REIPL_METHOD_FCP_RW_DIAG;
  466. else if (MACHINE_IS_VM)
  467. reipl_method = REIPL_METHOD_FCP_RO_VM;
  468. else
  469. reipl_method = REIPL_METHOD_FCP_RO_DIAG;
  470. break;
  471. case IPL_TYPE_FCP_DUMP:
  472. reipl_method = REIPL_METHOD_FCP_DUMP;
  473. break;
  474. case IPL_TYPE_NSS:
  475. reipl_method = REIPL_METHOD_NSS;
  476. break;
  477. case IPL_TYPE_UNKNOWN:
  478. reipl_method = REIPL_METHOD_DEFAULT;
  479. break;
  480. default:
  481. BUG();
  482. }
  483. reipl_type = type;
  484. return 0;
  485. }
  486. static ssize_t reipl_type_show(struct kset *kset, char *page)
  487. {
  488. return sprintf(page, "%s\n", ipl_type_str(reipl_type));
  489. }
  490. static ssize_t reipl_type_store(struct kset *kset, const char *buf,
  491. size_t len)
  492. {
  493. int rc = -EINVAL;
  494. if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
  495. rc = reipl_set_type(IPL_TYPE_CCW);
  496. else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
  497. rc = reipl_set_type(IPL_TYPE_FCP);
  498. else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
  499. rc = reipl_set_type(IPL_TYPE_NSS);
  500. return (rc != 0) ? rc : len;
  501. }
  502. static struct subsys_attribute reipl_type_attr =
  503. __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
  504. static decl_subsys(reipl, NULL, NULL);
  505. /*
  506. * dump section
  507. */
  508. /* FCP dump device attributes */
  509. DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
  510. dump_block_fcp->ipl_info.fcp.wwpn);
  511. DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
  512. dump_block_fcp->ipl_info.fcp.lun);
  513. DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
  514. dump_block_fcp->ipl_info.fcp.bootprog);
  515. DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
  516. dump_block_fcp->ipl_info.fcp.br_lba);
  517. DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
  518. dump_block_fcp->ipl_info.fcp.devno);
  519. static struct attribute *dump_fcp_attrs[] = {
  520. &sys_dump_fcp_device_attr.attr,
  521. &sys_dump_fcp_wwpn_attr.attr,
  522. &sys_dump_fcp_lun_attr.attr,
  523. &sys_dump_fcp_bootprog_attr.attr,
  524. &sys_dump_fcp_br_lba_attr.attr,
  525. NULL,
  526. };
  527. static struct attribute_group dump_fcp_attr_group = {
  528. .name = IPL_FCP_STR,
  529. .attrs = dump_fcp_attrs,
  530. };
  531. /* CCW dump device attributes */
  532. DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
  533. dump_block_ccw->ipl_info.ccw.devno);
  534. static struct attribute *dump_ccw_attrs[] = {
  535. &sys_dump_ccw_device_attr.attr,
  536. NULL,
  537. };
  538. static struct attribute_group dump_ccw_attr_group = {
  539. .name = IPL_CCW_STR,
  540. .attrs = dump_ccw_attrs,
  541. };
  542. /* dump type */
  543. static int dump_set_type(enum dump_type type)
  544. {
  545. if (!(dump_capabilities & type))
  546. return -EINVAL;
  547. switch(type) {
  548. case DUMP_TYPE_CCW:
  549. if (MACHINE_IS_VM)
  550. dump_method = DUMP_METHOD_CCW_VM;
  551. else
  552. dump_method = DUMP_METHOD_CCW_CIO;
  553. break;
  554. case DUMP_TYPE_FCP:
  555. dump_method = DUMP_METHOD_FCP_DIAG;
  556. break;
  557. default:
  558. dump_method = DUMP_METHOD_NONE;
  559. }
  560. dump_type = type;
  561. return 0;
  562. }
  563. static ssize_t dump_type_show(struct kset *kset, char *page)
  564. {
  565. return sprintf(page, "%s\n", dump_type_str(dump_type));
  566. }
  567. static ssize_t dump_type_store(struct kset *kset, const char *buf,
  568. size_t len)
  569. {
  570. int rc = -EINVAL;
  571. if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
  572. rc = dump_set_type(DUMP_TYPE_NONE);
  573. else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
  574. rc = dump_set_type(DUMP_TYPE_CCW);
  575. else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
  576. rc = dump_set_type(DUMP_TYPE_FCP);
  577. return (rc != 0) ? rc : len;
  578. }
  579. static struct subsys_attribute dump_type_attr =
  580. __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
  581. static decl_subsys(dump, NULL, NULL);
  582. /*
  583. * Shutdown actions section
  584. */
  585. static decl_subsys(shutdown_actions, NULL, NULL);
  586. /* on panic */
  587. static ssize_t on_panic_show(struct kset *kset, char *page)
  588. {
  589. return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
  590. }
  591. static ssize_t on_panic_store(struct kset *kset, const char *buf,
  592. size_t len)
  593. {
  594. if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
  595. on_panic_action = SHUTDOWN_REIPL;
  596. else if (strncmp(buf, SHUTDOWN_DUMP_STR,
  597. strlen(SHUTDOWN_DUMP_STR)) == 0)
  598. on_panic_action = SHUTDOWN_DUMP;
  599. else if (strncmp(buf, SHUTDOWN_STOP_STR,
  600. strlen(SHUTDOWN_STOP_STR)) == 0)
  601. on_panic_action = SHUTDOWN_STOP;
  602. else
  603. return -EINVAL;
  604. return len;
  605. }
  606. static struct subsys_attribute on_panic_attr =
  607. __ATTR(on_panic, 0644, on_panic_show, on_panic_store);
  608. void do_reipl(void)
  609. {
  610. struct ccw_dev_id devid;
  611. static char buf[100];
  612. char loadparm[LOADPARM_LEN + 1];
  613. switch (reipl_method) {
  614. case REIPL_METHOD_CCW_CIO:
  615. devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
  616. if (ipl_info.type == IPL_TYPE_CCW && devid.devno == ipl_devno)
  617. diag308(DIAG308_IPL, NULL);
  618. devid.ssid = 0;
  619. reipl_ccw_dev(&devid);
  620. break;
  621. case REIPL_METHOD_CCW_VM:
  622. reipl_get_ascii_loadparm(loadparm);
  623. if (strlen(loadparm) == 0)
  624. sprintf(buf, "IPL %X CLEAR",
  625. reipl_block_ccw->ipl_info.ccw.devno);
  626. else
  627. sprintf(buf, "IPL %X CLEAR LOADPARM '%s'",
  628. reipl_block_ccw->ipl_info.ccw.devno, loadparm);
  629. __cpcmd(buf, NULL, 0, NULL);
  630. break;
  631. case REIPL_METHOD_CCW_DIAG:
  632. diag308(DIAG308_SET, reipl_block_ccw);
  633. diag308(DIAG308_IPL, NULL);
  634. break;
  635. case REIPL_METHOD_FCP_RW_DIAG:
  636. diag308(DIAG308_SET, reipl_block_fcp);
  637. diag308(DIAG308_IPL, NULL);
  638. break;
  639. case REIPL_METHOD_FCP_RO_DIAG:
  640. diag308(DIAG308_IPL, NULL);
  641. break;
  642. case REIPL_METHOD_FCP_RO_VM:
  643. __cpcmd("IPL", NULL, 0, NULL);
  644. break;
  645. case REIPL_METHOD_NSS:
  646. sprintf(buf, "IPL %s", reipl_nss_name);
  647. __cpcmd(buf, NULL, 0, NULL);
  648. break;
  649. case REIPL_METHOD_DEFAULT:
  650. if (MACHINE_IS_VM)
  651. __cpcmd("IPL", NULL, 0, NULL);
  652. diag308(DIAG308_IPL, NULL);
  653. break;
  654. case REIPL_METHOD_FCP_DUMP:
  655. default:
  656. break;
  657. }
  658. signal_processor(smp_processor_id(), sigp_stop_and_store_status);
  659. }
  660. static void do_dump(void)
  661. {
  662. struct ccw_dev_id devid;
  663. static char buf[100];
  664. switch (dump_method) {
  665. case DUMP_METHOD_CCW_CIO:
  666. smp_send_stop();
  667. devid.devno = dump_block_ccw->ipl_info.ccw.devno;
  668. devid.ssid = 0;
  669. reipl_ccw_dev(&devid);
  670. break;
  671. case DUMP_METHOD_CCW_VM:
  672. smp_send_stop();
  673. sprintf(buf, "STORE STATUS");
  674. __cpcmd(buf, NULL, 0, NULL);
  675. sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
  676. __cpcmd(buf, NULL, 0, NULL);
  677. break;
  678. case DUMP_METHOD_CCW_DIAG:
  679. diag308(DIAG308_SET, dump_block_ccw);
  680. diag308(DIAG308_DUMP, NULL);
  681. break;
  682. case DUMP_METHOD_FCP_DIAG:
  683. diag308(DIAG308_SET, dump_block_fcp);
  684. diag308(DIAG308_DUMP, NULL);
  685. break;
  686. case DUMP_METHOD_NONE:
  687. default:
  688. return;
  689. }
  690. printk(KERN_EMERG "Dump failed!\n");
  691. }
  692. /* init functions */
  693. static int __init ipl_register_fcp_files(void)
  694. {
  695. int rc;
  696. rc = sysfs_create_group(&ipl_subsys.kobj,
  697. &ipl_fcp_attr_group);
  698. if (rc)
  699. goto out;
  700. rc = sysfs_create_bin_file(&ipl_subsys.kobj,
  701. &ipl_parameter_attr);
  702. if (rc)
  703. goto out_ipl_parm;
  704. rc = sysfs_create_bin_file(&ipl_subsys.kobj,
  705. &ipl_scp_data_attr);
  706. if (!rc)
  707. goto out;
  708. sysfs_remove_bin_file(&ipl_subsys.kobj, &ipl_parameter_attr);
  709. out_ipl_parm:
  710. sysfs_remove_group(&ipl_subsys.kobj, &ipl_fcp_attr_group);
  711. out:
  712. return rc;
  713. }
  714. static int __init ipl_init(void)
  715. {
  716. int rc;
  717. rc = firmware_register(&ipl_subsys);
  718. if (rc)
  719. return rc;
  720. switch (ipl_info.type) {
  721. case IPL_TYPE_CCW:
  722. rc = sysfs_create_group(&ipl_subsys.kobj,
  723. &ipl_ccw_attr_group);
  724. break;
  725. case IPL_TYPE_FCP:
  726. case IPL_TYPE_FCP_DUMP:
  727. rc = ipl_register_fcp_files();
  728. break;
  729. case IPL_TYPE_NSS:
  730. rc = sysfs_create_group(&ipl_subsys.kobj,
  731. &ipl_nss_attr_group);
  732. break;
  733. default:
  734. rc = sysfs_create_group(&ipl_subsys.kobj,
  735. &ipl_unknown_attr_group);
  736. break;
  737. }
  738. if (rc)
  739. firmware_unregister(&ipl_subsys);
  740. return rc;
  741. }
  742. static void __init reipl_probe(void)
  743. {
  744. void *buffer;
  745. buffer = (void *) get_zeroed_page(GFP_KERNEL);
  746. if (!buffer)
  747. return;
  748. if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
  749. diag308_set_works = 1;
  750. free_page((unsigned long)buffer);
  751. }
  752. static int __init reipl_nss_init(void)
  753. {
  754. int rc;
  755. if (!MACHINE_IS_VM)
  756. return 0;
  757. rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_nss_attr_group);
  758. if (rc)
  759. return rc;
  760. strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
  761. reipl_capabilities |= IPL_TYPE_NSS;
  762. return 0;
  763. }
  764. static int __init reipl_ccw_init(void)
  765. {
  766. int rc;
  767. reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
  768. if (!reipl_block_ccw)
  769. return -ENOMEM;
  770. rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_ccw_attr_group);
  771. if (rc) {
  772. free_page((unsigned long)reipl_block_ccw);
  773. return rc;
  774. }
  775. reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
  776. reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
  777. reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
  778. reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
  779. /* check if read scp info worked and set loadparm */
  780. if (sclp_ipl_info.is_valid)
  781. memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
  782. &sclp_ipl_info.loadparm, LOADPARM_LEN);
  783. else
  784. /* read scp info failed: set empty loadparm (EBCDIC blanks) */
  785. memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
  786. LOADPARM_LEN);
  787. /* FIXME: check for diag308_set_works when enabling diag ccw reipl */
  788. if (!MACHINE_IS_VM)
  789. sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
  790. if (ipl_info.type == IPL_TYPE_CCW)
  791. reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
  792. reipl_capabilities |= IPL_TYPE_CCW;
  793. return 0;
  794. }
  795. static int __init reipl_fcp_init(void)
  796. {
  797. int rc;
  798. if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP))
  799. return 0;
  800. if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP))
  801. make_attrs_ro(reipl_fcp_attrs);
  802. reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
  803. if (!reipl_block_fcp)
  804. return -ENOMEM;
  805. rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_fcp_attr_group);
  806. if (rc) {
  807. free_page((unsigned long)reipl_block_fcp);
  808. return rc;
  809. }
  810. if (ipl_info.type == IPL_TYPE_FCP) {
  811. memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
  812. } else {
  813. reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
  814. reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
  815. reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
  816. reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
  817. reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
  818. }
  819. reipl_capabilities |= IPL_TYPE_FCP;
  820. return 0;
  821. }
  822. static int __init reipl_init(void)
  823. {
  824. int rc;
  825. rc = firmware_register(&reipl_subsys);
  826. if (rc)
  827. return rc;
  828. rc = subsys_create_file(&reipl_subsys, &reipl_type_attr);
  829. if (rc) {
  830. firmware_unregister(&reipl_subsys);
  831. return rc;
  832. }
  833. rc = reipl_ccw_init();
  834. if (rc)
  835. return rc;
  836. rc = reipl_fcp_init();
  837. if (rc)
  838. return rc;
  839. rc = reipl_nss_init();
  840. if (rc)
  841. return rc;
  842. rc = reipl_set_type(ipl_info.type);
  843. if (rc)
  844. return rc;
  845. return 0;
  846. }
  847. static int __init dump_ccw_init(void)
  848. {
  849. int rc;
  850. dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
  851. if (!dump_block_ccw)
  852. return -ENOMEM;
  853. rc = sysfs_create_group(&dump_subsys.kobj, &dump_ccw_attr_group);
  854. if (rc) {
  855. free_page((unsigned long)dump_block_ccw);
  856. return rc;
  857. }
  858. dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
  859. dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
  860. dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
  861. dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
  862. dump_capabilities |= DUMP_TYPE_CCW;
  863. return 0;
  864. }
  865. static int __init dump_fcp_init(void)
  866. {
  867. int rc;
  868. if (!sclp_ipl_info.has_dump)
  869. return 0; /* LDIPL DUMP is not installed */
  870. if (!diag308_set_works)
  871. return 0;
  872. dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
  873. if (!dump_block_fcp)
  874. return -ENOMEM;
  875. rc = sysfs_create_group(&dump_subsys.kobj, &dump_fcp_attr_group);
  876. if (rc) {
  877. free_page((unsigned long)dump_block_fcp);
  878. return rc;
  879. }
  880. dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
  881. dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
  882. dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
  883. dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
  884. dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
  885. dump_capabilities |= DUMP_TYPE_FCP;
  886. return 0;
  887. }
  888. #define SHUTDOWN_ON_PANIC_PRIO 0
  889. static int shutdown_on_panic_notify(struct notifier_block *self,
  890. unsigned long event, void *data)
  891. {
  892. if (on_panic_action == SHUTDOWN_DUMP)
  893. do_dump();
  894. else if (on_panic_action == SHUTDOWN_REIPL)
  895. do_reipl();
  896. return NOTIFY_OK;
  897. }
  898. static struct notifier_block shutdown_on_panic_nb = {
  899. .notifier_call = shutdown_on_panic_notify,
  900. .priority = SHUTDOWN_ON_PANIC_PRIO
  901. };
  902. static int __init dump_init(void)
  903. {
  904. int rc;
  905. rc = firmware_register(&dump_subsys);
  906. if (rc)
  907. return rc;
  908. rc = subsys_create_file(&dump_subsys, &dump_type_attr);
  909. if (rc) {
  910. firmware_unregister(&dump_subsys);
  911. return rc;
  912. }
  913. rc = dump_ccw_init();
  914. if (rc)
  915. return rc;
  916. rc = dump_fcp_init();
  917. if (rc)
  918. return rc;
  919. dump_set_type(DUMP_TYPE_NONE);
  920. return 0;
  921. }
  922. static int __init shutdown_actions_init(void)
  923. {
  924. int rc;
  925. rc = firmware_register(&shutdown_actions_subsys);
  926. if (rc)
  927. return rc;
  928. rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr);
  929. if (rc) {
  930. firmware_unregister(&shutdown_actions_subsys);
  931. return rc;
  932. }
  933. atomic_notifier_chain_register(&panic_notifier_list,
  934. &shutdown_on_panic_nb);
  935. return 0;
  936. }
  937. static int __init s390_ipl_init(void)
  938. {
  939. int rc;
  940. sclp_get_ipl_info(&sclp_ipl_info);
  941. reipl_probe();
  942. rc = ipl_init();
  943. if (rc)
  944. return rc;
  945. rc = reipl_init();
  946. if (rc)
  947. return rc;
  948. rc = dump_init();
  949. if (rc)
  950. return rc;
  951. rc = shutdown_actions_init();
  952. if (rc)
  953. return rc;
  954. return 0;
  955. }
  956. __initcall(s390_ipl_init);
  957. void __init ipl_save_parameters(void)
  958. {
  959. struct cio_iplinfo iplinfo;
  960. unsigned int *ipl_ptr;
  961. void *src, *dst;
  962. if (cio_get_iplinfo(&iplinfo))
  963. return;
  964. ipl_devno = iplinfo.devno;
  965. ipl_flags |= IPL_DEVNO_VALID;
  966. if (!iplinfo.is_qdio)
  967. return;
  968. ipl_flags |= IPL_PARMBLOCK_VALID;
  969. ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR;
  970. src = (void *)(unsigned long)*ipl_ptr;
  971. dst = (void *)IPL_PARMBLOCK_ORIGIN;
  972. memmove(dst, src, PAGE_SIZE);
  973. *ipl_ptr = IPL_PARMBLOCK_ORIGIN;
  974. }
  975. static LIST_HEAD(rcall);
  976. static DEFINE_MUTEX(rcall_mutex);
  977. void register_reset_call(struct reset_call *reset)
  978. {
  979. mutex_lock(&rcall_mutex);
  980. list_add(&reset->list, &rcall);
  981. mutex_unlock(&rcall_mutex);
  982. }
  983. EXPORT_SYMBOL_GPL(register_reset_call);
  984. void unregister_reset_call(struct reset_call *reset)
  985. {
  986. mutex_lock(&rcall_mutex);
  987. list_del(&reset->list);
  988. mutex_unlock(&rcall_mutex);
  989. }
  990. EXPORT_SYMBOL_GPL(unregister_reset_call);
  991. static void do_reset_calls(void)
  992. {
  993. struct reset_call *reset;
  994. list_for_each_entry(reset, &rcall, list)
  995. reset->fn();
  996. }
  997. u32 dump_prefix_page;
  998. void s390_reset_system(void)
  999. {
  1000. struct _lowcore *lc;
  1001. lc = (struct _lowcore *)(unsigned long) store_prefix();
  1002. /* Stack for interrupt/machine check handler */
  1003. lc->panic_stack = S390_lowcore.panic_stack;
  1004. /* Save prefix page address for dump case */
  1005. dump_prefix_page = (u32)(unsigned long) lc;
  1006. /* Disable prefixing */
  1007. set_prefix(0);
  1008. /* Disable lowcore protection */
  1009. __ctl_clear_bit(0,28);
  1010. /* Set new machine check handler */
  1011. S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
  1012. S390_lowcore.mcck_new_psw.addr =
  1013. PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
  1014. /* Set new program check handler */
  1015. S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
  1016. S390_lowcore.program_new_psw.addr =
  1017. PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
  1018. do_reset_calls();
  1019. }