ipl.c 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843
  1. /*
  2. * arch/s390/kernel/ipl.c
  3. * ipl/reipl/dump support for Linux on s390.
  4. *
  5. * Copyright IBM Corp. 2005,2007
  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 <linux/fs.h>
  17. #include <asm/ipl.h>
  18. #include <asm/smp.h>
  19. #include <asm/setup.h>
  20. #include <asm/cpcmd.h>
  21. #include <asm/cio.h>
  22. #include <asm/ebcdic.h>
  23. #include <asm/reset.h>
  24. #include <asm/sclp.h>
  25. #include <asm/checksum.h>
  26. #define IPL_PARM_BLOCK_VERSION 0
  27. #define IPL_UNKNOWN_STR "unknown"
  28. #define IPL_CCW_STR "ccw"
  29. #define IPL_FCP_STR "fcp"
  30. #define IPL_FCP_DUMP_STR "fcp_dump"
  31. #define IPL_NSS_STR "nss"
  32. #define DUMP_CCW_STR "ccw"
  33. #define DUMP_FCP_STR "fcp"
  34. #define DUMP_NONE_STR "none"
  35. /*
  36. * Four shutdown trigger types are supported:
  37. * - panic
  38. * - halt
  39. * - power off
  40. * - reipl
  41. */
  42. #define ON_PANIC_STR "on_panic"
  43. #define ON_HALT_STR "on_halt"
  44. #define ON_POFF_STR "on_poff"
  45. #define ON_REIPL_STR "on_reboot"
  46. struct shutdown_action;
  47. struct shutdown_trigger {
  48. char *name;
  49. struct shutdown_action *action;
  50. };
  51. /*
  52. * The following shutdown action types are supported:
  53. */
  54. #define SHUTDOWN_ACTION_IPL_STR "ipl"
  55. #define SHUTDOWN_ACTION_REIPL_STR "reipl"
  56. #define SHUTDOWN_ACTION_DUMP_STR "dump"
  57. #define SHUTDOWN_ACTION_VMCMD_STR "vmcmd"
  58. #define SHUTDOWN_ACTION_STOP_STR "stop"
  59. #define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl"
  60. struct shutdown_action {
  61. char *name;
  62. void (*fn) (struct shutdown_trigger *trigger);
  63. int (*init) (void);
  64. };
  65. static char *ipl_type_str(enum ipl_type type)
  66. {
  67. switch (type) {
  68. case IPL_TYPE_CCW:
  69. return IPL_CCW_STR;
  70. case IPL_TYPE_FCP:
  71. return IPL_FCP_STR;
  72. case IPL_TYPE_FCP_DUMP:
  73. return IPL_FCP_DUMP_STR;
  74. case IPL_TYPE_NSS:
  75. return IPL_NSS_STR;
  76. case IPL_TYPE_UNKNOWN:
  77. default:
  78. return IPL_UNKNOWN_STR;
  79. }
  80. }
  81. enum dump_type {
  82. DUMP_TYPE_NONE = 1,
  83. DUMP_TYPE_CCW = 2,
  84. DUMP_TYPE_FCP = 4,
  85. };
  86. static char *dump_type_str(enum dump_type type)
  87. {
  88. switch (type) {
  89. case DUMP_TYPE_NONE:
  90. return DUMP_NONE_STR;
  91. case DUMP_TYPE_CCW:
  92. return DUMP_CCW_STR;
  93. case DUMP_TYPE_FCP:
  94. return DUMP_FCP_STR;
  95. default:
  96. return NULL;
  97. }
  98. }
  99. /*
  100. * Must be in data section since the bss section
  101. * is not cleared when these are accessed.
  102. */
  103. static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
  104. u32 ipl_flags __attribute__((__section__(".data"))) = 0;
  105. enum ipl_method {
  106. REIPL_METHOD_CCW_CIO,
  107. REIPL_METHOD_CCW_DIAG,
  108. REIPL_METHOD_CCW_VM,
  109. REIPL_METHOD_FCP_RO_DIAG,
  110. REIPL_METHOD_FCP_RW_DIAG,
  111. REIPL_METHOD_FCP_RO_VM,
  112. REIPL_METHOD_FCP_DUMP,
  113. REIPL_METHOD_NSS,
  114. REIPL_METHOD_NSS_DIAG,
  115. REIPL_METHOD_DEFAULT,
  116. };
  117. enum dump_method {
  118. DUMP_METHOD_NONE,
  119. DUMP_METHOD_CCW_CIO,
  120. DUMP_METHOD_CCW_DIAG,
  121. DUMP_METHOD_CCW_VM,
  122. DUMP_METHOD_FCP_DIAG,
  123. };
  124. static int diag308_set_works = 0;
  125. static struct ipl_parameter_block ipl_block;
  126. static int reipl_capabilities = IPL_TYPE_UNKNOWN;
  127. static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
  128. static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
  129. static struct ipl_parameter_block *reipl_block_fcp;
  130. static struct ipl_parameter_block *reipl_block_ccw;
  131. static struct ipl_parameter_block *reipl_block_nss;
  132. static struct ipl_parameter_block *reipl_block_actual;
  133. static int dump_capabilities = DUMP_TYPE_NONE;
  134. static enum dump_type dump_type = DUMP_TYPE_NONE;
  135. static enum dump_method dump_method = DUMP_METHOD_NONE;
  136. static struct ipl_parameter_block *dump_block_fcp;
  137. static struct ipl_parameter_block *dump_block_ccw;
  138. static struct sclp_ipl_info sclp_ipl_info;
  139. int diag308(unsigned long subcode, void *addr)
  140. {
  141. register unsigned long _addr asm("0") = (unsigned long) addr;
  142. register unsigned long _rc asm("1") = 0;
  143. asm volatile(
  144. " diag %0,%2,0x308\n"
  145. "0:\n"
  146. EX_TABLE(0b,0b)
  147. : "+d" (_addr), "+d" (_rc)
  148. : "d" (subcode) : "cc", "memory");
  149. return _rc;
  150. }
  151. EXPORT_SYMBOL_GPL(diag308);
  152. /* SYSFS */
  153. #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
  154. static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
  155. struct kobj_attribute *attr, \
  156. char *page) \
  157. { \
  158. return sprintf(page, _format, _value); \
  159. } \
  160. static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
  161. __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
  162. #define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
  163. static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
  164. struct kobj_attribute *attr, \
  165. char *page) \
  166. { \
  167. return sprintf(page, _fmt_out, \
  168. (unsigned long long) _value); \
  169. } \
  170. static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
  171. struct kobj_attribute *attr, \
  172. const char *buf, size_t len) \
  173. { \
  174. unsigned long long value; \
  175. if (sscanf(buf, _fmt_in, &value) != 1) \
  176. return -EINVAL; \
  177. _value = value; \
  178. return len; \
  179. } \
  180. static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
  181. __ATTR(_name,(S_IRUGO | S_IWUSR), \
  182. sys_##_prefix##_##_name##_show, \
  183. sys_##_prefix##_##_name##_store);
  184. #define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
  185. static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
  186. struct kobj_attribute *attr, \
  187. char *page) \
  188. { \
  189. return sprintf(page, _fmt_out, _value); \
  190. } \
  191. static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
  192. struct kobj_attribute *attr, \
  193. const char *buf, size_t len) \
  194. { \
  195. strncpy(_value, buf, sizeof(_value) - 1); \
  196. strstrip(_value); \
  197. return len; \
  198. } \
  199. static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
  200. __ATTR(_name,(S_IRUGO | S_IWUSR), \
  201. sys_##_prefix##_##_name##_show, \
  202. sys_##_prefix##_##_name##_store);
  203. static void make_attrs_ro(struct attribute **attrs)
  204. {
  205. while (*attrs) {
  206. (*attrs)->mode = S_IRUGO;
  207. attrs++;
  208. }
  209. }
  210. /*
  211. * ipl section
  212. */
  213. static __init enum ipl_type get_ipl_type(void)
  214. {
  215. struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
  216. if (ipl_flags & IPL_NSS_VALID)
  217. return IPL_TYPE_NSS;
  218. if (!(ipl_flags & IPL_DEVNO_VALID))
  219. return IPL_TYPE_UNKNOWN;
  220. if (!(ipl_flags & IPL_PARMBLOCK_VALID))
  221. return IPL_TYPE_CCW;
  222. if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION)
  223. return IPL_TYPE_UNKNOWN;
  224. if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
  225. return IPL_TYPE_UNKNOWN;
  226. if (ipl->ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
  227. return IPL_TYPE_FCP_DUMP;
  228. return IPL_TYPE_FCP;
  229. }
  230. struct ipl_info ipl_info;
  231. EXPORT_SYMBOL_GPL(ipl_info);
  232. static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
  233. char *page)
  234. {
  235. return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
  236. }
  237. static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
  238. /* VM IPL PARM routines */
  239. static void reipl_get_ascii_vmparm(char *dest,
  240. const struct ipl_parameter_block *ipb)
  241. {
  242. int i;
  243. int len = 0;
  244. char has_lowercase = 0;
  245. if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
  246. (ipb->ipl_info.ccw.vm_parm_len > 0)) {
  247. len = ipb->ipl_info.ccw.vm_parm_len;
  248. memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
  249. /* If at least one character is lowercase, we assume mixed
  250. * case; otherwise we convert everything to lowercase.
  251. */
  252. for (i = 0; i < len; i++)
  253. if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
  254. (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
  255. (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
  256. has_lowercase = 1;
  257. break;
  258. }
  259. if (!has_lowercase)
  260. EBC_TOLOWER(dest, len);
  261. EBCASC(dest, len);
  262. }
  263. dest[len] = 0;
  264. }
  265. void get_ipl_vmparm(char *dest)
  266. {
  267. if (diag308_set_works && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
  268. reipl_get_ascii_vmparm(dest, &ipl_block);
  269. else
  270. dest[0] = 0;
  271. }
  272. static ssize_t ipl_vm_parm_show(struct kobject *kobj,
  273. struct kobj_attribute *attr, char *page)
  274. {
  275. char parm[DIAG308_VMPARM_SIZE + 1] = {};
  276. get_ipl_vmparm(parm);
  277. return sprintf(page, "%s\n", parm);
  278. }
  279. static struct kobj_attribute sys_ipl_vm_parm_attr =
  280. __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
  281. static ssize_t sys_ipl_device_show(struct kobject *kobj,
  282. struct kobj_attribute *attr, char *page)
  283. {
  284. struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
  285. switch (ipl_info.type) {
  286. case IPL_TYPE_CCW:
  287. return sprintf(page, "0.0.%04x\n", ipl_devno);
  288. case IPL_TYPE_FCP:
  289. case IPL_TYPE_FCP_DUMP:
  290. return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
  291. default:
  292. return 0;
  293. }
  294. }
  295. static struct kobj_attribute sys_ipl_device_attr =
  296. __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
  297. static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr,
  298. char *buf, loff_t off, size_t count)
  299. {
  300. return memory_read_from_buffer(buf, count, &off, IPL_PARMBLOCK_START,
  301. IPL_PARMBLOCK_SIZE);
  302. }
  303. static struct bin_attribute ipl_parameter_attr = {
  304. .attr = {
  305. .name = "binary_parameter",
  306. .mode = S_IRUGO,
  307. },
  308. .size = PAGE_SIZE,
  309. .read = &ipl_parameter_read,
  310. };
  311. static ssize_t ipl_scp_data_read(struct kobject *kobj, struct bin_attribute *attr,
  312. char *buf, loff_t off, size_t count)
  313. {
  314. unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
  315. void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
  316. return memory_read_from_buffer(buf, count, &off, scp_data, size);
  317. }
  318. static struct bin_attribute ipl_scp_data_attr = {
  319. .attr = {
  320. .name = "scp_data",
  321. .mode = S_IRUGO,
  322. },
  323. .size = PAGE_SIZE,
  324. .read = ipl_scp_data_read,
  325. };
  326. /* FCP ipl device attributes */
  327. DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long)
  328. IPL_PARMBLOCK_START->ipl_info.fcp.wwpn);
  329. DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long)
  330. IPL_PARMBLOCK_START->ipl_info.fcp.lun);
  331. DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
  332. IPL_PARMBLOCK_START->ipl_info.fcp.bootprog);
  333. DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
  334. IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
  335. static struct attribute *ipl_fcp_attrs[] = {
  336. &sys_ipl_type_attr.attr,
  337. &sys_ipl_device_attr.attr,
  338. &sys_ipl_fcp_wwpn_attr.attr,
  339. &sys_ipl_fcp_lun_attr.attr,
  340. &sys_ipl_fcp_bootprog_attr.attr,
  341. &sys_ipl_fcp_br_lba_attr.attr,
  342. NULL,
  343. };
  344. static struct attribute_group ipl_fcp_attr_group = {
  345. .attrs = ipl_fcp_attrs,
  346. };
  347. /* CCW ipl device attributes */
  348. static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
  349. struct kobj_attribute *attr, char *page)
  350. {
  351. char loadparm[LOADPARM_LEN + 1] = {};
  352. if (!sclp_ipl_info.is_valid)
  353. return sprintf(page, "#unknown#\n");
  354. memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
  355. EBCASC(loadparm, LOADPARM_LEN);
  356. strstrip(loadparm);
  357. return sprintf(page, "%s\n", loadparm);
  358. }
  359. static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
  360. __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
  361. static struct attribute *ipl_ccw_attrs_vm[] = {
  362. &sys_ipl_type_attr.attr,
  363. &sys_ipl_device_attr.attr,
  364. &sys_ipl_ccw_loadparm_attr.attr,
  365. &sys_ipl_vm_parm_attr.attr,
  366. NULL,
  367. };
  368. static struct attribute *ipl_ccw_attrs_lpar[] = {
  369. &sys_ipl_type_attr.attr,
  370. &sys_ipl_device_attr.attr,
  371. &sys_ipl_ccw_loadparm_attr.attr,
  372. NULL,
  373. };
  374. static struct attribute_group ipl_ccw_attr_group_vm = {
  375. .attrs = ipl_ccw_attrs_vm,
  376. };
  377. static struct attribute_group ipl_ccw_attr_group_lpar = {
  378. .attrs = ipl_ccw_attrs_lpar
  379. };
  380. /* NSS ipl device attributes */
  381. DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
  382. static struct attribute *ipl_nss_attrs[] = {
  383. &sys_ipl_type_attr.attr,
  384. &sys_ipl_nss_name_attr.attr,
  385. &sys_ipl_ccw_loadparm_attr.attr,
  386. &sys_ipl_vm_parm_attr.attr,
  387. NULL,
  388. };
  389. static struct attribute_group ipl_nss_attr_group = {
  390. .attrs = ipl_nss_attrs,
  391. };
  392. /* UNKNOWN ipl device attributes */
  393. static struct attribute *ipl_unknown_attrs[] = {
  394. &sys_ipl_type_attr.attr,
  395. NULL,
  396. };
  397. static struct attribute_group ipl_unknown_attr_group = {
  398. .attrs = ipl_unknown_attrs,
  399. };
  400. static struct kset *ipl_kset;
  401. static int __init ipl_register_fcp_files(void)
  402. {
  403. int rc;
  404. rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
  405. if (rc)
  406. goto out;
  407. rc = sysfs_create_bin_file(&ipl_kset->kobj, &ipl_parameter_attr);
  408. if (rc)
  409. goto out_ipl_parm;
  410. rc = sysfs_create_bin_file(&ipl_kset->kobj, &ipl_scp_data_attr);
  411. if (!rc)
  412. goto out;
  413. sysfs_remove_bin_file(&ipl_kset->kobj, &ipl_parameter_attr);
  414. out_ipl_parm:
  415. sysfs_remove_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
  416. out:
  417. return rc;
  418. }
  419. static void ipl_run(struct shutdown_trigger *trigger)
  420. {
  421. diag308(DIAG308_IPL, NULL);
  422. if (MACHINE_IS_VM)
  423. __cpcmd("IPL", NULL, 0, NULL);
  424. else if (ipl_info.type == IPL_TYPE_CCW)
  425. reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
  426. }
  427. static int __init ipl_init(void)
  428. {
  429. int rc;
  430. ipl_kset = kset_create_and_add("ipl", NULL, firmware_kobj);
  431. if (!ipl_kset) {
  432. rc = -ENOMEM;
  433. goto out;
  434. }
  435. switch (ipl_info.type) {
  436. case IPL_TYPE_CCW:
  437. if (MACHINE_IS_VM)
  438. rc = sysfs_create_group(&ipl_kset->kobj,
  439. &ipl_ccw_attr_group_vm);
  440. else
  441. rc = sysfs_create_group(&ipl_kset->kobj,
  442. &ipl_ccw_attr_group_lpar);
  443. break;
  444. case IPL_TYPE_FCP:
  445. case IPL_TYPE_FCP_DUMP:
  446. rc = ipl_register_fcp_files();
  447. break;
  448. case IPL_TYPE_NSS:
  449. rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nss_attr_group);
  450. break;
  451. default:
  452. rc = sysfs_create_group(&ipl_kset->kobj,
  453. &ipl_unknown_attr_group);
  454. break;
  455. }
  456. out:
  457. if (rc)
  458. panic("ipl_init failed: rc = %i\n", rc);
  459. return 0;
  460. }
  461. static struct shutdown_action __refdata ipl_action = {
  462. .name = SHUTDOWN_ACTION_IPL_STR,
  463. .fn = ipl_run,
  464. .init = ipl_init,
  465. };
  466. /*
  467. * reipl shutdown action: Reboot Linux on shutdown.
  468. */
  469. /* VM IPL PARM attributes */
  470. static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
  471. char *page)
  472. {
  473. char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
  474. reipl_get_ascii_vmparm(vmparm, ipb);
  475. return sprintf(page, "%s\n", vmparm);
  476. }
  477. static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb,
  478. size_t vmparm_max,
  479. const char *buf, size_t len)
  480. {
  481. int i, ip_len;
  482. /* ignore trailing newline */
  483. ip_len = len;
  484. if ((len > 0) && (buf[len - 1] == '\n'))
  485. ip_len--;
  486. if (ip_len > vmparm_max)
  487. return -EINVAL;
  488. /* parm is used to store kernel options, check for common chars */
  489. for (i = 0; i < ip_len; i++)
  490. if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i])))
  491. return -EINVAL;
  492. memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
  493. ipb->ipl_info.ccw.vm_parm_len = ip_len;
  494. if (ip_len > 0) {
  495. ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
  496. memcpy(ipb->ipl_info.ccw.vm_parm, buf, ip_len);
  497. ASCEBC(ipb->ipl_info.ccw.vm_parm, ip_len);
  498. } else {
  499. ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID;
  500. }
  501. return len;
  502. }
  503. /* NSS wrapper */
  504. static ssize_t reipl_nss_vmparm_show(struct kobject *kobj,
  505. struct kobj_attribute *attr, char *page)
  506. {
  507. return reipl_generic_vmparm_show(reipl_block_nss, page);
  508. }
  509. static ssize_t reipl_nss_vmparm_store(struct kobject *kobj,
  510. struct kobj_attribute *attr,
  511. const char *buf, size_t len)
  512. {
  513. return reipl_generic_vmparm_store(reipl_block_nss, 56, buf, len);
  514. }
  515. /* CCW wrapper */
  516. static ssize_t reipl_ccw_vmparm_show(struct kobject *kobj,
  517. struct kobj_attribute *attr, char *page)
  518. {
  519. return reipl_generic_vmparm_show(reipl_block_ccw, page);
  520. }
  521. static ssize_t reipl_ccw_vmparm_store(struct kobject *kobj,
  522. struct kobj_attribute *attr,
  523. const char *buf, size_t len)
  524. {
  525. return reipl_generic_vmparm_store(reipl_block_ccw, 64, buf, len);
  526. }
  527. static struct kobj_attribute sys_reipl_nss_vmparm_attr =
  528. __ATTR(parm, S_IRUGO | S_IWUSR, reipl_nss_vmparm_show,
  529. reipl_nss_vmparm_store);
  530. static struct kobj_attribute sys_reipl_ccw_vmparm_attr =
  531. __ATTR(parm, S_IRUGO | S_IWUSR, reipl_ccw_vmparm_show,
  532. reipl_ccw_vmparm_store);
  533. /* FCP reipl device attributes */
  534. DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
  535. reipl_block_fcp->ipl_info.fcp.wwpn);
  536. DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n",
  537. reipl_block_fcp->ipl_info.fcp.lun);
  538. DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
  539. reipl_block_fcp->ipl_info.fcp.bootprog);
  540. DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
  541. reipl_block_fcp->ipl_info.fcp.br_lba);
  542. DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
  543. reipl_block_fcp->ipl_info.fcp.devno);
  544. static struct attribute *reipl_fcp_attrs[] = {
  545. &sys_reipl_fcp_device_attr.attr,
  546. &sys_reipl_fcp_wwpn_attr.attr,
  547. &sys_reipl_fcp_lun_attr.attr,
  548. &sys_reipl_fcp_bootprog_attr.attr,
  549. &sys_reipl_fcp_br_lba_attr.attr,
  550. NULL,
  551. };
  552. static struct attribute_group reipl_fcp_attr_group = {
  553. .name = IPL_FCP_STR,
  554. .attrs = reipl_fcp_attrs,
  555. };
  556. /* CCW reipl device attributes */
  557. DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
  558. reipl_block_ccw->ipl_info.ccw.devno);
  559. static void reipl_get_ascii_loadparm(char *loadparm,
  560. struct ipl_parameter_block *ibp)
  561. {
  562. memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN);
  563. EBCASC(loadparm, LOADPARM_LEN);
  564. loadparm[LOADPARM_LEN] = 0;
  565. strstrip(loadparm);
  566. }
  567. static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
  568. char *page)
  569. {
  570. char buf[LOADPARM_LEN + 1];
  571. reipl_get_ascii_loadparm(buf, ipb);
  572. return sprintf(page, "%s\n", buf);
  573. }
  574. static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
  575. const char *buf, size_t len)
  576. {
  577. int i, lp_len;
  578. /* ignore trailing newline */
  579. lp_len = len;
  580. if ((len > 0) && (buf[len - 1] == '\n'))
  581. lp_len--;
  582. /* loadparm can have max 8 characters and must not start with a blank */
  583. if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
  584. return -EINVAL;
  585. /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
  586. for (i = 0; i < lp_len; i++) {
  587. if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
  588. (buf[i] == '.'))
  589. continue;
  590. return -EINVAL;
  591. }
  592. /* initialize loadparm with blanks */
  593. memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN);
  594. /* copy and convert to ebcdic */
  595. memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len);
  596. ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN);
  597. return len;
  598. }
  599. /* NSS wrapper */
  600. static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
  601. struct kobj_attribute *attr, char *page)
  602. {
  603. return reipl_generic_loadparm_show(reipl_block_nss, page);
  604. }
  605. static ssize_t reipl_nss_loadparm_store(struct kobject *kobj,
  606. struct kobj_attribute *attr,
  607. const char *buf, size_t len)
  608. {
  609. return reipl_generic_loadparm_store(reipl_block_nss, buf, len);
  610. }
  611. /* CCW wrapper */
  612. static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
  613. struct kobj_attribute *attr, char *page)
  614. {
  615. return reipl_generic_loadparm_show(reipl_block_ccw, page);
  616. }
  617. static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
  618. struct kobj_attribute *attr,
  619. const char *buf, size_t len)
  620. {
  621. return reipl_generic_loadparm_store(reipl_block_ccw, buf, len);
  622. }
  623. static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
  624. __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
  625. reipl_ccw_loadparm_store);
  626. static struct attribute *reipl_ccw_attrs_vm[] = {
  627. &sys_reipl_ccw_device_attr.attr,
  628. &sys_reipl_ccw_loadparm_attr.attr,
  629. &sys_reipl_ccw_vmparm_attr.attr,
  630. NULL,
  631. };
  632. static struct attribute *reipl_ccw_attrs_lpar[] = {
  633. &sys_reipl_ccw_device_attr.attr,
  634. &sys_reipl_ccw_loadparm_attr.attr,
  635. NULL,
  636. };
  637. static struct attribute_group reipl_ccw_attr_group_vm = {
  638. .name = IPL_CCW_STR,
  639. .attrs = reipl_ccw_attrs_vm,
  640. };
  641. static struct attribute_group reipl_ccw_attr_group_lpar = {
  642. .name = IPL_CCW_STR,
  643. .attrs = reipl_ccw_attrs_lpar,
  644. };
  645. /* NSS reipl device attributes */
  646. static void reipl_get_ascii_nss_name(char *dst,
  647. struct ipl_parameter_block *ipb)
  648. {
  649. memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
  650. EBCASC(dst, NSS_NAME_SIZE);
  651. dst[NSS_NAME_SIZE] = 0;
  652. }
  653. static ssize_t reipl_nss_name_show(struct kobject *kobj,
  654. struct kobj_attribute *attr, char *page)
  655. {
  656. char nss_name[NSS_NAME_SIZE + 1] = {};
  657. reipl_get_ascii_nss_name(nss_name, reipl_block_nss);
  658. return sprintf(page, "%s\n", nss_name);
  659. }
  660. static ssize_t reipl_nss_name_store(struct kobject *kobj,
  661. struct kobj_attribute *attr,
  662. const char *buf, size_t len)
  663. {
  664. int nss_len;
  665. /* ignore trailing newline */
  666. nss_len = len;
  667. if ((len > 0) && (buf[len - 1] == '\n'))
  668. nss_len--;
  669. if (nss_len > NSS_NAME_SIZE)
  670. return -EINVAL;
  671. memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE);
  672. if (nss_len > 0) {
  673. reipl_block_nss->ipl_info.ccw.vm_flags |=
  674. DIAG308_VM_FLAGS_NSS_VALID;
  675. memcpy(reipl_block_nss->ipl_info.ccw.nss_name, buf, nss_len);
  676. ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
  677. EBC_TOUPPER(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
  678. } else {
  679. reipl_block_nss->ipl_info.ccw.vm_flags &=
  680. ~DIAG308_VM_FLAGS_NSS_VALID;
  681. }
  682. return len;
  683. }
  684. static struct kobj_attribute sys_reipl_nss_name_attr =
  685. __ATTR(name, S_IRUGO | S_IWUSR, reipl_nss_name_show,
  686. reipl_nss_name_store);
  687. static struct kobj_attribute sys_reipl_nss_loadparm_attr =
  688. __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nss_loadparm_show,
  689. reipl_nss_loadparm_store);
  690. static struct attribute *reipl_nss_attrs[] = {
  691. &sys_reipl_nss_name_attr.attr,
  692. &sys_reipl_nss_loadparm_attr.attr,
  693. &sys_reipl_nss_vmparm_attr.attr,
  694. NULL,
  695. };
  696. static struct attribute_group reipl_nss_attr_group = {
  697. .name = IPL_NSS_STR,
  698. .attrs = reipl_nss_attrs,
  699. };
  700. /* reipl type */
  701. static int reipl_set_type(enum ipl_type type)
  702. {
  703. if (!(reipl_capabilities & type))
  704. return -EINVAL;
  705. switch(type) {
  706. case IPL_TYPE_CCW:
  707. if (diag308_set_works)
  708. reipl_method = REIPL_METHOD_CCW_DIAG;
  709. else if (MACHINE_IS_VM)
  710. reipl_method = REIPL_METHOD_CCW_VM;
  711. else
  712. reipl_method = REIPL_METHOD_CCW_CIO;
  713. reipl_block_actual = reipl_block_ccw;
  714. break;
  715. case IPL_TYPE_FCP:
  716. if (diag308_set_works)
  717. reipl_method = REIPL_METHOD_FCP_RW_DIAG;
  718. else if (MACHINE_IS_VM)
  719. reipl_method = REIPL_METHOD_FCP_RO_VM;
  720. else
  721. reipl_method = REIPL_METHOD_FCP_RO_DIAG;
  722. reipl_block_actual = reipl_block_fcp;
  723. break;
  724. case IPL_TYPE_FCP_DUMP:
  725. reipl_method = REIPL_METHOD_FCP_DUMP;
  726. break;
  727. case IPL_TYPE_NSS:
  728. if (diag308_set_works)
  729. reipl_method = REIPL_METHOD_NSS_DIAG;
  730. else
  731. reipl_method = REIPL_METHOD_NSS;
  732. reipl_block_actual = reipl_block_nss;
  733. break;
  734. case IPL_TYPE_UNKNOWN:
  735. reipl_method = REIPL_METHOD_DEFAULT;
  736. break;
  737. default:
  738. BUG();
  739. }
  740. reipl_type = type;
  741. return 0;
  742. }
  743. static ssize_t reipl_type_show(struct kobject *kobj,
  744. struct kobj_attribute *attr, char *page)
  745. {
  746. return sprintf(page, "%s\n", ipl_type_str(reipl_type));
  747. }
  748. static ssize_t reipl_type_store(struct kobject *kobj,
  749. struct kobj_attribute *attr,
  750. const char *buf, size_t len)
  751. {
  752. int rc = -EINVAL;
  753. if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
  754. rc = reipl_set_type(IPL_TYPE_CCW);
  755. else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
  756. rc = reipl_set_type(IPL_TYPE_FCP);
  757. else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
  758. rc = reipl_set_type(IPL_TYPE_NSS);
  759. return (rc != 0) ? rc : len;
  760. }
  761. static struct kobj_attribute reipl_type_attr =
  762. __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
  763. static struct kset *reipl_kset;
  764. static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
  765. const enum ipl_method m)
  766. {
  767. char loadparm[LOADPARM_LEN + 1] = {};
  768. char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
  769. char nss_name[NSS_NAME_SIZE + 1] = {};
  770. size_t pos = 0;
  771. reipl_get_ascii_loadparm(loadparm, ipb);
  772. reipl_get_ascii_nss_name(nss_name, ipb);
  773. reipl_get_ascii_vmparm(vmparm, ipb);
  774. switch (m) {
  775. case REIPL_METHOD_CCW_VM:
  776. pos = sprintf(dst, "IPL %X CLEAR", ipb->ipl_info.ccw.devno);
  777. break;
  778. case REIPL_METHOD_NSS:
  779. pos = sprintf(dst, "IPL %s", nss_name);
  780. break;
  781. default:
  782. break;
  783. }
  784. if (strlen(loadparm) > 0)
  785. pos += sprintf(dst + pos, " LOADPARM '%s'", loadparm);
  786. if (strlen(vmparm) > 0)
  787. sprintf(dst + pos, " PARM %s", vmparm);
  788. }
  789. static void reipl_run(struct shutdown_trigger *trigger)
  790. {
  791. struct ccw_dev_id devid;
  792. static char buf[128];
  793. switch (reipl_method) {
  794. case REIPL_METHOD_CCW_CIO:
  795. devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
  796. devid.ssid = 0;
  797. reipl_ccw_dev(&devid);
  798. break;
  799. case REIPL_METHOD_CCW_VM:
  800. get_ipl_string(buf, reipl_block_ccw, REIPL_METHOD_CCW_VM);
  801. __cpcmd(buf, NULL, 0, NULL);
  802. break;
  803. case REIPL_METHOD_CCW_DIAG:
  804. diag308(DIAG308_SET, reipl_block_ccw);
  805. diag308(DIAG308_IPL, NULL);
  806. break;
  807. case REIPL_METHOD_FCP_RW_DIAG:
  808. diag308(DIAG308_SET, reipl_block_fcp);
  809. diag308(DIAG308_IPL, NULL);
  810. break;
  811. case REIPL_METHOD_FCP_RO_DIAG:
  812. diag308(DIAG308_IPL, NULL);
  813. break;
  814. case REIPL_METHOD_FCP_RO_VM:
  815. __cpcmd("IPL", NULL, 0, NULL);
  816. break;
  817. case REIPL_METHOD_NSS_DIAG:
  818. diag308(DIAG308_SET, reipl_block_nss);
  819. diag308(DIAG308_IPL, NULL);
  820. break;
  821. case REIPL_METHOD_NSS:
  822. get_ipl_string(buf, reipl_block_nss, REIPL_METHOD_NSS);
  823. __cpcmd(buf, NULL, 0, NULL);
  824. break;
  825. case REIPL_METHOD_DEFAULT:
  826. if (MACHINE_IS_VM)
  827. __cpcmd("IPL", NULL, 0, NULL);
  828. diag308(DIAG308_IPL, NULL);
  829. break;
  830. case REIPL_METHOD_FCP_DUMP:
  831. break;
  832. }
  833. disabled_wait((unsigned long) __builtin_return_address(0));
  834. }
  835. static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
  836. {
  837. ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
  838. ipb->hdr.version = IPL_PARM_BLOCK_VERSION;
  839. ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
  840. ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW;
  841. }
  842. static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
  843. {
  844. /* LOADPARM */
  845. /* check if read scp info worked and set loadparm */
  846. if (sclp_ipl_info.is_valid)
  847. memcpy(ipb->ipl_info.ccw.load_parm,
  848. &sclp_ipl_info.loadparm, LOADPARM_LEN);
  849. else
  850. /* read scp info failed: set empty loadparm (EBCDIC blanks) */
  851. memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN);
  852. ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
  853. /* VM PARM */
  854. if (MACHINE_IS_VM && diag308_set_works &&
  855. (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) {
  856. ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
  857. ipb->ipl_info.ccw.vm_parm_len =
  858. ipl_block.ipl_info.ccw.vm_parm_len;
  859. memcpy(ipb->ipl_info.ccw.vm_parm,
  860. ipl_block.ipl_info.ccw.vm_parm, DIAG308_VMPARM_SIZE);
  861. }
  862. }
  863. static int __init reipl_nss_init(void)
  864. {
  865. int rc;
  866. if (!MACHINE_IS_VM)
  867. return 0;
  868. reipl_block_nss = (void *) get_zeroed_page(GFP_KERNEL);
  869. if (!reipl_block_nss)
  870. return -ENOMEM;
  871. if (!diag308_set_works)
  872. sys_reipl_nss_vmparm_attr.attr.mode = S_IRUGO;
  873. rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
  874. if (rc)
  875. return rc;
  876. reipl_block_ccw_init(reipl_block_nss);
  877. if (ipl_info.type == IPL_TYPE_NSS) {
  878. memset(reipl_block_nss->ipl_info.ccw.nss_name,
  879. ' ', NSS_NAME_SIZE);
  880. memcpy(reipl_block_nss->ipl_info.ccw.nss_name,
  881. kernel_nss_name, strlen(kernel_nss_name));
  882. ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
  883. reipl_block_nss->ipl_info.ccw.vm_flags |=
  884. DIAG308_VM_FLAGS_NSS_VALID;
  885. reipl_block_ccw_fill_parms(reipl_block_nss);
  886. }
  887. reipl_capabilities |= IPL_TYPE_NSS;
  888. return 0;
  889. }
  890. static int __init reipl_ccw_init(void)
  891. {
  892. int rc;
  893. reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
  894. if (!reipl_block_ccw)
  895. return -ENOMEM;
  896. if (MACHINE_IS_VM) {
  897. if (!diag308_set_works)
  898. sys_reipl_ccw_vmparm_attr.attr.mode = S_IRUGO;
  899. rc = sysfs_create_group(&reipl_kset->kobj,
  900. &reipl_ccw_attr_group_vm);
  901. } else {
  902. if(!diag308_set_works)
  903. sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
  904. rc = sysfs_create_group(&reipl_kset->kobj,
  905. &reipl_ccw_attr_group_lpar);
  906. }
  907. if (rc)
  908. return rc;
  909. reipl_block_ccw_init(reipl_block_ccw);
  910. if (ipl_info.type == IPL_TYPE_CCW) {
  911. reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
  912. reipl_block_ccw_fill_parms(reipl_block_ccw);
  913. }
  914. reipl_capabilities |= IPL_TYPE_CCW;
  915. return 0;
  916. }
  917. static int __init reipl_fcp_init(void)
  918. {
  919. int rc;
  920. if (!diag308_set_works) {
  921. if (ipl_info.type == IPL_TYPE_FCP)
  922. make_attrs_ro(reipl_fcp_attrs);
  923. else
  924. return 0;
  925. }
  926. reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
  927. if (!reipl_block_fcp)
  928. return -ENOMEM;
  929. rc = sysfs_create_group(&reipl_kset->kobj, &reipl_fcp_attr_group);
  930. if (rc) {
  931. free_page((unsigned long)reipl_block_fcp);
  932. return rc;
  933. }
  934. if (ipl_info.type == IPL_TYPE_FCP) {
  935. memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
  936. } else {
  937. reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
  938. reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
  939. reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
  940. reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
  941. reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
  942. }
  943. reipl_capabilities |= IPL_TYPE_FCP;
  944. return 0;
  945. }
  946. static int __init reipl_init(void)
  947. {
  948. int rc;
  949. reipl_kset = kset_create_and_add("reipl", NULL, firmware_kobj);
  950. if (!reipl_kset)
  951. return -ENOMEM;
  952. rc = sysfs_create_file(&reipl_kset->kobj, &reipl_type_attr.attr);
  953. if (rc) {
  954. kset_unregister(reipl_kset);
  955. return rc;
  956. }
  957. rc = reipl_ccw_init();
  958. if (rc)
  959. return rc;
  960. rc = reipl_fcp_init();
  961. if (rc)
  962. return rc;
  963. rc = reipl_nss_init();
  964. if (rc)
  965. return rc;
  966. rc = reipl_set_type(ipl_info.type);
  967. if (rc)
  968. return rc;
  969. return 0;
  970. }
  971. static struct shutdown_action __refdata reipl_action = {
  972. .name = SHUTDOWN_ACTION_REIPL_STR,
  973. .fn = reipl_run,
  974. .init = reipl_init,
  975. };
  976. /*
  977. * dump shutdown action: Dump Linux on shutdown.
  978. */
  979. /* FCP dump device attributes */
  980. DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
  981. dump_block_fcp->ipl_info.fcp.wwpn);
  982. DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
  983. dump_block_fcp->ipl_info.fcp.lun);
  984. DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
  985. dump_block_fcp->ipl_info.fcp.bootprog);
  986. DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
  987. dump_block_fcp->ipl_info.fcp.br_lba);
  988. DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
  989. dump_block_fcp->ipl_info.fcp.devno);
  990. static struct attribute *dump_fcp_attrs[] = {
  991. &sys_dump_fcp_device_attr.attr,
  992. &sys_dump_fcp_wwpn_attr.attr,
  993. &sys_dump_fcp_lun_attr.attr,
  994. &sys_dump_fcp_bootprog_attr.attr,
  995. &sys_dump_fcp_br_lba_attr.attr,
  996. NULL,
  997. };
  998. static struct attribute_group dump_fcp_attr_group = {
  999. .name = IPL_FCP_STR,
  1000. .attrs = dump_fcp_attrs,
  1001. };
  1002. /* CCW dump device attributes */
  1003. DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
  1004. dump_block_ccw->ipl_info.ccw.devno);
  1005. static struct attribute *dump_ccw_attrs[] = {
  1006. &sys_dump_ccw_device_attr.attr,
  1007. NULL,
  1008. };
  1009. static struct attribute_group dump_ccw_attr_group = {
  1010. .name = IPL_CCW_STR,
  1011. .attrs = dump_ccw_attrs,
  1012. };
  1013. /* dump type */
  1014. static int dump_set_type(enum dump_type type)
  1015. {
  1016. if (!(dump_capabilities & type))
  1017. return -EINVAL;
  1018. switch (type) {
  1019. case DUMP_TYPE_CCW:
  1020. if (diag308_set_works)
  1021. dump_method = DUMP_METHOD_CCW_DIAG;
  1022. else if (MACHINE_IS_VM)
  1023. dump_method = DUMP_METHOD_CCW_VM;
  1024. else
  1025. dump_method = DUMP_METHOD_CCW_CIO;
  1026. break;
  1027. case DUMP_TYPE_FCP:
  1028. dump_method = DUMP_METHOD_FCP_DIAG;
  1029. break;
  1030. default:
  1031. dump_method = DUMP_METHOD_NONE;
  1032. }
  1033. dump_type = type;
  1034. return 0;
  1035. }
  1036. static ssize_t dump_type_show(struct kobject *kobj,
  1037. struct kobj_attribute *attr, char *page)
  1038. {
  1039. return sprintf(page, "%s\n", dump_type_str(dump_type));
  1040. }
  1041. static ssize_t dump_type_store(struct kobject *kobj,
  1042. struct kobj_attribute *attr,
  1043. const char *buf, size_t len)
  1044. {
  1045. int rc = -EINVAL;
  1046. if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
  1047. rc = dump_set_type(DUMP_TYPE_NONE);
  1048. else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
  1049. rc = dump_set_type(DUMP_TYPE_CCW);
  1050. else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
  1051. rc = dump_set_type(DUMP_TYPE_FCP);
  1052. return (rc != 0) ? rc : len;
  1053. }
  1054. static struct kobj_attribute dump_type_attr =
  1055. __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
  1056. static struct kset *dump_kset;
  1057. static void dump_run(struct shutdown_trigger *trigger)
  1058. {
  1059. struct ccw_dev_id devid;
  1060. static char buf[100];
  1061. switch (dump_method) {
  1062. case DUMP_METHOD_CCW_CIO:
  1063. smp_send_stop();
  1064. devid.devno = dump_block_ccw->ipl_info.ccw.devno;
  1065. devid.ssid = 0;
  1066. reipl_ccw_dev(&devid);
  1067. break;
  1068. case DUMP_METHOD_CCW_VM:
  1069. smp_send_stop();
  1070. sprintf(buf, "STORE STATUS");
  1071. __cpcmd(buf, NULL, 0, NULL);
  1072. sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
  1073. __cpcmd(buf, NULL, 0, NULL);
  1074. break;
  1075. case DUMP_METHOD_CCW_DIAG:
  1076. diag308(DIAG308_SET, dump_block_ccw);
  1077. diag308(DIAG308_DUMP, NULL);
  1078. break;
  1079. case DUMP_METHOD_FCP_DIAG:
  1080. diag308(DIAG308_SET, dump_block_fcp);
  1081. diag308(DIAG308_DUMP, NULL);
  1082. break;
  1083. case DUMP_METHOD_NONE:
  1084. return;
  1085. }
  1086. printk(KERN_EMERG "Dump failed!\n");
  1087. }
  1088. static int __init dump_ccw_init(void)
  1089. {
  1090. int rc;
  1091. dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
  1092. if (!dump_block_ccw)
  1093. return -ENOMEM;
  1094. rc = sysfs_create_group(&dump_kset->kobj, &dump_ccw_attr_group);
  1095. if (rc) {
  1096. free_page((unsigned long)dump_block_ccw);
  1097. return rc;
  1098. }
  1099. dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
  1100. dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
  1101. dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
  1102. dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
  1103. dump_capabilities |= DUMP_TYPE_CCW;
  1104. return 0;
  1105. }
  1106. static int __init dump_fcp_init(void)
  1107. {
  1108. int rc;
  1109. if (!sclp_ipl_info.has_dump)
  1110. return 0; /* LDIPL DUMP is not installed */
  1111. if (!diag308_set_works)
  1112. return 0;
  1113. dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
  1114. if (!dump_block_fcp)
  1115. return -ENOMEM;
  1116. rc = sysfs_create_group(&dump_kset->kobj, &dump_fcp_attr_group);
  1117. if (rc) {
  1118. free_page((unsigned long)dump_block_fcp);
  1119. return rc;
  1120. }
  1121. dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
  1122. dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
  1123. dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
  1124. dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
  1125. dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
  1126. dump_capabilities |= DUMP_TYPE_FCP;
  1127. return 0;
  1128. }
  1129. static int __init dump_init(void)
  1130. {
  1131. int rc;
  1132. dump_kset = kset_create_and_add("dump", NULL, firmware_kobj);
  1133. if (!dump_kset)
  1134. return -ENOMEM;
  1135. rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr);
  1136. if (rc) {
  1137. kset_unregister(dump_kset);
  1138. return rc;
  1139. }
  1140. rc = dump_ccw_init();
  1141. if (rc)
  1142. return rc;
  1143. rc = dump_fcp_init();
  1144. if (rc)
  1145. return rc;
  1146. dump_set_type(DUMP_TYPE_NONE);
  1147. return 0;
  1148. }
  1149. static struct shutdown_action __refdata dump_action = {
  1150. .name = SHUTDOWN_ACTION_DUMP_STR,
  1151. .fn = dump_run,
  1152. .init = dump_init,
  1153. };
  1154. static void dump_reipl_run(struct shutdown_trigger *trigger)
  1155. {
  1156. preempt_disable();
  1157. /*
  1158. * Bypass dynamic address translation (DAT) when storing IPL parameter
  1159. * information block address and checksum into the prefix area
  1160. * (corresponding to absolute addresses 0-8191).
  1161. * When enhanced DAT applies and the STE format control in one,
  1162. * the absolute address is formed without prefixing. In this case a
  1163. * normal store (stg/st) into the prefix area would no more match to
  1164. * absolute addresses 0-8191.
  1165. */
  1166. #ifdef CONFIG_64BIT
  1167. asm volatile("sturg %0,%1"
  1168. :: "a" ((unsigned long) reipl_block_actual),
  1169. "a" (&lowcore_ptr[smp_processor_id()]->ipib));
  1170. #else
  1171. asm volatile("stura %0,%1"
  1172. :: "a" ((unsigned long) reipl_block_actual),
  1173. "a" (&lowcore_ptr[smp_processor_id()]->ipib));
  1174. #endif
  1175. asm volatile("stura %0,%1"
  1176. :: "a" (csum_partial(reipl_block_actual,
  1177. reipl_block_actual->hdr.len, 0)),
  1178. "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum));
  1179. preempt_enable();
  1180. dump_run(trigger);
  1181. }
  1182. static int __init dump_reipl_init(void)
  1183. {
  1184. if (!diag308_set_works)
  1185. return -EOPNOTSUPP;
  1186. else
  1187. return 0;
  1188. }
  1189. static struct shutdown_action __refdata dump_reipl_action = {
  1190. .name = SHUTDOWN_ACTION_DUMP_REIPL_STR,
  1191. .fn = dump_reipl_run,
  1192. .init = dump_reipl_init,
  1193. };
  1194. /*
  1195. * vmcmd shutdown action: Trigger vm command on shutdown.
  1196. */
  1197. static char vmcmd_on_reboot[128];
  1198. static char vmcmd_on_panic[128];
  1199. static char vmcmd_on_halt[128];
  1200. static char vmcmd_on_poff[128];
  1201. DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot);
  1202. DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic);
  1203. DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt);
  1204. DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff);
  1205. static struct attribute *vmcmd_attrs[] = {
  1206. &sys_vmcmd_on_reboot_attr.attr,
  1207. &sys_vmcmd_on_panic_attr.attr,
  1208. &sys_vmcmd_on_halt_attr.attr,
  1209. &sys_vmcmd_on_poff_attr.attr,
  1210. NULL,
  1211. };
  1212. static struct attribute_group vmcmd_attr_group = {
  1213. .attrs = vmcmd_attrs,
  1214. };
  1215. static struct kset *vmcmd_kset;
  1216. static void vmcmd_run(struct shutdown_trigger *trigger)
  1217. {
  1218. char *cmd, *next_cmd;
  1219. if (strcmp(trigger->name, ON_REIPL_STR) == 0)
  1220. cmd = vmcmd_on_reboot;
  1221. else if (strcmp(trigger->name, ON_PANIC_STR) == 0)
  1222. cmd = vmcmd_on_panic;
  1223. else if (strcmp(trigger->name, ON_HALT_STR) == 0)
  1224. cmd = vmcmd_on_halt;
  1225. else if (strcmp(trigger->name, ON_POFF_STR) == 0)
  1226. cmd = vmcmd_on_poff;
  1227. else
  1228. return;
  1229. if (strlen(cmd) == 0)
  1230. return;
  1231. do {
  1232. next_cmd = strchr(cmd, '\n');
  1233. if (next_cmd) {
  1234. next_cmd[0] = 0;
  1235. next_cmd += 1;
  1236. }
  1237. __cpcmd(cmd, NULL, 0, NULL);
  1238. cmd = next_cmd;
  1239. } while (cmd != NULL);
  1240. }
  1241. static int vmcmd_init(void)
  1242. {
  1243. if (!MACHINE_IS_VM)
  1244. return -ENOTSUPP;
  1245. vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj);
  1246. if (!vmcmd_kset)
  1247. return -ENOMEM;
  1248. return sysfs_create_group(&vmcmd_kset->kobj, &vmcmd_attr_group);
  1249. }
  1250. static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
  1251. vmcmd_run, vmcmd_init};
  1252. /*
  1253. * stop shutdown action: Stop Linux on shutdown.
  1254. */
  1255. static void stop_run(struct shutdown_trigger *trigger)
  1256. {
  1257. if (strcmp(trigger->name, ON_PANIC_STR) == 0)
  1258. disabled_wait((unsigned long) __builtin_return_address(0));
  1259. else {
  1260. signal_processor(smp_processor_id(), sigp_stop);
  1261. for (;;);
  1262. }
  1263. }
  1264. static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
  1265. stop_run, NULL};
  1266. /* action list */
  1267. static struct shutdown_action *shutdown_actions_list[] = {
  1268. &ipl_action, &reipl_action, &dump_reipl_action, &dump_action,
  1269. &vmcmd_action, &stop_action};
  1270. #define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
  1271. /*
  1272. * Trigger section
  1273. */
  1274. static struct kset *shutdown_actions_kset;
  1275. static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
  1276. size_t len)
  1277. {
  1278. int i;
  1279. for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
  1280. if (!shutdown_actions_list[i])
  1281. continue;
  1282. if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
  1283. trigger->action = shutdown_actions_list[i];
  1284. return len;
  1285. }
  1286. }
  1287. return -EINVAL;
  1288. }
  1289. /* on reipl */
  1290. static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR,
  1291. &reipl_action};
  1292. static ssize_t on_reboot_show(struct kobject *kobj,
  1293. struct kobj_attribute *attr, char *page)
  1294. {
  1295. return sprintf(page, "%s\n", on_reboot_trigger.action->name);
  1296. }
  1297. static ssize_t on_reboot_store(struct kobject *kobj,
  1298. struct kobj_attribute *attr,
  1299. const char *buf, size_t len)
  1300. {
  1301. return set_trigger(buf, &on_reboot_trigger, len);
  1302. }
  1303. static struct kobj_attribute on_reboot_attr =
  1304. __ATTR(on_reboot, 0644, on_reboot_show, on_reboot_store);
  1305. static void do_machine_restart(char *__unused)
  1306. {
  1307. smp_send_stop();
  1308. on_reboot_trigger.action->fn(&on_reboot_trigger);
  1309. reipl_run(NULL);
  1310. }
  1311. void (*_machine_restart)(char *command) = do_machine_restart;
  1312. /* on panic */
  1313. static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action};
  1314. static ssize_t on_panic_show(struct kobject *kobj,
  1315. struct kobj_attribute *attr, char *page)
  1316. {
  1317. return sprintf(page, "%s\n", on_panic_trigger.action->name);
  1318. }
  1319. static ssize_t on_panic_store(struct kobject *kobj,
  1320. struct kobj_attribute *attr,
  1321. const char *buf, size_t len)
  1322. {
  1323. return set_trigger(buf, &on_panic_trigger, len);
  1324. }
  1325. static struct kobj_attribute on_panic_attr =
  1326. __ATTR(on_panic, 0644, on_panic_show, on_panic_store);
  1327. static void do_panic(void)
  1328. {
  1329. on_panic_trigger.action->fn(&on_panic_trigger);
  1330. stop_run(&on_panic_trigger);
  1331. }
  1332. /* on halt */
  1333. static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
  1334. static ssize_t on_halt_show(struct kobject *kobj,
  1335. struct kobj_attribute *attr, char *page)
  1336. {
  1337. return sprintf(page, "%s\n", on_halt_trigger.action->name);
  1338. }
  1339. static ssize_t on_halt_store(struct kobject *kobj,
  1340. struct kobj_attribute *attr,
  1341. const char *buf, size_t len)
  1342. {
  1343. return set_trigger(buf, &on_halt_trigger, len);
  1344. }
  1345. static struct kobj_attribute on_halt_attr =
  1346. __ATTR(on_halt, 0644, on_halt_show, on_halt_store);
  1347. static void do_machine_halt(void)
  1348. {
  1349. smp_send_stop();
  1350. on_halt_trigger.action->fn(&on_halt_trigger);
  1351. stop_run(&on_halt_trigger);
  1352. }
  1353. void (*_machine_halt)(void) = do_machine_halt;
  1354. /* on power off */
  1355. static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action};
  1356. static ssize_t on_poff_show(struct kobject *kobj,
  1357. struct kobj_attribute *attr, char *page)
  1358. {
  1359. return sprintf(page, "%s\n", on_poff_trigger.action->name);
  1360. }
  1361. static ssize_t on_poff_store(struct kobject *kobj,
  1362. struct kobj_attribute *attr,
  1363. const char *buf, size_t len)
  1364. {
  1365. return set_trigger(buf, &on_poff_trigger, len);
  1366. }
  1367. static struct kobj_attribute on_poff_attr =
  1368. __ATTR(on_poff, 0644, on_poff_show, on_poff_store);
  1369. static void do_machine_power_off(void)
  1370. {
  1371. smp_send_stop();
  1372. on_poff_trigger.action->fn(&on_poff_trigger);
  1373. stop_run(&on_poff_trigger);
  1374. }
  1375. void (*_machine_power_off)(void) = do_machine_power_off;
  1376. static void __init shutdown_triggers_init(void)
  1377. {
  1378. shutdown_actions_kset = kset_create_and_add("shutdown_actions", NULL,
  1379. firmware_kobj);
  1380. if (!shutdown_actions_kset)
  1381. goto fail;
  1382. if (sysfs_create_file(&shutdown_actions_kset->kobj,
  1383. &on_reboot_attr.attr))
  1384. goto fail;
  1385. if (sysfs_create_file(&shutdown_actions_kset->kobj,
  1386. &on_panic_attr.attr))
  1387. goto fail;
  1388. if (sysfs_create_file(&shutdown_actions_kset->kobj,
  1389. &on_halt_attr.attr))
  1390. goto fail;
  1391. if (sysfs_create_file(&shutdown_actions_kset->kobj,
  1392. &on_poff_attr.attr))
  1393. goto fail;
  1394. return;
  1395. fail:
  1396. panic("shutdown_triggers_init failed\n");
  1397. }
  1398. static void __init shutdown_actions_init(void)
  1399. {
  1400. int i;
  1401. for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
  1402. if (!shutdown_actions_list[i]->init)
  1403. continue;
  1404. if (shutdown_actions_list[i]->init())
  1405. shutdown_actions_list[i] = NULL;
  1406. }
  1407. }
  1408. static int __init s390_ipl_init(void)
  1409. {
  1410. sclp_get_ipl_info(&sclp_ipl_info);
  1411. shutdown_actions_init();
  1412. shutdown_triggers_init();
  1413. return 0;
  1414. }
  1415. __initcall(s390_ipl_init);
  1416. static void __init strncpy_skip_quote(char *dst, char *src, int n)
  1417. {
  1418. int sx, dx;
  1419. dx = 0;
  1420. for (sx = 0; src[sx] != 0; sx++) {
  1421. if (src[sx] == '"')
  1422. continue;
  1423. dst[dx++] = src[sx];
  1424. if (dx >= n)
  1425. break;
  1426. }
  1427. }
  1428. static int __init vmcmd_on_reboot_setup(char *str)
  1429. {
  1430. if (!MACHINE_IS_VM)
  1431. return 1;
  1432. strncpy_skip_quote(vmcmd_on_reboot, str, 127);
  1433. vmcmd_on_reboot[127] = 0;
  1434. on_reboot_trigger.action = &vmcmd_action;
  1435. return 1;
  1436. }
  1437. __setup("vmreboot=", vmcmd_on_reboot_setup);
  1438. static int __init vmcmd_on_panic_setup(char *str)
  1439. {
  1440. if (!MACHINE_IS_VM)
  1441. return 1;
  1442. strncpy_skip_quote(vmcmd_on_panic, str, 127);
  1443. vmcmd_on_panic[127] = 0;
  1444. on_panic_trigger.action = &vmcmd_action;
  1445. return 1;
  1446. }
  1447. __setup("vmpanic=", vmcmd_on_panic_setup);
  1448. static int __init vmcmd_on_halt_setup(char *str)
  1449. {
  1450. if (!MACHINE_IS_VM)
  1451. return 1;
  1452. strncpy_skip_quote(vmcmd_on_halt, str, 127);
  1453. vmcmd_on_halt[127] = 0;
  1454. on_halt_trigger.action = &vmcmd_action;
  1455. return 1;
  1456. }
  1457. __setup("vmhalt=", vmcmd_on_halt_setup);
  1458. static int __init vmcmd_on_poff_setup(char *str)
  1459. {
  1460. if (!MACHINE_IS_VM)
  1461. return 1;
  1462. strncpy_skip_quote(vmcmd_on_poff, str, 127);
  1463. vmcmd_on_poff[127] = 0;
  1464. on_poff_trigger.action = &vmcmd_action;
  1465. return 1;
  1466. }
  1467. __setup("vmpoff=", vmcmd_on_poff_setup);
  1468. static int on_panic_notify(struct notifier_block *self,
  1469. unsigned long event, void *data)
  1470. {
  1471. do_panic();
  1472. return NOTIFY_OK;
  1473. }
  1474. static struct notifier_block on_panic_nb = {
  1475. .notifier_call = on_panic_notify,
  1476. .priority = INT_MIN,
  1477. };
  1478. void __init setup_ipl(void)
  1479. {
  1480. ipl_info.type = get_ipl_type();
  1481. switch (ipl_info.type) {
  1482. case IPL_TYPE_CCW:
  1483. ipl_info.data.ccw.dev_id.devno = ipl_devno;
  1484. ipl_info.data.ccw.dev_id.ssid = 0;
  1485. break;
  1486. case IPL_TYPE_FCP:
  1487. case IPL_TYPE_FCP_DUMP:
  1488. ipl_info.data.fcp.dev_id.devno =
  1489. IPL_PARMBLOCK_START->ipl_info.fcp.devno;
  1490. ipl_info.data.fcp.dev_id.ssid = 0;
  1491. ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
  1492. ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
  1493. break;
  1494. case IPL_TYPE_NSS:
  1495. strncpy(ipl_info.data.nss.name, kernel_nss_name,
  1496. sizeof(ipl_info.data.nss.name));
  1497. break;
  1498. case IPL_TYPE_UNKNOWN:
  1499. /* We have no info to copy */
  1500. break;
  1501. }
  1502. atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
  1503. }
  1504. void __init ipl_update_parameters(void)
  1505. {
  1506. int rc;
  1507. rc = diag308(DIAG308_STORE, &ipl_block);
  1508. if ((rc == DIAG308_RC_OK) || (rc == DIAG308_RC_NOCONFIG))
  1509. diag308_set_works = 1;
  1510. }
  1511. void __init ipl_save_parameters(void)
  1512. {
  1513. struct cio_iplinfo iplinfo;
  1514. unsigned int *ipl_ptr;
  1515. void *src, *dst;
  1516. if (cio_get_iplinfo(&iplinfo))
  1517. return;
  1518. ipl_devno = iplinfo.devno;
  1519. ipl_flags |= IPL_DEVNO_VALID;
  1520. if (!iplinfo.is_qdio)
  1521. return;
  1522. ipl_flags |= IPL_PARMBLOCK_VALID;
  1523. ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR;
  1524. src = (void *)(unsigned long)*ipl_ptr;
  1525. dst = (void *)IPL_PARMBLOCK_ORIGIN;
  1526. memmove(dst, src, PAGE_SIZE);
  1527. *ipl_ptr = IPL_PARMBLOCK_ORIGIN;
  1528. }
  1529. static LIST_HEAD(rcall);
  1530. static DEFINE_MUTEX(rcall_mutex);
  1531. void register_reset_call(struct reset_call *reset)
  1532. {
  1533. mutex_lock(&rcall_mutex);
  1534. list_add(&reset->list, &rcall);
  1535. mutex_unlock(&rcall_mutex);
  1536. }
  1537. EXPORT_SYMBOL_GPL(register_reset_call);
  1538. void unregister_reset_call(struct reset_call *reset)
  1539. {
  1540. mutex_lock(&rcall_mutex);
  1541. list_del(&reset->list);
  1542. mutex_unlock(&rcall_mutex);
  1543. }
  1544. EXPORT_SYMBOL_GPL(unregister_reset_call);
  1545. static void do_reset_calls(void)
  1546. {
  1547. struct reset_call *reset;
  1548. list_for_each_entry(reset, &rcall, list)
  1549. reset->fn();
  1550. }
  1551. u32 dump_prefix_page;
  1552. void s390_reset_system(void)
  1553. {
  1554. struct _lowcore *lc;
  1555. lc = (struct _lowcore *)(unsigned long) store_prefix();
  1556. /* Stack for interrupt/machine check handler */
  1557. lc->panic_stack = S390_lowcore.panic_stack;
  1558. /* Save prefix page address for dump case */
  1559. dump_prefix_page = (u32)(unsigned long) lc;
  1560. /* Disable prefixing */
  1561. set_prefix(0);
  1562. /* Disable lowcore protection */
  1563. __ctl_clear_bit(0,28);
  1564. /* Set new machine check handler */
  1565. S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
  1566. S390_lowcore.mcck_new_psw.addr =
  1567. PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
  1568. /* Set new program check handler */
  1569. S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
  1570. S390_lowcore.program_new_psw.addr =
  1571. PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
  1572. do_reset_calls();
  1573. }