aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/lowcore.h1
-rw-r--r--arch/s390/kernel/asm-offsets.c7
-rw-r--r--arch/s390/kernel/sclp.S5
-rw-r--r--arch/s390/kernel/smp.c36
-rw-r--r--arch/s390/kernel/swsusp_asm64.S91
5 files changed, 71 insertions, 69 deletions
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index a3ff9b01bf7d..f2ef4b619ce1 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -86,6 +86,7 @@
86#define __LC_PGM_OLD_PSW 0x0150 86#define __LC_PGM_OLD_PSW 0x0150
87#define __LC_MCK_OLD_PSW 0x0160 87#define __LC_MCK_OLD_PSW 0x0160
88#define __LC_IO_OLD_PSW 0x0170 88#define __LC_IO_OLD_PSW 0x0170
89#define __LC_RESTART_PSW 0x01a0
89#define __LC_EXT_NEW_PSW 0x01b0 90#define __LC_EXT_NEW_PSW 0x01b0
90#define __LC_SVC_NEW_PSW 0x01c0 91#define __LC_SVC_NEW_PSW 0x01c0
91#define __LC_PGM_NEW_PSW 0x01d0 92#define __LC_PGM_NEW_PSW 0x01d0
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index fa9905ce7d0b..63e46433e81d 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -7,6 +7,7 @@
7#include <linux/sched.h> 7#include <linux/sched.h>
8#include <linux/kbuild.h> 8#include <linux/kbuild.h>
9#include <asm/vdso.h> 9#include <asm/vdso.h>
10#include <asm/sigp.h>
10 11
11int main(void) 12int main(void)
12{ 13{
@@ -59,6 +60,10 @@ int main(void)
59 DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); 60 DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
60 DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); 61 DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
61 DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); 62 DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
62 63 /* constants for SIGP */
64 DEFINE(__SIGP_STOP, sigp_stop);
65 DEFINE(__SIGP_RESTART, sigp_restart);
66 DEFINE(__SIGP_SENSE, sigp_sense);
67 DEFINE(__SIGP_INITIAL_CPU_RESET, sigp_initial_cpu_reset);
63 return 0; 68 return 0;
64} 69}
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
index 20639dfe0c42..e27ca63076d1 100644
--- a/arch/s390/kernel/sclp.S
+++ b/arch/s390/kernel/sclp.S
@@ -24,8 +24,6 @@ LC_EXT_INT_CODE = 0x86 # addr of ext int code
24# R3 = external interruption parameter if R2=0 24# R3 = external interruption parameter if R2=0
25# 25#
26 26
27.section ".init.text","ax"
28
29_sclp_wait_int: 27_sclp_wait_int:
30 stm %r6,%r15,24(%r15) # save registers 28 stm %r6,%r15,24(%r15) # save registers
31 basr %r13,0 # get base register 29 basr %r13,0 # get base register
@@ -318,9 +316,8 @@ _sclp_print_early:
318 .long _sclp_work_area 316 .long _sclp_work_area
319.Lascebc: 317.Lascebc:
320 .long _ascebc 318 .long _ascebc
321.previous
322 319
323.section ".init.data","a" 320.section .data,"aw",@progbits
324 .balign 4096 321 .balign 4096
325_sclp_work_area: 322_sclp_work_area:
326 .fill 4096 323 .fill 4096
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 6f14734abe72..b4b6396e6cf0 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -1041,42 +1041,6 @@ out:
1041static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, 1041static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show,
1042 dispatching_store); 1042 dispatching_store);
1043 1043
1044/*
1045 * If the resume kernel runs on another cpu than the suspended kernel,
1046 * we have to switch the cpu IDs in the logical map.
1047 */
1048void smp_switch_boot_cpu_in_resume(u32 resume_phys_cpu_id,
1049 struct _lowcore *suspend_lowcore)
1050{
1051 int cpu, suspend_cpu_id, resume_cpu_id;
1052 u32 suspend_phys_cpu_id;
1053
1054 suspend_phys_cpu_id = __cpu_logical_map[suspend_lowcore->cpu_nr];
1055 suspend_cpu_id = suspend_lowcore->cpu_nr;
1056
1057 for_each_present_cpu(cpu) {
1058 if (__cpu_logical_map[cpu] == resume_phys_cpu_id) {
1059 resume_cpu_id = cpu;
1060 goto found;
1061 }
1062 }
1063 panic("Could not find resume cpu in logical map.\n");
1064
1065found:
1066 printk("Resume cpu ID: %i/%i\n", resume_phys_cpu_id, resume_cpu_id);
1067 printk("Suspend cpu ID: %i/%i\n", suspend_phys_cpu_id, suspend_cpu_id);
1068
1069 __cpu_logical_map[resume_cpu_id] = suspend_phys_cpu_id;
1070 __cpu_logical_map[suspend_cpu_id] = resume_phys_cpu_id;
1071
1072 lowcore_ptr[suspend_cpu_id]->cpu_addr = resume_phys_cpu_id;
1073}
1074
1075u32 smp_get_phys_cpu_id(void)
1076{
1077 return __cpu_logical_map[smp_processor_id()];
1078}
1079
1080static int __init topology_init(void) 1044static int __init topology_init(void)
1081{ 1045{
1082 int cpu; 1046 int cpu;
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index fc056810a017..fe927d0bc20b 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -9,6 +9,7 @@
9 9
10#include <asm/page.h> 10#include <asm/page.h>
11#include <asm/ptrace.h> 11#include <asm/ptrace.h>
12#include <asm/thread_info.h>
12#include <asm/asm-offsets.h> 13#include <asm/asm-offsets.h>
13 14
14/* 15/*
@@ -41,6 +42,9 @@ swsusp_arch_suspend:
41 /* Get pointer to save area */ 42 /* Get pointer to save area */
42 lghi %r1,0x1000 43 lghi %r1,0x1000
43 44
45 /* Save CPU address */
46 stap __LC_CPU_ADDRESS(%r1)
47
44 /* Store registers */ 48 /* Store registers */
45 mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */ 49 mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */
46 stfpc 0x31c(%r1) /* store fpu control */ 50 stfpc 0x31c(%r1) /* store fpu control */
@@ -105,12 +109,7 @@ swsusp_arch_resume:
105 /* Make all free pages stable */ 109 /* Make all free pages stable */
106 lghi %r2,1 110 lghi %r2,1
107 brasl %r14,arch_set_page_states 111 brasl %r14,arch_set_page_states
108#ifdef CONFIG_SMP 112
109 /* Save boot cpu number */
110 brasl %r14,smp_get_phys_cpu_id
111 larl %r1,saved_cpu_id
112 st %r2,0(%r1)
113#endif
114 /* Deactivate DAT */ 113 /* Deactivate DAT */
115 stnsm __SF_EMPTY(%r15),0xfb 114 stnsm __SF_EMPTY(%r15),0xfb
116 115
@@ -139,12 +138,10 @@ swsusp_arch_resume:
139 138
140 /* Reset System */ 139 /* Reset System */
141 larl %r1,restart_entry 140 larl %r1,restart_entry
142 larl %r2,restart_psw 141 larl %r2,.Lrestart_diag308_psw
143 og %r1,0(%r2) 142 og %r1,0(%r2)
144 stg %r1,0(%r0) 143 stg %r1,0(%r0)
145 larl %r1,saved_pgm_check_psw 144 larl %r1,.Lnew_pgm_check_psw
146 mvc 0(16,%r1),__LC_PGM_NEW_PSW(%r0)
147 larl %r1,new_pgm_check_psw
148 epsw %r2,%r3 145 epsw %r2,%r3
149 stm %r2,%r3,0(%r1) 146 stm %r2,%r3,0(%r1)
150 mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1) 147 mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1)
@@ -154,12 +151,54 @@ restart_entry:
154 lhi %r1,1 151 lhi %r1,1
155 sigp %r1,%r0,0x12 152 sigp %r1,%r0,0x12
156 sam64 153 sam64
157 larl %r1,new_pgm_check_psw 154 larl %r1,.Lnew_pgm_check_psw
158 lpswe 0(%r1) 155 lpswe 0(%r1)
159pgm_check_entry: 156pgm_check_entry:
160 larl %r1,saved_pgm_check_psw
161 mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1)
162 157
158 /* Switch to original suspend CPU */
159 larl %r1,.Lresume_cpu /* Resume CPU address: r2 */
160 stap 0(%r1)
161 llgh %r2,0(%r1)
162 lghi %r3,0x1000
163 llgh %r1,__LC_CPU_ADDRESS(%r3) /* Suspend CPU address: r1 */
164 cgr %r1,%r2
165 je restore_registers /* r1 = r2 -> nothing to do */
166 larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
167 mvc __LC_RESTART_PSW(16,%r0),0(%r4)
1683:
169 sigp %r9,%r1,__SIGP_INITIAL_CPU_RESET
170 brc 8,4f /* accepted */
171 brc 2,3b /* busy, try again */
172
173 /* Suspend CPU not available -> panic */
174 larl %r15,init_thread_union
175 ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER)
176 larl %r2,.Lpanic_string
177 larl %r3,_sclp_print_early
178 lghi %r1,0
179 sam31
180 sigp %r1,%r0,0x12
181 basr %r14,%r3
182 larl %r3,.Ldisabled_wait_31
183 lpsw 0(%r3)
1844:
185 /* Switch to suspend CPU */
186 sigp %r9,%r1,__SIGP_RESTART /* start suspend CPU */
187 brc 2,4b /* busy, try again */
1885:
189 sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */
1906: j 6b
191
192restart_suspend:
193 larl %r1,.Lresume_cpu
194 llgh %r2,0(%r1)
1957:
196 sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */
197 brc 2,7b /* busy, try again */
198 tmll %r9,0x40 /* Test if resume CPU is stopped */
199 jz 7b
200
201restore_registers:
163 /* Restore registers */ 202 /* Restore registers */
164 lghi %r13,0x1000 /* %r1 = pointer to save arae */ 203 lghi %r13,0x1000 /* %r1 = pointer to save arae */
165 204
@@ -193,13 +232,6 @@ pgm_check_entry:
193 /* Pointer to save area */ 232 /* Pointer to save area */
194 lghi %r13,0x1000 233 lghi %r13,0x1000
195 234
196#ifdef CONFIG_SMP
197 /* Switch CPUs */
198 larl %r1,saved_cpu_id
199 llgf %r2,0(%r1)
200 llgf %r3,0x318(%r13)
201 brasl %r14,smp_switch_boot_cpu_in_resume
202#endif
203 /* Restore prefix register */ 235 /* Restore prefix register */
204 spx 0x318(%r13) 236 spx 0x318(%r13)
205 237
@@ -217,13 +249,16 @@ pgm_check_entry:
217 249
218 .section .data.nosave,"aw",@progbits 250 .section .data.nosave,"aw",@progbits
219 .align 8 251 .align 8
220restart_psw: 252.Ldisabled_wait_31:
253 .long 0x000a0000,0x00000000
254.Lpanic_string:
255 .asciz "Resume not possible because suspend CPU is no longer available"
256 .align 8
257.Lrestart_diag308_psw:
221 .long 0x00080000,0x80000000 258 .long 0x00080000,0x80000000
222new_pgm_check_psw: 259.Lrestart_suspend_psw:
260 .quad 0x0000000180000000,restart_suspend
261.Lnew_pgm_check_psw:
223 .quad 0,pgm_check_entry 262 .quad 0,pgm_check_entry
224saved_pgm_check_psw: 263.Lresume_cpu:
225 .quad 0,0 264 .byte 0,0
226#ifdef CONFIG_SMP
227saved_cpu_id:
228 .long 0
229#endif