aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ipl.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r--arch/s390/kernel/ipl.c74
1 files changed, 61 insertions, 13 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 2dcf590faba6..6f3711a0eaaa 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -23,7 +23,7 @@
23#include <asm/ebcdic.h> 23#include <asm/ebcdic.h>
24#include <asm/reset.h> 24#include <asm/reset.h>
25#include <asm/sclp.h> 25#include <asm/sclp.h>
26#include <asm/setup.h> 26#include <asm/checksum.h>
27 27
28#define IPL_PARM_BLOCK_VERSION 0 28#define IPL_PARM_BLOCK_VERSION 0
29 29
@@ -56,13 +56,14 @@ struct shutdown_trigger {
56}; 56};
57 57
58/* 58/*
59 * Five shutdown action types are supported: 59 * The following shutdown action types are supported:
60 */ 60 */
61#define SHUTDOWN_ACTION_IPL_STR "ipl" 61#define SHUTDOWN_ACTION_IPL_STR "ipl"
62#define SHUTDOWN_ACTION_REIPL_STR "reipl" 62#define SHUTDOWN_ACTION_REIPL_STR "reipl"
63#define SHUTDOWN_ACTION_DUMP_STR "dump" 63#define SHUTDOWN_ACTION_DUMP_STR "dump"
64#define SHUTDOWN_ACTION_VMCMD_STR "vmcmd" 64#define SHUTDOWN_ACTION_VMCMD_STR "vmcmd"
65#define SHUTDOWN_ACTION_STOP_STR "stop" 65#define SHUTDOWN_ACTION_STOP_STR "stop"
66#define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl"
66 67
67struct shutdown_action { 68struct shutdown_action {
68 char *name; 69 char *name;
@@ -146,6 +147,7 @@ static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
146static struct ipl_parameter_block *reipl_block_fcp; 147static struct ipl_parameter_block *reipl_block_fcp;
147static struct ipl_parameter_block *reipl_block_ccw; 148static struct ipl_parameter_block *reipl_block_ccw;
148static struct ipl_parameter_block *reipl_block_nss; 149static struct ipl_parameter_block *reipl_block_nss;
150static struct ipl_parameter_block *reipl_block_actual;
149 151
150static int dump_capabilities = DUMP_TYPE_NONE; 152static int dump_capabilities = DUMP_TYPE_NONE;
151static enum dump_type dump_type = DUMP_TYPE_NONE; 153static enum dump_type dump_type = DUMP_TYPE_NONE;
@@ -835,6 +837,7 @@ static int reipl_set_type(enum ipl_type type)
835 reipl_method = REIPL_METHOD_CCW_VM; 837 reipl_method = REIPL_METHOD_CCW_VM;
836 else 838 else
837 reipl_method = REIPL_METHOD_CCW_CIO; 839 reipl_method = REIPL_METHOD_CCW_CIO;
840 reipl_block_actual = reipl_block_ccw;
838 break; 841 break;
839 case IPL_TYPE_FCP: 842 case IPL_TYPE_FCP:
840 if (diag308_set_works) 843 if (diag308_set_works)
@@ -843,6 +846,7 @@ static int reipl_set_type(enum ipl_type type)
843 reipl_method = REIPL_METHOD_FCP_RO_VM; 846 reipl_method = REIPL_METHOD_FCP_RO_VM;
844 else 847 else
845 reipl_method = REIPL_METHOD_FCP_RO_DIAG; 848 reipl_method = REIPL_METHOD_FCP_RO_DIAG;
849 reipl_block_actual = reipl_block_fcp;
846 break; 850 break;
847 case IPL_TYPE_FCP_DUMP: 851 case IPL_TYPE_FCP_DUMP:
848 reipl_method = REIPL_METHOD_FCP_DUMP; 852 reipl_method = REIPL_METHOD_FCP_DUMP;
@@ -852,6 +856,7 @@ static int reipl_set_type(enum ipl_type type)
852 reipl_method = REIPL_METHOD_NSS_DIAG; 856 reipl_method = REIPL_METHOD_NSS_DIAG;
853 else 857 else
854 reipl_method = REIPL_METHOD_NSS; 858 reipl_method = REIPL_METHOD_NSS;
859 reipl_block_actual = reipl_block_nss;
855 break; 860 break;
856 case IPL_TYPE_UNKNOWN: 861 case IPL_TYPE_UNKNOWN:
857 reipl_method = REIPL_METHOD_DEFAULT; 862 reipl_method = REIPL_METHOD_DEFAULT;
@@ -960,7 +965,6 @@ static void reipl_run(struct shutdown_trigger *trigger)
960 diag308(DIAG308_IPL, NULL); 965 diag308(DIAG308_IPL, NULL);
961 break; 966 break;
962 case REIPL_METHOD_FCP_DUMP: 967 case REIPL_METHOD_FCP_DUMP:
963 default:
964 break; 968 break;
965 } 969 }
966 disabled_wait((unsigned long) __builtin_return_address(0)); 970 disabled_wait((unsigned long) __builtin_return_address(0));
@@ -1069,10 +1073,12 @@ static int __init reipl_fcp_init(void)
1069{ 1073{
1070 int rc; 1074 int rc;
1071 1075
1072 if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP)) 1076 if (!diag308_set_works) {
1073 return 0; 1077 if (ipl_info.type == IPL_TYPE_FCP)
1074 if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP)) 1078 make_attrs_ro(reipl_fcp_attrs);
1075 make_attrs_ro(reipl_fcp_attrs); 1079 else
1080 return 0;
1081 }
1076 1082
1077 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); 1083 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
1078 if (!reipl_block_fcp) 1084 if (!reipl_block_fcp)
@@ -1253,7 +1259,6 @@ static void dump_run(struct shutdown_trigger *trigger)
1253 diag308(DIAG308_DUMP, NULL); 1259 diag308(DIAG308_DUMP, NULL);
1254 break; 1260 break;
1255 case DUMP_METHOD_NONE: 1261 case DUMP_METHOD_NONE:
1256 default:
1257 return; 1262 return;
1258 } 1263 }
1259 printk(KERN_EMERG "Dump failed!\n"); 1264 printk(KERN_EMERG "Dump failed!\n");
@@ -1332,6 +1337,49 @@ static struct shutdown_action __refdata dump_action = {
1332 .init = dump_init, 1337 .init = dump_init,
1333}; 1338};
1334 1339
1340static void dump_reipl_run(struct shutdown_trigger *trigger)
1341{
1342 preempt_disable();
1343 /*
1344 * Bypass dynamic address translation (DAT) when storing IPL parameter
1345 * information block address and checksum into the prefix area
1346 * (corresponding to absolute addresses 0-8191).
1347 * When enhanced DAT applies and the STE format control in one,
1348 * the absolute address is formed without prefixing. In this case a
1349 * normal store (stg/st) into the prefix area would no more match to
1350 * absolute addresses 0-8191.
1351 */
1352#ifdef CONFIG_64BIT
1353 asm volatile("sturg %0,%1"
1354 :: "a" ((unsigned long) reipl_block_actual),
1355 "a" (&lowcore_ptr[smp_processor_id()]->ipib));
1356#else
1357 asm volatile("stura %0,%1"
1358 :: "a" ((unsigned long) reipl_block_actual),
1359 "a" (&lowcore_ptr[smp_processor_id()]->ipib));
1360#endif
1361 asm volatile("stura %0,%1"
1362 :: "a" (csum_partial(reipl_block_actual,
1363 reipl_block_actual->hdr.len, 0)),
1364 "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum));
1365 preempt_enable();
1366 dump_run(trigger);
1367}
1368
1369static int __init dump_reipl_init(void)
1370{
1371 if (!diag308_set_works)
1372 return -EOPNOTSUPP;
1373 else
1374 return 0;
1375}
1376
1377static struct shutdown_action __refdata dump_reipl_action = {
1378 .name = SHUTDOWN_ACTION_DUMP_REIPL_STR,
1379 .fn = dump_reipl_run,
1380 .init = dump_reipl_init,
1381};
1382
1335/* 1383/*
1336 * vmcmd shutdown action: Trigger vm command on shutdown. 1384 * vmcmd shutdown action: Trigger vm command on shutdown.
1337 */ 1385 */
@@ -1421,7 +1469,8 @@ static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
1421/* action list */ 1469/* action list */
1422 1470
1423static struct shutdown_action *shutdown_actions_list[] = { 1471static struct shutdown_action *shutdown_actions_list[] = {
1424 &ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action}; 1472 &ipl_action, &reipl_action, &dump_reipl_action, &dump_action,
1473 &vmcmd_action, &stop_action};
1425#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *)) 1474#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
1426 1475
1427/* 1476/*
@@ -1434,11 +1483,11 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
1434 size_t len) 1483 size_t len)
1435{ 1484{
1436 int i; 1485 int i;
1486
1437 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { 1487 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
1438 if (!shutdown_actions_list[i]) 1488 if (!shutdown_actions_list[i])
1439 continue; 1489 continue;
1440 if (strncmp(buf, shutdown_actions_list[i]->name, 1490 if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
1441 strlen(shutdown_actions_list[i]->name)) == 0) {
1442 trigger->action = shutdown_actions_list[i]; 1491 trigger->action = shutdown_actions_list[i];
1443 return len; 1492 return len;
1444 } 1493 }
@@ -1672,7 +1721,7 @@ static int on_panic_notify(struct notifier_block *self,
1672 1721
1673static struct notifier_block on_panic_nb = { 1722static struct notifier_block on_panic_nb = {
1674 .notifier_call = on_panic_notify, 1723 .notifier_call = on_panic_notify,
1675 .priority = 0, 1724 .priority = INT_MIN,
1676}; 1725};
1677 1726
1678void __init setup_ipl(void) 1727void __init setup_ipl(void)
@@ -1696,7 +1745,6 @@ void __init setup_ipl(void)
1696 sizeof(ipl_info.data.nss.name)); 1745 sizeof(ipl_info.data.nss.name));
1697 break; 1746 break;
1698 case IPL_TYPE_UNKNOWN: 1747 case IPL_TYPE_UNKNOWN:
1699 default:
1700 /* We have no info to copy */ 1748 /* We have no info to copy */
1701 break; 1749 break;
1702 } 1750 }