diff options
| author | Michael Holzheu <holzheu@linux.vnet.ibm.com> | 2011-08-03 10:44:19 -0400 |
|---|---|---|
| committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2011-08-03 10:44:19 -0400 |
| commit | 7dd6b3343fdc190712d1620ee8848d25c4c77c33 (patch) | |
| tree | e4c3258880f88096f9ecf65fa2cca20e62b5813d | |
| parent | 944291de33b26a8b403f13f5eb0cc51fb982aa1e (diff) | |
[S390] Add PSW restart shutdown trigger
With this patch a new S390 shutdown trigger "restart" is added. If under
z/VM "systerm restart" is entered or under the HMC the "PSW restart" button
is pressed, the PSW located at 0 (31 bit) or 0x1a0 (64 bit) bit is loaded.
Now we execute do_restart() that processes the restart action that is
defined under /sys/firmware/shutdown_actions/on_restart. Currently the
following actions are possible: reipl (default), stop, vmcmd, dump, and
dump_reipl.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
| -rw-r--r-- | arch/s390/include/asm/lowcore.h | 11 | ||||
| -rw-r--r-- | arch/s390/include/asm/system.h | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/asm-offsets.c | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/entry.S | 28 | ||||
| -rw-r--r-- | arch/s390/kernel/entry64.S | 20 | ||||
| -rw-r--r-- | arch/s390/kernel/ipl.c | 39 | ||||
| -rw-r--r-- | arch/s390/kernel/setup.c | 24 | ||||
| -rw-r--r-- | arch/s390/kernel/smp.c | 11 | ||||
| -rw-r--r-- | arch/s390/mm/maccess.c | 16 |
9 files changed, 146 insertions, 5 deletions
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index f26280d9e88d..e85c911aabf0 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h | |||
| @@ -18,6 +18,7 @@ void system_call(void); | |||
| 18 | void pgm_check_handler(void); | 18 | void pgm_check_handler(void); |
| 19 | void mcck_int_handler(void); | 19 | void mcck_int_handler(void); |
| 20 | void io_int_handler(void); | 20 | void io_int_handler(void); |
| 21 | void psw_restart_int_handler(void); | ||
| 21 | 22 | ||
| 22 | #ifdef CONFIG_32BIT | 23 | #ifdef CONFIG_32BIT |
| 23 | 24 | ||
| @@ -150,7 +151,10 @@ struct _lowcore { | |||
| 150 | */ | 151 | */ |
| 151 | __u32 ipib; /* 0x0e00 */ | 152 | __u32 ipib; /* 0x0e00 */ |
| 152 | __u32 ipib_checksum; /* 0x0e04 */ | 153 | __u32 ipib_checksum; /* 0x0e04 */ |
| 153 | __u8 pad_0x0e08[0x0f00-0x0e08]; /* 0x0e08 */ | 154 | |
| 155 | /* 64 bit save area */ | ||
| 156 | __u64 save_area_64; /* 0x0e08 */ | ||
| 157 | __u8 pad_0x0e10[0x0f00-0x0e10]; /* 0x0e10 */ | ||
| 154 | 158 | ||
| 155 | /* Extended facility list */ | 159 | /* Extended facility list */ |
| 156 | __u64 stfle_fac_list[32]; /* 0x0f00 */ | 160 | __u64 stfle_fac_list[32]; /* 0x0f00 */ |
| @@ -286,7 +290,10 @@ struct _lowcore { | |||
| 286 | */ | 290 | */ |
| 287 | __u64 ipib; /* 0x0e00 */ | 291 | __u64 ipib; /* 0x0e00 */ |
| 288 | __u32 ipib_checksum; /* 0x0e08 */ | 292 | __u32 ipib_checksum; /* 0x0e08 */ |
| 289 | __u8 pad_0x0e0c[0x0f00-0x0e0c]; /* 0x0e0c */ | 293 | |
| 294 | /* 64 bit save area */ | ||
| 295 | __u64 save_area_64; /* 0x0e0c */ | ||
| 296 | __u8 pad_0x0e14[0x0f00-0x0e14]; /* 0x0e14 */ | ||
| 290 | 297 | ||
| 291 | /* Extended facility list */ | 298 | /* Extended facility list */ |
| 292 | __u64 stfle_fac_list[32]; /* 0x0f00 */ | 299 | __u64 stfle_fac_list[32]; /* 0x0f00 */ |
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h index d382629a0172..6582f69f2389 100644 --- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h | |||
| @@ -113,6 +113,7 @@ extern void pfault_fini(void); | |||
| 113 | 113 | ||
| 114 | extern void cmma_init(void); | 114 | extern void cmma_init(void); |
| 115 | extern int memcpy_real(void *, void *, size_t); | 115 | extern int memcpy_real(void *, void *, size_t); |
| 116 | extern void copy_to_absolute_zero(void *dest, void *src, size_t count); | ||
| 116 | 117 | ||
| 117 | #define finish_arch_switch(prev) do { \ | 118 | #define finish_arch_switch(prev) do { \ |
| 118 | set_fs(current->thread.mm_segment); \ | 119 | set_fs(current->thread.mm_segment); \ |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 05d8f38734ec..199a537d4f36 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
| @@ -142,6 +142,7 @@ int main(void) | |||
| 142 | DEFINE(__LC_FPREGS_SAVE_AREA, offsetof(struct _lowcore, floating_pt_save_area)); | 142 | DEFINE(__LC_FPREGS_SAVE_AREA, offsetof(struct _lowcore, floating_pt_save_area)); |
| 143 | DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area)); | 143 | DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area)); |
| 144 | DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area)); | 144 | DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area)); |
| 145 | DEFINE(__LC_SAVE_AREA_64, offsetof(struct _lowcore, save_area_64)); | ||
| 145 | #ifdef CONFIG_32BIT | 146 | #ifdef CONFIG_32BIT |
| 146 | DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr)); | 147 | DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr)); |
| 147 | #else /* CONFIG_32BIT */ | 148 | #else /* CONFIG_32BIT */ |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 3eab7cfab07c..02ec8fe7d03f 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
| @@ -849,6 +849,34 @@ restart_crash: | |||
| 849 | restart_go: | 849 | restart_go: |
| 850 | #endif | 850 | #endif |
| 851 | 851 | ||
| 852 | # | ||
| 853 | # PSW restart interrupt handler | ||
| 854 | # | ||
| 855 | ENTRY(psw_restart_int_handler) | ||
| 856 | st %r15,__LC_SAVE_AREA_64(%r0) # save r15 | ||
| 857 | basr %r15,0 | ||
| 858 | 0: l %r15,.Lrestart_stack-0b(%r15) # load restart stack | ||
| 859 | l %r15,0(%r15) | ||
| 860 | ahi %r15,-SP_SIZE # make room for pt_regs | ||
| 861 | stm %r0,%r14,SP_R0(%r15) # store gprs %r0-%r14 to stack | ||
| 862 | mvc SP_R15(4,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack | ||
| 863 | mvc SP_PSW(8,%r15),__LC_RST_OLD_PSW(%r0) # store restart old psw | ||
| 864 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0 | ||
| 865 | basr %r14,0 | ||
| 866 | 1: l %r14,.Ldo_restart-1b(%r14) | ||
| 867 | basr %r14,%r14 | ||
| 868 | |||
| 869 | basr %r14,0 # load disabled wait PSW if | ||
| 870 | 2: lpsw restart_psw_crash-2b(%r14) # do_restart returns | ||
| 871 | .align 4 | ||
| 872 | .Ldo_restart: | ||
| 873 | .long do_restart | ||
| 874 | .Lrestart_stack: | ||
| 875 | .long restart_stack | ||
| 876 | .align 8 | ||
| 877 | restart_psw_crash: | ||
| 878 | .long 0x000a0000,0x00000000 + restart_psw_crash | ||
| 879 | |||
| 852 | .section .kprobes.text, "ax" | 880 | .section .kprobes.text, "ax" |
| 853 | 881 | ||
| 854 | #ifdef CONFIG_CHECK_STACK | 882 | #ifdef CONFIG_CHECK_STACK |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 7a0fd426ca92..5f729d627cef 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
| @@ -865,6 +865,26 @@ restart_crash: | |||
| 865 | restart_go: | 865 | restart_go: |
| 866 | #endif | 866 | #endif |
| 867 | 867 | ||
| 868 | # | ||
| 869 | # PSW restart interrupt handler | ||
| 870 | # | ||
| 871 | ENTRY(psw_restart_int_handler) | ||
| 872 | stg %r15,__LC_SAVE_AREA_64(%r0) # save r15 | ||
| 873 | larl %r15,restart_stack # load restart stack | ||
| 874 | lg %r15,0(%r15) | ||
| 875 | aghi %r15,-SP_SIZE # make room for pt_regs | ||
| 876 | stmg %r0,%r14,SP_R0(%r15) # store gprs %r0-%r14 to stack | ||
| 877 | mvc SP_R15(8,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack | ||
| 878 | mvc SP_PSW(16,%r15),__LC_RST_OLD_PSW(%r0)# store restart old psw | ||
| 879 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0 | ||
| 880 | brasl %r14,do_restart | ||
| 881 | |||
| 882 | larl %r14,restart_psw_crash # load disabled wait PSW if | ||
| 883 | lpswe 0(%r14) # do_restart returns | ||
| 884 | .align 8 | ||
| 885 | restart_psw_crash: | ||
| 886 | .quad 0x0002000080000000,0x0000000000000000 + restart_psw_crash | ||
| 887 | |||
| 868 | .section .kprobes.text, "ax" | 888 | .section .kprobes.text, "ax" |
| 869 | 889 | ||
| 870 | #ifdef CONFIG_CHECK_STACK | 890 | #ifdef CONFIG_CHECK_STACK |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index a689070be287..059c59027ac0 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
| @@ -45,11 +45,13 @@ | |||
| 45 | * - halt | 45 | * - halt |
| 46 | * - power off | 46 | * - power off |
| 47 | * - reipl | 47 | * - reipl |
| 48 | * - restart | ||
| 48 | */ | 49 | */ |
| 49 | #define ON_PANIC_STR "on_panic" | 50 | #define ON_PANIC_STR "on_panic" |
| 50 | #define ON_HALT_STR "on_halt" | 51 | #define ON_HALT_STR "on_halt" |
| 51 | #define ON_POFF_STR "on_poff" | 52 | #define ON_POFF_STR "on_poff" |
| 52 | #define ON_REIPL_STR "on_reboot" | 53 | #define ON_REIPL_STR "on_reboot" |
| 54 | #define ON_RESTART_STR "on_restart" | ||
| 53 | 55 | ||
| 54 | struct shutdown_action; | 56 | struct shutdown_action; |
| 55 | struct shutdown_trigger { | 57 | struct shutdown_trigger { |
| @@ -1544,17 +1546,20 @@ static char vmcmd_on_reboot[128]; | |||
| 1544 | static char vmcmd_on_panic[128]; | 1546 | static char vmcmd_on_panic[128]; |
| 1545 | static char vmcmd_on_halt[128]; | 1547 | static char vmcmd_on_halt[128]; |
| 1546 | static char vmcmd_on_poff[128]; | 1548 | static char vmcmd_on_poff[128]; |
| 1549 | static char vmcmd_on_restart[128]; | ||
| 1547 | 1550 | ||
| 1548 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot); | 1551 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot); |
| 1549 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic); | 1552 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic); |
| 1550 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt); | 1553 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt); |
| 1551 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff); | 1554 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff); |
| 1555 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_restart, "%s\n", "%s\n", vmcmd_on_restart); | ||
| 1552 | 1556 | ||
| 1553 | static struct attribute *vmcmd_attrs[] = { | 1557 | static struct attribute *vmcmd_attrs[] = { |
| 1554 | &sys_vmcmd_on_reboot_attr.attr, | 1558 | &sys_vmcmd_on_reboot_attr.attr, |
| 1555 | &sys_vmcmd_on_panic_attr.attr, | 1559 | &sys_vmcmd_on_panic_attr.attr, |
| 1556 | &sys_vmcmd_on_halt_attr.attr, | 1560 | &sys_vmcmd_on_halt_attr.attr, |
| 1557 | &sys_vmcmd_on_poff_attr.attr, | 1561 | &sys_vmcmd_on_poff_attr.attr, |
| 1562 | &sys_vmcmd_on_restart_attr.attr, | ||
| 1558 | NULL, | 1563 | NULL, |
| 1559 | }; | 1564 | }; |
| 1560 | 1565 | ||
| @@ -1576,6 +1581,8 @@ static void vmcmd_run(struct shutdown_trigger *trigger) | |||
| 1576 | cmd = vmcmd_on_halt; | 1581 | cmd = vmcmd_on_halt; |
| 1577 | else if (strcmp(trigger->name, ON_POFF_STR) == 0) | 1582 | else if (strcmp(trigger->name, ON_POFF_STR) == 0) |
| 1578 | cmd = vmcmd_on_poff; | 1583 | cmd = vmcmd_on_poff; |
