diff options
-rw-r--r-- | arch/s390/include/asm/lowcore.h | 1 | ||||
-rw-r--r-- | arch/s390/kernel/asm-offsets.c | 7 | ||||
-rw-r--r-- | arch/s390/kernel/sclp.S | 5 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 36 | ||||
-rw-r--r-- | arch/s390/kernel/swsusp_asm64.S | 91 |
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 | ||
11 | int main(void) | 12 | int 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: | |||
1041 | static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, | 1041 | static 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 | */ | ||
1048 | void 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 | |||
1065 | found: | ||
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 | |||
1075 | u32 smp_get_phys_cpu_id(void) | ||
1076 | { | ||
1077 | return __cpu_logical_map[smp_processor_id()]; | ||
1078 | } | ||
1079 | |||
1080 | static int __init topology_init(void) | 1044 | static 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) |
159 | pgm_check_entry: | 156 | pgm_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) | ||
168 | 3: | ||
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) | ||
184 | 4: | ||
185 | /* Switch to suspend CPU */ | ||
186 | sigp %r9,%r1,__SIGP_RESTART /* start suspend CPU */ | ||
187 | brc 2,4b /* busy, try again */ | ||
188 | 5: | ||
189 | sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */ | ||
190 | 6: j 6b | ||
191 | |||
192 | restart_suspend: | ||
193 | larl %r1,.Lresume_cpu | ||
194 | llgh %r2,0(%r1) | ||
195 | 7: | ||
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 | |||
201 | restore_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 |
220 | restart_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 |
222 | new_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 |
224 | saved_pgm_check_psw: | 263 | .Lresume_cpu: |
225 | .quad 0,0 | 264 | .byte 0,0 |
226 | #ifdef CONFIG_SMP | ||
227 | saved_cpu_id: | ||
228 | .long 0 | ||
229 | #endif | ||