aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ipl.c
diff options
context:
space:
mode:
authorFrank Munzert <munzert@de.ibm.com>2009-03-26 10:23:43 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-03-26 10:24:03 -0400
commit099b765139929efdcf232f8870804accf8c4cdc5 (patch)
tree9869bb629def6f49d5d3b82e8e0b301cabbc1b8c /arch/s390/kernel/ipl.c
parentd7fd5f1e3b195a8232b3ed768ac2809ddce8ca46 (diff)
[S390] Automatic IPL after dump
Provide new shutdown action "dump_reipl" for automatic ipl after dump. Signed-off-by: Frank Munzert <munzert@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r--arch/s390/kernel/ipl.c56
1 files changed, 52 insertions, 4 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 2dcf590faba6..5663c1f8e46a 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -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;
@@ -1332,6 +1337,48 @@ 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" (cksm(reipl_block_actual, reipl_block_actual->hdr.len)),
1363 "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum));
1364 preempt_enable();
1365 dump_run(trigger);
1366}
1367
1368static int __init dump_reipl_init(void)
1369{
1370 if (!diag308_set_works)
1371 return -EOPNOTSUPP;
1372 else
1373 return 0;
1374}
1375
1376static struct shutdown_action __refdata dump_reipl_action = {
1377 .name = SHUTDOWN_ACTION_DUMP_REIPL_STR,
1378 .fn = dump_reipl_run,
1379 .init = dump_reipl_init,
1380};
1381
1335/* 1382/*
1336 * vmcmd shutdown action: Trigger vm command on shutdown. 1383 * vmcmd shutdown action: Trigger vm command on shutdown.
1337 */ 1384 */
@@ -1421,7 +1468,8 @@ static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
1421/* action list */ 1468/* action list */
1422 1469
1423static struct shutdown_action *shutdown_actions_list[] = { 1470static struct shutdown_action *shutdown_actions_list[] = {
1424 &ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action}; 1471 &ipl_action, &reipl_action, &dump_reipl_action, &dump_action,
1472 &vmcmd_action, &stop_action};
1425#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *)) 1473#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
1426 1474
1427/* 1475/*
@@ -1434,11 +1482,11 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
1434 size_t len) 1482 size_t len)
1435{ 1483{
1436 int i; 1484 int i;
1485
1437 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { 1486 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
1438 if (!shutdown_actions_list[i]) 1487 if (!shutdown_actions_list[i])
1439 continue; 1488 continue;
1440 if (strncmp(buf, shutdown_actions_list[i]->name, 1489 if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
1441 strlen(shutdown_actions_list[i]->name)) == 0) {
1442 trigger->action = shutdown_actions_list[i]; 1490 trigger->action = shutdown_actions_list[i];
1443 return len; 1491 return len;
1444 } 1492 }