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.c99
1 files changed, 58 insertions, 41 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index affa8e68124a..8342e65a140d 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -2,7 +2,7 @@
2 * arch/s390/kernel/ipl.c 2 * arch/s390/kernel/ipl.c
3 * ipl/reipl/dump support for Linux on s390. 3 * ipl/reipl/dump support for Linux on s390.
4 * 4 *
5 * Copyright IBM Corp. 2005,2007 5 * Copyright IBM Corp. 2005,2012
6 * Author(s): Michael Holzheu <holzheu@de.ibm.com> 6 * Author(s): Michael Holzheu <holzheu@de.ibm.com>
7 * Heiko Carstens <heiko.carstens@de.ibm.com> 7 * Heiko Carstens <heiko.carstens@de.ibm.com>
8 * Volker Sameske <sameske@de.ibm.com> 8 * Volker Sameske <sameske@de.ibm.com>
@@ -17,6 +17,7 @@
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/gfp.h> 18#include <linux/gfp.h>
19#include <linux/crash_dump.h> 19#include <linux/crash_dump.h>
20#include <linux/debug_locks.h>
20#include <asm/ipl.h> 21#include <asm/ipl.h>
21#include <asm/smp.h> 22#include <asm/smp.h>
22#include <asm/setup.h> 23#include <asm/setup.h>
@@ -25,8 +26,9 @@
25#include <asm/ebcdic.h> 26#include <asm/ebcdic.h>
26#include <asm/reset.h> 27#include <asm/reset.h>
27#include <asm/sclp.h> 28#include <asm/sclp.h>
28#include <asm/sigp.h>
29#include <asm/checksum.h> 29#include <asm/checksum.h>
30#include <asm/debug.h>
31#include <asm/os_info.h>
30#include "entry.h" 32#include "entry.h"
31 33
32#define IPL_PARM_BLOCK_VERSION 0 34#define IPL_PARM_BLOCK_VERSION 0
@@ -571,7 +573,7 @@ static void __ipl_run(void *unused)
571 573
572static void ipl_run(struct shutdown_trigger *trigger) 574static void ipl_run(struct shutdown_trigger *trigger)
573{ 575{
574 smp_switch_to_ipl_cpu(__ipl_run, NULL); 576 smp_call_ipl_cpu(__ipl_run, NULL);
575} 577}
576 578
577static int __init ipl_init(void) 579static int __init ipl_init(void)
@@ -950,6 +952,13 @@ static struct attribute_group reipl_nss_attr_group = {
950 .attrs = reipl_nss_attrs, 952 .attrs = reipl_nss_attrs,
951}; 953};
952 954
955static void set_reipl_block_actual(struct ipl_parameter_block *reipl_block)
956{
957 reipl_block_actual = reipl_block;
958 os_info_entry_add(OS_INFO_REIPL_BLOCK, reipl_block_actual,
959 reipl_block->hdr.len);
960}
961
953/* reipl type */ 962/* reipl type */
954 963
955static int reipl_set_type(enum ipl_type type) 964static int reipl_set_type(enum ipl_type type)
@@ -965,7 +974,7 @@ static int reipl_set_type(enum ipl_type type)
965 reipl_method = REIPL_METHOD_CCW_VM; 974 reipl_method = REIPL_METHOD_CCW_VM;
966 else 975 else
967 reipl_method = REIPL_METHOD_CCW_CIO; 976 reipl_method = REIPL_METHOD_CCW_CIO;
968 reipl_block_actual = reipl_block_ccw; 977 set_reipl_block_actual(reipl_block_ccw);
969 break; 978 break;
970 case IPL_TYPE_FCP: 979 case IPL_TYPE_FCP:
971 if (diag308_set_works) 980 if (diag308_set_works)
@@ -974,7 +983,7 @@ static int reipl_set_type(enum ipl_type type)
974 reipl_method = REIPL_METHOD_FCP_RO_VM; 983 reipl_method = REIPL_METHOD_FCP_RO_VM;
975 else 984 else
976 reipl_method = REIPL_METHOD_FCP_RO_DIAG; 985 reipl_method = REIPL_METHOD_FCP_RO_DIAG;
977 reipl_block_actual = reipl_block_fcp; 986 set_reipl_block_actual(reipl_block_fcp);
978 break; 987 break;
979 case IPL_TYPE_FCP_DUMP: 988 case IPL_TYPE_FCP_DUMP:
980 reipl_method = REIPL_METHOD_FCP_DUMP; 989 reipl_method = REIPL_METHOD_FCP_DUMP;
@@ -984,7 +993,7 @@ static int reipl_set_type(enum ipl_type type)
984 reipl_method = REIPL_METHOD_NSS_DIAG; 993 reipl_method = REIPL_METHOD_NSS_DIAG;
985 else 994 else
986 reipl_method = REIPL_METHOD_NSS; 995 reipl_method = REIPL_METHOD_NSS;
987 reipl_block_actual = reipl_block_nss; 996 set_reipl_block_actual(reipl_block_nss);
988 break; 997 break;
989 case IPL_TYPE_UNKNOWN: 998 case IPL_TYPE_UNKNOWN:
990 reipl_method = REIPL_METHOD_DEFAULT; 999 reipl_method = REIPL_METHOD_DEFAULT;
@@ -1101,7 +1110,7 @@ static void __reipl_run(void *unused)
1101 1110
1102static void reipl_run(struct shutdown_trigger *trigger) 1111static void reipl_run(struct shutdown_trigger *trigger)
1103{ 1112{
1104 smp_switch_to_ipl_cpu(__reipl_run, NULL); 1113 smp_call_ipl_cpu(__reipl_run, NULL);
1105} 1114}
1106 1115
1107static void reipl_block_ccw_init(struct ipl_parameter_block *ipb) 1116static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
@@ -1256,6 +1265,29 @@ static int __init reipl_fcp_init(void)
1256 return 0; 1265 return 0;
1257} 1266}
1258 1267
1268static int __init reipl_type_init(void)
1269{
1270 enum ipl_type reipl_type = ipl_info.type;
1271 struct ipl_parameter_block *reipl_block;
1272 unsigned long size;
1273
1274 reipl_block = os_info_old_entry(OS_INFO_REIPL_BLOCK, &size);
1275 if (!reipl_block)
1276 goto out;
1277 /*
1278 * If we have an OS info reipl block, this will be used
1279 */
1280 if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_FCP) {
1281 memcpy(reipl_block_fcp, reipl_block, size);
1282 reipl_type = IPL_TYPE_FCP;
1283 } else if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_CCW) {
1284 memcpy(reipl_block_ccw, reipl_block, size);
1285 reipl_type = IPL_TYPE_CCW;
1286 }
1287out:
1288 return reipl_set_type(reipl_type);
1289}
1290
1259static int __init reipl_init(void) 1291static int __init reipl_init(void)
1260{ 1292{
1261 int rc; 1293 int rc;
@@ -1277,10 +1309,7 @@ static int __init reipl_init(void)
1277 rc = reipl_nss_init(); 1309 rc = reipl_nss_init();
1278 if (rc) 1310 if (rc)
1279 return rc; 1311 return rc;
1280 rc = reipl_set_type(ipl_info.type); 1312 return reipl_type_init();
1281 if (rc)
1282 return rc;
1283 return 0;
1284} 1313}
1285 1314
1286static struct shutdown_action __refdata reipl_action = { 1315static struct shutdown_action __refdata reipl_action = {
@@ -1421,7 +1450,7 @@ static void dump_run(struct shutdown_trigger *trigger)
1421 if (dump_method == DUMP_METHOD_NONE) 1450 if (dump_method == DUMP_METHOD_NONE)
1422 return; 1451 return;
1423 smp_send_stop(); 1452 smp_send_stop();
1424 smp_switch_to_ipl_cpu(__dump_run, NULL); 1453 smp_call_ipl_cpu(__dump_run, NULL);
1425} 1454}
1426 1455
1427static int __init dump_ccw_init(void) 1456static int __init dump_ccw_init(void)
@@ -1499,30 +1528,12 @@ static struct shutdown_action __refdata dump_action = {
1499 1528
1500static void dump_reipl_run(struct shutdown_trigger *trigger) 1529static void dump_reipl_run(struct shutdown_trigger *trigger)
1501{ 1530{
1502 preempt_disable(); 1531 u32 csum;
1503 /* 1532
1504 * Bypass dynamic address translation (DAT) when storing IPL parameter 1533 csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0);
1505 * information block address and checksum into the prefix area 1534 copy_to_absolute_zero(&S390_lowcore.ipib_checksum, &csum, sizeof(csum));
1506 * (corresponding to absolute addresses 0-8191). 1535 copy_to_absolute_zero(&S390_lowcore.ipib, &reipl_block_actual,
1507 * When enhanced DAT applies and the STE format control in one, 1536 sizeof(reipl_block_actual));
1508 * the absolute address is formed without prefixing. In this case a
1509 * normal store (stg/st) into the prefix area would no more match to
1510 * absolute addresses 0-8191.
1511 */
1512#ifdef CONFIG_64BIT
1513 asm volatile("sturg %0,%1"
1514 :: "a" ((unsigned long) reipl_block_actual),
1515 "a" (&lowcore_ptr[smp_processor_id()]->ipib));
1516#else
1517 asm volatile("stura %0,%1"
1518 :: "a" ((unsigned long) reipl_block_actual),
1519 "a" (&lowcore_ptr[smp_processor_id()]->ipib));
1520#endif
1521 asm volatile("stura %0,%1"
1522 :: "a" (csum_partial(reipl_block_actual,
1523 reipl_block_actual->hdr.len, 0)),
1524 "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum));
1525 preempt_enable();
1526 dump_run(trigger); 1537 dump_run(trigger);
1527} 1538}
1528 1539
@@ -1623,9 +1634,7 @@ static void stop_run(struct shutdown_trigger *trigger)
1623 if (strcmp(trigger->name, ON_PANIC_STR) == 0 || 1634 if (strcmp(trigger->name, ON_PANIC_STR) == 0 ||
1624 strcmp(trigger->name, ON_RESTART_STR) == 0) 1635 strcmp(trigger->name, ON_RESTART_STR) == 0)
1625 disabled_wait((unsigned long) __builtin_return_address(0)); 1636 disabled_wait((unsigned long) __builtin_return_address(0));
1626 while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) 1637 smp_stop_cpu();
1627 cpu_relax();
1628 for (;;);
1629} 1638}
1630 1639
1631static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR, 1640static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
@@ -1713,6 +1722,7 @@ static struct kobj_attribute on_panic_attr =
1713 1722
1714static void do_panic(void) 1723static void do_panic(void)
1715{ 1724{
1725 lgr_info_log();
1716 on_panic_trigger.action->fn(&on_panic_trigger); 1726 on_panic_trigger.action->fn(&on_panic_trigger);
1717 stop_run(&on_panic_trigger); 1727 stop_run(&on_panic_trigger);
1718} 1728}
@@ -1738,9 +1748,8 @@ static ssize_t on_restart_store(struct kobject *kobj,
1738static struct kobj_attribute on_restart_attr = 1748static struct kobj_attribute on_restart_attr =
1739 __ATTR(on_restart, 0644, on_restart_show, on_restart_store); 1749 __ATTR(on_restart, 0644, on_restart_show, on_restart_store);
1740 1750
1741void do_restart(void) 1751static void __do_restart(void *ignore)
1742{ 1752{
1743 smp_restart_with_online_cpu();
1744 smp_send_stop(); 1753 smp_send_stop();
1745#ifdef CONFIG_CRASH_DUMP 1754#ifdef CONFIG_CRASH_DUMP
1746 crash_kexec(NULL); 1755 crash_kexec(NULL);
@@ -1749,6 +1758,14 @@ void do_restart(void)
1749 stop_run(&on_restart_trigger); 1758 stop_run(&on_restart_trigger);
1750} 1759}
1751 1760
1761void do_restart(void)
1762{
1763 tracing_off();
1764 debug_locks_off();
1765 lgr_info_log();
1766 smp_call_online_cpu(__do_restart, NULL);
1767}
1768
1752/* on halt */ 1769/* on halt */
1753 1770
1754static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action}; 1771static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};