diff options
Diffstat (limited to 'arch/s390')
155 files changed, 6807 insertions, 3730 deletions
diff --git a/arch/s390/Kbuild b/arch/s390/Kbuild new file mode 100644 index 000000000000..ae4b01060edd --- /dev/null +++ b/arch/s390/Kbuild | |||
@@ -0,0 +1,6 @@ | |||
1 | obj-y += kernel/ | ||
2 | obj-y += mm/ | ||
3 | obj-y += crypto/ | ||
4 | obj-y += appldata/ | ||
5 | obj-y += hypfs/ | ||
6 | obj-y += kvm/ | ||
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index f0777a47e3a5..c03fef7a9c22 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -1,18 +1,8 @@ | |||
1 | # | ||
2 | # For a description of the syntax of this configuration file, | ||
3 | # see Documentation/kbuild/kconfig-language.txt. | ||
4 | # | ||
5 | |||
6 | config SCHED_MC | ||
7 | def_bool y | ||
8 | depends on SMP | ||
9 | |||
10 | config MMU | 1 | config MMU |
11 | def_bool y | 2 | def_bool y |
12 | 3 | ||
13 | config ZONE_DMA | 4 | config ZONE_DMA |
14 | def_bool y | 5 | def_bool y |
15 | depends on 64BIT | ||
16 | 6 | ||
17 | config LOCKDEP_SUPPORT | 7 | config LOCKDEP_SUPPORT |
18 | def_bool y | 8 | def_bool y |
@@ -30,12 +20,10 @@ config RWSEM_XCHGADD_ALGORITHM | |||
30 | def_bool y | 20 | def_bool y |
31 | 21 | ||
32 | config ARCH_HAS_ILOG2_U32 | 22 | config ARCH_HAS_ILOG2_U32 |
33 | bool | 23 | def_bool n |
34 | default n | ||
35 | 24 | ||
36 | config ARCH_HAS_ILOG2_U64 | 25 | config ARCH_HAS_ILOG2_U64 |
37 | bool | 26 | def_bool n |
38 | default n | ||
39 | 27 | ||
40 | config GENERIC_HWEIGHT | 28 | config GENERIC_HWEIGHT |
41 | def_bool y | 29 | def_bool y |
@@ -47,9 +35,7 @@ config GENERIC_CLOCKEVENTS | |||
47 | def_bool y | 35 | def_bool y |
48 | 36 | ||
49 | config GENERIC_BUG | 37 | config GENERIC_BUG |
50 | bool | 38 | def_bool y if BUG |
51 | depends on BUG | ||
52 | default y | ||
53 | 39 | ||
54 | config GENERIC_BUG_RELATIVE_POINTERS | 40 | config GENERIC_BUG_RELATIVE_POINTERS |
55 | def_bool y | 41 | def_bool y |
@@ -60,14 +46,14 @@ config NO_IOMEM | |||
60 | config NO_DMA | 46 | config NO_DMA |
61 | def_bool y | 47 | def_bool y |
62 | 48 | ||
49 | config ARCH_DMA_ADDR_T_64BIT | ||
50 | def_bool 64BIT | ||
51 | |||
63 | config GENERIC_LOCKBREAK | 52 | config GENERIC_LOCKBREAK |
64 | bool | 53 | def_bool y if SMP && PREEMPT |
65 | default y | ||
66 | depends on SMP && PREEMPT | ||
67 | 54 | ||
68 | config PGSTE | 55 | config PGSTE |
69 | bool | 56 | def_bool y if KVM |
70 | default y if KVM | ||
71 | 57 | ||
72 | config VIRT_CPU_ACCOUNTING | 58 | config VIRT_CPU_ACCOUNTING |
73 | def_bool y | 59 | def_bool y |
@@ -75,8 +61,6 @@ config VIRT_CPU_ACCOUNTING | |||
75 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | 61 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC |
76 | def_bool y | 62 | def_bool y |
77 | 63 | ||
78 | mainmenu "Linux Kernel Configuration" | ||
79 | |||
80 | config S390 | 64 | config S390 |
81 | def_bool y | 65 | def_bool y |
82 | select USE_GENERIC_SMP_HELPERS if SMP | 66 | select USE_GENERIC_SMP_HELPERS if SMP |
@@ -84,22 +68,28 @@ config S390 | |||
84 | select HAVE_FUNCTION_TRACER | 68 | select HAVE_FUNCTION_TRACER |
85 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST | 69 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST |
86 | select HAVE_FTRACE_MCOUNT_RECORD | 70 | select HAVE_FTRACE_MCOUNT_RECORD |
71 | select HAVE_C_RECORDMCOUNT | ||
87 | select HAVE_SYSCALL_TRACEPOINTS | 72 | select HAVE_SYSCALL_TRACEPOINTS |
88 | select HAVE_DYNAMIC_FTRACE | 73 | select HAVE_DYNAMIC_FTRACE |
89 | select HAVE_FUNCTION_GRAPH_TRACER | 74 | select HAVE_FUNCTION_GRAPH_TRACER |
90 | select HAVE_REGS_AND_STACK_ACCESS_API | 75 | select HAVE_REGS_AND_STACK_ACCESS_API |
91 | select HAVE_DEFAULT_NO_SPIN_MUTEXES | ||
92 | select HAVE_OPROFILE | 76 | select HAVE_OPROFILE |
93 | select HAVE_KPROBES | 77 | select HAVE_KPROBES |
94 | select HAVE_KRETPROBES | 78 | select HAVE_KRETPROBES |
95 | select HAVE_KVM if 64BIT | 79 | select HAVE_KVM if 64BIT |
96 | select HAVE_ARCH_TRACEHOOK | 80 | select HAVE_ARCH_TRACEHOOK |
97 | select INIT_ALL_POSSIBLE | 81 | select INIT_ALL_POSSIBLE |
82 | select HAVE_IRQ_WORK | ||
98 | select HAVE_PERF_EVENTS | 83 | select HAVE_PERF_EVENTS |
99 | select HAVE_KERNEL_GZIP | 84 | select HAVE_KERNEL_GZIP |
100 | select HAVE_KERNEL_BZIP2 | 85 | select HAVE_KERNEL_BZIP2 |
101 | select HAVE_KERNEL_LZMA | 86 | select HAVE_KERNEL_LZMA |
102 | select HAVE_KERNEL_LZO | 87 | select HAVE_KERNEL_LZO |
88 | select HAVE_KERNEL_XZ | ||
89 | select HAVE_GET_USER_PAGES_FAST | ||
90 | select HAVE_ARCH_MUTEX_CPU_RELAX | ||
91 | select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 | ||
92 | select HAVE_RCU_TABLE_FREE if SMP | ||
103 | select ARCH_INLINE_SPIN_TRYLOCK | 93 | select ARCH_INLINE_SPIN_TRYLOCK |
104 | select ARCH_INLINE_SPIN_TRYLOCK_BH | 94 | select ARCH_INLINE_SPIN_TRYLOCK_BH |
105 | select ARCH_INLINE_SPIN_LOCK | 95 | select ARCH_INLINE_SPIN_LOCK |
@@ -130,8 +120,7 @@ config S390 | |||
130 | select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE | 120 | select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE |
131 | 121 | ||
132 | config SCHED_OMIT_FRAME_POINTER | 122 | config SCHED_OMIT_FRAME_POINTER |
133 | bool | 123 | def_bool y |
134 | default y | ||
135 | 124 | ||
136 | source "init/Kconfig" | 125 | source "init/Kconfig" |
137 | 126 | ||
@@ -144,20 +133,21 @@ comment "Processor type and features" | |||
144 | source "kernel/time/Kconfig" | 133 | source "kernel/time/Kconfig" |
145 | 134 | ||
146 | config 64BIT | 135 | config 64BIT |
147 | bool "64 bit kernel" | 136 | def_bool y |
137 | prompt "64 bit kernel" | ||
148 | help | 138 | help |
149 | Select this option if you have a 64 bit IBM zSeries machine | 139 | Select this option if you have an IBM z/Architecture machine |
150 | and want to use the 64 bit addressing mode. | 140 | and want to use the 64 bit addressing mode. |
151 | 141 | ||
152 | config 32BIT | 142 | config 32BIT |
153 | bool | 143 | def_bool y if !64BIT |
154 | default y if !64BIT | ||
155 | 144 | ||
156 | config KTIME_SCALAR | 145 | config KTIME_SCALAR |
157 | def_bool 32BIT | 146 | def_bool 32BIT |
158 | 147 | ||
159 | config SMP | 148 | config SMP |
160 | bool "Symmetric multi-processing support" | 149 | def_bool y |
150 | prompt "Symmetric multi-processing support" | ||
161 | ---help--- | 151 | ---help--- |
162 | This enables support for systems with more than one CPU. If you have | 152 | This enables support for systems with more than one CPU. If you have |
163 | a system with only one CPU, like most personal computers, say N. If | 153 | a system with only one CPU, like most personal computers, say N. If |
@@ -189,25 +179,44 @@ config NR_CPUS | |||
189 | approximately sixteen kilobytes to the kernel image. | 179 | approximately sixteen kilobytes to the kernel image. |
190 | 180 | ||
191 | config HOTPLUG_CPU | 181 | config HOTPLUG_CPU |
192 | bool "Support for hot-pluggable CPUs" | 182 | def_bool y |
183 | prompt "Support for hot-pluggable CPUs" | ||
193 | depends on SMP | 184 | depends on SMP |
194 | select HOTPLUG | 185 | select HOTPLUG |
195 | default n | ||
196 | help | 186 | help |
197 | Say Y here to be able to turn CPUs off and on. CPUs | 187 | Say Y here to be able to turn CPUs off and on. CPUs |
198 | can be controlled through /sys/devices/system/cpu/cpu#. | 188 | can be controlled through /sys/devices/system/cpu/cpu#. |
199 | Say N if you want to disable CPU hotplug. | 189 | Say N if you want to disable CPU hotplug. |
200 | 190 | ||
191 | config SCHED_MC | ||
192 | def_bool y | ||
193 | prompt "Multi-core scheduler support" | ||
194 | depends on SMP | ||
195 | help | ||
196 | Multi-core scheduler support improves the CPU scheduler's decision | ||
197 | making when dealing with multi-core CPU chips at a cost of slightly | ||
198 | increased overhead in some places. | ||
199 | |||
200 | config SCHED_BOOK | ||
201 | def_bool y | ||
202 | prompt "Book scheduler support" | ||
203 | depends on SMP && SCHED_MC | ||
204 | help | ||
205 | Book scheduler support improves the CPU scheduler's decision making | ||
206 | when dealing with machines that have several books. | ||
207 | |||
201 | config MATHEMU | 208 | config MATHEMU |
202 | bool "IEEE FPU emulation" | 209 | def_bool y |
210 | prompt "IEEE FPU emulation" | ||
203 | depends on MARCH_G5 | 211 | depends on MARCH_G5 |
204 | help | 212 | help |
205 | This option is required for IEEE compliant floating point arithmetic | 213 | This option is required for IEEE compliant floating point arithmetic |
206 | on older S/390 machines. Say Y unless you know your machine doesn't | 214 | on older ESA/390 machines. Say Y unless you know your machine doesn't |
207 | need this. | 215 | need this. |
208 | 216 | ||
209 | config COMPAT | 217 | config COMPAT |
210 | bool "Kernel support for 31 bit emulation" | 218 | def_bool y |
219 | prompt "Kernel support for 31 bit emulation" | ||
211 | depends on 64BIT | 220 | depends on 64BIT |
212 | select COMPAT_BINFMT_ELF | 221 | select COMPAT_BINFMT_ELF |
213 | help | 222 | help |
@@ -217,23 +226,10 @@ config COMPAT | |||
217 | executing 31 bit applications. It is safe to say "Y". | 226 | executing 31 bit applications. It is safe to say "Y". |
218 | 227 | ||
219 | config SYSVIPC_COMPAT | 228 | config SYSVIPC_COMPAT |
220 | bool | 229 | def_bool y if COMPAT && SYSVIPC |
221 | depends on COMPAT && SYSVIPC | ||
222 | default y | ||
223 | 230 | ||
224 | config AUDIT_ARCH | 231 | config AUDIT_ARCH |
225 | bool | 232 | def_bool y |
226 | default y | ||
227 | |||
228 | config S390_EXEC_PROTECT | ||
229 | bool "Data execute protection" | ||
230 | help | ||
231 | This option allows to enable a buffer overflow protection for user | ||
232 | space programs and it also selects the addressing mode option above. | ||
233 | The kernel parameter noexec=on will enable this feature and also | ||
234 | switch the addressing modes, default is disabled. Enabling this (via | ||
235 | kernel parameter) on machines earlier than IBM System z9-109 EC/BC | ||
236 | will reduce system performance. | ||
237 | 233 | ||
238 | comment "Code generation options" | 234 | comment "Code generation options" |
239 | 235 | ||
@@ -242,46 +238,52 @@ choice | |||
242 | default MARCH_G5 | 238 | default MARCH_G5 |
243 | 239 | ||
244 | config MARCH_G5 | 240 | config MARCH_G5 |
245 | bool "S/390 model G5 and G6" | 241 | bool "System/390 model G5 and G6" |
246 | depends on !64BIT | 242 | depends on !64BIT |
247 | help | 243 | help |
248 | Select this to build a 31 bit kernel that works | 244 | Select this to build a 31 bit kernel that works |
249 | on all S/390 and zSeries machines. | 245 | on all ESA/390 and z/Architecture machines. |
250 | 246 | ||
251 | config MARCH_Z900 | 247 | config MARCH_Z900 |
252 | bool "IBM eServer zSeries model z800 and z900" | 248 | bool "IBM zSeries model z800 and z900" |
253 | help | 249 | help |
254 | Select this to optimize for zSeries machines. This | 250 | Select this to enable optimizations for model z800/z900 (2064 and |
255 | will enable some optimizations that are not available | 251 | 2066 series). This will enable some optimizations that are not |
256 | on older 31 bit only CPUs. | 252 | available on older ESA/390 (31 Bit) only CPUs. |
257 | 253 | ||
258 | config MARCH_Z990 | 254 | config MARCH_Z990 |
259 | bool "IBM eServer zSeries model z890 and z990" | 255 | bool "IBM zSeries model z890 and z990" |
260 | help | 256 | help |
261 | Select this enable optimizations for model z890/z990. | 257 | Select this to enable optimizations for model z890/z990 (2084 and |
262 | This will be slightly faster but does not work on | 258 | 2086 series). The kernel will be slightly faster but will not work |
263 | older machines such as the z900. | 259 | on older machines. |
264 | 260 | ||
265 | config MARCH_Z9_109 | 261 | config MARCH_Z9_109 |
266 | bool "IBM System z9" | 262 | bool "IBM System z9" |
267 | help | 263 | help |
268 | Select this to enable optimizations for IBM System z9-109, IBM | 264 | Select this to enable optimizations for IBM System z9 (2094 and |
269 | System z9 Enterprise Class (z9 EC), and IBM System z9 Business | 265 | 2096 series). The kernel will be slightly faster but will not work |
270 | Class (z9 BC). The kernel will be slightly faster but will not | 266 | on older machines. |
271 | work on older machines such as the z990, z890, z900, and z800. | ||
272 | 267 | ||
273 | config MARCH_Z10 | 268 | config MARCH_Z10 |
274 | bool "IBM System z10" | 269 | bool "IBM System z10" |
275 | help | 270 | help |
276 | Select this to enable optimizations for IBM System z10. The | 271 | Select this to enable optimizations for IBM System z10 (2097 and |
277 | kernel will be slightly faster but will not work on older | 272 | 2098 series). The kernel will be slightly faster but will not work |
278 | machines such as the z990, z890, z900, z800, z9-109, z9-ec | 273 | on older machines. |
279 | and z9-bc. | 274 | |
275 | config MARCH_Z196 | ||
276 | bool "IBM zEnterprise 196" | ||
277 | help | ||
278 | Select this to enable optimizations for IBM zEnterprise 196 | ||
279 | (2817 series). The kernel will be slightly faster but will not work | ||
280 | on older machines. | ||
280 | 281 | ||
281 | endchoice | 282 | endchoice |
282 | 283 | ||
283 | config PACK_STACK | 284 | config PACK_STACK |
284 | bool "Pack kernel stack" | 285 | def_bool y |
286 | prompt "Pack kernel stack" | ||
285 | help | 287 | help |
286 | This option enables the compiler option -mkernel-backchain if it | 288 | This option enables the compiler option -mkernel-backchain if it |
287 | is available. If the option is available the compiler supports | 289 | is available. If the option is available the compiler supports |
@@ -294,7 +296,8 @@ config PACK_STACK | |||
294 | Say Y if you are unsure. | 296 | Say Y if you are unsure. |
295 | 297 | ||
296 | config SMALL_STACK | 298 | config SMALL_STACK |
297 | bool "Use 8kb for kernel stack instead of 16kb" | 299 | def_bool n |
300 | prompt "Use 8kb for kernel stack instead of 16kb" | ||
298 | depends on PACK_STACK && 64BIT && !LOCKDEP | 301 | depends on PACK_STACK && 64BIT && !LOCKDEP |
299 | help | 302 | help |
300 | If you say Y here and the compiler supports the -mkernel-backchain | 303 | If you say Y here and the compiler supports the -mkernel-backchain |
@@ -306,7 +309,8 @@ config SMALL_STACK | |||
306 | Say N if you are unsure. | 309 | Say N if you are unsure. |
307 | 310 | ||
308 | config CHECK_STACK | 311 | config CHECK_STACK |
309 | bool "Detect kernel stack overflow" | 312 | def_bool y |
313 | prompt "Detect kernel stack overflow" | ||
310 | help | 314 | help |
311 | This option enables the compiler option -mstack-guard and | 315 | This option enables the compiler option -mstack-guard and |
312 | -mstack-size if they are available. If the compiler supports them | 316 | -mstack-size if they are available. If the compiler supports them |
@@ -329,25 +333,16 @@ config STACK_GUARD | |||
329 | The minimum size for the stack guard should be 256 for 31 bit and | 333 | The minimum size for the stack guard should be 256 for 31 bit and |
330 | 512 for 64 bit. | 334 | 512 for 64 bit. |
331 | 335 | ||
332 | config WARN_STACK | 336 | config WARN_DYNAMIC_STACK |
333 | bool "Emit compiler warnings for function with broken stack usage" | 337 | def_bool n |
338 | prompt "Emit compiler warnings for function with dynamic stack usage" | ||
334 | help | 339 | help |
335 | This option enables the compiler options -mwarn-framesize and | 340 | This option enables the compiler option -mwarn-dynamicstack. If the |
336 | -mwarn-dynamicstack. If the compiler supports these options it | 341 | compiler supports this options generates warnings for functions |
337 | will generate warnings for function which either use alloca or | 342 | that dynamically allocate stack space using alloca. |
338 | create a stack frame bigger than CONFIG_WARN_STACK_SIZE. | ||
339 | 343 | ||
340 | Say N if you are unsure. | 344 | Say N if you are unsure. |
341 | 345 | ||
342 | config WARN_STACK_SIZE | ||
343 | int "Maximum frame size considered safe (128-2048)" | ||
344 | range 128 2048 | ||
345 | depends on WARN_STACK | ||
346 | default "2048" | ||
347 | help | ||
348 | This allows you to specify the maximum frame size a function may | ||
349 | have without the compiler complaining about it. | ||
350 | |||
351 | config ARCH_POPULATES_NODE_MAP | 346 | config ARCH_POPULATES_NODE_MAP |
352 | def_bool y | 347 | def_bool y |
353 | 348 | ||
@@ -365,24 +360,24 @@ config ARCH_SPARSEMEM_DEFAULT | |||
365 | def_bool y | 360 | def_bool y |
366 | 361 | ||
367 | config ARCH_SELECT_MEMORY_MODEL | 362 | config ARCH_SELECT_MEMORY_MODEL |
368 | def_bool y | 363 | def_bool y |
369 | 364 | ||
370 | config ARCH_ENABLE_MEMORY_HOTPLUG | 365 | config ARCH_ENABLE_MEMORY_HOTPLUG |
371 | def_bool y | 366 | def_bool y if SPARSEMEM |
372 | depends on SPARSEMEM | ||
373 | 367 | ||
374 | config ARCH_ENABLE_MEMORY_HOTREMOVE | 368 | config ARCH_ENABLE_MEMORY_HOTREMOVE |
375 | def_bool y | 369 | def_bool y |
376 | 370 | ||
377 | config ARCH_HIBERNATION_POSSIBLE | 371 | config ARCH_HIBERNATION_POSSIBLE |
378 | def_bool y if 64BIT | 372 | def_bool y if 64BIT |
379 | 373 | ||
380 | source "mm/Kconfig" | 374 | source "mm/Kconfig" |
381 | 375 | ||
382 | comment "I/O subsystem configuration" | 376 | comment "I/O subsystem configuration" |
383 | 377 | ||
384 | config QDIO | 378 | config QDIO |
385 | tristate "QDIO support" | 379 | def_tristate y |
380 | prompt "QDIO support" | ||
386 | ---help--- | 381 | ---help--- |
387 | This driver provides the Queued Direct I/O base support for | 382 | This driver provides the Queued Direct I/O base support for |
388 | IBM System z. | 383 | IBM System z. |
@@ -393,7 +388,8 @@ config QDIO | |||
393 | If unsure, say Y. | 388 | If unsure, say Y. |
394 | 389 | ||
395 | config CHSC_SCH | 390 | config CHSC_SCH |
396 | tristate "Support for CHSC subchannels" | 391 | def_tristate m |
392 | prompt "Support for CHSC subchannels" | ||
397 | help | 393 | help |
398 | This driver allows usage of CHSC subchannels. A CHSC subchannel | 394 | This driver allows usage of CHSC subchannels. A CHSC subchannel |
399 | is usually present on LPAR only. | 395 | is usually present on LPAR only. |
@@ -411,7 +407,8 @@ config CHSC_SCH | |||
411 | comment "Misc" | 407 | comment "Misc" |
412 | 408 | ||
413 | config IPL | 409 | config IPL |
414 | bool "Builtin IPL record support" | 410 | def_bool y |
411 | prompt "Builtin IPL record support" | ||
415 | help | 412 | help |
416 | If you want to use the produced kernel to IPL directly from a | 413 | If you want to use the produced kernel to IPL directly from a |
417 | device, you have to merge a bootsector specific to the device | 414 | device, you have to merge a bootsector specific to the device |
@@ -443,7 +440,8 @@ config FORCE_MAX_ZONEORDER | |||
443 | default "9" | 440 | default "9" |
444 | 441 | ||
445 | config PFAULT | 442 | config PFAULT |
446 | bool "Pseudo page fault support" | 443 | def_bool y |
444 | prompt "Pseudo page fault support" | ||
447 | help | 445 | help |
448 | Select this option, if you want to use PFAULT pseudo page fault | 446 | Select this option, if you want to use PFAULT pseudo page fault |
449 | handling under VM. If running native or in LPAR, this option | 447 | handling under VM. If running native or in LPAR, this option |
@@ -455,7 +453,8 @@ config PFAULT | |||
455 | this option. | 453 | this option. |
456 | 454 | ||
457 | config SHARED_KERNEL | 455 | config SHARED_KERNEL |
458 | bool "VM shared kernel support" | 456 | def_bool y |
457 | prompt "VM shared kernel support" | ||
459 | help | 458 | help |
460 | Select this option, if you want to share the text segment of the | 459 | Select this option, if you want to share the text segment of the |
461 | Linux kernel between different VM guests. This reduces memory | 460 | Linux kernel between different VM guests. This reduces memory |
@@ -466,7 +465,8 @@ config SHARED_KERNEL | |||
466 | doing and want to exploit this feature. | 465 | doing and want to exploit this feature. |
467 | 466 | ||
468 | config CMM | 467 | config CMM |
469 | tristate "Cooperative memory management" | 468 | def_tristate n |
469 | prompt "Cooperative memory management" | ||
470 | help | 470 | help |
471 | Select this option, if you want to enable the kernel interface | 471 | Select this option, if you want to enable the kernel interface |
472 | to reduce the memory size of the system. This is accomplished | 472 | to reduce the memory size of the system. This is accomplished |
@@ -478,14 +478,16 @@ config CMM | |||
478 | option. | 478 | option. |
479 | 479 | ||
480 | config CMM_IUCV | 480 | config CMM_IUCV |
481 | bool "IUCV special message interface to cooperative memory management" | 481 | def_bool y |
482 | prompt "IUCV special message interface to cooperative memory management" | ||
482 | depends on CMM && (SMSGIUCV=y || CMM=SMSGIUCV) | 483 | depends on CMM && (SMSGIUCV=y || CMM=SMSGIUCV) |
483 | help | 484 | help |
484 | Select this option to enable the special message interface to | 485 | Select this option to enable the special message interface to |
485 | the cooperative memory management. | 486 | the cooperative memory management. |
486 | 487 | ||
487 | config APPLDATA_BASE | 488 | config APPLDATA_BASE |
488 | bool "Linux - VM Monitor Stream, base infrastructure" | 489 | def_bool n |
490 | prompt "Linux - VM Monitor Stream, base infrastructure" | ||
489 | depends on PROC_FS | 491 | depends on PROC_FS |
490 | help | 492 | help |
491 | This provides a kernel interface for creating and updating z/VM APPLDATA | 493 | This provides a kernel interface for creating and updating z/VM APPLDATA |
@@ -500,7 +502,8 @@ config APPLDATA_BASE | |||
500 | The /proc entries can also be read from, showing the current settings. | 502 | The /proc entries can also be read from, showing the current settings. |
501 | 503 | ||
502 | config APPLDATA_MEM | 504 | config APPLDATA_MEM |
503 | tristate "Monitor memory management statistics" | 505 | def_tristate m |
506 | prompt "Monitor memory management statistics" | ||
504 | depends on APPLDATA_BASE && VM_EVENT_COUNTERS | 507 | depends on APPLDATA_BASE && VM_EVENT_COUNTERS |
505 | help | 508 | help |
506 | This provides memory management related data to the Linux - VM Monitor | 509 | This provides memory management related data to the Linux - VM Monitor |
@@ -516,7 +519,8 @@ config APPLDATA_MEM | |||
516 | appldata_mem.o. | 519 | appldata_mem.o. |
517 | 520 | ||
518 | config APPLDATA_OS | 521 | config APPLDATA_OS |
519 | tristate "Monitor OS statistics" | 522 | def_tristate m |
523 | prompt "Monitor OS statistics" | ||
520 | depends on APPLDATA_BASE | 524 | depends on APPLDATA_BASE |
521 | help | 525 | help |
522 | This provides OS related data to the Linux - VM Monitor Stream, like | 526 | This provides OS related data to the Linux - VM Monitor Stream, like |
@@ -530,7 +534,8 @@ config APPLDATA_OS | |||
530 | appldata_os.o. | 534 | appldata_os.o. |
531 | 535 | ||
532 | config APPLDATA_NET_SUM | 536 | config APPLDATA_NET_SUM |
533 | tristate "Monitor overall network statistics" | 537 | def_tristate m |
538 | prompt "Monitor overall network statistics" | ||
534 | depends on APPLDATA_BASE && NET | 539 | depends on APPLDATA_BASE && NET |
535 | help | 540 | help |
536 | This provides network related data to the Linux - VM Monitor Stream, | 541 | This provides network related data to the Linux - VM Monitor Stream, |
@@ -547,31 +552,34 @@ config APPLDATA_NET_SUM | |||
547 | source kernel/Kconfig.hz | 552 | source kernel/Kconfig.hz |
548 | 553 | ||
549 | config S390_HYPFS_FS | 554 | config S390_HYPFS_FS |
550 | bool "s390 hypervisor file system support" | 555 | def_bool y |
556 | prompt "s390 hypervisor file system support" | ||
551 | select SYS_HYPERVISOR | 557 | select SYS_HYPERVISOR |
552 | default y | ||
553 | help | 558 | help |
554 | This is a virtual file system intended to provide accounting | 559 | This is a virtual file system intended to provide accounting |
555 | information in an s390 hypervisor environment. | 560 | information in an s390 hypervisor environment. |
556 | 561 | ||
557 | config KEXEC | 562 | config KEXEC |
558 | bool "kexec system call" | 563 | def_bool n |
564 | prompt "kexec system call" | ||
559 | help | 565 | help |
560 | kexec is a system call that implements the ability to shutdown your | 566 | kexec is a system call that implements the ability to shutdown your |
561 | current kernel, and to start another kernel. It is like a reboot | 567 | current kernel, and to start another kernel. It is like a reboot |
562 | but is independent of hardware/microcode support. | 568 | but is independent of hardware/microcode support. |
563 | 569 | ||
564 | config ZFCPDUMP | 570 | config ZFCPDUMP |
565 | bool "zfcpdump support" | 571 | def_bool n |
572 | prompt "zfcpdump support" | ||
566 | select SMP | 573 | select SMP |
567 | default n | ||
568 | help | 574 | help |
569 | Select this option if you want to build an zfcpdump enabled kernel. | 575 | Select this option if you want to build an zfcpdump enabled kernel. |
570 | Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this. | 576 | Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this. |
571 | 577 | ||
572 | config S390_GUEST | 578 | config S390_GUEST |
573 | bool "s390 guest support for KVM (EXPERIMENTAL)" | 579 | def_bool y |
580 | prompt "s390 guest support for KVM (EXPERIMENTAL)" | ||
574 | depends on 64BIT && EXPERIMENTAL | 581 | depends on 64BIT && EXPERIMENTAL |
582 | select VIRTUALIZATION | ||
575 | select VIRTIO | 583 | select VIRTIO |
576 | select VIRTIO_RING | 584 | select VIRTIO_RING |
577 | select VIRTIO_CONSOLE | 585 | select VIRTIO_CONSOLE |
@@ -582,9 +590,9 @@ bool "s390 guest support for KVM (EXPERIMENTAL)" | |||
582 | the default console. | 590 | the default console. |
583 | 591 | ||
584 | config SECCOMP | 592 | config SECCOMP |
585 | bool "Enable seccomp to safely compute untrusted bytecode" | 593 | def_bool y |
594 | prompt "Enable seccomp to safely compute untrusted bytecode" | ||
586 | depends on PROC_FS | 595 | depends on PROC_FS |
587 | default y | ||
588 | help | 596 | help |
589 | This kernel feature is useful for number crunching applications | 597 | This kernel feature is useful for number crunching applications |
590 | that may need to compute untrusted bytecode during their | 598 | that may need to compute untrusted bytecode during their |
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug index 45e0c6199f36..d76cef3fef37 100644 --- a/arch/s390/Kconfig.debug +++ b/arch/s390/Kconfig.debug | |||
@@ -1,13 +1,25 @@ | |||
1 | menu "Kernel hacking" | 1 | menu "Kernel hacking" |
2 | 2 | ||
3 | config TRACE_IRQFLAGS_SUPPORT | 3 | config TRACE_IRQFLAGS_SUPPORT |
4 | bool | 4 | def_bool y |
5 | default y | ||
6 | 5 | ||
7 | source "lib/Kconfig.debug" | 6 | source "lib/Kconfig.debug" |
8 | 7 | ||
8 | config STRICT_DEVMEM | ||
9 | def_bool y | ||
10 | prompt "Filter access to /dev/mem" | ||
11 | ---help--- | ||
12 | This option restricts access to /dev/mem. If this option is | ||
13 | disabled, you allow userspace access to all memory, including | ||
14 | kernel and userspace memory. Accidental memory access is likely | ||
15 | to be disastrous. | ||
16 | Memory access is required for experts who want to debug the kernel. | ||
17 | |||
18 | If you are unsure, say Y. | ||
19 | |||
9 | config DEBUG_STRICT_USER_COPY_CHECKS | 20 | config DEBUG_STRICT_USER_COPY_CHECKS |
10 | bool "Strict user copy size checks" | 21 | def_bool n |
22 | prompt "Strict user copy size checks" | ||
11 | ---help--- | 23 | ---help--- |
12 | Enabling this option turns a certain set of sanity checks for user | 24 | Enabling this option turns a certain set of sanity checks for user |
13 | copy operations into compile time warnings. | 25 | copy operations into compile time warnings. |
@@ -19,4 +31,7 @@ config DEBUG_STRICT_USER_COPY_CHECKS | |||
19 | 31 | ||
20 | If unsure, or if you run an older (pre 4.4) gcc, say N. | 32 | If unsure, or if you run an older (pre 4.4) gcc, say N. |
21 | 33 | ||
34 | config DEBUG_SET_MODULE_RONX | ||
35 | def_bool y | ||
36 | depends on MODULES | ||
22 | endmenu | 37 | endmenu |
diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 0c9e6c6d2a64..27a0b5df5ead 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile | |||
@@ -40,6 +40,7 @@ cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900) | |||
40 | cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) | 40 | cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) |
41 | cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109) | 41 | cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109) |
42 | cflags-$(CONFIG_MARCH_Z10) += $(call cc-option,-march=z10) | 42 | cflags-$(CONFIG_MARCH_Z10) += $(call cc-option,-march=z10) |
43 | cflags-$(CONFIG_MARCH_Z196) += $(call cc-option,-march=z196) | ||
43 | 44 | ||
44 | #KBUILD_IMAGE is necessary for make rpm | 45 | #KBUILD_IMAGE is necessary for make rpm |
45 | KBUILD_IMAGE :=arch/s390/boot/image | 46 | KBUILD_IMAGE :=arch/s390/boot/image |
@@ -79,8 +80,7 @@ endif | |||
79 | endif | 80 | endif |
80 | 81 | ||
81 | ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y) | 82 | ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y) |
82 | cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack | 83 | cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack |
83 | cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE) | ||
84 | endif | 84 | endif |
85 | 85 | ||
86 | KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y) | 86 | KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y) |
@@ -94,8 +94,8 @@ head-y := arch/s390/kernel/head.o | |||
94 | head-y += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o) | 94 | head-y += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o) |
95 | head-y += arch/s390/kernel/init_task.o | 95 | head-y += arch/s390/kernel/init_task.o |
96 | 96 | ||
97 | core-y += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \ | 97 | # See arch/s390/Kbuild for content of core part of the kernel |
98 | arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/ | 98 | core-y += arch/s390/ |
99 | 99 | ||
100 | libs-y += arch/s390/lib/ | 100 | libs-y += arch/s390/lib/ |
101 | drivers-y += drivers/s390/ | 101 | drivers-y += drivers/s390/ |
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 5c91995b74e4..24bff4f1cc52 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c | |||
@@ -130,9 +130,7 @@ static void appldata_work_fn(struct work_struct *work) | |||
130 | { | 130 | { |
131 | struct list_head *lh; | 131 | struct list_head *lh; |
132 | struct appldata_ops *ops; | 132 | struct appldata_ops *ops; |
133 | int i; | ||
134 | 133 | ||
135 | i = 0; | ||
136 | get_online_cpus(); | 134 | get_online_cpus(); |
137 | mutex_lock(&appldata_ops_mutex); | 135 | mutex_lock(&appldata_ops_mutex); |
138 | list_for_each(lh, &appldata_ops_list) { | 136 | list_for_each(lh, &appldata_ops_list) { |
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c index e43fe7537031..f7d3dc555bdb 100644 --- a/arch/s390/appldata/appldata_mem.c +++ b/arch/s390/appldata/appldata_mem.c | |||
@@ -92,9 +92,7 @@ static void appldata_get_mem_data(void *data) | |||
92 | mem_data->pswpin = ev[PSWPIN]; | 92 | mem_data->pswpin = ev[PSWPIN]; |
93 | mem_data->pswpout = ev[PSWPOUT]; | 93 | mem_data->pswpout = ev[PSWPOUT]; |
94 | mem_data->pgalloc = ev[PGALLOC_NORMAL]; | 94 | mem_data->pgalloc = ev[PGALLOC_NORMAL]; |
95 | #ifdef CONFIG_ZONE_DMA | ||
96 | mem_data->pgalloc += ev[PGALLOC_DMA]; | 95 | mem_data->pgalloc += ev[PGALLOC_DMA]; |
97 | #endif | ||
98 | mem_data->pgfault = ev[PGFAULT]; | 96 | mem_data->pgfault = ev[PGFAULT]; |
99 | mem_data->pgmajfault = ev[PGMAJFAULT]; | 97 | mem_data->pgmajfault = ev[PGMAJFAULT]; |
100 | 98 | ||
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile index 8800cf090694..635d677d3281 100644 --- a/arch/s390/boot/Makefile +++ b/arch/s390/boot/Makefile | |||
@@ -6,7 +6,7 @@ COMPILE_VERSION := __linux_compile_version_id__`hostname | \ | |||
6 | tr -c '[0-9A-Za-z]' '_'`__`date | \ | 6 | tr -c '[0-9A-Za-z]' '_'`__`date | \ |
7 | tr -c '[0-9A-Za-z]' '_'`_t | 7 | tr -c '[0-9A-Za-z]' '_'`_t |
8 | 8 | ||
9 | EXTRA_CFLAGS := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I. | 9 | ccflags-y := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I. |
10 | 10 | ||
11 | targets := image | 11 | targets := image |
12 | targets += bzImage | 12 | targets += bzImage |
diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile index 1c999f726a58..10e22c4ec4a7 100644 --- a/arch/s390/boot/compressed/Makefile +++ b/arch/s390/boot/compressed/Makefile | |||
@@ -7,7 +7,8 @@ | |||
7 | BITS := $(if $(CONFIG_64BIT),64,31) | 7 | BITS := $(if $(CONFIG_64BIT),64,31) |
8 | 8 | ||
9 | targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ | 9 | targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ |
10 | vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o sizes.h head$(BITS).o | 10 | vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o \ |
11 | sizes.h head$(BITS).o | ||
11 | 12 | ||
12 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 | 13 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 |
13 | KBUILD_CFLAGS += $(cflags-y) | 14 | KBUILD_CFLAGS += $(cflags-y) |
@@ -48,6 +49,7 @@ suffix-$(CONFIG_KERNEL_GZIP) := gz | |||
48 | suffix-$(CONFIG_KERNEL_BZIP2) := bz2 | 49 | suffix-$(CONFIG_KERNEL_BZIP2) := bz2 |
49 | suffix-$(CONFIG_KERNEL_LZMA) := lzma | 50 | suffix-$(CONFIG_KERNEL_LZMA) := lzma |
50 | suffix-$(CONFIG_KERNEL_LZO) := lzo | 51 | suffix-$(CONFIG_KERNEL_LZO) := lzo |
52 | suffix-$(CONFIG_KERNEL_XZ) := xz | ||
51 | 53 | ||
52 | $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) | 54 | $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) |
53 | $(call if_changed,gzip) | 55 | $(call if_changed,gzip) |
@@ -57,6 +59,8 @@ $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) | |||
57 | $(call if_changed,lzma) | 59 | $(call if_changed,lzma) |
58 | $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) | 60 | $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) |
59 | $(call if_changed,lzo) | 61 | $(call if_changed,lzo) |
62 | $(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y) | ||
63 | $(call if_changed,xzkern) | ||
60 | 64 | ||
61 | LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T | 65 | LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T |
62 | $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) | 66 | $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) |
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c index 0851eb1e919e..028f23ea81d1 100644 --- a/arch/s390/boot/compressed/misc.c +++ b/arch/s390/boot/compressed/misc.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #undef memset | 19 | #undef memset |
20 | #undef memcpy | 20 | #undef memcpy |
21 | #undef memmove | 21 | #undef memmove |
22 | #define memmove memmove | ||
22 | #define memzero(s, n) memset((s), 0, (n)) | 23 | #define memzero(s, n) memset((s), 0, (n)) |
23 | 24 | ||
24 | /* Symbols defined by linker scripts */ | 25 | /* Symbols defined by linker scripts */ |
@@ -54,6 +55,10 @@ static unsigned long free_mem_end_ptr; | |||
54 | #include "../../../../lib/decompress_unlzo.c" | 55 | #include "../../../../lib/decompress_unlzo.c" |
55 | #endif | 56 | #endif |
56 | 57 | ||
58 | #ifdef CONFIG_KERNEL_XZ | ||
59 | #include "../../../../lib/decompress_unxz.c" | ||
60 | #endif | ||
61 | |||
57 | extern _sclp_print_early(const char *); | 62 | extern _sclp_print_early(const char *); |
58 | 63 | ||
59 | int puts(const char *s) | 64 | int puts(const char *s) |
@@ -133,11 +138,12 @@ unsigned long decompress_kernel(void) | |||
133 | unsigned long output_addr; | 138 | unsigned long output_addr; |
134 | unsigned char *output; | 139 | unsigned char *output; |
135 | 140 | ||
136 | check_ipl_parmblock((void *) 0, (unsigned long) output + SZ__bss_start); | 141 | output_addr = ((unsigned long) &_end + HEAP_SIZE + 4095UL) & -4096UL; |
142 | check_ipl_parmblock((void *) 0, output_addr + SZ__bss_start); | ||
137 | memset(&_bss, 0, &_ebss - &_bss); | 143 | memset(&_bss, 0, &_ebss - &_bss); |
138 | free_mem_ptr = (unsigned long)&_end; | 144 | free_mem_ptr = (unsigned long)&_end; |
139 | free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; | 145 | free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; |
140 | output = (unsigned char *) ((free_mem_end_ptr + 4095UL) & -4096UL); | 146 | output = (unsigned char *) output_addr; |
141 | 147 | ||
142 | #ifdef CONFIG_BLK_DEV_INITRD | 148 | #ifdef CONFIG_BLK_DEV_INITRD |
143 | /* | 149 | /* |
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile index 1cf81d77c5a5..7f0b7cda6259 100644 --- a/arch/s390/crypto/Makefile +++ b/arch/s390/crypto/Makefile | |||
@@ -8,3 +8,4 @@ obj-$(CONFIG_CRYPTO_SHA512_S390) += sha512_s390.o sha_common.o | |||
8 | obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o | 8 | obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o |
9 | obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o | 9 | obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o |
10 | obj-$(CONFIG_S390_PRNG) += prng.o | 10 | obj-$(CONFIG_S390_PRNG) += prng.o |
11 | obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o | ||
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index 58f46734465f..a9ce135893f8 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c | |||
@@ -31,7 +31,8 @@ | |||
31 | #define AES_KEYLEN_192 2 | 31 | #define AES_KEYLEN_192 2 |
32 | #define AES_KEYLEN_256 4 | 32 | #define AES_KEYLEN_256 4 |
33 | 33 | ||
34 | static char keylen_flag = 0; | 34 | static u8 *ctrblk; |
35 | static char keylen_flag; | ||
35 | 36 | ||
36 | struct s390_aes_ctx { | 37 | struct s390_aes_ctx { |
37 | u8 iv[AES_BLOCK_SIZE]; | 38 | u8 iv[AES_BLOCK_SIZE]; |
@@ -45,6 +46,24 @@ struct s390_aes_ctx { | |||
45 | } fallback; | 46 | } fallback; |
46 | }; | 47 | }; |
47 | 48 | ||
49 | struct pcc_param { | ||
50 | u8 key[32]; | ||
51 | u8 tweak[16]; | ||
52 | u8 block[16]; | ||
53 | u8 bit[16]; | ||
54 | u8 xts[16]; | ||
55 | }; | ||
56 | |||
57 | struct s390_xts_ctx { | ||
58 | u8 key[32]; | ||
59 | u8 xts_param[16]; | ||
60 | struct pcc_param pcc; | ||
61 | long enc; | ||
62 | long dec; | ||
63 | int key_len; | ||
64 | struct crypto_blkcipher *fallback; | ||
65 | }; | ||
66 | |||
48 | /* | 67 | /* |
49 | * Check if the key_len is supported by the HW. | 68 | * Check if the key_len is supported by the HW. |
50 | * Returns 0 if it is, a positive number if it is not and software fallback is | 69 | * Returns 0 if it is, a positive number if it is not and software fallback is |
@@ -504,15 +523,337 @@ static struct crypto_alg cbc_aes_alg = { | |||
504 | } | 523 | } |
505 | }; | 524 | }; |
506 | 525 | ||
526 | static int xts_fallback_setkey(struct crypto_tfm *tfm, const u8 *key, | ||
527 | unsigned int len) | ||
528 | { | ||
529 | struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); | ||
530 | unsigned int ret; | ||
531 | |||
532 | xts_ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; | ||
533 | xts_ctx->fallback->base.crt_flags |= (tfm->crt_flags & | ||
534 | CRYPTO_TFM_REQ_MASK); | ||
535 | |||
536 | ret = crypto_blkcipher_setkey(xts_ctx->fallback, key, len); | ||
537 | if (ret) { | ||
538 | tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; | ||
539 | tfm->crt_flags |= (xts_ctx->fallback->base.crt_flags & | ||
540 | CRYPTO_TFM_RES_MASK); | ||
541 | } | ||
542 | return ret; | ||
543 | } | ||
544 | |||
545 | static int xts_fallback_decrypt(struct blkcipher_desc *desc, | ||
546 | struct scatterlist *dst, struct scatterlist *src, | ||
547 | unsigned int nbytes) | ||
548 | { | ||
549 | struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm); | ||
550 | struct crypto_blkcipher *tfm; | ||
551 | unsigned int ret; | ||
552 | |||
553 | tfm = desc->tfm; | ||
554 | desc->tfm = xts_ctx->fallback; | ||
555 | |||
556 | ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes); | ||
557 | |||
558 | desc->tfm = tfm; | ||
559 | return ret; | ||
560 | } | ||
561 | |||
562 | static int xts_fallback_encrypt(struct blkcipher_desc *desc, | ||
563 | struct scatterlist *dst, struct scatterlist *src, | ||
564 | unsigned int nbytes) | ||
565 | { | ||
566 | struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm); | ||
567 | struct crypto_blkcipher *tfm; | ||
568 | unsigned int ret; | ||
569 | |||
570 | tfm = desc->tfm; | ||
571 | desc->tfm = xts_ctx->fallback; | ||
572 | |||
573 | ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes); | ||
574 | |||
575 | desc->tfm = tfm; | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, | ||
580 | unsigned int key_len) | ||
581 | { | ||
582 | struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); | ||
583 | u32 *flags = &tfm->crt_flags; | ||
584 | |||
585 | switch (key_len) { | ||
586 | case 32: | ||
587 | xts_ctx->enc = KM_XTS_128_ENCRYPT; | ||
588 | xts_ctx->dec = KM_XTS_128_DECRYPT; | ||
589 | memcpy(xts_ctx->key + 16, in_key, 16); | ||
590 | memcpy(xts_ctx->pcc.key + 16, in_key + 16, 16); | ||
591 | break; | ||
592 | case 48: | ||
593 | xts_ctx->enc = 0; | ||
594 | xts_ctx->dec = 0; | ||
595 | xts_fallback_setkey(tfm, in_key, key_len); | ||
596 | break; | ||
597 | case 64: | ||
598 | xts_ctx->enc = KM_XTS_256_ENCRYPT; | ||
599 | xts_ctx->dec = KM_XTS_256_DECRYPT; | ||
600 | memcpy(xts_ctx->key, in_key, 32); | ||
601 | memcpy(xts_ctx->pcc.key, in_key + 32, 32); | ||
602 | break; | ||
603 | default: | ||
604 | *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | ||
605 | return -EINVAL; | ||
606 | } | ||
607 | xts_ctx->key_len = key_len; | ||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | static int xts_aes_crypt(struct blkcipher_desc *desc, long func, | ||
612 | struct s390_xts_ctx *xts_ctx, | ||
613 | struct blkcipher_walk *walk) | ||
614 | { | ||
615 | unsigned int offset = (xts_ctx->key_len >> 1) & 0x10; | ||
616 | int ret = blkcipher_walk_virt(desc, walk); | ||
617 | unsigned int nbytes = walk->nbytes; | ||
618 | unsigned int n; | ||
619 | u8 *in, *out; | ||
620 | void *param; | ||
621 | |||
622 | if (!nbytes) | ||
623 | goto out; | ||
624 | |||
625 | memset(xts_ctx->pcc.block, 0, sizeof(xts_ctx->pcc.block)); | ||
626 | memset(xts_ctx->pcc.bit, 0, sizeof(xts_ctx->pcc.bit)); | ||
627 | memset(xts_ctx->pcc.xts, 0, sizeof(xts_ctx->pcc.xts)); | ||
628 | memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak)); | ||
629 | param = xts_ctx->pcc.key + offset; | ||
630 | ret = crypt_s390_pcc(func, param); | ||
631 | BUG_ON(ret < 0); | ||
632 | |||
633 | memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16); | ||
634 | param = xts_ctx->key + offset; | ||
635 | do { | ||
636 | /* only use complete blocks */ | ||
637 | n = nbytes & ~(AES_BLOCK_SIZE - 1); | ||
638 | out = walk->dst.virt.addr; | ||
639 | in = walk->src.virt.addr; | ||
640 | |||
641 | ret = crypt_s390_km(func, param, out, in, n); | ||
642 | BUG_ON(ret < 0 || ret != n); | ||
643 | |||
644 | nbytes &= AES_BLOCK_SIZE - 1; | ||
645 | ret = blkcipher_walk_done(desc, walk, nbytes); | ||
646 | } while ((nbytes = walk->nbytes)); | ||
647 | out: | ||
648 | return ret; | ||
649 | } | ||
650 | |||
651 | static int xts_aes_encrypt(struct blkcipher_desc *desc, | ||
652 | struct scatterlist *dst, struct scatterlist *src, | ||
653 | unsigned int nbytes) | ||
654 | { | ||
655 | struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm); | ||
656 | struct blkcipher_walk walk; | ||
657 | |||
658 | if (unlikely(xts_ctx->key_len == 48)) | ||
659 | return xts_fallback_encrypt(desc, dst, src, nbytes); | ||
660 | |||
661 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
662 | return xts_aes_crypt(desc, xts_ctx->enc, xts_ctx, &walk); | ||
663 | } | ||
664 | |||
665 | static int xts_aes_decrypt(struct blkcipher_desc *desc, | ||
666 | struct scatterlist *dst, struct scatterlist *src, | ||
667 | unsigned int nbytes) | ||
668 | { | ||
669 | struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm); | ||
670 | struct blkcipher_walk walk; | ||
671 | |||
672 | if (unlikely(xts_ctx->key_len == 48)) | ||
673 | return xts_fallback_decrypt(desc, dst, src, nbytes); | ||
674 | |||
675 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
676 | return xts_aes_crypt(desc, xts_ctx->dec, xts_ctx, &walk); | ||
677 | } | ||
678 | |||
679 | static int xts_fallback_init(struct crypto_tfm *tfm) | ||
680 | { | ||
681 | const char *name = tfm->__crt_alg->cra_name; | ||
682 | struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); | ||
683 | |||
684 | xts_ctx->fallback = crypto_alloc_blkcipher(name, 0, | ||
685 | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK); | ||
686 | |||
687 | if (IS_ERR(xts_ctx->fallback)) { | ||
688 | pr_err("Allocating XTS fallback algorithm %s failed\n", | ||
689 | name); | ||
690 | return PTR_ERR(xts_ctx->fallback); | ||
691 | } | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | static void xts_fallback_exit(struct crypto_tfm *tfm) | ||
696 | { | ||
697 | struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); | ||
698 | |||
699 | crypto_free_blkcipher(xts_ctx->fallback); | ||
700 | xts_ctx->fallback = NULL; | ||
701 | } | ||
702 | |||
703 | static struct crypto_alg xts_aes_alg = { | ||
704 | .cra_name = "xts(aes)", | ||
705 | .cra_driver_name = "xts-aes-s390", | ||
706 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, | ||
707 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | | ||
708 | CRYPTO_ALG_NEED_FALLBACK, | ||
709 | .cra_blocksize = AES_BLOCK_SIZE, | ||
710 | .cra_ctxsize = sizeof(struct s390_xts_ctx), | ||
711 | .cra_type = &crypto_blkcipher_type, | ||
712 | .cra_module = THIS_MODULE, | ||
713 | .cra_list = LIST_HEAD_INIT(xts_aes_alg.cra_list), | ||
714 | .cra_init = xts_fallback_init, | ||
715 | .cra_exit = xts_fallback_exit, | ||
716 | .cra_u = { | ||
717 | .blkcipher = { | ||
718 | .min_keysize = 2 * AES_MIN_KEY_SIZE, | ||
719 | .max_keysize = 2 * AES_MAX_KEY_SIZE, | ||
720 | .ivsize = AES_BLOCK_SIZE, | ||
721 | .setkey = xts_aes_set_key, | ||
722 | .encrypt = xts_aes_encrypt, | ||
723 | .decrypt = xts_aes_decrypt, | ||
724 | } | ||
725 | } | ||
726 | }; | ||
727 | |||
728 | static int ctr_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, | ||
729 | unsigned int key_len) | ||
730 | { | ||
731 | struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); | ||
732 | |||
733 | switch (key_len) { | ||
734 | case 16: | ||
735 | sctx->enc = KMCTR_AES_128_ENCRYPT; | ||
736 | sctx->dec = KMCTR_AES_128_DECRYPT; | ||
737 | break; | ||
738 | case 24: | ||
739 | sctx->enc = KMCTR_AES_192_ENCRYPT; | ||
740 | sctx->dec = KMCTR_AES_192_DECRYPT; | ||
741 | break; | ||
742 | case 32: | ||
743 | sctx->enc = KMCTR_AES_256_ENCRYPT; | ||
744 | sctx->dec = KMCTR_AES_256_DECRYPT; | ||
745 | break; | ||
746 | } | ||
747 | |||
748 | return aes_set_key(tfm, in_key, key_len); | ||
749 | } | ||
750 | |||
751 | static int ctr_aes_crypt(struct blkcipher_desc *desc, long func, | ||
752 | struct s390_aes_ctx *sctx, struct blkcipher_walk *walk) | ||
753 | { | ||
754 | int ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE); | ||
755 | unsigned int i, n, nbytes; | ||
756 | u8 buf[AES_BLOCK_SIZE]; | ||
757 | u8 *out, *in; | ||
758 | |||
759 | if (!walk->nbytes) | ||
760 | return ret; | ||
761 | |||
762 | memcpy(ctrblk, walk->iv, AES_BLOCK_SIZE); | ||
763 | while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) { | ||
764 | out = walk->dst.virt.addr; | ||
765 | in = walk->src.virt.addr; | ||
766 | while (nbytes >= AES_BLOCK_SIZE) { | ||
767 | /* only use complete blocks, max. PAGE_SIZE */ | ||
768 | n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : | ||
769 | nbytes & ~(AES_BLOCK_SIZE - 1); | ||
770 | for (i = AES_BLOCK_SIZE; i < n; i += AES_BLOCK_SIZE) { | ||
771 | memcpy(ctrblk + i, ctrblk + i - AES_BLOCK_SIZE, | ||
772 | AES_BLOCK_SIZE); | ||
773 | crypto_inc(ctrblk + i, AES_BLOCK_SIZE); | ||
774 | } | ||
775 | ret = crypt_s390_kmctr(func, sctx->key, out, in, n, ctrblk); | ||
776 | BUG_ON(ret < 0 || ret != n); | ||
777 | if (n > AES_BLOCK_SIZE) | ||
778 | memcpy(ctrblk, ctrblk + n - AES_BLOCK_SIZE, | ||
779 | AES_BLOCK_SIZE); | ||
780 | crypto_inc(ctrblk, AES_BLOCK_SIZE); | ||
781 | out += n; | ||
782 | in += n; | ||
783 | nbytes -= n; | ||
784 | } | ||
785 | ret = blkcipher_walk_done(desc, walk, nbytes); | ||
786 | } | ||
787 | /* | ||
788 | * final block may be < AES_BLOCK_SIZE, copy only nbytes | ||
789 | */ | ||
790 | if (nbytes) { | ||
791 | out = walk->dst.virt.addr; | ||
792 | in = walk->src.virt.addr; | ||
793 | ret = crypt_s390_kmctr(func, sctx->key, buf, in, | ||
794 | AES_BLOCK_SIZE, ctrblk); | ||
795 | BUG_ON(ret < 0 || ret != AES_BLOCK_SIZE); | ||
796 | memcpy(out, buf, nbytes); | ||
797 | crypto_inc(ctrblk, AES_BLOCK_SIZE); | ||
798 | ret = blkcipher_walk_done(desc, walk, 0); | ||
799 | } | ||
800 | memcpy(walk->iv, ctrblk, AES_BLOCK_SIZE); | ||
801 | return ret; | ||
802 | } | ||
803 | |||
804 | static int ctr_aes_encrypt(struct blkcipher_desc *desc, | ||
805 | struct scatterlist *dst, struct scatterlist *src, | ||
806 | unsigned int nbytes) | ||
807 | { | ||
808 | struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | ||
809 | struct blkcipher_walk walk; | ||
810 | |||
811 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
812 | return ctr_aes_crypt(desc, sctx->enc, sctx, &walk); | ||
813 | } | ||
814 | |||
815 | static int ctr_aes_decrypt(struct blkcipher_desc *desc, | ||
816 | struct scatterlist *dst, struct scatterlist *src, | ||
817 | unsigned int nbytes) | ||
818 | { | ||
819 | struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | ||
820 | struct blkcipher_walk walk; | ||
821 | |||
822 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
823 | return ctr_aes_crypt(desc, sctx->dec, sctx, &walk); | ||
824 | } | ||
825 | |||
826 | static struct crypto_alg ctr_aes_alg = { | ||
827 | .cra_name = "ctr(aes)", | ||
828 | .cra_driver_name = "ctr-aes-s390", | ||
829 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, | ||
830 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
831 | .cra_blocksize = 1, | ||
832 | .cra_ctxsize = sizeof(struct s390_aes_ctx), | ||
833 | .cra_type = &crypto_blkcipher_type, | ||
834 | .cra_module = THIS_MODULE, | ||
835 | .cra_list = LIST_HEAD_INIT(ctr_aes_alg.cra_list), | ||
836 | .cra_u = { | ||
837 | .blkcipher = { | ||
838 | .min_keysize = AES_MIN_KEY_SIZE, | ||
839 | .max_keysize = AES_MAX_KEY_SIZE, | ||
840 | .ivsize = AES_BLOCK_SIZE, | ||
841 | .setkey = ctr_aes_set_key, | ||
842 | .encrypt = ctr_aes_encrypt, | ||
843 | .decrypt = ctr_aes_decrypt, | ||
844 | } | ||
845 | } | ||
846 | }; | ||
847 | |||
507 | static int __init aes_s390_init(void) | 848 | static int __init aes_s390_init(void) |
508 | { | 849 | { |
509 | int ret; | 850 | int ret; |
510 | 851 | ||
511 | if (crypt_s390_func_available(KM_AES_128_ENCRYPT)) | 852 | if (crypt_s390_func_available(KM_AES_128_ENCRYPT, CRYPT_S390_MSA)) |
512 | keylen_flag |= AES_KEYLEN_128; | 853 | keylen_flag |= AES_KEYLEN_128; |
513 | if (crypt_s390_func_available(KM_AES_192_ENCRYPT)) | 854 | if (crypt_s390_func_available(KM_AES_192_ENCRYPT, CRYPT_S390_MSA)) |
514 | keylen_flag |= AES_KEYLEN_192; | 855 | keylen_flag |= AES_KEYLEN_192; |
515 | if (crypt_s390_func_available(KM_AES_256_ENCRYPT)) | 856 | if (crypt_s390_func_available(KM_AES_256_ENCRYPT, CRYPT_S390_MSA)) |
516 | keylen_flag |= AES_KEYLEN_256; | 857 | keylen_flag |= AES_KEYLEN_256; |
517 | 858 | ||
518 | if (!keylen_flag) | 859 | if (!keylen_flag) |
@@ -535,9 +876,40 @@ static int __init aes_s390_init(void) | |||
535 | if (ret) | 876 | if (ret) |
536 | goto cbc_aes_err; | 877 | goto cbc_aes_err; |
537 | 878 | ||
879 | if (crypt_s390_func_available(KM_XTS_128_ENCRYPT, | ||
880 | CRYPT_S390_MSA | CRYPT_S390_MSA4) && | ||
881 | crypt_s390_func_available(KM_XTS_256_ENCRYPT, | ||
882 | CRYPT_S390_MSA | CRYPT_S390_MSA4)) { | ||
883 | ret = crypto_register_alg(&xts_aes_alg); | ||
884 | if (ret) | ||
885 | goto xts_aes_err; | ||
886 | } | ||
887 | |||
888 | if (crypt_s390_func_available(KMCTR_AES_128_ENCRYPT, | ||
889 | CRYPT_S390_MSA | CRYPT_S390_MSA4) && | ||
890 | crypt_s390_func_available(KMCTR_AES_192_ENCRYPT, | ||
891 | CRYPT_S390_MSA | CRYPT_S390_MSA4) && | ||
892 | crypt_s390_func_available(KMCTR_AES_256_ENCRYPT, | ||
893 | CRYPT_S390_MSA | CRYPT_S390_MSA4)) { | ||
894 | ctrblk = (u8 *) __get_free_page(GFP_KERNEL); | ||
895 | if (!ctrblk) { | ||
896 | ret = -ENOMEM; | ||
897 | goto ctr_aes_err; | ||
898 | } | ||
899 | ret = crypto_register_alg(&ctr_aes_alg); | ||
900 | if (ret) { | ||
901 | free_page((unsigned long) ctrblk); | ||
902 | goto ctr_aes_err; | ||
903 | } | ||
904 | } | ||
905 | |||
538 | out: | 906 | out: |
539 | return ret; | 907 | return ret; |
540 | 908 | ||
909 | ctr_aes_err: | ||
910 | crypto_unregister_alg(&xts_aes_alg); | ||
911 | xts_aes_err: | ||
912 | crypto_unregister_alg(&cbc_aes_alg); | ||
541 | cbc_aes_err: | 913 | cbc_aes_err: |
542 | crypto_unregister_alg(&ecb_aes_alg); | 914 | crypto_unregister_alg(&ecb_aes_alg); |
543 | ecb_aes_err: | 915 | ecb_aes_err: |
@@ -548,6 +920,9 @@ aes_err: | |||
548 | 920 | ||
549 | static void __exit aes_s390_fini(void) | 921 | static void __exit aes_s390_fini(void) |
550 | { | 922 | { |
923 | crypto_unregister_alg(&ctr_aes_alg); | ||
924 | free_page((unsigned long) ctrblk); | ||
925 | crypto_unregister_alg(&xts_aes_alg); | ||
551 | crypto_unregister_alg(&cbc_aes_alg); | 926 | crypto_unregister_alg(&cbc_aes_alg); |
552 | crypto_unregister_alg(&ecb_aes_alg); | 927 | crypto_unregister_alg(&ecb_aes_alg); |
553 | crypto_unregister_alg(&aes_alg); | 928 | crypto_unregister_alg(&aes_alg); |
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h index 0ef9829f2ad6..49676771bd66 100644 --- a/arch/s390/crypto/crypt_s390.h +++ b/arch/s390/crypto/crypt_s390.h | |||
@@ -24,13 +24,18 @@ | |||
24 | #define CRYPT_S390_PRIORITY 300 | 24 | #define CRYPT_S390_PRIORITY 300 |
25 | #define CRYPT_S390_COMPOSITE_PRIORITY 400 | 25 | #define CRYPT_S390_COMPOSITE_PRIORITY 400 |
26 | 26 | ||
27 | #define CRYPT_S390_MSA 0x1 | ||
28 | #define CRYPT_S390_MSA3 0x2 | ||
29 | #define CRYPT_S390_MSA4 0x4 | ||
30 | |||
27 | /* s390 cryptographic operations */ | 31 | /* s390 cryptographic operations */ |
28 | enum crypt_s390_operations { | 32 | enum crypt_s390_operations { |
29 | CRYPT_S390_KM = 0x0100, | 33 | CRYPT_S390_KM = 0x0100, |
30 | CRYPT_S390_KMC = 0x0200, | 34 | CRYPT_S390_KMC = 0x0200, |
31 | CRYPT_S390_KIMD = 0x0300, | 35 | CRYPT_S390_KIMD = 0x0300, |
32 | CRYPT_S390_KLMD = 0x0400, | 36 | CRYPT_S390_KLMD = 0x0400, |
33 | CRYPT_S390_KMAC = 0x0500 | 37 | CRYPT_S390_KMAC = 0x0500, |
38 | CRYPT_S390_KMCTR = 0x0600 | ||
34 | }; | 39 | }; |
35 | 40 | ||
36 | /* | 41 | /* |
@@ -51,6 +56,10 @@ enum crypt_s390_km_func { | |||
51 | KM_AES_192_DECRYPT = CRYPT_S390_KM | 0x13 | 0x80, | 56 | KM_AES_192_DECRYPT = CRYPT_S390_KM | 0x13 | 0x80, |
52 | KM_AES_256_ENCRYPT = CRYPT_S390_KM | 0x14, | 57 | KM_AES_256_ENCRYPT = CRYPT_S390_KM | 0x14, |
53 | KM_AES_256_DECRYPT = CRYPT_S390_KM | 0x14 | 0x80, | 58 | KM_AES_256_DECRYPT = CRYPT_S390_KM | 0x14 | 0x80, |
59 | KM_XTS_128_ENCRYPT = CRYPT_S390_KM | 0x32, | ||
60 | KM_XTS_128_DECRYPT = CRYPT_S390_KM | 0x32 | 0x80, | ||
61 | KM_XTS_256_ENCRYPT = CRYPT_S390_KM | 0x34, | ||
62 | KM_XTS_256_DECRYPT = CRYPT_S390_KM | 0x34 | 0x80, | ||
54 | }; | 63 | }; |
55 | 64 | ||
56 | /* | 65 | /* |
@@ -75,6 +84,26 @@ enum crypt_s390_kmc_func { | |||
75 | }; | 84 | }; |
76 | 85 | ||
77 | /* | 86 | /* |
87 | * function codes for KMCTR (CIPHER MESSAGE WITH COUNTER) | ||
88 | * instruction | ||
89 | */ | ||
90 | enum crypt_s390_kmctr_func { | ||
91 | KMCTR_QUERY = CRYPT_S390_KMCTR | 0x0, | ||
92 | KMCTR_DEA_ENCRYPT = CRYPT_S390_KMCTR | 0x1, | ||
93 | KMCTR_DEA_DECRYPT = CRYPT_S390_KMCTR | 0x1 | 0x80, | ||
94 | KMCTR_TDEA_128_ENCRYPT = CRYPT_S390_KMCTR | 0x2, | ||
95 | KMCTR_TDEA_128_DECRYPT = CRYPT_S390_KMCTR | 0x2 | 0x80, | ||
96 | KMCTR_TDEA_192_ENCRYPT = CRYPT_S390_KMCTR | 0x3, | ||
97 | KMCTR_TDEA_192_DECRYPT = CRYPT_S390_KMCTR | 0x3 | 0x80, | ||
98 | KMCTR_AES_128_ENCRYPT = CRYPT_S390_KMCTR | 0x12, | ||
99 | KMCTR_AES_128_DECRYPT = CRYPT_S390_KMCTR | 0x12 | 0x80, | ||
100 | KMCTR_AES_192_ENCRYPT = CRYPT_S390_KMCTR | 0x13, | ||
101 | KMCTR_AES_192_DECRYPT = CRYPT_S390_KMCTR | 0x13 | 0x80, | ||
102 | KMCTR_AES_256_ENCRYPT = CRYPT_S390_KMCTR | 0x14, | ||
103 | KMCTR_AES_256_DECRYPT = CRYPT_S390_KMCTR | 0x14 | 0x80, | ||
104 | }; | ||
105 | |||
106 | /* | ||
78 | * function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) | 107 | * function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) |
79 | * instruction | 108 | * instruction |
80 | */ | 109 | */ |
@@ -83,6 +112,7 @@ enum crypt_s390_kimd_func { | |||
83 | KIMD_SHA_1 = CRYPT_S390_KIMD | 1, | 112 | KIMD_SHA_1 = CRYPT_S390_KIMD | 1, |
84 | KIMD_SHA_256 = CRYPT_S390_KIMD | 2, | 113 | KIMD_SHA_256 = CRYPT_S390_KIMD | 2, |
85 | KIMD_SHA_512 = CRYPT_S390_KIMD | 3, | 114 | KIMD_SHA_512 = CRYPT_S390_KIMD | 3, |
115 | KIMD_GHASH = CRYPT_S390_KIMD | 65, | ||
86 | }; | 116 | }; |
87 | 117 | ||
88 | /* | 118 | /* |
@@ -284,6 +314,45 @@ static inline int crypt_s390_kmac(long func, void *param, | |||
284 | } | 314 | } |
285 | 315 | ||
286 | /** | 316 | /** |
317 | * crypt_s390_kmctr: | ||
318 | * @func: the function code passed to KMCTR; see crypt_s390_kmctr_func | ||
319 | * @param: address of parameter block; see POP for details on each func | ||
320 | * @dest: address of destination memory area | ||
321 | * @src: address of source memory area | ||
322 | * @src_len: length of src operand in bytes | ||
323 | * @counter: address of counter value | ||
324 | * | ||
325 | * Executes the KMCTR (CIPHER MESSAGE WITH COUNTER) operation of the CPU. | ||
326 | * | ||
327 | * Returns -1 for failure, 0 for the query func, number of processed | ||
328 | * bytes for encryption/decryption funcs | ||
329 | */ | ||
330 | static inline int crypt_s390_kmctr(long func, void *param, u8 *dest, | ||
331 | const u8 *src, long src_len, u8 *counter) | ||
332 | { | ||
333 | register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; | ||
334 | register void *__param asm("1") = param; | ||
335 | register const u8 *__src asm("2") = src; | ||
336 | register long __src_len asm("3") = src_len; | ||
337 | register u8 *__dest asm("4") = dest; | ||
338 | register u8 *__ctr asm("6") = counter; | ||
339 | int ret = -1; | ||
340 | |||
341 | asm volatile( | ||
342 | "0: .insn rrf,0xb92d0000,%3,%1,%4,0 \n" /* KMCTR opcode */ | ||
343 | "1: brc 1,0b \n" /* handle partial completion */ | ||
344 | " la %0,0\n" | ||
345 | "2:\n" | ||
346 | EX_TABLE(0b,2b) EX_TABLE(1b,2b) | ||
347 | : "+d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest), | ||
348 | "+a" (__ctr) | ||
349 | : "d" (__func), "a" (__param) : "cc", "memory"); | ||
350 | if (ret < 0) | ||
351 | return ret; | ||
352 | return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; | ||
353 | } | ||
354 | |||
355 | /** | ||
287 | * crypt_s390_func_available: | 356 | * crypt_s390_func_available: |
288 | * @func: the function code of the specific function; 0 if op in general | 357 | * @func: the function code of the specific function; 0 if op in general |
289 | * | 358 | * |
@@ -291,13 +360,17 @@ static inline int crypt_s390_kmac(long func, void *param, | |||
291 | * | 360 | * |
292 | * Returns 1 if func available; 0 if func or op in general not available | 361 | * Returns 1 if func available; 0 if func or op in general not available |
293 | */ | 362 | */ |
294 | static inline int crypt_s390_func_available(int func) | 363 | static inline int crypt_s390_func_available(int func, |
364 | unsigned int facility_mask) | ||
295 | { | 365 | { |
296 | unsigned char status[16]; | 366 | unsigned char status[16]; |
297 | int ret; | 367 | int ret; |
298 | 368 | ||
299 | /* check if CPACF facility (bit 17) is available */ | 369 | if (facility_mask & CRYPT_S390_MSA && !test_facility(17)) |
300 | if (!(stfl() & 1ULL << (31 - 17))) | 370 | return 0; |
371 | if (facility_mask & CRYPT_S390_MSA3 && !test_facility(76)) | ||
372 | return 0; | ||
373 | if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77)) | ||
301 | return 0; | 374 | return 0; |
302 | 375 | ||
303 | switch (func & CRYPT_S390_OP_MASK) { | 376 | switch (func & CRYPT_S390_OP_MASK) { |
@@ -316,6 +389,10 @@ static inline int crypt_s390_func_available(int func) | |||
316 | case CRYPT_S390_KMAC: | 389 | case CRYPT_S390_KMAC: |
317 | ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); | 390 | ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); |
318 | break; | 391 | break; |
392 | case CRYPT_S390_KMCTR: | ||
393 | ret = crypt_s390_kmctr(KMCTR_QUERY, &status, NULL, NULL, 0, | ||
394 | NULL); | ||
395 | break; | ||
319 | default: | 396 | default: |
320 | return 0; | 397 | return 0; |
321 | } | 398 | } |
@@ -326,4 +403,31 @@ static inline int crypt_s390_func_available(int func) | |||
326 | return (status[func >> 3] & (0x80 >> (func & 7))) != 0; | 403 | return (status[func >> 3] & (0x80 >> (func & 7))) != 0; |
327 | } | 404 | } |
328 | 405 | ||
406 | /** | ||
407 | * crypt_s390_pcc: | ||
408 | * @func: the function code passed to KM; see crypt_s390_km_func | ||
409 | * @param: address of parameter block; see POP for details on each func | ||
410 | * | ||
411 | * Executes the PCC (PERFORM CRYPTOGRAPHIC COMPUTATION) operation of the CPU. | ||
412 | * | ||
413 | * Returns -1 for failure, 0 for success. | ||
414 | */ | ||
415 | static inline int crypt_s390_pcc(long func, void *param) | ||
416 | { | ||
417 | register long __func asm("0") = func & 0x7f; /* encrypt or decrypt */ | ||
418 | register void *__param asm("1") = param; | ||
419 | int ret = -1; | ||
420 | |||
421 | asm volatile( | ||
422 | "0: .insn rre,0xb92c0000,0,0 \n" /* PCC opcode */ | ||
423 | "1: brc 1,0b \n" /* handle partial completion */ | ||
424 | " la %0,0\n" | ||
425 | "2:\n" | ||
426 | EX_TABLE(0b,2b) EX_TABLE(1b,2b) | ||
427 | : "+d" (ret) | ||
428 | : "d" (__func), "a" (__param) : "cc", "memory"); | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | |||
329 | #endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */ | 433 | #endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */ |
diff --git a/arch/s390/crypto/des_check_key.c b/arch/s390/crypto/des_check_key.c deleted file mode 100644 index 5706af266442..000000000000 --- a/arch/s390/crypto/des_check_key.c +++ /dev/null | |||
@@ -1,132 +0,0 @@ | |||
1 | /* | ||
2 | * Cryptographic API. | ||
3 | * | ||
4 | * Function for checking keys for the DES and Tripple DES Encryption | ||
5 | * algorithms. | ||
6 | * | ||
7 | * Originally released as descore by Dana L. How <how@isl.stanford.edu>. | ||
8 | * Modified by Raimar Falke <rf13@inf.tu-dresden.de> for the Linux-Kernel. | ||
9 | * Derived from Cryptoapi and Nettle implementations, adapted for in-place | ||
10 | * scatterlist interface. Changed LGPL to GPL per section 3 of the LGPL. | ||
11 | * | ||
12 | * s390 Version: | ||
13 | * Copyright IBM Corp. 2003 | ||
14 | * Author(s): Thomas Spatzier | ||
15 | * Jan Glauber (jan.glauber@de.ibm.com) | ||
16 | * | ||
17 | * Derived from "crypto/des.c" | ||
18 | * Copyright (c) 1992 Dana L. How. | ||
19 | * Copyright (c) Raimar Falke <rf13@inf.tu-dresden.de> | ||
20 | * Copyright (c) Gisle Sflensminde <gisle@ii.uib.no> | ||
21 | * Copyright (C) 2001 Niels Mvller. | ||
22 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> | ||
23 | * | ||
24 | * This program is free software; you can redistribute it and/or modify | ||
25 | * it under the terms of the GNU General Public License as published by | ||
26 | * the Free Software Foundation; either version 2 of the License, or | ||
27 | * (at your option) any later version. | ||
28 | * | ||
29 | */ | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/crypto.h> | ||
34 | #include "crypto_des.h" | ||
35 | |||
36 | #define ROR(d,c,o) ((d) = (d) >> (c) | (d) << (o)) | ||
37 | |||
38 | static const u8 parity[] = { | ||
39 | 8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3, | ||
40 | 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, | ||
41 | 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, | ||
42 | 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, | ||
43 | 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8, | ||
44 | 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, | ||
45 | 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0, | ||
46 | 4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8, | ||
47 | }; | ||
48 | |||
49 | /* | ||
50 | * RFC2451: Weak key checks SHOULD be performed. | ||
51 | */ | ||
52 | int | ||
53 | crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags) | ||
54 | { | ||
55 | u32 n, w; | ||
56 | |||
57 | n = parity[key[0]]; n <<= 4; | ||
58 | n |= parity[key[1]]; n <<= 4; | ||
59 | n |= parity[key[2]]; n <<= 4; | ||
60 | n |= parity[key[3]]; n <<= 4; | ||
61 | n |= parity[key[4]]; n <<= 4; | ||
62 | n |= parity[key[5]]; n <<= 4; | ||
63 | n |= parity[key[6]]; n <<= 4; | ||
64 | n |= parity[key[7]]; | ||
65 | w = 0x88888888L; | ||
66 | |||
67 | if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY) | ||
68 | && !((n - (w >> 3)) & w)) { /* 1 in 10^10 keys passes this test */ | ||
69 | if (n < 0x41415151) { | ||
70 | if (n < 0x31312121) { | ||
71 | if (n < 0x14141515) { | ||
72 | /* 01 01 01 01 01 01 01 01 */ | ||
73 | if (n == 0x11111111) goto weak; | ||
74 | /* 01 1F 01 1F 01 0E 01 0E */ | ||
75 | if (n == 0x13131212) goto weak; | ||
76 | } else { | ||
77 | /* 01 E0 01 E0 01 F1 01 F1 */ | ||
78 | if (n == 0x14141515) goto weak; | ||
79 | /* 01 FE 01 FE 01 FE 01 FE */ | ||
80 | if (n == 0x16161616) goto weak; | ||
81 | } | ||
82 | } else { | ||
83 | if (n < 0x34342525) { | ||
84 | /* 1F 01 1F 01 0E 01 0E 01 */ | ||
85 | if (n == 0x31312121) goto weak; | ||
86 | /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */ | ||
87 | if (n == 0x33332222) goto weak; | ||
88 | } else { | ||
89 | /* 1F E0 1F E0 0E F1 0E F1 */ | ||
90 | if (n == 0x34342525) goto weak; | ||
91 | /* 1F FE 1F FE 0E FE 0E FE */ | ||
92 | if (n == 0x36362626) goto weak; | ||
93 | } | ||
94 | } | ||
95 | } else { | ||
96 | if (n < 0x61616161) { | ||
97 | if (n < 0x44445555) { | ||
98 | /* E0 01 E0 01 F1 01 F1 01 */ | ||
99 | if (n == 0x41415151) goto weak; | ||
100 | /* E0 1F E0 1F F1 0E F1 0E */ | ||
101 | if (n == 0x43435252) goto weak; | ||
102 | } else { | ||
103 | /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */ | ||
104 | if (n == 0x44445555) goto weak; | ||
105 | /* E0 FE E0 FE F1 FE F1 FE */ | ||
106 | if (n == 0x46465656) goto weak; | ||
107 | } | ||
108 | } else { | ||
109 | if (n < 0x64646565) { | ||
110 | /* FE 01 FE 01 FE 01 FE 01 */ | ||
111 | if (n == 0x61616161) goto weak; | ||
112 | /* FE 1F FE 1F FE 0E FE 0E */ | ||
113 | if (n == 0x63636262) goto weak; | ||
114 | } else { | ||
115 | /* FE E0 FE E0 FE F1 FE F1 */ | ||
116 | if (n == 0x64646565) goto weak; | ||
117 | /* FE FE FE FE FE FE FE FE */ | ||
118 | if (n == 0x66666666) goto weak; | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | return 0; | ||
124 | weak: | ||
125 | *flags |= CRYPTO_TFM_RES_WEAK_KEY; | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | EXPORT_SYMBOL(crypto_des_check_key); | ||
130 | |||
131 | MODULE_LICENSE("GPL"); | ||
132 | MODULE_DESCRIPTION("Key Check function for DES & DES3 Cipher Algorithms"); | ||
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c index cc5420118393..a52bfd124d86 100644 --- a/arch/s390/crypto/des_s390.c +++ b/arch/s390/crypto/des_s390.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * s390 implementation of the DES Cipher Algorithm. | 4 | * s390 implementation of the DES Cipher Algorithm. |
5 | * | 5 | * |
6 | * Copyright IBM Corp. 2003,2007 | 6 | * Copyright IBM Corp. 2003,2011 |
7 | * Author(s): Thomas Spatzier | 7 | * Author(s): Thomas Spatzier |
8 | * Jan Glauber (jan.glauber@de.ibm.com) | 8 | * Jan Glauber (jan.glauber@de.ibm.com) |
9 | * | 9 | * |
@@ -22,22 +22,19 @@ | |||
22 | 22 | ||
23 | #include "crypt_s390.h" | 23 | #include "crypt_s390.h" |
24 | 24 | ||
25 | #define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE) | 25 | #define DES3_KEY_SIZE (3 * DES_KEY_SIZE) |
26 | 26 | ||
27 | struct crypt_s390_des_ctx { | 27 | static u8 *ctrblk; |
28 | u8 iv[DES_BLOCK_SIZE]; | ||
29 | u8 key[DES_KEY_SIZE]; | ||
30 | }; | ||
31 | 28 | ||
32 | struct crypt_s390_des3_192_ctx { | 29 | struct s390_des_ctx { |
33 | u8 iv[DES_BLOCK_SIZE]; | 30 | u8 iv[DES_BLOCK_SIZE]; |
34 | u8 key[DES3_192_KEY_SIZE]; | 31 | u8 key[DES3_KEY_SIZE]; |
35 | }; | 32 | }; |
36 | 33 | ||
37 | static int des_setkey(struct crypto_tfm *tfm, const u8 *key, | 34 | static int des_setkey(struct crypto_tfm *tfm, const u8 *key, |
38 | unsigned int keylen) | 35 | unsigned int key_len) |
39 | { | 36 | { |
40 | struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm); | 37 | struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); |
41 | u32 *flags = &tfm->crt_flags; | 38 | u32 *flags = &tfm->crt_flags; |
42 | u32 tmp[DES_EXPKEY_WORDS]; | 39 | u32 tmp[DES_EXPKEY_WORDS]; |
43 | 40 | ||
@@ -47,22 +44,22 @@ static int des_setkey(struct crypto_tfm *tfm, const u8 *key, | |||
47 | return -EINVAL; | 44 | return -EINVAL; |
48 | } | 45 | } |
49 | 46 | ||
50 | memcpy(dctx->key, key, keylen); | 47 | memcpy(ctx->key, key, key_len); |
51 | return 0; | 48 | return 0; |
52 | } | 49 | } |
53 | 50 | ||
54 | static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) | 51 | static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) |
55 | { | 52 | { |
56 | struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm); | 53 | struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); |
57 | 54 | ||
58 | crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, out, in, DES_BLOCK_SIZE); | 55 | crypt_s390_km(KM_DEA_ENCRYPT, ctx->key, out, in, DES_BLOCK_SIZE); |
59 | } | 56 | } |
60 | 57 | ||
61 | static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) | 58 | static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) |
62 | { | 59 | { |
63 | struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm); | 60 | struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); |
64 | 61 | ||
65 | crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE); | 62 | crypt_s390_km(KM_DEA_DECRYPT, ctx->key, out, in, DES_BLOCK_SIZE); |
66 | } | 63 | } |
67 | 64 | ||
68 | static struct crypto_alg des_alg = { | 65 | static struct crypto_alg des_alg = { |
@@ -71,7 +68,7 @@ static struct crypto_alg des_alg = { | |||
71 | .cra_priority = CRYPT_S390_PRIORITY, | 68 | .cra_priority = CRYPT_S390_PRIORITY, |
72 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, | 69 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, |
73 | .cra_blocksize = DES_BLOCK_SIZE, | 70 | .cra_blocksize = DES_BLOCK_SIZE, |
74 | .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), | 71 | .cra_ctxsize = sizeof(struct s390_des_ctx), |
75 | .cra_module = THIS_MODULE, | 72 | .cra_module = THIS_MODULE, |
76 | .cra_list = LIST_HEAD_INIT(des_alg.cra_list), | 73 | .cra_list = LIST_HEAD_INIT(des_alg.cra_list), |
77 | .cra_u = { | 74 | .cra_u = { |
@@ -86,7 +83,7 @@ static struct crypto_alg des_alg = { | |||
86 | }; | 83 | }; |
87 | 84 | ||
88 | static int ecb_desall_crypt(struct blkcipher_desc *desc, long func, | 85 | static int ecb_desall_crypt(struct blkcipher_desc *desc, long func, |
89 | void *param, struct blkcipher_walk *walk) | 86 | u8 *key, struct blkcipher_walk *walk) |
90 | { | 87 | { |
91 | int ret = blkcipher_walk_virt(desc, walk); | 88 | int ret = blkcipher_walk_virt(desc, walk); |
92 | unsigned int nbytes; | 89 | unsigned int nbytes; |
@@ -97,7 +94,7 @@ static int ecb_desall_crypt(struct blkcipher_desc *desc, long func, | |||
97 | u8 *out = walk->dst.virt.addr; | 94 | u8 *out = walk->dst.virt.addr; |
98 | u8 *in = walk->src.virt.addr; | 95 | u8 *in = walk->src.virt.addr; |
99 | 96 | ||
100 | ret = crypt_s390_km(func, param, out, in, n); | 97 | ret = crypt_s390_km(func, key, out, in, n); |
101 | BUG_ON((ret < 0) || (ret != n)); | 98 | BUG_ON((ret < 0) || (ret != n)); |
102 | 99 | ||
103 | nbytes &= DES_BLOCK_SIZE - 1; | 100 | nbytes &= DES_BLOCK_SIZE - 1; |
@@ -108,7 +105,7 @@ static int ecb_desall_crypt(struct blkcipher_desc *desc, long func, | |||
108 | } | 105 | } |
109 | 106 | ||
110 | static int cbc_desall_crypt(struct blkcipher_desc *desc, long func, | 107 | static int cbc_desall_crypt(struct blkcipher_desc *desc, long func, |
111 | void *param, struct blkcipher_walk *walk) | 108 | u8 *iv, struct blkcipher_walk *walk) |
112 | { | 109 | { |
113 | int ret = blkcipher_walk_virt(desc, walk); | 110 | int ret = blkcipher_walk_virt(desc, walk); |
114 | unsigned int nbytes = walk->nbytes; | 111 | unsigned int nbytes = walk->nbytes; |
@@ -116,20 +113,20 @@ static int cbc_desall_crypt(struct blkcipher_desc *desc, long func, | |||
116 | if (!nbytes) | 113 | if (!nbytes) |
117 | goto out; | 114 | goto out; |
118 | 115 | ||
119 | memcpy(param, walk->iv, DES_BLOCK_SIZE); | 116 | memcpy(iv, walk->iv, DES_BLOCK_SIZE); |
120 | do { | 117 | do { |
121 | /* only use complete blocks */ | 118 | /* only use complete blocks */ |
122 | unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); | 119 | unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); |
123 | u8 *out = walk->dst.virt.addr; | 120 | u8 *out = walk->dst.virt.addr; |
124 | u8 *in = walk->src.virt.addr; | 121 | u8 *in = walk->src.virt.addr; |
125 | 122 | ||
126 | ret = crypt_s390_kmc(func, param, out, in, n); | 123 | ret = crypt_s390_kmc(func, iv, out, in, n); |
127 | BUG_ON((ret < 0) || (ret != n)); | 124 | BUG_ON((ret < 0) || (ret != n)); |
128 | 125 | ||
129 | nbytes &= DES_BLOCK_SIZE - 1; | 126 | nbytes &= DES_BLOCK_SIZE - 1; |
130 | ret = blkcipher_walk_done(desc, walk, nbytes); | 127 | ret = blkcipher_walk_done(desc, walk, nbytes); |
131 | } while ((nbytes = walk->nbytes)); | 128 | } while ((nbytes = walk->nbytes)); |
132 | memcpy(walk->iv, param, DES_BLOCK_SIZE); | 129 | memcpy(walk->iv, iv, DES_BLOCK_SIZE); |
133 | 130 | ||
134 | out: | 131 | out: |
135 | return ret; | 132 | return ret; |
@@ -139,22 +136,22 @@ static int ecb_des_encrypt(struct blkcipher_desc *desc, | |||
139 | struct scatterlist *dst, struct scatterlist *src, | 136 | struct scatterlist *dst, struct scatterlist *src, |
140 | unsigned int nbytes) | 137 | unsigned int nbytes) |
141 | { | 138 | { |
142 | struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | 139 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); |
143 | struct blkcipher_walk walk; | 140 | struct blkcipher_walk walk; |
144 | 141 | ||
145 | blkcipher_walk_init(&walk, dst, src, nbytes); | 142 | blkcipher_walk_init(&walk, dst, src, nbytes); |
146 | return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, sctx->key, &walk); | 143 | return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, ctx->key, &walk); |
147 | } | 144 | } |
148 | 145 | ||
149 | static int ecb_des_decrypt(struct blkcipher_desc *desc, | 146 | static int ecb_des_decrypt(struct blkcipher_desc *desc, |
150 | struct scatterlist *dst, struct scatterlist *src, | 147 | struct scatterlist *dst, struct scatterlist *src, |
151 | unsigned int nbytes) | 148 | unsigned int nbytes) |
152 | { | 149 | { |
153 | struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | 150 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); |
154 | struct blkcipher_walk walk; | 151 | struct blkcipher_walk walk; |
155 | 152 | ||
156 | blkcipher_walk_init(&walk, dst, src, nbytes); | 153 | blkcipher_walk_init(&walk, dst, src, nbytes); |
157 | return ecb_desall_crypt(desc, KM_DEA_DECRYPT, sctx->key, &walk); | 154 | return ecb_desall_crypt(desc, KM_DEA_DECRYPT, ctx->key, &walk); |
158 | } | 155 | } |
159 | 156 | ||
160 | static struct crypto_alg ecb_des_alg = { | 157 | static struct crypto_alg ecb_des_alg = { |
@@ -163,7 +160,7 @@ static struct crypto_alg ecb_des_alg = { | |||
163 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, | 160 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, |
164 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | 161 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, |
165 | .cra_blocksize = DES_BLOCK_SIZE, | 162 | .cra_blocksize = DES_BLOCK_SIZE, |
166 | .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), | 163 | .cra_ctxsize = sizeof(struct s390_des_ctx), |
167 | .cra_type = &crypto_blkcipher_type, | 164 | .cra_type = &crypto_blkcipher_type, |
168 | .cra_module = THIS_MODULE, | 165 | .cra_module = THIS_MODULE, |
169 | .cra_list = LIST_HEAD_INIT(ecb_des_alg.cra_list), | 166 | .cra_list = LIST_HEAD_INIT(ecb_des_alg.cra_list), |
@@ -182,22 +179,22 @@ static int cbc_des_encrypt(struct blkcipher_desc *desc, | |||
182 | struct scatterlist *dst, struct scatterlist *src, | 179 | struct scatterlist *dst, struct scatterlist *src, |
183 | unsigned int nbytes) | 180 | unsigned int nbytes) |
184 | { | 181 | { |
185 | struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | 182 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); |
186 | struct blkcipher_walk walk; | 183 | struct blkcipher_walk walk; |
187 | 184 | ||
188 | blkcipher_walk_init(&walk, dst, src, nbytes); | 185 | blkcipher_walk_init(&walk, dst, src, nbytes); |
189 | return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, sctx->iv, &walk); | 186 | return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, ctx->iv, &walk); |
190 | } | 187 | } |
191 | 188 | ||
192 | static int cbc_des_decrypt(struct blkcipher_desc *desc, | 189 | static int cbc_des_decrypt(struct blkcipher_desc *desc, |
193 | struct scatterlist *dst, struct scatterlist *src, | 190 | struct scatterlist *dst, struct scatterlist *src, |
194 | unsigned int nbytes) | 191 | unsigned int nbytes) |
195 | { | 192 | { |
196 | struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | 193 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); |
197 | struct blkcipher_walk walk; | 194 | struct blkcipher_walk walk; |
198 | 195 | ||
199 | blkcipher_walk_init(&walk, dst, src, nbytes); | 196 | blkcipher_walk_init(&walk, dst, src, nbytes); |
200 | return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, sctx->iv, &walk); | 197 | return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, ctx->iv, &walk); |
201 | } | 198 | } |
202 | 199 | ||
203 | static struct crypto_alg cbc_des_alg = { | 200 | static struct crypto_alg cbc_des_alg = { |
@@ -206,7 +203,7 @@ static struct crypto_alg cbc_des_alg = { | |||
206 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, | 203 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, |
207 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | 204 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, |
208 | .cra_blocksize = DES_BLOCK_SIZE, | 205 | .cra_blocksize = DES_BLOCK_SIZE, |
209 | .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), | 206 | .cra_ctxsize = sizeof(struct s390_des_ctx), |
210 | .cra_type = &crypto_blkcipher_type, | 207 | .cra_type = &crypto_blkcipher_type, |
211 | .cra_module = THIS_MODULE, | 208 | .cra_module = THIS_MODULE, |
212 | .cra_list = LIST_HEAD_INIT(cbc_des_alg.cra_list), | 209 | .cra_list = LIST_HEAD_INIT(cbc_des_alg.cra_list), |
@@ -235,10 +232,10 @@ static struct crypto_alg cbc_des_alg = { | |||
235 | * property. | 232 | * property. |
236 | * | 233 | * |
237 | */ | 234 | */ |
238 | static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key, | 235 | static int des3_setkey(struct crypto_tfm *tfm, const u8 *key, |
239 | unsigned int keylen) | 236 | unsigned int key_len) |
240 | { | 237 | { |
241 | struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm); | 238 | struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); |
242 | u32 *flags = &tfm->crt_flags; | 239 | u32 *flags = &tfm->crt_flags; |
243 | 240 | ||
244 | if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && | 241 | if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && |
@@ -248,141 +245,276 @@ static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key, | |||
248 | *flags |= CRYPTO_TFM_RES_WEAK_KEY; | 245 | *flags |= CRYPTO_TFM_RES_WEAK_KEY; |
249 | return -EINVAL; | 246 | return -EINVAL; |
250 | } | 247 | } |
251 | memcpy(dctx->key, key, keylen); | 248 | memcpy(ctx->key, key, key_len); |
252 | return 0; | 249 | return 0; |
253 | } | 250 | } |
254 | 251 | ||
255 | static void des3_192_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) | 252 | static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) |
256 | { | 253 | { |
257 | struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm); | 254 | struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); |
258 | 255 | ||
259 | crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, | 256 | crypt_s390_km(KM_TDEA_192_ENCRYPT, ctx->key, dst, src, DES_BLOCK_SIZE); |
260 | DES_BLOCK_SIZE); | ||
261 | } | 257 | } |
262 | 258 | ||
263 | static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) | 259 | static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) |
264 | { | 260 | { |
265 | struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm); | 261 | struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); |
266 | 262 | ||
267 | crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, | 263 | crypt_s390_km(KM_TDEA_192_DECRYPT, ctx->key, dst, src, DES_BLOCK_SIZE); |
268 | DES_BLOCK_SIZE); | ||
269 | } | 264 | } |
270 | 265 | ||
271 | static struct crypto_alg des3_192_alg = { | 266 | static struct crypto_alg des3_alg = { |
272 | .cra_name = "des3_ede", | 267 | .cra_name = "des3_ede", |
273 | .cra_driver_name = "des3_ede-s390", | 268 | .cra_driver_name = "des3_ede-s390", |
274 | .cra_priority = CRYPT_S390_PRIORITY, | 269 | .cra_priority = CRYPT_S390_PRIORITY, |
275 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, | 270 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, |
276 | .cra_blocksize = DES_BLOCK_SIZE, | 271 | .cra_blocksize = DES_BLOCK_SIZE, |
277 | .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), | 272 | .cra_ctxsize = sizeof(struct s390_des_ctx), |
278 | .cra_module = THIS_MODULE, | 273 | .cra_module = THIS_MODULE, |
279 | .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), | 274 | .cra_list = LIST_HEAD_INIT(des3_alg.cra_list), |
280 | .cra_u = { | 275 | .cra_u = { |
281 | .cipher = { | 276 | .cipher = { |
282 | .cia_min_keysize = DES3_192_KEY_SIZE, | 277 | .cia_min_keysize = DES3_KEY_SIZE, |
283 | .cia_max_keysize = DES3_192_KEY_SIZE, | 278 | .cia_max_keysize = DES3_KEY_SIZE, |
284 | .cia_setkey = des3_192_setkey, | 279 | .cia_setkey = des3_setkey, |
285 | .cia_encrypt = des3_192_encrypt, | 280 | .cia_encrypt = des3_encrypt, |
286 | .cia_decrypt = des3_192_decrypt, | 281 | .cia_decrypt = des3_decrypt, |
287 | } | 282 | } |
288 | } | 283 | } |
289 | }; | 284 | }; |
290 | 285 | ||
291 | static int ecb_des3_192_encrypt(struct blkcipher_desc *desc, | 286 | static int ecb_des3_encrypt(struct blkcipher_desc *desc, |
292 | struct scatterlist *dst, | 287 | struct scatterlist *dst, struct scatterlist *src, |
293 | struct scatterlist *src, unsigned int nbytes) | 288 | unsigned int nbytes) |
294 | { | 289 | { |
295 | struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | 290 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); |
296 | struct blkcipher_walk walk; | 291 | struct blkcipher_walk walk; |
297 | 292 | ||
298 | blkcipher_walk_init(&walk, dst, src, nbytes); | 293 | blkcipher_walk_init(&walk, dst, src, nbytes); |
299 | return ecb_desall_crypt(desc, KM_TDEA_192_ENCRYPT, sctx->key, &walk); | 294 | return ecb_desall_crypt(desc, KM_TDEA_192_ENCRYPT, ctx->key, &walk); |
300 | } | 295 | } |
301 | 296 | ||
302 | static int ecb_des3_192_decrypt(struct blkcipher_desc *desc, | 297 | static int ecb_des3_decrypt(struct blkcipher_desc *desc, |
303 | struct scatterlist *dst, | 298 | struct scatterlist *dst, struct scatterlist *src, |
304 | struct scatterlist *src, unsigned int nbytes) | 299 | unsigned int nbytes) |
305 | { | 300 | { |
306 | struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | 301 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); |
307 | struct blkcipher_walk walk; | 302 | struct blkcipher_walk walk; |
308 | 303 | ||
309 | blkcipher_walk_init(&walk, dst, src, nbytes); | 304 | blkcipher_walk_init(&walk, dst, src, nbytes); |
310 | return ecb_desall_crypt(desc, KM_TDEA_192_DECRYPT, sctx->key, &walk); | 305 | return ecb_desall_crypt(desc, KM_TDEA_192_DECRYPT, ctx->key, &walk); |
311 | } | 306 | } |
312 | 307 | ||
313 | static struct crypto_alg ecb_des3_192_alg = { | 308 | static struct crypto_alg ecb_des3_alg = { |
314 | .cra_name = "ecb(des3_ede)", | 309 | .cra_name = "ecb(des3_ede)", |
315 | .cra_driver_name = "ecb-des3_ede-s390", | 310 | .cra_driver_name = "ecb-des3_ede-s390", |
316 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, | 311 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, |
317 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | 312 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, |
318 | .cra_blocksize = DES_BLOCK_SIZE, | 313 | .cra_blocksize = DES_BLOCK_SIZE, |
319 | .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), | 314 | .cra_ctxsize = sizeof(struct s390_des_ctx), |
320 | .cra_type = &crypto_blkcipher_type, | 315 | .cra_type = &crypto_blkcipher_type, |
321 | .cra_module = THIS_MODULE, | 316 | .cra_module = THIS_MODULE, |
322 | .cra_list = LIST_HEAD_INIT( | 317 | .cra_list = LIST_HEAD_INIT( |
323 | ecb_des3_192_alg.cra_list), | 318 | ecb_des3_alg.cra_list), |
324 | .cra_u = { | 319 | .cra_u = { |
325 | .blkcipher = { | 320 | .blkcipher = { |
326 | .min_keysize = DES3_192_KEY_SIZE, | 321 | .min_keysize = DES3_KEY_SIZE, |
327 | .max_keysize = DES3_192_KEY_SIZE, | 322 | .max_keysize = DES3_KEY_SIZE, |
328 | .setkey = des3_192_setkey, | 323 | .setkey = des3_setkey, |
329 | .encrypt = ecb_des3_192_encrypt, | 324 | .encrypt = ecb_des3_encrypt, |
330 | .decrypt = ecb_des3_192_decrypt, | 325 | .decrypt = ecb_des3_decrypt, |
331 | } | 326 | } |
332 | } | 327 | } |
333 | }; | 328 | }; |
334 | 329 | ||
335 | static int cbc_des3_192_encrypt(struct blkcipher_desc *desc, | 330 | static int cbc_des3_encrypt(struct blkcipher_desc *desc, |
336 | struct scatterlist *dst, | 331 | struct scatterlist *dst, struct scatterlist *src, |
337 | struct scatterlist *src, unsigned int nbytes) | 332 | unsigned int nbytes) |
338 | { | 333 | { |
339 | struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | 334 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); |
340 | struct blkcipher_walk walk; | 335 | struct blkcipher_walk walk; |
341 | 336 | ||
342 | blkcipher_walk_init(&walk, dst, src, nbytes); | 337 | blkcipher_walk_init(&walk, dst, src, nbytes); |
343 | return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, sctx->iv, &walk); | 338 | return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, ctx->iv, &walk); |
344 | } | 339 | } |
345 | 340 | ||
346 | static int cbc_des3_192_decrypt(struct blkcipher_desc *desc, | 341 | static int cbc_des3_decrypt(struct blkcipher_desc *desc, |
347 | struct scatterlist *dst, | 342 | struct scatterlist *dst, struct scatterlist *src, |
348 | struct scatterlist *src, unsigned int nbytes) | 343 | unsigned int nbytes) |
349 | { | 344 | { |
350 | struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); | 345 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); |
351 | struct blkcipher_walk walk; | 346 | struct blkcipher_walk walk; |
352 | 347 | ||
353 | blkcipher_walk_init(&walk, dst, src, nbytes); | 348 | blkcipher_walk_init(&walk, dst, src, nbytes); |
354 | return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, sctx->iv, &walk); | 349 | return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, ctx->iv, &walk); |
355 | } | 350 | } |
356 | 351 | ||
357 | static struct crypto_alg cbc_des3_192_alg = { | 352 | static struct crypto_alg cbc_des3_alg = { |
358 | .cra_name = "cbc(des3_ede)", | 353 | .cra_name = "cbc(des3_ede)", |
359 | .cra_driver_name = "cbc-des3_ede-s390", | 354 | .cra_driver_name = "cbc-des3_ede-s390", |
360 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, | 355 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, |
361 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | 356 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, |
362 | .cra_blocksize = DES_BLOCK_SIZE, | 357 | .cra_blocksize = DES_BLOCK_SIZE, |
363 | .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), | 358 | .cra_ctxsize = sizeof(struct s390_des_ctx), |
364 | .cra_type = &crypto_blkcipher_type, | 359 | .cra_type = &crypto_blkcipher_type, |
365 | .cra_module = THIS_MODULE, | 360 | .cra_module = THIS_MODULE, |
366 | .cra_list = LIST_HEAD_INIT( | 361 | .cra_list = LIST_HEAD_INIT( |
367 | cbc_des3_192_alg.cra_list), | 362 | cbc_des3_alg.cra_list), |
368 | .cra_u = { | 363 | .cra_u = { |
369 | .blkcipher = { | 364 | .blkcipher = { |
370 | .min_keysize = DES3_192_KEY_SIZE, | 365 | .min_keysize = DES3_KEY_SIZE, |
371 | .max_keysize = DES3_192_KEY_SIZE, | 366 | .max_keysize = DES3_KEY_SIZE, |
372 | .ivsize = DES_BLOCK_SIZE, | 367 | .ivsize = DES_BLOCK_SIZE, |
373 | .setkey = des3_192_setkey, | 368 | .setkey = des3_setkey, |
374 | .encrypt = cbc_des3_192_encrypt, | 369 | .encrypt = cbc_des3_encrypt, |
375 | .decrypt = cbc_des3_192_decrypt, | 370 | .decrypt = cbc_des3_decrypt, |
376 | } | 371 | } |
377 | } | 372 | } |
378 | }; | 373 | }; |
379 | 374 | ||
380 | static int des_s390_init(void) | 375 | static int ctr_desall_crypt(struct blkcipher_desc *desc, long func, |
376 | struct s390_des_ctx *ctx, struct blkcipher_walk *walk) | ||
377 | { | ||
378 | int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE); | ||
379 | unsigned int i, n, nbytes; | ||
380 | u8 buf[DES_BLOCK_SIZE]; | ||
381 | u8 *out, *in; | ||
382 | |||
383 | memcpy(ctrblk, walk->iv, DES_BLOCK_SIZE); | ||
384 | while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { | ||
385 | out = walk->dst.virt.addr; | ||
386 | in = walk->src.virt.addr; | ||
387 | while (nbytes >= DES_BLOCK_SIZE) { | ||
388 | /* align to block size, max. PAGE_SIZE */ | ||
389 | n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : | ||
390 | nbytes & ~(DES_BLOCK_SIZE - 1); | ||
391 | for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) { | ||
392 | memcpy(ctrblk + i, ctrblk + i - DES_BLOCK_SIZE, | ||
393 | DES_BLOCK_SIZE); | ||
394 | crypto_inc(ctrblk + i, DES_BLOCK_SIZE); | ||
395 | } | ||
396 | ret = crypt_s390_kmctr(func, ctx->key, out, in, n, ctrblk); | ||
397 | BUG_ON((ret < 0) || (ret != n)); | ||
398 | if (n > DES_BLOCK_SIZE) | ||
399 | memcpy(ctrblk, ctrblk + n - DES_BLOCK_SIZE, | ||
400 | DES_BLOCK_SIZE); | ||
401 | crypto_inc(ctrblk, DES_BLOCK_SIZE); | ||
402 | out += n; | ||
403 | in += n; | ||
404 | nbytes -= n; | ||
405 | } | ||
406 | ret = blkcipher_walk_done(desc, walk, nbytes); | ||
407 | } | ||
408 | |||
409 | /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ | ||
410 | if (nbytes) { | ||
411 | out = walk->dst.virt.addr; | ||
412 | in = walk->src.virt.addr; | ||
413 | ret = crypt_s390_kmctr(func, ctx->key, buf, in, | ||
414 | DES_BLOCK_SIZE, ctrblk); | ||
415 | BUG_ON(ret < 0 || ret != DES_BLOCK_SIZE); | ||
416 | memcpy(out, buf, nbytes); | ||
417 | crypto_inc(ctrblk, DES_BLOCK_SIZE); | ||
418 | ret = blkcipher_walk_done(desc, walk, 0); | ||
419 | } | ||
420 | memcpy(walk->iv, ctrblk, DES_BLOCK_SIZE); | ||
421 | return ret; | ||
422 | } | ||
423 | |||
424 | static int ctr_des_encrypt(struct blkcipher_desc *desc, | ||
425 | struct scatterlist *dst, struct scatterlist *src, | ||
426 | unsigned int nbytes) | ||
427 | { | ||
428 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
429 | struct blkcipher_walk walk; | ||
430 | |||
431 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
432 | return ctr_desall_crypt(desc, KMCTR_DEA_ENCRYPT, ctx, &walk); | ||
433 | } | ||
434 | |||
435 | static int ctr_des_decrypt(struct blkcipher_desc *desc, | ||
436 | struct scatterlist *dst, struct scatterlist *src, | ||
437 | unsigned int nbytes) | ||
438 | { | ||
439 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
440 | struct blkcipher_walk walk; | ||
441 | |||
442 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
443 | return ctr_desall_crypt(desc, KMCTR_DEA_DECRYPT, ctx, &walk); | ||
444 | } | ||
445 | |||
446 | static struct crypto_alg ctr_des_alg = { | ||
447 | .cra_name = "ctr(des)", | ||
448 | .cra_driver_name = "ctr-des-s390", | ||
449 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, | ||
450 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
451 | .cra_blocksize = 1, | ||
452 | .cra_ctxsize = sizeof(struct s390_des_ctx), | ||
453 | .cra_type = &crypto_blkcipher_type, | ||
454 | .cra_module = THIS_MODULE, | ||
455 | .cra_list = LIST_HEAD_INIT(ctr_des_alg.cra_list), | ||
456 | .cra_u = { | ||
457 | .blkcipher = { | ||
458 | .min_keysize = DES_KEY_SIZE, | ||
459 | .max_keysize = DES_KEY_SIZE, | ||
460 | .ivsize = DES_BLOCK_SIZE, | ||
461 | .setkey = des_setkey, | ||
462 | .encrypt = ctr_des_encrypt, | ||
463 | .decrypt = ctr_des_decrypt, | ||
464 | } | ||
465 | } | ||
466 | }; | ||
467 | |||
468 | static int ctr_des3_encrypt(struct blkcipher_desc *desc, | ||
469 | struct scatterlist *dst, struct scatterlist *src, | ||
470 | unsigned int nbytes) | ||
471 | { | ||
472 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
473 | struct blkcipher_walk walk; | ||
474 | |||
475 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
476 | return ctr_desall_crypt(desc, KMCTR_TDEA_192_ENCRYPT, ctx, &walk); | ||
477 | } | ||
478 | |||
479 | static int ctr_des3_decrypt(struct blkcipher_desc *desc, | ||
480 | struct scatterlist *dst, struct scatterlist *src, | ||
481 | unsigned int nbytes) | ||
482 | { | ||
483 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
484 | struct blkcipher_walk walk; | ||
485 | |||
486 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
487 | return ctr_desall_crypt(desc, KMCTR_TDEA_192_DECRYPT, ctx, &walk); | ||
488 | } | ||
489 | |||
490 | static struct crypto_alg ctr_des3_alg = { | ||
491 | .cra_name = "ctr(des3_ede)", | ||
492 | .cra_driver_name = "ctr-des3_ede-s390", | ||
493 | .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, | ||
494 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
495 | .cra_blocksize = 1, | ||
496 | .cra_ctxsize = sizeof(struct s390_des_ctx), | ||
497 | .cra_type = &crypto_blkcipher_type, | ||
498 | .cra_module = THIS_MODULE, | ||
499 | .cra_list = LIST_HEAD_INIT(ctr_des3_alg.cra_list), | ||
500 | .cra_u = { | ||
501 | .blkcipher = { | ||
502 | .min_keysize = DES3_KEY_SIZE, | ||
503 | .max_keysize = DES3_KEY_SIZE, | ||
504 | .ivsize = DES_BLOCK_SIZE, | ||
505 | .setkey = des3_setkey, | ||
506 | .encrypt = ctr_des3_encrypt, | ||
507 | .decrypt = ctr_des3_decrypt, | ||
508 | } | ||
509 | } | ||
510 | }; | ||
511 | |||
512 | static int __init des_s390_init(void) | ||
381 | { | 513 | { |
382 | int ret; | 514 | int ret; |
383 | 515 | ||
384 | if (!crypt_s390_func_available(KM_DEA_ENCRYPT) || | 516 | if (!crypt_s390_func_available(KM_DEA_ENCRYPT, CRYPT_S390_MSA) || |
385 | !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)) | 517 | !crypt_s390_func_available(KM_TDEA_192_ENCRYPT, CRYPT_S390_MSA)) |
386 | return -EOPNOTSUPP; | 518 | return -EOPNOTSUPP; |
387 | 519 | ||
388 | ret = crypto_register_alg(&des_alg); | 520 | ret = crypto_register_alg(&des_alg); |
@@ -394,23 +526,46 @@ static int des_s390_init(void) | |||
394 | ret = crypto_register_alg(&cbc_des_alg); | 526 | ret = crypto_register_alg(&cbc_des_alg); |
395 | if (ret) | 527 | if (ret) |
396 | goto cbc_des_err; | 528 | goto cbc_des_err; |
397 | ret = crypto_register_alg(&des3_192_alg); | 529 | ret = crypto_register_alg(&des3_alg); |
398 | if (ret) | 530 | if (ret) |
399 | goto des3_192_err; | 531 | goto des3_err; |
400 | ret = crypto_register_alg(&ecb_des3_192_alg); | 532 | ret = crypto_register_alg(&ecb_des3_alg); |
401 | if (ret) | 533 | if (ret) |
402 | goto ecb_des3_192_err; | 534 | goto ecb_des3_err; |
403 | ret = crypto_register_alg(&cbc_des3_192_alg); | 535 | ret = crypto_register_alg(&cbc_des3_alg); |
404 | if (ret) | 536 | if (ret) |
405 | goto cbc_des3_192_err; | 537 | goto cbc_des3_err; |
538 | |||
539 | if (crypt_s390_func_available(KMCTR_DEA_ENCRYPT, | ||
540 | CRYPT_S390_MSA | CRYPT_S390_MSA4) && | ||
541 | crypt_s390_func_available(KMCTR_TDEA_192_ENCRYPT, | ||
542 | CRYPT_S390_MSA | CRYPT_S390_MSA4)) { | ||
543 | ret = crypto_register_alg(&ctr_des_alg); | ||
544 | if (ret) | ||
545 | goto ctr_des_err; | ||
546 | ret = crypto_register_alg(&ctr_des3_alg); | ||
547 | if (ret) | ||
548 | goto ctr_des3_err; | ||
549 | ctrblk = (u8 *) __get_free_page(GFP_KERNEL); | ||
550 | if (!ctrblk) { | ||
551 | ret = -ENOMEM; | ||
552 | goto ctr_mem_err; | ||
553 | } | ||
554 | } | ||
406 | out: | 555 | out: |
407 | return ret; | 556 | return ret; |
408 | 557 | ||
409 | cbc_des3_192_err: | 558 | ctr_mem_err: |
410 | crypto_unregister_alg(&ecb_des3_192_alg); | 559 | crypto_unregister_alg(&ctr_des3_alg); |
411 | ecb_des3_192_err: | 560 | ctr_des3_err: |
412 | crypto_unregister_alg(&des3_192_alg); | 561 | crypto_unregister_alg(&ctr_des_alg); |
413 | des3_192_err: | 562 | ctr_des_err: |
563 | crypto_unregister_alg(&cbc_des3_alg); | ||
564 | cbc_des3_err: | ||
565 | crypto_unregister_alg(&ecb_des3_alg); | ||
566 | ecb_des3_err: | ||
567 | crypto_unregister_alg(&des3_alg); | ||
568 | des3_err: | ||
414 | crypto_unregister_alg(&cbc_des_alg); | 569 | crypto_unregister_alg(&cbc_des_alg); |
415 | cbc_des_err: | 570 | cbc_des_err: |
416 | crypto_unregister_alg(&ecb_des_alg); | 571 | crypto_unregister_alg(&ecb_des_alg); |
@@ -422,9 +577,14 @@ des_err: | |||
422 | 577 | ||
423 | static void __exit des_s390_exit(void) | 578 | static void __exit des_s390_exit(void) |
424 | { | 579 | { |
425 | crypto_unregister_alg(&cbc_des3_192_alg); | 580 | if (ctrblk) { |
426 | crypto_unregister_alg(&ecb_des3_192_alg); | 581 | crypto_unregister_alg(&ctr_des_alg); |
427 | crypto_unregister_alg(&des3_192_alg); | 582 | crypto_unregister_alg(&ctr_des3_alg); |
583 | free_page((unsigned long) ctrblk); | ||
584 | } | ||
585 | crypto_unregister_alg(&cbc_des3_alg); | ||
586 | crypto_unregister_alg(&ecb_des3_alg); | ||
587 | crypto_unregister_alg(&des3_alg); | ||
428 | crypto_unregister_alg(&cbc_des_alg); | 588 | crypto_unregister_alg(&cbc_des_alg); |
429 | crypto_unregister_alg(&ecb_des_alg); | 589 | crypto_unregister_alg(&ecb_des_alg); |
430 | crypto_unregister_alg(&des_alg); | 590 | crypto_unregister_alg(&des_alg); |
diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c new file mode 100644 index 000000000000..b1bd170f24b1 --- /dev/null +++ b/arch/s390/crypto/ghash_s390.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * Cryptographic API. | ||
3 | * | ||
4 | * s390 implementation of the GHASH algorithm for GCM (Galois/Counter Mode). | ||
5 | * | ||
6 | * Copyright IBM Corp. 2011 | ||
7 | * Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com> | ||
8 | */ | ||
9 | |||
10 | #include <crypto/internal/hash.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | #include "crypt_s390.h" | ||
14 | |||
15 | #define GHASH_BLOCK_SIZE 16 | ||
16 | #define GHASH_DIGEST_SIZE 16 | ||
17 | |||
18 | struct ghash_ctx { | ||
19 | u8 icv[16]; | ||
20 | u8 key[16]; | ||
21 | }; | ||
22 | |||
23 | struct ghash_desc_ctx { | ||
24 | u8 buffer[GHASH_BLOCK_SIZE]; | ||
25 | u32 bytes; | ||
26 | }; | ||
27 | |||
28 | static int ghash_init(struct shash_desc *desc) | ||
29 | { | ||
30 | struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); | ||
31 | |||
32 | memset(dctx, 0, sizeof(*dctx)); | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int ghash_setkey(struct crypto_shash *tfm, | ||
38 | const u8 *key, unsigned int keylen) | ||
39 | { | ||
40 | struct ghash_ctx *ctx = crypto_shash_ctx(tfm); | ||
41 | |||
42 | if (keylen != GHASH_BLOCK_SIZE) { | ||
43 | crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); | ||
44 | return -EINVAL; | ||
45 | } | ||
46 | |||
47 | memcpy(ctx->key, key, GHASH_BLOCK_SIZE); | ||
48 | memset(ctx->icv, 0, GHASH_BLOCK_SIZE); | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static int ghash_update(struct shash_desc *desc, | ||
54 | const u8 *src, unsigned int srclen) | ||
55 | { | ||
56 | struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); | ||
57 | struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); | ||
58 | unsigned int n; | ||
59 | u8 *buf = dctx->buffer; | ||
60 | int ret; | ||
61 | |||
62 | if (dctx->bytes) { | ||
63 | u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes); | ||
64 | |||
65 | n = min(srclen, dctx->bytes); | ||
66 | dctx->bytes -= n; | ||
67 | srclen -= n; | ||
68 | |||
69 | memcpy(pos, src, n); | ||
70 | src += n; | ||
71 | |||
72 | if (!dctx->bytes) { | ||
73 | ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, | ||
74 | GHASH_BLOCK_SIZE); | ||
75 | BUG_ON(ret != GHASH_BLOCK_SIZE); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | n = srclen & ~(GHASH_BLOCK_SIZE - 1); | ||
80 | if (n) { | ||
81 | ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n); | ||
82 | BUG_ON(ret != n); | ||
83 | src += n; | ||
84 | srclen -= n; | ||
85 | } | ||
86 | |||
87 | if (srclen) { | ||
88 | dctx->bytes = GHASH_BLOCK_SIZE - srclen; | ||
89 | memcpy(buf, src, srclen); | ||
90 | } | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) | ||
96 | { | ||
97 | u8 *buf = dctx->buffer; | ||
98 | int ret; | ||
99 | |||
100 | if (dctx->bytes) { | ||
101 | u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes); | ||
102 | |||
103 | memset(pos, 0, dctx->bytes); | ||
104 | |||
105 | ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE); | ||
106 | BUG_ON(ret != GHASH_BLOCK_SIZE); | ||
107 | } | ||
108 | |||
109 | dctx->bytes = 0; | ||
110 | } | ||
111 | |||
112 | static int ghash_final(struct shash_desc *desc, u8 *dst) | ||
113 | { | ||
114 | struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); | ||
115 | struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); | ||
116 | |||
117 | ghash_flush(ctx, dctx); | ||
118 | memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static struct shash_alg ghash_alg = { | ||
124 | .digestsize = GHASH_DIGEST_SIZE, | ||
125 | .init = ghash_init, | ||
126 | .update = ghash_update, | ||
127 | .final = ghash_final, | ||
128 | .setkey = ghash_setkey, | ||
129 | .descsize = sizeof(struct ghash_desc_ctx), | ||
130 | .base = { | ||
131 | .cra_name = "ghash", | ||
132 | .cra_driver_name = "ghash-s390", | ||
133 | .cra_priority = CRYPT_S390_PRIORITY, | ||
134 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | ||
135 | .cra_blocksize = GHASH_BLOCK_SIZE, | ||
136 | .cra_ctxsize = sizeof(struct ghash_ctx), | ||
137 | .cra_module = THIS_MODULE, | ||
138 | .cra_list = LIST_HEAD_INIT(ghash_alg.base.cra_list), | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | static int __init ghash_mod_init(void) | ||
143 | { | ||
144 | if (!crypt_s390_func_available(KIMD_GHASH, | ||
145 | CRYPT_S390_MSA | CRYPT_S390_MSA4)) | ||
146 | return -EOPNOTSUPP; | ||
147 | |||
148 | return crypto_register_shash(&ghash_alg); | ||
149 | } | ||
150 | |||
151 | static void __exit ghash_mod_exit(void) | ||
152 | { | ||
153 | crypto_unregister_shash(&ghash_alg); | ||
154 | } | ||
155 | |||
156 | module_init(ghash_mod_init); | ||
157 | module_exit(ghash_mod_exit); | ||
158 | |||
159 | MODULE_ALIAS("ghash"); | ||
160 | |||
161 | MODULE_LICENSE("GPL"); | ||
162 | MODULE_DESCRIPTION("GHASH Message Digest Algorithm, s390 implementation"); | ||
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c index aa819dac2360..0808fbf0f7d3 100644 --- a/arch/s390/crypto/prng.c +++ b/arch/s390/crypto/prng.c | |||
@@ -76,7 +76,7 @@ static void prng_seed(int nbytes) | |||
76 | 76 | ||
77 | /* Add the entropy */ | 77 | /* Add the entropy */ |
78 | while (nbytes >= 8) { | 78 | while (nbytes >= 8) { |
79 | *((__u64 *)parm_block) ^= *((__u64 *)buf+i*8); | 79 | *((__u64 *)parm_block) ^= *((__u64 *)(buf+i)); |
80 | prng_add_entropy(); | 80 | prng_add_entropy(); |
81 | i += 8; | 81 | i += 8; |
82 | nbytes -= 8; | 82 | nbytes -= 8; |
@@ -152,6 +152,7 @@ static const struct file_operations prng_fops = { | |||
152 | .open = &prng_open, | 152 | .open = &prng_open, |
153 | .release = NULL, | 153 | .release = NULL, |
154 | .read = &prng_read, | 154 | .read = &prng_read, |
155 | .llseek = noop_llseek, | ||
155 | }; | 156 | }; |
156 | 157 | ||
157 | static struct miscdevice prng_dev = { | 158 | static struct miscdevice prng_dev = { |
@@ -165,7 +166,7 @@ static int __init prng_init(void) | |||
165 | int ret; | 166 | int ret; |
166 | 167 | ||
167 | /* check if the CPU has a PRNG */ | 168 | /* check if the CPU has a PRNG */ |
168 | if (!crypt_s390_func_available(KMC_PRNG)) | 169 | if (!crypt_s390_func_available(KMC_PRNG, CRYPT_S390_MSA)) |
169 | return -EOPNOTSUPP; | 170 | return -EOPNOTSUPP; |
170 | 171 | ||
171 | if (prng_chunk_size < 8) | 172 | if (prng_chunk_size < 8) |
diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c index f6de7826c979..e9868c6e0a08 100644 --- a/arch/s390/crypto/sha1_s390.c +++ b/arch/s390/crypto/sha1_s390.c | |||
@@ -90,7 +90,7 @@ static struct shash_alg alg = { | |||
90 | 90 | ||
91 | static int __init sha1_s390_init(void) | 91 | static int __init sha1_s390_init(void) |
92 | { | 92 | { |
93 | if (!crypt_s390_func_available(KIMD_SHA_1)) | 93 | if (!crypt_s390_func_available(KIMD_SHA_1, CRYPT_S390_MSA)) |
94 | return -EOPNOTSUPP; | 94 | return -EOPNOTSUPP; |
95 | return crypto_register_shash(&alg); | 95 | return crypto_register_shash(&alg); |
96 | } | 96 | } |
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c index 61a7db372121..5ed8d64fc2ed 100644 --- a/arch/s390/crypto/sha256_s390.c +++ b/arch/s390/crypto/sha256_s390.c | |||
@@ -86,7 +86,7 @@ static struct shash_alg alg = { | |||
86 | 86 | ||
87 | static int sha256_s390_init(void) | 87 | static int sha256_s390_init(void) |
88 | { | 88 | { |
89 | if (!crypt_s390_func_available(KIMD_SHA_256)) | 89 | if (!crypt_s390_func_available(KIMD_SHA_256, CRYPT_S390_MSA)) |
90 | return -EOPNOTSUPP; | 90 | return -EOPNOTSUPP; |
91 | 91 | ||
92 | return crypto_register_shash(&alg); | 92 | return crypto_register_shash(&alg); |
diff --git a/arch/s390/crypto/sha512_s390.c b/arch/s390/crypto/sha512_s390.c index 4bf73d0dc525..32a81383b69c 100644 --- a/arch/s390/crypto/sha512_s390.c +++ b/arch/s390/crypto/sha512_s390.c | |||
@@ -132,7 +132,7 @@ static int __init init(void) | |||
132 | { | 132 | { |
133 | int ret; | 133 | int ret; |
134 | 134 | ||
135 | if (!crypt_s390_func_available(KIMD_SHA_512)) | 135 | if (!crypt_s390_func_available(KIMD_SHA_512, CRYPT_S390_MSA)) |
136 | return -EOPNOTSUPP; | 136 | return -EOPNOTSUPP; |
137 | if ((ret = crypto_register_shash(&sha512_alg)) < 0) | 137 | if ((ret = crypto_register_shash(&sha512_alg)) < 0) |
138 | goto out; | 138 | goto out; |
diff --git a/arch/s390/crypto/sha_common.c b/arch/s390/crypto/sha_common.c index f42dbabc0d30..48884f89ab92 100644 --- a/arch/s390/crypto/sha_common.c +++ b/arch/s390/crypto/sha_common.c | |||
@@ -38,6 +38,7 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len) | |||
38 | BUG_ON(ret != bsize); | 38 | BUG_ON(ret != bsize); |
39 | data += bsize - index; | 39 | data += bsize - index; |
40 | len -= bsize - index; | 40 | len -= bsize - index; |
41 | index = 0; | ||
41 | } | 42 | } |
42 | 43 | ||
43 | /* process as many blocks as possible */ | 44 | /* process as many blocks as possible */ |
diff --git a/arch/s390/defconfig b/arch/s390/defconfig index e40ac6ee6526..29c82c640a88 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig | |||
@@ -2,17 +2,24 @@ CONFIG_EXPERIMENTAL=y | |||
2 | CONFIG_SYSVIPC=y | 2 | CONFIG_SYSVIPC=y |
3 | CONFIG_POSIX_MQUEUE=y | 3 | CONFIG_POSIX_MQUEUE=y |
4 | CONFIG_AUDIT=y | 4 | CONFIG_AUDIT=y |
5 | CONFIG_RCU_TRACE=y | ||
5 | CONFIG_IKCONFIG=y | 6 | CONFIG_IKCONFIG=y |
6 | CONFIG_IKCONFIG_PROC=y | 7 | CONFIG_IKCONFIG_PROC=y |
7 | CONFIG_CGROUPS=y | 8 | CONFIG_CGROUPS=y |
8 | CONFIG_CGROUP_NS=y | 9 | CONFIG_CPUSETS=y |
9 | CONFIG_SYSFS_DEPRECATED_V2=y | 10 | CONFIG_CGROUP_CPUACCT=y |
10 | CONFIG_UTS_NS=y | 11 | CONFIG_RESOURCE_COUNTERS=y |
11 | CONFIG_IPC_NS=y | 12 | CONFIG_CGROUP_MEM_RES_CTLR=y |
13 | CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y | ||
14 | CONFIG_CGROUP_SCHED=y | ||
15 | CONFIG_RT_GROUP_SCHED=y | ||
16 | CONFIG_BLK_CGROUP=y | ||
12 | CONFIG_BLK_DEV_INITRD=y | 17 | CONFIG_BLK_DEV_INITRD=y |
13 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | 18 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set |
14 | # CONFIG_COMPAT_BRK is not set | 19 | # CONFIG_COMPAT_BRK is not set |
15 | CONFIG_SLAB=y | 20 | CONFIG_SLAB=y |
21 | CONFIG_PROFILING=y | ||
22 | CONFIG_OPROFILE=y | ||
16 | CONFIG_KPROBES=y | 23 | CONFIG_KPROBES=y |
17 | CONFIG_MODULES=y | 24 | CONFIG_MODULES=y |
18 | CONFIG_MODULE_UNLOAD=y | 25 | CONFIG_MODULE_UNLOAD=y |
@@ -20,24 +27,14 @@ CONFIG_MODVERSIONS=y | |||
20 | CONFIG_DEFAULT_DEADLINE=y | 27 | CONFIG_DEFAULT_DEADLINE=y |
21 | CONFIG_NO_HZ=y | 28 | CONFIG_NO_HZ=y |
22 | CONFIG_HIGH_RES_TIMERS=y | 29 | CONFIG_HIGH_RES_TIMERS=y |
23 | CONFIG_64BIT=y | ||
24 | CONFIG_SMP=y | ||
25 | CONFIG_NR_CPUS=32 | ||
26 | CONFIG_COMPAT=y | ||
27 | CONFIG_S390_EXEC_PROTECT=y | ||
28 | CONFIG_PACK_STACK=y | ||
29 | CONFIG_CHECK_STACK=y | ||
30 | CONFIG_PREEMPT=y | 30 | CONFIG_PREEMPT=y |
31 | CONFIG_MEMORY_HOTPLUG=y | 31 | CONFIG_MEMORY_HOTPLUG=y |
32 | CONFIG_MEMORY_HOTREMOVE=y | 32 | CONFIG_MEMORY_HOTREMOVE=y |
33 | CONFIG_QDIO=y | 33 | CONFIG_KSM=y |
34 | CONFIG_CHSC_SCH=m | ||
35 | CONFIG_IPL=y | ||
36 | CONFIG_BINFMT_MISC=m | 34 | CONFIG_BINFMT_MISC=m |
37 | CONFIG_PFAULT=y | 35 | CONFIG_CMM=m |
38 | CONFIG_HZ_100=y | 36 | CONFIG_HZ_100=y |
39 | CONFIG_KEXEC=y | 37 | CONFIG_KEXEC=y |
40 | CONFIG_S390_GUEST=y | ||
41 | CONFIG_PM=y | 38 | CONFIG_PM=y |
42 | CONFIG_HIBERNATION=y | 39 | CONFIG_HIBERNATION=y |
43 | CONFIG_PACKET=y | 40 | CONFIG_PACKET=y |
@@ -46,16 +43,15 @@ CONFIG_NET_KEY=y | |||
46 | CONFIG_AFIUCV=m | 43 | CONFIG_AFIUCV=m |
47 | CONFIG_INET=y | 44 | CONFIG_INET=y |
48 | CONFIG_IP_MULTICAST=y | 45 | CONFIG_IP_MULTICAST=y |
46 | # CONFIG_INET_LRO is not set | ||
49 | CONFIG_IPV6=y | 47 | CONFIG_IPV6=y |
50 | CONFIG_NETFILTER=y | 48 | CONFIG_NET_SCTPPROBE=m |
51 | CONFIG_NETFILTER_NETLINK_QUEUE=m | 49 | CONFIG_L2TP=m |
52 | CONFIG_NETFILTER_NETLINK_LOG=m | 50 | CONFIG_L2TP_DEBUGFS=m |
53 | CONFIG_NF_CONNTRACK=m | 51 | CONFIG_VLAN_8021Q=y |
54 | # CONFIG_NF_CT_PROTO_SCTP is not set | ||
55 | CONFIG_NET_SCHED=y | 52 | CONFIG_NET_SCHED=y |
56 | CONFIG_NET_SCH_CBQ=m | 53 | CONFIG_NET_SCH_CBQ=m |
57 | CONFIG_NET_SCH_PRIO=m | 54 | CONFIG_NET_SCH_PRIO=m |
58 | CONFIG_NET_SCH_MULTIQ=y | ||
59 | CONFIG_NET_SCH_RED=m | 55 | CONFIG_NET_SCH_RED=m |
60 | CONFIG_NET_SCH_SFQ=m | 56 | CONFIG_NET_SCH_SFQ=m |
61 | CONFIG_NET_SCH_TEQL=m | 57 | CONFIG_NET_SCH_TEQL=m |
@@ -69,28 +65,14 @@ CONFIG_NET_CLS_U32=m | |||
69 | CONFIG_CLS_U32_MARK=y | 65 | CONFIG_CLS_U32_MARK=y |
70 | CONFIG_NET_CLS_RSVP=m | 66 | CONFIG_NET_CLS_RSVP=m |
71 | CONFIG_NET_CLS_RSVP6=m | 67 | CONFIG_NET_CLS_RSVP6=m |
72 | CONFIG_NET_CLS_FLOW=m | ||
73 | CONFIG_NET_CLS_ACT=y | 68 | CONFIG_NET_CLS_ACT=y |
74 | CONFIG_NET_ACT_POLICE=y | 69 | CONFIG_NET_ACT_POLICE=y |
75 | CONFIG_NET_ACT_NAT=m | ||
76 | CONFIG_CAN=m | ||
77 | CONFIG_CAN_RAW=m | ||
78 | CONFIG_CAN_BCM=m | ||
79 | CONFIG_CAN_VCAN=m | ||
80 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 70 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
81 | # CONFIG_FIRMWARE_IN_KERNEL is not set | 71 | # CONFIG_FIRMWARE_IN_KERNEL is not set |
82 | CONFIG_BLK_DEV_LOOP=m | 72 | CONFIG_BLK_DEV_LOOP=m |
83 | CONFIG_BLK_DEV_NBD=m | 73 | CONFIG_BLK_DEV_NBD=m |
84 | CONFIG_BLK_DEV_RAM=y | 74 | CONFIG_BLK_DEV_RAM=y |
85 | CONFIG_BLK_DEV_XIP=y | 75 | CONFIG_VIRTIO_BLK=y |
86 | CONFIG_BLK_DEV_XPRAM=m | ||
87 | CONFIG_DASD=y | ||
88 | CONFIG_DASD_PROFILE=y | ||
89 | CONFIG_DASD_ECKD=y | ||
90 | CONFIG_DASD_FBA=y | ||
91 | CONFIG_DASD_DIAG=y | ||
92 | CONFIG_DASD_EER=y | ||
93 | CONFIG_VIRTIO_BLK=m | ||
94 | CONFIG_SCSI=y | 76 | CONFIG_SCSI=y |
95 | CONFIG_BLK_DEV_SD=y | 77 | CONFIG_BLK_DEV_SD=y |
96 | CONFIG_CHR_DEV_ST=y | 78 | CONFIG_CHR_DEV_ST=y |
@@ -102,101 +84,93 @@ CONFIG_SCSI_CONSTANTS=y | |||
102 | CONFIG_SCSI_LOGGING=y | 84 | CONFIG_SCSI_LOGGING=y |
103 | CONFIG_SCSI_SCAN_ASYNC=y | 85 | CONFIG_SCSI_SCAN_ASYNC=y |
104 | CONFIG_ZFCP=y | 86 | CONFIG_ZFCP=y |
105 | CONFIG_SCSI_DH=m | 87 | CONFIG_ZFCP_DIF=y |
106 | CONFIG_SCSI_DH_RDAC=m | ||
107 | CONFIG_SCSI_DH_HP_SW=m | ||
108 | CONFIG_SCSI_DH_EMC=m | ||
109 | CONFIG_SCSI_DH_ALUA=m | ||
110 | CONFIG_SCSI_OSD_INITIATOR=m | ||
111 | CONFIG_SCSI_OSD_ULD=m | ||
112 | CONFIG_MD=y | ||
113 | CONFIG_BLK_DEV_MD=y | ||
114 | CONFIG_MD_LINEAR=m | ||
115 | CONFIG_MD_RAID0=m | ||
116 | CONFIG_MD_RAID1=m | ||
117 | CONFIG_MD_MULTIPATH=m | ||
118 | CONFIG_BLK_DEV_DM=y | ||
119 | CONFIG_DM_CRYPT=y | ||
120 | CONFIG_DM_SNAPSHOT=y | ||
121 | CONFIG_DM_MIRROR=y | ||
122 | CONFIG_DM_ZERO=y | ||
123 | CONFIG_DM_MULTIPATH=m | ||
124 | CONFIG_NETDEVICES=y | 88 | CONFIG_NETDEVICES=y |
125 | CONFIG_DUMMY=m | 89 | CONFIG_DUMMY=m |
126 | CONFIG_BONDING=m | 90 | CONFIG_BONDING=m |
127 | CONFIG_EQUALIZER=m | 91 | CONFIG_EQUALIZER=m |
128 | CONFIG_TUN=m | 92 | CONFIG_TUN=m |
129 | CONFIG_VETH=m | ||
130 | CONFIG_NET_ETHERNET=y | 93 | CONFIG_NET_ETHERNET=y |
131 | CONFIG_LCS=m | 94 | CONFIG_VIRTIO_NET=y |
132 | CONFIG_CTCM=m | ||
133 | CONFIG_QETH=y | ||
134 | CONFIG_QETH_L2=y | ||
135 | CONFIG_QETH_L3=y | ||
136 | CONFIG_VIRTIO_NET=m | ||
137 | CONFIG_HW_RANDOM_VIRTIO=m | ||
138 | CONFIG_RAW_DRIVER=m | 95 | CONFIG_RAW_DRIVER=m |
139 | CONFIG_TN3270=y | ||
140 | CONFIG_TN3270_TTY=y | ||
141 | CONFIG_TN3270_FS=m | ||
142 | CONFIG_TN3270_CONSOLE=y | ||
143 | CONFIG_TN3215=y | ||
144 | CONFIG_TN3215_CONSOLE=y | ||
145 | CONFIG_SCLP_TTY=y | ||
146 | CONFIG_SCLP_CONSOLE=y | ||
147 | CONFIG_SCLP_VT220_TTY=y | ||
148 | CONFIG_SCLP_VT220_CONSOLE=y | ||
149 | CONFIG_SCLP_CPI=m | ||
150 | CONFIG_SCLP_ASYNC=m | ||
151 | CONFIG_S390_TAPE=m | ||
152 | CONFIG_S390_TAPE_BLOCK=y | ||
153 | CONFIG_S390_TAPE_34XX=m | ||
154 | CONFIG_ACCESSIBILITY=y | ||
155 | CONFIG_EXT2_FS=y | 96 | CONFIG_EXT2_FS=y |
156 | CONFIG_EXT3_FS=y | 97 | CONFIG_EXT3_FS=y |
157 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | 98 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set |
99 | CONFIG_EXT4_FS=y | ||
100 | CONFIG_EXT4_FS_POSIX_ACL=y | ||
101 | CONFIG_EXT4_FS_SECURITY=y | ||
158 | CONFIG_PROC_KCORE=y | 102 | CONFIG_PROC_KCORE=y |
159 | CONFIG_TMPFS=y | 103 | CONFIG_TMPFS=y |
160 | CONFIG_TMPFS_POSIX_ACL=y | 104 | CONFIG_TMPFS_POSIX_ACL=y |
161 | CONFIG_NFS_FS=y | 105 | # CONFIG_NETWORK_FILESYSTEMS is not set |
162 | CONFIG_NFS_V3=y | ||
163 | CONFIG_NFSD=y | ||
164 | CONFIG_NFSD_V3=y | ||
165 | CONFIG_PARTITION_ADVANCED=y | 106 | CONFIG_PARTITION_ADVANCED=y |
166 | CONFIG_IBM_PARTITION=y | 107 | CONFIG_IBM_PARTITION=y |
167 | CONFIG_DLM=m | 108 | CONFIG_DLM=m |
168 | CONFIG_MAGIC_SYSRQ=y | 109 | CONFIG_MAGIC_SYSRQ=y |
169 | CONFIG_DEBUG_KERNEL=y | 110 | CONFIG_DEBUG_KERNEL=y |
170 | # CONFIG_SCHED_DEBUG is not set | 111 | CONFIG_TIMER_STATS=y |
171 | CONFIG_DEBUG_SPINLOCK=y | 112 | CONFIG_PROVE_LOCKING=y |
172 | CONFIG_DEBUG_MUTEXES=y | 113 | CONFIG_PROVE_RCU=y |
114 | CONFIG_LOCK_STAT=y | ||
115 | CONFIG_DEBUG_LOCKDEP=y | ||
173 | CONFIG_DEBUG_SPINLOCK_SLEEP=y | 116 | CONFIG_DEBUG_SPINLOCK_SLEEP=y |
117 | CONFIG_DEBUG_LIST=y | ||
118 | CONFIG_DEBUG_NOTIFIERS=y | ||
174 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | 119 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set |
120 | CONFIG_KPROBES_SANITY_TEST=y | ||
175 | CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y | 121 | CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y |
122 | CONFIG_CPU_NOTIFIER_ERROR_INJECT=m | ||
123 | CONFIG_LATENCYTOP=y | ||
176 | CONFIG_SYSCTL_SYSCALL_CHECK=y | 124 | CONFIG_SYSCTL_SYSCALL_CHECK=y |
177 | CONFIG_SAMPLES=y | 125 | CONFIG_DEBUG_PAGEALLOC=y |
178 | CONFIG_CRYPTO_FIPS=y | 126 | # CONFIG_FTRACE is not set |
127 | # CONFIG_STRICT_DEVMEM is not set | ||
128 | CONFIG_CRYPTO_NULL=m | ||
129 | CONFIG_CRYPTO_CRYPTD=m | ||
179 | CONFIG_CRYPTO_AUTHENC=m | 130 | CONFIG_CRYPTO_AUTHENC=m |
131 | CONFIG_CRYPTO_TEST=m | ||
180 | CONFIG_CRYPTO_CCM=m | 132 | CONFIG_CRYPTO_CCM=m |
181 | CONFIG_CRYPTO_GCM=m | 133 | CONFIG_CRYPTO_GCM=m |
134 | CONFIG_CRYPTO_CBC=y | ||
182 | CONFIG_CRYPTO_CTS=m | 135 | CONFIG_CRYPTO_CTS=m |
183 | CONFIG_CRYPTO_ECB=m | 136 | CONFIG_CRYPTO_ECB=m |
137 | CONFIG_CRYPTO_LRW=m | ||
184 | CONFIG_CRYPTO_PCBC=m | 138 | CONFIG_CRYPTO_PCBC=m |
139 | CONFIG_CRYPTO_XTS=m | ||
140 | CONFIG_CRYPTO_XCBC=m | ||
185 | CONFIG_CRYPTO_VMAC=m | 141 | CONFIG_CRYPTO_VMAC=m |
142 | CONFIG_CRYPTO_MD4=m | ||
143 | CONFIG_CRYPTO_MICHAEL_MIC=m | ||
186 | CONFIG_CRYPTO_RMD128=m | 144 | CONFIG_CRYPTO_RMD128=m |
187 | CONFIG_CRYPTO_RMD160=m | 145 | CONFIG_CRYPTO_RMD160=m |
188 | CONFIG_CRYPTO_RMD256=m | 146 | CONFIG_CRYPTO_RMD256=m |
189 | CONFIG_CRYPTO_RMD320=m | 147 | CONFIG_CRYPTO_RMD320=m |
148 | CONFIG_CRYPTO_SHA256=m | ||
149 | CONFIG_CRYPTO_SHA512=m | ||
150 | CONFIG_CRYPTO_TGR192=m | ||
151 | CONFIG_CRYPTO_WP512=m | ||
152 | CONFIG_CRYPTO_ANUBIS=m | ||
153 | CONFIG_CRYPTO_ARC4=m | ||
154 | CONFIG_CRYPTO_BLOWFISH=m | ||
190 | CONFIG_CRYPTO_CAMELLIA=m | 155 | CONFIG_CRYPTO_CAMELLIA=m |
156 | CONFIG_CRYPTO_CAST5=m | ||
157 | CONFIG_CRYPTO_CAST6=m | ||
158 | CONFIG_CRYPTO_DES=m | ||
191 | CONFIG_CRYPTO_FCRYPT=m | 159 | CONFIG_CRYPTO_FCRYPT=m |
160 | CONFIG_CRYPTO_KHAZAD=m | ||
192 | CONFIG_CRYPTO_SALSA20=m | 161 | CONFIG_CRYPTO_SALSA20=m |
193 | CONFIG_CRYPTO_SEED=m | 162 | CONFIG_CRYPTO_SEED=m |
163 | CONFIG_CRYPTO_SERPENT=m | ||
164 | CONFIG_CRYPTO_TEA=m | ||
165 | CONFIG_CRYPTO_TWOFISH=m | ||
166 | CONFIG_CRYPTO_DEFLATE=m | ||
194 | CONFIG_CRYPTO_ZLIB=m | 167 | CONFIG_CRYPTO_ZLIB=m |
195 | CONFIG_CRYPTO_LZO=m | 168 | CONFIG_CRYPTO_LZO=m |
196 | CONFIG_ZCRYPT=m | 169 | CONFIG_ZCRYPT=m |
170 | CONFIG_CRYPTO_SHA1_S390=m | ||
171 | CONFIG_CRYPTO_SHA256_S390=m | ||
197 | CONFIG_CRYPTO_SHA512_S390=m | 172 | CONFIG_CRYPTO_SHA512_S390=m |
198 | CONFIG_CRC_T10DIF=y | 173 | CONFIG_CRYPTO_DES_S390=m |
199 | CONFIG_CRC32=m | 174 | CONFIG_CRYPTO_AES_S390=m |
200 | CONFIG_CRC7=m | 175 | CONFIG_CRC7=m |
201 | CONFIG_KVM=m | 176 | CONFIG_VIRTIO_BALLOON=y |
202 | CONFIG_VIRTIO_BALLOON=m | ||
diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile index b08d2abf6178..2e671d5004ca 100644 --- a/arch/s390/hypfs/Makefile +++ b/arch/s390/hypfs/Makefile | |||
@@ -4,4 +4,4 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o | 5 | obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o |
6 | 6 | ||
7 | s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o | 7 | s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o |
diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h index fa487d4cc08b..d9df5a060a83 100644 --- a/arch/s390/hypfs/hypfs.h +++ b/arch/s390/hypfs/hypfs.h | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/debugfs.h> | 14 | #include <linux/debugfs.h> |
15 | #include <linux/workqueue.h> | ||
16 | #include <linux/kref.h> | ||
15 | 17 | ||
16 | #define REG_FILE_MODE 0440 | 18 | #define REG_FILE_MODE 0440 |
17 | #define UPDATE_FILE_MODE 0220 | 19 | #define UPDATE_FILE_MODE 0220 |
@@ -38,6 +40,33 @@ extern int hypfs_vm_init(void); | |||
38 | extern void hypfs_vm_exit(void); | 40 | extern void hypfs_vm_exit(void); |
39 | extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root); | 41 | extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root); |
40 | 42 | ||
41 | /* Directory for debugfs files */ | 43 | /* debugfs interface */ |
42 | extern struct dentry *hypfs_dbfs_dir; | 44 | struct hypfs_dbfs_file; |
45 | |||
46 | struct hypfs_dbfs_data { | ||
47 | void *buf; | ||
48 | void *buf_free_ptr; | ||
49 | size_t size; | ||
50 | struct hypfs_dbfs_file *dbfs_file; | ||
51 | struct kref kref; | ||
52 | }; | ||
53 | |||
54 | struct hypfs_dbfs_file { | ||
55 | const char *name; | ||
56 | int (*data_create)(void **data, void **data_free_ptr, | ||
57 | size_t *size); | ||
58 | void (*data_free)(const void *buf_free_ptr); | ||
59 | |||
60 | /* Private data for hypfs_dbfs.c */ | ||
61 | struct hypfs_dbfs_data *data; | ||
62 | struct delayed_work data_free_work; | ||
63 | struct mutex lock; | ||
64 | struct dentry *dentry; | ||
65 | }; | ||
66 | |||
67 | extern int hypfs_dbfs_init(void); | ||
68 | extern void hypfs_dbfs_exit(void); | ||
69 | extern int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df); | ||
70 | extern void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df); | ||
71 | |||
43 | #endif /* _HYPFS_H_ */ | 72 | #endif /* _HYPFS_H_ */ |
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c new file mode 100644 index 000000000000..b478013b7fec --- /dev/null +++ b/arch/s390/hypfs/hypfs_dbfs.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Hypervisor filesystem for Linux on s390 - debugfs interface | ||
3 | * | ||
4 | * Copyright (C) IBM Corp. 2010 | ||
5 | * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/slab.h> | ||
9 | #include "hypfs.h" | ||
10 | |||
11 | static struct dentry *dbfs_dir; | ||
12 | |||
13 | static struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f) | ||
14 | { | ||
15 | struct hypfs_dbfs_data *data; | ||
16 | |||
17 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
18 | if (!data) | ||
19 | return NULL; | ||
20 | kref_init(&data->kref); | ||
21 | data->dbfs_file = f; | ||
22 | return data; | ||
23 | } | ||
24 | |||
25 | static void hypfs_dbfs_data_free(struct kref *kref) | ||
26 | { | ||
27 | struct hypfs_dbfs_data *data; | ||
28 | |||
29 | data = container_of(kref, struct hypfs_dbfs_data, kref); | ||
30 | data->dbfs_file->data_free(data->buf_free_ptr); | ||
31 | kfree(data); | ||
32 | } | ||
33 | |||
34 | static void data_free_delayed(struct work_struct *work) | ||
35 | { | ||
36 | struct hypfs_dbfs_data *data; | ||
37 | struct hypfs_dbfs_file *df; | ||
38 | |||
39 | df = container_of(work, struct hypfs_dbfs_file, data_free_work.work); | ||
40 | mutex_lock(&df->lock); | ||
41 | data = df->data; | ||
42 | df->data = NULL; | ||
43 | mutex_unlock(&df->lock); | ||
44 | kref_put(&data->kref, hypfs_dbfs_data_free); | ||
45 | } | ||
46 | |||
47 | static ssize_t dbfs_read(struct file *file, char __user *buf, | ||
48 | size_t size, loff_t *ppos) | ||
49 | { | ||
50 | struct hypfs_dbfs_data *data; | ||
51 | struct hypfs_dbfs_file *df; | ||
52 | ssize_t rc; | ||
53 | |||
54 | if (*ppos != 0) | ||
55 | return 0; | ||
56 | |||
57 | df = file->f_path.dentry->d_inode->i_private; | ||
58 | mutex_lock(&df->lock); | ||
59 | if (!df->data) { | ||
60 | data = hypfs_dbfs_data_alloc(df); | ||
61 | if (!data) { | ||
62 | mutex_unlock(&df->lock); | ||
63 | return -ENOMEM; | ||
64 | } | ||
65 | rc = df->data_create(&data->buf, &data->buf_free_ptr, | ||
66 | &data->size); | ||
67 | if (rc) { | ||
68 | mutex_unlock(&df->lock); | ||
69 | kfree(data); | ||
70 | return rc; | ||
71 | } | ||
72 | df->data = data; | ||
73 | schedule_delayed_work(&df->data_free_work, HZ); | ||
74 | } | ||
75 | data = df->data; | ||
76 | kref_get(&data->kref); | ||
77 | mutex_unlock(&df->lock); | ||
78 | |||
79 | rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size); | ||
80 | kref_put(&data->kref, hypfs_dbfs_data_free); | ||
81 | return rc; | ||
82 | } | ||
83 | |||
84 | static const struct file_operations dbfs_ops = { | ||
85 | .read = dbfs_read, | ||
86 | .llseek = no_llseek, | ||
87 | }; | ||
88 | |||
89 | int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) | ||
90 | { | ||
91 | df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, | ||
92 | &dbfs_ops); | ||
93 | if (IS_ERR(df->dentry)) | ||
94 | return PTR_ERR(df->dentry); | ||
95 | mutex_init(&df->lock); | ||
96 | INIT_DELAYED_WORK(&df->data_free_work, data_free_delayed); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df) | ||
101 | { | ||
102 | debugfs_remove(df->dentry); | ||
103 | } | ||
104 | |||
105 | int hypfs_dbfs_init(void) | ||
106 | { | ||
107 | dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); | ||
108 | if (IS_ERR(dbfs_dir)) | ||
109 | return PTR_ERR(dbfs_dir); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | void hypfs_dbfs_exit(void) | ||
114 | { | ||
115 | debugfs_remove(dbfs_dir); | ||
116 | } | ||
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index 1211bb1d2f24..6023c6dc1fb7 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c | |||
@@ -555,80 +555,38 @@ struct dbfs_d204 { | |||
555 | char buf[]; /* d204 buffer */ | 555 | char buf[]; /* d204 buffer */ |
556 | } __attribute__ ((packed)); | 556 | } __attribute__ ((packed)); |
557 | 557 | ||
558 | struct dbfs_d204_private { | 558 | static int dbfs_d204_create(void **data, void **data_free_ptr, size_t *size) |
559 | struct dbfs_d204 *d204; /* Aligned d204 data with header */ | ||
560 | void *base; /* Base pointer (needed for vfree) */ | ||
561 | }; | ||
562 | |||
563 | static int dbfs_d204_open(struct inode *inode, struct file *file) | ||
564 | { | 559 | { |
565 | struct dbfs_d204_private *data; | ||
566 | struct dbfs_d204 *d204; | 560 | struct dbfs_d204 *d204; |
567 | int rc, buf_size; | 561 | int rc, buf_size; |
562 | void *base; | ||
568 | 563 | ||
569 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
570 | if (!data) | ||
571 | return -ENOMEM; | ||
572 | buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr); | 564 | buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr); |
573 | data->base = vmalloc(buf_size); | 565 | base = vmalloc(buf_size); |
574 | if (!data->base) { | 566 | if (!base) |
575 | rc = -ENOMEM; | 567 | return -ENOMEM; |
576 | goto fail_kfree_data; | 568 | memset(base, 0, buf_size); |
569 | d204 = page_align_ptr(base + sizeof(d204->hdr)) - sizeof(d204->hdr); | ||
570 | rc = diag204_do_store(d204->buf, diag204_buf_pages); | ||
571 | if (rc) { | ||
572 | vfree(base); | ||
573 | return rc; | ||
577 | } | 574 | } |
578 | memset(data->base, 0, buf_size); | ||
579 | d204 = page_align_ptr(data->base + sizeof(d204->hdr)) | ||
580 | - sizeof(d204->hdr); | ||
581 | rc = diag204_do_store(&d204->buf, diag204_buf_pages); | ||
582 | if (rc) | ||
583 | goto fail_vfree_base; | ||
584 | d204->hdr.version = DBFS_D204_HDR_VERSION; | 575 | d204->hdr.version = DBFS_D204_HDR_VERSION; |
585 | d204->hdr.len = PAGE_SIZE * diag204_buf_pages; | 576 | d204->hdr.len = PAGE_SIZE * diag204_buf_pages; |
586 | d204->hdr.sc = diag204_store_sc; | 577 | d204->hdr.sc = diag204_store_sc; |
587 | data->d204 = d204; | 578 | *data = d204; |
588 | file->private_data = data; | 579 | *data_free_ptr = base; |
589 | return nonseekable_open(inode, file); | 580 | *size = d204->hdr.len + sizeof(struct dbfs_d204_hdr); |
590 | |||
591 | fail_vfree_base: | ||
592 | vfree(data->base); | ||
593 | fail_kfree_data: | ||
594 | kfree(data); | ||
595 | return rc; | ||
596 | } | ||
597 | |||
598 | static int dbfs_d204_release(struct inode *inode, struct file *file) | ||
599 | { | ||
600 | struct dbfs_d204_private *data = file->private_data; | ||
601 | |||
602 | vfree(data->base); | ||
603 | kfree(data); | ||
604 | return 0; | 581 | return 0; |
605 | } | 582 | } |
606 | 583 | ||
607 | static ssize_t dbfs_d204_read(struct file *file, char __user *buf, | 584 | static struct hypfs_dbfs_file dbfs_file_d204 = { |
608 | size_t size, loff_t *ppos) | 585 | .name = "diag_204", |
609 | { | 586 | .data_create = dbfs_d204_create, |
610 | struct dbfs_d204_private *data = file->private_data; | 587 | .data_free = vfree, |
611 | |||
612 | return simple_read_from_buffer(buf, size, ppos, data->d204, | ||
613 | data->d204->hdr.len + | ||
614 | sizeof(data->d204->hdr)); | ||
615 | } | ||
616 | |||
617 | static const struct file_operations dbfs_d204_ops = { | ||
618 | .open = dbfs_d204_open, | ||
619 | .read = dbfs_d204_read, | ||
620 | .release = dbfs_d204_release, | ||
621 | }; | 588 | }; |
622 | 589 | ||
623 | static int hypfs_dbfs_init(void) | ||
624 | { | ||
625 | dbfs_d204_file = debugfs_create_file("diag_204", 0400, hypfs_dbfs_dir, | ||
626 | NULL, &dbfs_d204_ops); | ||
627 | if (IS_ERR(dbfs_d204_file)) | ||
628 | return PTR_ERR(dbfs_d204_file); | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | __init int hypfs_diag_init(void) | 590 | __init int hypfs_diag_init(void) |
633 | { | 591 | { |
634 | int rc; | 592 | int rc; |
@@ -637,18 +595,21 @@ __init int hypfs_diag_init(void) | |||
637 | pr_err("The hardware system does not support hypfs\n"); | 595 | pr_err("The hardware system does not support hypfs\n"); |
638 | return -ENODATA; | 596 | return -ENODATA; |
639 | } | 597 | } |
640 | rc = diag224_get_name_table(); | ||
641 | if (rc) { | ||
642 | diag204_free_buffer(); | ||
643 | pr_err("The hardware system does not provide all " | ||
644 | "functions required by hypfs\n"); | ||
645 | } | ||
646 | if (diag204_info_type == INFO_EXT) { | 598 | if (diag204_info_type == INFO_EXT) { |
647 | rc = hypfs_dbfs_init(); | 599 | rc = hypfs_dbfs_create_file(&dbfs_file_d204); |
648 | if (rc) | 600 | if (rc) |
649 | diag204_free_buffer(); | 601 | return rc; |
650 | } | 602 | } |
651 | return rc; | 603 | if (MACHINE_IS_LPAR) { |
604 | rc = diag224_get_name_table(); | ||
605 | if (rc) { | ||
606 | pr_err("The hardware system does not provide all " | ||
607 | "functions required by hypfs\n"); | ||
608 | debugfs_remove(dbfs_d204_file); | ||
609 | return rc; | ||
610 | } | ||
611 | } | ||
612 | return 0; | ||
652 | } | 613 | } |
653 | 614 | ||
654 | void hypfs_diag_exit(void) | 615 | void hypfs_diag_exit(void) |
@@ -656,6 +617,7 @@ void hypfs_diag_exit(void) | |||
656 | debugfs_remove(dbfs_d204_file); | 617 | debugfs_remove(dbfs_d204_file); |
657 | diag224_delete_name_table(); | 618 | diag224_delete_name_table(); |
658 | diag204_free_buffer(); | 619 | diag204_free_buffer(); |
620 | hypfs_dbfs_remove_file(&dbfs_file_d204); | ||
659 | } | 621 | } |
660 | 622 | ||
661 | /* | 623 | /* |
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c index ee5ab1a578e7..e54796002f61 100644 --- a/arch/s390/hypfs/hypfs_vm.c +++ b/arch/s390/hypfs/hypfs_vm.c | |||
@@ -20,8 +20,6 @@ static char local_guest[] = " "; | |||
20 | static char all_guests[] = "* "; | 20 | static char all_guests[] = "* "; |
21 | static char *guest_query; | 21 | static char *guest_query; |
22 | 22 | ||
23 | static struct dentry *dbfs_d2fc_file; | ||
24 | |||
25 | struct diag2fc_data { | 23 | struct diag2fc_data { |
26 | __u32 version; | 24 | __u32 version; |
27 | __u32 flags; | 25 | __u32 flags; |
@@ -104,7 +102,7 @@ static void *diag2fc_store(char *query, unsigned int *count, int offset) | |||
104 | return data; | 102 | return data; |
105 | } | 103 | } |
106 | 104 | ||
107 | static void diag2fc_free(void *data) | 105 | static void diag2fc_free(const void *data) |
108 | { | 106 | { |
109 | vfree(data); | 107 | vfree(data); |
110 | } | 108 | } |
@@ -239,42 +237,29 @@ struct dbfs_d2fc { | |||
239 | char buf[]; /* d2fc buffer */ | 237 | char buf[]; /* d2fc buffer */ |
240 | } __attribute__ ((packed)); | 238 | } __attribute__ ((packed)); |
241 | 239 | ||
242 | static int dbfs_d2fc_open(struct inode *inode, struct file *file) | 240 | static int dbfs_diag2fc_create(void **data, void **data_free_ptr, size_t *size) |
243 | { | 241 | { |
244 | struct dbfs_d2fc *data; | 242 | struct dbfs_d2fc *d2fc; |
245 | unsigned int count; | 243 | unsigned int count; |
246 | 244 | ||
247 | data = diag2fc_store(guest_query, &count, sizeof(data->hdr)); | 245 | d2fc = diag2fc_store(guest_query, &count, sizeof(d2fc->hdr)); |
248 | if (IS_ERR(data)) | 246 | if (IS_ERR(d2fc)) |
249 | return PTR_ERR(data); | 247 | return PTR_ERR(d2fc); |
250 | get_clock_ext(data->hdr.tod_ext); | 248 | get_clock_ext(d2fc->hdr.tod_ext); |
251 | data->hdr.len = count * sizeof(struct diag2fc_data); | 249 | d2fc->hdr.len = count * sizeof(struct diag2fc_data); |
252 | data->hdr.version = DBFS_D2FC_HDR_VERSION; | 250 | d2fc->hdr.version = DBFS_D2FC_HDR_VERSION; |
253 | data->hdr.count = count; | 251 | d2fc->hdr.count = count; |
254 | memset(&data->hdr.reserved, 0, sizeof(data->hdr.reserved)); | 252 | memset(&d2fc->hdr.reserved, 0, sizeof(d2fc->hdr.reserved)); |
255 | file->private_data = data; | 253 | *data = d2fc; |
256 | return nonseekable_open(inode, file); | 254 | *data_free_ptr = d2fc; |
257 | } | 255 | *size = d2fc->hdr.len + sizeof(struct dbfs_d2fc_hdr); |
258 | |||
259 | static int dbfs_d2fc_release(struct inode *inode, struct file *file) | ||
260 | { | ||
261 | diag2fc_free(file->private_data); | ||
262 | return 0; | 256 | return 0; |
263 | } | 257 | } |
264 | 258 | ||
265 | static ssize_t dbfs_d2fc_read(struct file *file, char __user *buf, | 259 | static struct hypfs_dbfs_file dbfs_file_2fc = { |
266 | size_t size, loff_t *ppos) | 260 | .name = "diag_2fc", |
267 | { | 261 | .data_create = dbfs_diag2fc_create, |
268 | struct dbfs_d2fc *data = file->private_data; | 262 | .data_free = diag2fc_free, |
269 | |||
270 | return simple_read_from_buffer(buf, size, ppos, data, data->hdr.len + | ||
271 | sizeof(struct dbfs_d2fc_hdr)); | ||
272 | } | ||
273 | |||
274 | static const struct file_operations dbfs_d2fc_ops = { | ||
275 | .open = dbfs_d2fc_open, | ||
276 | .read = dbfs_d2fc_read, | ||
277 | .release = dbfs_d2fc_release, | ||
278 | }; | 263 | }; |
279 | 264 | ||
280 | int hypfs_vm_init(void) | 265 | int hypfs_vm_init(void) |
@@ -287,18 +272,12 @@ int hypfs_vm_init(void) | |||
287 | guest_query = local_guest; | 272 | guest_query = local_guest; |
288 | else | 273 | else |
289 | return -EACCES; | 274 | return -EACCES; |
290 | 275 | return hypfs_dbfs_create_file(&dbfs_file_2fc); | |
291 | dbfs_d2fc_file = debugfs_create_file("diag_2fc", 0400, hypfs_dbfs_dir, | ||
292 | NULL, &dbfs_d2fc_ops); | ||
293 | if (IS_ERR(dbfs_d2fc_file)) | ||
294 | return PTR_ERR(dbfs_d2fc_file); | ||
295 | |||
296 | return 0; | ||
297 | } | 276 | } |
298 | 277 | ||
299 | void hypfs_vm_exit(void) | 278 | void hypfs_vm_exit(void) |
300 | { | 279 | { |
301 | if (!MACHINE_IS_VM) | 280 | if (!MACHINE_IS_VM) |
302 | return; | 281 | return; |
303 | debugfs_remove(dbfs_d2fc_file); | 282 | hypfs_dbfs_remove_file(&dbfs_file_2fc); |
304 | } | 283 | } |
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index 98a4a4c267a7..6fe874fc5f8e 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c | |||
@@ -46,8 +46,6 @@ static const struct super_operations hypfs_s_ops; | |||
46 | /* start of list of all dentries, which have to be deleted on update */ | 46 | /* start of list of all dentries, which have to be deleted on update */ |
47 | static struct dentry *hypfs_last_dentry; | 47 | static struct dentry *hypfs_last_dentry; |
48 | 48 | ||
49 | struct dentry *hypfs_dbfs_dir; | ||
50 | |||
51 | static void hypfs_update_update(struct super_block *sb) | 49 | static void hypfs_update_update(struct super_block *sb) |
52 | { | 50 | { |
53 | struct hypfs_sb_info *sb_info = sb->s_fs_info; | 51 | struct hypfs_sb_info *sb_info = sb->s_fs_info; |
@@ -316,10 +314,10 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent) | |||
316 | return 0; | 314 | return 0; |
317 | } | 315 | } |
318 | 316 | ||
319 | static int hypfs_get_super(struct file_system_type *fst, int flags, | 317 | static struct dentry *hypfs_mount(struct file_system_type *fst, int flags, |
320 | const char *devname, void *data, struct vfsmount *mnt) | 318 | const char *devname, void *data) |
321 | { | 319 | { |
322 | return get_sb_single(fst, flags, data, hypfs_fill_super, mnt); | 320 | return mount_single(fst, flags, data, hypfs_fill_super); |
323 | } | 321 | } |
324 | 322 | ||
325 | static void hypfs_kill_super(struct super_block *sb) | 323 | static void hypfs_kill_super(struct super_block *sb) |
@@ -449,12 +447,13 @@ static const struct file_operations hypfs_file_ops = { | |||
449 | .write = do_sync_write, | 447 | .write = do_sync_write, |
450 | .aio_read = hypfs_aio_read, | 448 | .aio_read = hypfs_aio_read, |
451 | .aio_write = hypfs_aio_write, | 449 | .aio_write = hypfs_aio_write, |
450 | .llseek = no_llseek, | ||
452 | }; | 451 | }; |
453 | 452 | ||
454 | static struct file_system_type hypfs_type = { | 453 | static struct file_system_type hypfs_type = { |
455 | .owner = THIS_MODULE, | 454 | .owner = THIS_MODULE, |
456 | .name = "s390_hypfs", | 455 | .name = "s390_hypfs", |
457 | .get_sb = hypfs_get_super, | 456 | .mount = hypfs_mount, |
458 | .kill_sb = hypfs_kill_super | 457 | .kill_sb = hypfs_kill_super |
459 | }; | 458 | }; |
460 | 459 | ||
@@ -470,13 +469,12 @@ static int __init hypfs_init(void) | |||
470 | { | 469 | { |
471 | int rc; | 470 | int rc; |
472 | 471 | ||
473 | hypfs_dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); | 472 | rc = hypfs_dbfs_init(); |
474 | if (IS_ERR(hypfs_dbfs_dir)) | 473 | if (rc) |
475 | return PTR_ERR(hypfs_dbfs_dir); | 474 | return rc; |
476 | |||
477 | if (hypfs_diag_init()) { | 475 | if (hypfs_diag_init()) { |
478 | rc = -ENODATA; | 476 | rc = -ENODATA; |
479 | goto fail_debugfs_remove; | 477 | goto fail_dbfs_exit; |
480 | } | 478 | } |
481 | if (hypfs_vm_init()) { | 479 | if (hypfs_vm_init()) { |
482 | rc = -ENODATA; | 480 | rc = -ENODATA; |
@@ -498,9 +496,8 @@ fail_hypfs_vm_exit: | |||
498 | hypfs_vm_exit(); | 496 | hypfs_vm_exit(); |
499 | fail_hypfs_diag_exit: | 497 | fail_hypfs_diag_exit: |
500 | hypfs_diag_exit(); | 498 | hypfs_diag_exit(); |
501 | fail_debugfs_remove: | 499 | fail_dbfs_exit: |
502 | debugfs_remove(hypfs_dbfs_dir); | 500 | hypfs_dbfs_exit(); |
503 | |||
504 | pr_err("Initialization of hypfs failed with rc=%i\n", rc); | 501 | pr_err("Initialization of hypfs failed with rc=%i\n", rc); |
505 | return rc; | 502 | return rc; |
506 | } | 503 | } |
@@ -509,7 +506,7 @@ static void __exit hypfs_exit(void) | |||
509 | { | 506 | { |
510 | hypfs_diag_exit(); | 507 | hypfs_diag_exit(); |
511 | hypfs_vm_exit(); | 508 | hypfs_vm_exit(); |
512 | debugfs_remove(hypfs_dbfs_dir); | 509 | hypfs_dbfs_exit(); |
513 | unregister_filesystem(&hypfs_type); | 510 | unregister_filesystem(&hypfs_type); |
514 | kobject_put(s390_kobj); | 511 | kobject_put(s390_kobj); |
515 | } | 512 | } |
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index 42e512ba8b43..287d7bbb6d36 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild | |||
@@ -5,6 +5,7 @@ header-y += chsc.h | |||
5 | header-y += cmb.h | 5 | header-y += cmb.h |
6 | header-y += dasd.h | 6 | header-y += dasd.h |
7 | header-y += debug.h | 7 | header-y += debug.h |
8 | header-y += kvm_virtio.h | ||
8 | header-y += monwriter.h | 9 | header-y += monwriter.h |
9 | header-y += qeth.h | 10 | header-y += qeth.h |
10 | header-y += schid.h | 11 | header-y += schid.h |
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index 76daea117181..d9db13810d15 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h | |||
@@ -9,7 +9,7 @@ | |||
9 | * | 9 | * |
10 | * Atomic operations that C can't guarantee us. | 10 | * Atomic operations that C can't guarantee us. |
11 | * Useful for resource counting etc. | 11 | * Useful for resource counting etc. |
12 | * s390 uses 'Compare And Swap' for atomicity in SMP enviroment. | 12 | * s390 uses 'Compare And Swap' for atomicity in SMP environment. |
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
@@ -36,14 +36,19 @@ | |||
36 | 36 | ||
37 | static inline int atomic_read(const atomic_t *v) | 37 | static inline int atomic_read(const atomic_t *v) |
38 | { | 38 | { |
39 | barrier(); | 39 | int c; |
40 | return v->counter; | 40 | |
41 | asm volatile( | ||
42 | " l %0,%1\n" | ||
43 | : "=d" (c) : "Q" (v->counter)); | ||
44 | return c; | ||
41 | } | 45 | } |
42 | 46 | ||
43 | static inline void atomic_set(atomic_t *v, int i) | 47 | static inline void atomic_set(atomic_t *v, int i) |
44 | { | 48 | { |
45 | v->counter = i; | 49 | asm volatile( |
46 | barrier(); | 50 | " st %1,%0\n" |
51 | : "=Q" (v->counter) : "d" (i)); | ||
47 | } | 52 | } |
48 | 53 | ||
49 | static inline int atomic_add_return(int i, atomic_t *v) | 54 | static inline int atomic_add_return(int i, atomic_t *v) |
@@ -128,14 +133,19 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) | |||
128 | 133 | ||
129 | static inline long long atomic64_read(const atomic64_t *v) | 134 | static inline long long atomic64_read(const atomic64_t *v) |
130 | { | 135 | { |
131 | barrier(); | 136 | long long c; |
132 | return v->counter; | 137 | |
138 | asm volatile( | ||
139 | " lg %0,%1\n" | ||
140 | : "=d" (c) : "Q" (v->counter)); | ||
141 | return c; | ||
133 | } | 142 | } |
134 | 143 | ||
135 | static inline void atomic64_set(atomic64_t *v, long long i) | 144 | static inline void atomic64_set(atomic64_t *v, long long i) |
136 | { | 145 | { |
137 | v->counter = i; | 146 | asm volatile( |
138 | barrier(); | 147 | " stg %1,%0\n" |
148 | : "=Q" (v->counter) : "d" (i)); | ||
139 | } | 149 | } |
140 | 150 | ||
141 | static inline long long atomic64_add_return(long long i, atomic64_t *v) | 151 | static inline long long atomic64_add_return(long long i, atomic64_t *v) |
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index 2e05972c5085..667c6e9f6a34 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h | |||
@@ -621,6 +621,7 @@ static inline unsigned long find_first_zero_bit(const unsigned long *addr, | |||
621 | bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes)); | 621 | bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes)); |
622 | return (bits < size) ? bits : size; | 622 | return (bits < size) ? bits : size; |
623 | } | 623 | } |
624 | #define find_first_zero_bit find_first_zero_bit | ||
624 | 625 | ||
625 | /** | 626 | /** |
626 | * find_first_bit - find the first set bit in a memory region | 627 | * find_first_bit - find the first set bit in a memory region |
@@ -641,6 +642,7 @@ static inline unsigned long find_first_bit(const unsigned long * addr, | |||
641 | bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes)); | 642 | bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes)); |
642 | return (bits < size) ? bits : size; | 643 | return (bits < size) ? bits : size; |
643 | } | 644 | } |
645 | #define find_first_bit find_first_bit | ||
644 | 646 | ||
645 | /** | 647 | /** |
646 | * find_next_zero_bit - find the first zero bit in a memory region | 648 | * find_next_zero_bit - find the first zero bit in a memory region |
@@ -677,6 +679,7 @@ static inline int find_next_zero_bit (const unsigned long * addr, | |||
677 | } | 679 | } |
678 | return offset + find_first_zero_bit(p, size); | 680 | return offset + find_first_zero_bit(p, size); |
679 | } | 681 | } |
682 | #define find_next_zero_bit find_next_zero_bit | ||
680 | 683 | ||
681 | /** | 684 | /** |
682 | * find_next_bit - find the first set bit in a memory region | 685 | * find_next_bit - find the first set bit in a memory region |
@@ -713,6 +716,7 @@ static inline int find_next_bit (const unsigned long * addr, | |||
713 | } | 716 | } |
714 | return offset + find_first_bit(p, size); | 717 | return offset + find_first_bit(p, size); |
715 | } | 718 | } |
719 | #define find_next_bit find_next_bit | ||
716 | 720 | ||
717 | /* | 721 | /* |
718 | * Every architecture must define this function. It's the fastest | 722 | * Every architecture must define this function. It's the fastest |
@@ -742,18 +746,7 @@ static inline int sched_find_first_bit(unsigned long *b) | |||
742 | * 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 | 746 | * 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 |
743 | */ | 747 | */ |
744 | 748 | ||
745 | #define ext2_set_bit(nr, addr) \ | 749 | static inline int find_first_zero_bit_le(void *vaddr, unsigned int size) |
746 | __test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) | ||
747 | #define ext2_set_bit_atomic(lock, nr, addr) \ | ||
748 | test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) | ||
749 | #define ext2_clear_bit(nr, addr) \ | ||
750 | __test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) | ||
751 | #define ext2_clear_bit_atomic(lock, nr, addr) \ | ||
752 | test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) | ||
753 | #define ext2_test_bit(nr, addr) \ | ||
754 | test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) | ||
755 | |||
756 | static inline int ext2_find_first_zero_bit(void *vaddr, unsigned int size) | ||
757 | { | 750 | { |
758 | unsigned long bytes, bits; | 751 | unsigned long bytes, bits; |
759 | 752 | ||
@@ -763,8 +756,9 @@ static inline int ext2_find_first_zero_bit(void *vaddr, unsigned int size) | |||
763 | bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes)); | 756 | bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes)); |
764 | return (bits < size) ? bits : size; | 757 | return (bits < size) ? bits : size; |
765 | } | 758 | } |
759 | #define find_first_zero_bit_le find_first_zero_bit_le | ||
766 | 760 | ||
767 | static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size, | 761 | static inline int find_next_zero_bit_le(void *vaddr, unsigned long size, |
768 | unsigned long offset) | 762 | unsigned long offset) |
769 | { | 763 | { |
770 | unsigned long *addr = vaddr, *p; | 764 | unsigned long *addr = vaddr, *p; |
@@ -790,11 +784,11 @@ static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size, | |||
790 | size -= __BITOPS_WORDSIZE; | 784 | size -= __BITOPS_WORDSIZE; |
791 | p++; | 785 | p++; |
792 | } | 786 | } |
793 | return offset + ext2_find_first_zero_bit(p, size); | 787 | return offset + find_first_zero_bit_le(p, size); |
794 | } | 788 | } |
789 | #define find_next_zero_bit_le find_next_zero_bit_le | ||
795 | 790 | ||
796 | static inline unsigned long ext2_find_first_bit(void *vaddr, | 791 | static inline unsigned long find_first_bit_le(void *vaddr, unsigned long size) |
797 | unsigned long size) | ||
798 | { | 792 | { |
799 | unsigned long bytes, bits; | 793 | unsigned long bytes, bits; |
800 | 794 | ||
@@ -804,8 +798,9 @@ static inline unsigned long ext2_find_first_bit(void *vaddr, | |||
804 | bits = __ffs_word(bytes*8, __load_ulong_le(vaddr, bytes)); | 798 | bits = __ffs_word(bytes*8, __load_ulong_le(vaddr, bytes)); |
805 | return (bits < size) ? bits : size; | 799 | return (bits < size) ? bits : size; |
806 | } | 800 | } |
801 | #define find_first_bit_le find_first_bit_le | ||
807 | 802 | ||
808 | static inline int ext2_find_next_bit(void *vaddr, unsigned long size, | 803 | static inline int find_next_bit_le(void *vaddr, unsigned long size, |
809 | unsigned long offset) | 804 | unsigned long offset) |
810 | { | 805 | { |
811 | unsigned long *addr = vaddr, *p; | 806 | unsigned long *addr = vaddr, *p; |
@@ -831,10 +826,17 @@ static inline int ext2_find_next_bit(void *vaddr, unsigned long size, | |||
831 | size -= __BITOPS_WORDSIZE; | 826 | size -= __BITOPS_WORDSIZE; |
832 | p++; | 827 | p++; |
833 | } | 828 | } |
834 | return offset + ext2_find_first_bit(p, size); | 829 | return offset + find_first_bit_le(p, size); |
835 | } | 830 | } |
831 | #define find_next_bit_le find_next_bit_le | ||
832 | |||
833 | #include <asm-generic/bitops/le.h> | ||
834 | |||
835 | #define ext2_set_bit_atomic(lock, nr, addr) \ | ||
836 | test_and_set_bit_le(nr, addr) | ||
837 | #define ext2_clear_bit_atomic(lock, nr, addr) \ | ||
838 | test_and_clear_bit_le(nr, addr) | ||
836 | 839 | ||
837 | #include <asm-generic/bitops/minix.h> | ||
838 | 840 | ||
839 | #endif /* __KERNEL__ */ | 841 | #endif /* __KERNEL__ */ |
840 | 842 | ||
diff --git a/arch/s390/include/asm/cache.h b/arch/s390/include/asm/cache.h index 24aafa68b643..2a30d5ac0667 100644 --- a/arch/s390/include/asm/cache.h +++ b/arch/s390/include/asm/cache.h | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #define L1_CACHE_BYTES 256 | 14 | #define L1_CACHE_BYTES 256 |
15 | #define L1_CACHE_SHIFT 8 | 15 | #define L1_CACHE_SHIFT 8 |
16 | #define NET_SKB_PAD 32 | ||
16 | 17 | ||
17 | #define __read_mostly __attribute__((__section__(".data..read_mostly"))) | 18 | #define __read_mostly __attribute__((__section__(".data..read_mostly"))) |
18 | 19 | ||
diff --git a/arch/s390/include/asm/cacheflush.h b/arch/s390/include/asm/cacheflush.h index 405cc97c6249..3e20383d0921 100644 --- a/arch/s390/include/asm/cacheflush.h +++ b/arch/s390/include/asm/cacheflush.h | |||
@@ -1,32 +1,16 @@ | |||
1 | #ifndef _S390_CACHEFLUSH_H | 1 | #ifndef _S390_CACHEFLUSH_H |
2 | #define _S390_CACHEFLUSH_H | 2 | #define _S390_CACHEFLUSH_H |
3 | 3 | ||
4 | /* Keep includes the same across arches. */ | ||
5 | #include <linux/mm.h> | ||
6 | |||
7 | /* Caches aren't brain-dead on the s390. */ | 4 | /* Caches aren't brain-dead on the s390. */ |
8 | #define flush_cache_all() do { } while (0) | 5 | #include <asm-generic/cacheflush.h> |
9 | #define flush_cache_mm(mm) do { } while (0) | ||
10 | #define flush_cache_dup_mm(mm) do { } while (0) | ||
11 | #define flush_cache_range(vma, start, end) do { } while (0) | ||
12 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | ||
13 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | ||
14 | #define flush_dcache_page(page) do { } while (0) | ||
15 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | ||
16 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | ||
17 | #define flush_icache_range(start, end) do { } while (0) | ||
18 | #define flush_icache_page(vma,pg) do { } while (0) | ||
19 | #define flush_icache_user_range(vma,pg,adr,len) do { } while (0) | ||
20 | #define flush_cache_vmap(start, end) do { } while (0) | ||
21 | #define flush_cache_vunmap(start, end) do { } while (0) | ||
22 | |||
23 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | ||
24 | memcpy(dst, src, len) | ||
25 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | ||
26 | memcpy(dst, src, len) | ||
27 | 6 | ||
28 | #ifdef CONFIG_DEBUG_PAGEALLOC | 7 | #ifdef CONFIG_DEBUG_PAGEALLOC |
29 | void kernel_map_pages(struct page *page, int numpages, int enable); | 8 | void kernel_map_pages(struct page *page, int numpages, int enable); |
30 | #endif | 9 | #endif |
31 | 10 | ||
11 | int set_memory_ro(unsigned long addr, int numpages); | ||
12 | int set_memory_rw(unsigned long addr, int numpages); | ||
13 | int set_memory_nx(unsigned long addr, int numpages); | ||
14 | int set_memory_x(unsigned long addr, int numpages); | ||
15 | |||
32 | #endif /* _S390_CACHEFLUSH_H */ | 16 | #endif /* _S390_CACHEFLUSH_H */ |
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index f3ba0fa98de6..623f2fb71774 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h | |||
@@ -92,6 +92,16 @@ struct ccw_device { | |||
92 | }; | 92 | }; |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * Possible events used by the path_event notifier. | ||
96 | */ | ||
97 | #define PE_NONE 0x0 | ||
98 | #define PE_PATH_GONE 0x1 /* A path is no longer available. */ | ||
99 | #define PE_PATH_AVAILABLE 0x2 /* A path has become available and | ||
100 | was successfully verified. */ | ||
101 | #define PE_PATHGROUP_ESTABLISHED 0x4 /* A pathgroup was reset and had | ||
102 | to be established again. */ | ||
103 | |||
104 | /* | ||
95 | * Possible CIO actions triggered by the unit check handler. | 105 | * Possible CIO actions triggered by the unit check handler. |
96 | */ | 106 | */ |
97 | enum uc_todo { | 107 | enum uc_todo { |
@@ -102,13 +112,13 @@ enum uc_todo { | |||
102 | 112 | ||
103 | /** | 113 | /** |
104 | * struct ccw driver - device driver for channel attached devices | 114 | * struct ccw driver - device driver for channel attached devices |
105 | * @owner: owning module | ||
106 | * @ids: ids supported by this driver | 115 | * @ids: ids supported by this driver |
107 | * @probe: function called on probe | 116 | * @probe: function called on probe |
108 | * @remove: function called on remove | 117 | * @remove: function called on remove |
109 | * @set_online: called when setting device online | 118 | * @set_online: called when setting device online |
110 | * @set_offline: called when setting device offline | 119 | * @set_offline: called when setting device offline |
111 | * @notify: notify driver of device state changes | 120 | * @notify: notify driver of device state changes |
121 | * @path_event: notify driver of channel path events | ||
112 | * @shutdown: called at device shutdown | 122 | * @shutdown: called at device shutdown |
113 | * @prepare: prepare for pm state transition | 123 | * @prepare: prepare for pm state transition |
114 | * @complete: undo work done in @prepare | 124 | * @complete: undo work done in @prepare |
@@ -117,16 +127,15 @@ enum uc_todo { | |||
117 | * @restore: callback for restoring after hibernation | 127 | * @restore: callback for restoring after hibernation |
118 | * @uc_handler: callback for unit check handler | 128 | * @uc_handler: callback for unit check handler |
119 | * @driver: embedded device driver structure | 129 | * @driver: embedded device driver structure |
120 | * @name: device driver name | ||
121 | */ | 130 | */ |
122 | struct ccw_driver { | 131 | struct ccw_driver { |
123 | struct module *owner; | ||
124 | struct ccw_device_id *ids; | 132 | struct ccw_device_id *ids; |
125 | int (*probe) (struct ccw_device *); | 133 | int (*probe) (struct ccw_device *); |
126 | void (*remove) (struct ccw_device *); | 134 | void (*remove) (struct ccw_device *); |
127 | int (*set_online) (struct ccw_device *); | 135 | int (*set_online) (struct ccw_device *); |
128 | int (*set_offline) (struct ccw_device *); | 136 | int (*set_offline) (struct ccw_device *); |
129 | int (*notify) (struct ccw_device *, int); | 137 | int (*notify) (struct ccw_device *, int); |
138 | void (*path_event) (struct ccw_device *, int *); | ||
130 | void (*shutdown) (struct ccw_device *); | 139 | void (*shutdown) (struct ccw_device *); |
131 | int (*prepare) (struct ccw_device *); | 140 | int (*prepare) (struct ccw_device *); |
132 | void (*complete) (struct ccw_device *); | 141 | void (*complete) (struct ccw_device *); |
@@ -135,7 +144,6 @@ struct ccw_driver { | |||
135 | int (*restore)(struct ccw_device *); | 144 | int (*restore)(struct ccw_device *); |
136 | enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *); | 145 | enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *); |
137 | struct device_driver driver; | 146 | struct device_driver driver; |
138 | char *name; | ||
139 | }; | 147 | }; |
140 | 148 | ||
141 | extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, | 149 | extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, |
@@ -192,6 +200,8 @@ int ccw_device_tm_start_timeout(struct ccw_device *, struct tcw *, | |||
192 | unsigned long, u8, int); | 200 | unsigned long, u8, int); |
193 | int ccw_device_tm_intrg(struct ccw_device *cdev); | 201 | int ccw_device_tm_intrg(struct ccw_device *cdev); |
194 | 202 | ||
203 | int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask); | ||
204 | |||
195 | extern int ccw_device_set_online(struct ccw_device *cdev); | 205 | extern int ccw_device_set_online(struct ccw_device *cdev); |
196 | extern int ccw_device_set_offline(struct ccw_device *cdev); | 206 | extern int ccw_device_set_offline(struct ccw_device *cdev); |
197 | 207 | ||
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index c79c1e787b86..f2ea2c56a7e1 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h | |||
@@ -29,8 +29,6 @@ struct ccwgroup_device { | |||
29 | 29 | ||
30 | /** | 30 | /** |
31 | * struct ccwgroup_driver - driver for ccw group devices | 31 | * struct ccwgroup_driver - driver for ccw group devices |
32 | * @owner: driver owner | ||
33 | * @name: driver name | ||
34 | * @max_slaves: maximum number of slave devices | 32 | * @max_slaves: maximum number of slave devices |
35 | * @driver_id: unique id | 33 | * @driver_id: unique id |
36 | * @probe: function called on probe | 34 | * @probe: function called on probe |
@@ -46,8 +44,6 @@ struct ccwgroup_device { | |||
46 | * @driver: embedded driver structure | 44 | * @driver: embedded driver structure |
47 | */ | 45 | */ |
48 | struct ccwgroup_driver { | 46 | struct ccwgroup_driver { |
49 | struct module *owner; | ||
50 | char *name; | ||
51 | int max_slaves; | 47 | int max_slaves; |
52 | unsigned long driver_id; | 48 | unsigned long driver_id; |
53 | 49 | ||
diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h index e34347d567a6..fc50a3342da3 100644 --- a/arch/s390/include/asm/cio.h +++ b/arch/s390/include/asm/cio.h | |||
@@ -183,7 +183,7 @@ struct esw3 { | |||
183 | * The irb that is handed to the device driver when an interrupt occurs. For | 183 | * The irb that is handed to the device driver when an interrupt occurs. For |
184 | * solicited interrupts, the common I/O layer already performs checks whether | 184 | * solicited interrupts, the common I/O layer already performs checks whether |
185 | * a field is valid; a field not being valid is always passed as %0. | 185 | * a field is valid; a field not being valid is always passed as %0. |
186 | * If a unit check occured, @ecw may contain sense data; this is retrieved | 186 | * If a unit check occurred, @ecw may contain sense data; this is retrieved |
187 | * by the common I/O layer itself if the device doesn't support concurrent | 187 | * by the common I/O layer itself if the device doesn't support concurrent |
188 | * sense (so that the device driver never needs to perform basic sene itself). | 188 | * sense (so that the device driver never needs to perform basic sene itself). |
189 | * For unsolicited interrupts, the irb is passed as-is (expect for sense data, | 189 | * For unsolicited interrupts, the irb is passed as-is (expect for sense data, |
diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h new file mode 100644 index 000000000000..81d7908416cf --- /dev/null +++ b/arch/s390/include/asm/cmpxchg.h | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 1999, 2011 | ||
3 | * | ||
4 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, | ||
5 | */ | ||
6 | |||
7 | #ifndef __ASM_CMPXCHG_H | ||
8 | #define __ASM_CMPXCHG_H | ||
9 | |||
10 | #include <linux/types.h> | ||
11 | |||
12 | extern void __xchg_called_with_bad_pointer(void); | ||
13 | |||
14 | static inline unsigned long __xchg(unsigned long x, void *ptr, int size) | ||
15 | { | ||
16 | unsigned long addr, old; | ||
17 | int shift; | ||
18 | |||
19 | switch (size) { | ||
20 | case 1: | ||
21 | addr = (unsigned long) ptr; | ||
22 | shift = (3 ^ (addr & 3)) << 3; | ||
23 | addr ^= addr & 3; | ||
24 | asm volatile( | ||
25 | " l %0,%4\n" | ||
26 | "0: lr 0,%0\n" | ||
27 | " nr 0,%3\n" | ||
28 | " or 0,%2\n" | ||
29 | " cs %0,0,%4\n" | ||
30 | " jl 0b\n" | ||
31 | : "=&d" (old), "=Q" (*(int *) addr) | ||
32 | : "d" (x << shift), "d" (~(255 << shift)), | ||
33 | "Q" (*(int *) addr) : "memory", "cc", "0"); | ||
34 | return old >> shift; | ||
35 | case 2: | ||
36 | addr = (unsigned long) ptr; | ||
37 | shift = (2 ^ (addr & 2)) << 3; | ||
38 | addr ^= addr & 2; | ||
39 | asm volatile( | ||
40 | " l %0,%4\n" | ||
41 | "0: lr 0,%0\n" | ||
42 | " nr 0,%3\n" | ||
43 | " or 0,%2\n" | ||
44 | " cs %0,0,%4\n" | ||
45 | " jl 0b\n" | ||
46 | : "=&d" (old), "=Q" (*(int *) addr) | ||
47 | : "d" (x << shift), "d" (~(65535 << shift)), | ||
48 | "Q" (*(int *) addr) : "memory", "cc", "0"); | ||
49 | return old >> shift; | ||
50 | case 4: | ||
51 | asm volatile( | ||
52 | " l %0,%3\n" | ||
53 | "0: cs %0,%2,%3\n" | ||
54 | " jl 0b\n" | ||
55 | : "=&d" (old), "=Q" (*(int *) ptr) | ||
56 | : "d" (x), "Q" (*(int *) ptr) | ||
57 | : "memory", "cc"); | ||
58 | return old; | ||
59 | #ifdef CONFIG_64BIT | ||
60 | case 8: | ||
61 | asm volatile( | ||
62 | " lg %0,%3\n" | ||
63 | "0: csg %0,%2,%3\n" | ||
64 | " jl 0b\n" | ||
65 | : "=&d" (old), "=m" (*(long *) ptr) | ||
66 | : "d" (x), "Q" (*(long *) ptr) | ||
67 | : "memory", "cc"); | ||
68 | return old; | ||
69 | #endif /* CONFIG_64BIT */ | ||
70 | } | ||
71 | __xchg_called_with_bad_pointer(); | ||
72 | return x; | ||
73 | } | ||
74 | |||
75 | #define xchg(ptr, x) \ | ||
76 | ({ \ | ||
77 | __typeof__(*(ptr)) __ret; \ | ||
78 | __ret = (__typeof__(*(ptr))) \ | ||
79 | __xchg((unsigned long)(x), (void *)(ptr), sizeof(*(ptr)));\ | ||
80 | __ret; \ | ||
81 | }) | ||
82 | |||
83 | /* | ||
84 | * Atomic compare and exchange. Compare OLD with MEM, if identical, | ||
85 | * store NEW in MEM. Return the initial value in MEM. Success is | ||
86 | * indicated by comparing RETURN with OLD. | ||
87 | */ | ||
88 | |||
89 | #define __HAVE_ARCH_CMPXCHG | ||
90 | |||
91 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
92 | |||
93 | static inline unsigned long __cmpxchg(void *ptr, unsigned long old, | ||
94 | unsigned long new, int size) | ||
95 | { | ||
96 | unsigned long addr, prev, tmp; | ||
97 | int shift; | ||
98 | |||
99 | switch (size) { | ||
100 | case 1: | ||
101 | addr = (unsigned long) ptr; | ||
102 | shift = (3 ^ (addr & 3)) << 3; | ||
103 | addr ^= addr & 3; | ||
104 | asm volatile( | ||
105 | " l %0,%2\n" | ||
106 | "0: nr %0,%5\n" | ||
107 | " lr %1,%0\n" | ||
108 | " or %0,%3\n" | ||
109 | " or %1,%4\n" | ||
110 | " cs %0,%1,%2\n" | ||
111 | " jnl 1f\n" | ||
112 | " xr %1,%0\n" | ||
113 | " nr %1,%5\n" | ||
114 | " jnz 0b\n" | ||
115 | "1:" | ||
116 | : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) | ||
117 | : "d" (old << shift), "d" (new << shift), | ||
118 | "d" (~(255 << shift)), "Q" (*(int *) ptr) | ||
119 | : "memory", "cc"); | ||
120 | return prev >> shift; | ||
121 | case 2: | ||
122 | addr = (unsigned long) ptr; | ||
123 | shift = (2 ^ (addr & 2)) << 3; | ||
124 | addr ^= addr & 2; | ||
125 | asm volatile( | ||
126 | " l %0,%2\n" | ||
127 | "0: nr %0,%5\n" | ||
128 | " lr %1,%0\n" | ||
129 | " or %0,%3\n" | ||
130 | " or %1,%4\n" | ||
131 | " cs %0,%1,%2\n" | ||
132 | " jnl 1f\n" | ||
133 | " xr %1,%0\n" | ||
134 | " nr %1,%5\n" | ||
135 | " jnz 0b\n" | ||
136 | "1:" | ||
137 | : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) | ||
138 | : "d" (old << shift), "d" (new << shift), | ||
139 | "d" (~(65535 << shift)), "Q" (*(int *) ptr) | ||
140 | : "memory", "cc"); | ||
141 | return prev >> shift; | ||
142 | case 4: | ||
143 | asm volatile( | ||
144 | " cs %0,%3,%1\n" | ||
145 | : "=&d" (prev), "=Q" (*(int *) ptr) | ||
146 | : "0" (old), "d" (new), "Q" (*(int *) ptr) | ||
147 | : "memory", "cc"); | ||
148 | return prev; | ||
149 | #ifdef CONFIG_64BIT | ||
150 | case 8: | ||
151 | asm volatile( | ||
152 | " csg %0,%3,%1\n" | ||
153 | : "=&d" (prev), "=Q" (*(long *) ptr) | ||
154 | : "0" (old), "d" (new), "Q" (*(long *) ptr) | ||
155 | : "memory", "cc"); | ||
156 | return prev; | ||
157 | #endif /* CONFIG_64BIT */ | ||
158 | } | ||
159 | __cmpxchg_called_with_bad_pointer(); | ||
160 | return old; | ||
161 | } | ||
162 | |||
163 | #define cmpxchg(ptr, o, n) \ | ||
164 | ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ | ||
165 | (unsigned long)(n), sizeof(*(ptr)))) | ||
166 | |||
167 | #ifdef CONFIG_64BIT | ||
168 | #define cmpxchg64(ptr, o, n) \ | ||
169 | ({ \ | ||
170 | cmpxchg((ptr), (o), (n)); \ | ||
171 | }) | ||
172 | #else /* CONFIG_64BIT */ | ||
173 | static inline unsigned long long __cmpxchg64(void *ptr, | ||
174 | unsigned long long old, | ||
175 | unsigned long long new) | ||
176 | { | ||
177 | register_pair rp_old = {.pair = old}; | ||
178 | register_pair rp_new = {.pair = new}; | ||
179 | |||
180 | asm volatile( | ||
181 | " cds %0,%2,%1" | ||
182 | : "+&d" (rp_old), "=Q" (ptr) | ||
183 | : "d" (rp_new), "Q" (ptr) | ||
184 | : "cc"); | ||
185 | return rp_old.pair; | ||
186 | } | ||
187 | #define cmpxchg64(ptr, o, n) \ | ||
188 | ((__typeof__(*(ptr)))__cmpxchg64((ptr), \ | ||
189 | (unsigned long long)(o), \ | ||
190 | (unsigned long long)(n))) | ||
191 | #endif /* CONFIG_64BIT */ | ||
192 | |||
193 | #include <asm-generic/cmpxchg-local.h> | ||
194 | |||
195 | static inline unsigned long __cmpxchg_local(void *ptr, | ||
196 | unsigned long old, | ||
197 | unsigned long new, int size) | ||
198 | { | ||
199 | switch (size) { | ||
200 | case 1: | ||
201 | case 2: | ||
202 | case 4: | ||
203 | #ifdef CONFIG_64BIT | ||
204 | case 8: | ||
205 | #endif | ||
206 | return __cmpxchg(ptr, old, new, size); | ||
207 | default: | ||
208 | return __cmpxchg_local_generic(ptr, old, new, size); | ||
209 | } | ||
210 | |||
211 | return old; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make | ||
216 | * them available. | ||
217 | */ | ||
218 | #define cmpxchg_local(ptr, o, n) \ | ||
219 | ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ | ||
220 | (unsigned long)(n), sizeof(*(ptr)))) | ||
221 | |||
222 | #define cmpxchg64_local(ptr, o, n) cmpxchg64((ptr), (o), (n)) | ||
223 | |||
224 | #endif /* __ASM_CMPXCHG_H */ | ||
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index a875c2f542e1..da359ca6fe55 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h | |||
@@ -169,7 +169,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
169 | 169 | ||
170 | static inline int is_compat_task(void) | 170 | static inline int is_compat_task(void) |
171 | { | 171 | { |
172 | return test_thread_flag(TIF_31BIT); | 172 | return is_32bit_task(); |
173 | } | 173 | } |
174 | 174 | ||
175 | #else | 175 | #else |
diff --git a/arch/s390/include/asm/cpu.h b/arch/s390/include/asm/cpu.h index 471234b90574..e0b69540216f 100644 --- a/arch/s390/include/asm/cpu.h +++ b/arch/s390/include/asm/cpu.h | |||
@@ -20,7 +20,7 @@ struct cpuid | |||
20 | unsigned int ident : 24; | 20 | unsigned int ident : 24; |
21 | unsigned int machine : 16; | 21 | unsigned int machine : 16; |
22 | unsigned int unused : 16; | 22 | unsigned int unused : 16; |
23 | } __packed; | 23 | } __attribute__ ((packed, aligned(8))); |
24 | 24 | ||
25 | #endif /* __ASSEMBLY__ */ | 25 | #endif /* __ASSEMBLY__ */ |
26 | #endif /* _ASM_S390_CPU_H */ | 26 | #endif /* _ASM_S390_CPU_H */ |
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index 8b1a52a137c5..081434878296 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h | |||
@@ -73,18 +73,18 @@ cputime64_to_jiffies64(cputime64_t cputime) | |||
73 | } | 73 | } |
74 | 74 | ||
75 | /* | 75 | /* |
76 | * Convert cputime to milliseconds and back. | 76 | * Convert cputime to microseconds and back. |
77 | */ | 77 | */ |
78 | static inline unsigned int | 78 | static inline unsigned int |
79 | cputime_to_msecs(const cputime_t cputime) | 79 | cputime_to_usecs(const cputime_t cputime) |
80 | { | 80 | { |
81 | return cputime_div(cputime, 4096000); | 81 | return cputime_div(cputime, 4096); |
82 | } | 82 | } |
83 | 83 | ||
84 | static inline cputime_t | 84 | static inline cputime_t |
85 | msecs_to_cputime(const unsigned int m) | 85 | usecs_to_cputime(const unsigned int m) |
86 | { | 86 | { |
87 | return (cputime_t) m * 4096000; | 87 | return (cputime_t) m * 4096; |
88 | } | 88 | } |
89 | 89 | ||
90 | /* | 90 | /* |
@@ -202,7 +202,7 @@ static inline void s390_idle_check(struct pt_regs *regs, __u64 int_clock, | |||
202 | 202 | ||
203 | static inline int s390_nohz_delay(int cpu) | 203 | static inline int s390_nohz_delay(int cpu) |
204 | { | 204 | { |
205 | return per_cpu(s390_idle, cpu).nohz_delay != 0; | 205 | return __get_cpu_var(s390_idle).nohz_delay != 0; |
206 | } | 206 | } |
207 | 207 | ||
208 | #define arch_needs_cpu(cpu) s390_nohz_delay(cpu) | 208 | #define arch_needs_cpu(cpu) s390_nohz_delay(cpu) |
diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h index 218bce81ec70..0be28efe5b66 100644 --- a/arch/s390/include/asm/dasd.h +++ b/arch/s390/include/asm/dasd.h | |||
@@ -73,6 +73,7 @@ typedef struct dasd_information2_t { | |||
73 | * 0x02: use diag discipline (diag) | 73 | * 0x02: use diag discipline (diag) |
74 | * 0x04: set the device initially online (internal use only) | 74 | * 0x04: set the device initially online (internal use only) |
75 | * 0x08: enable ERP related logging | 75 | * 0x08: enable ERP related logging |
76 | * 0x20: give access to raw eckd data | ||
76 | */ | 77 | */ |
77 | #define DASD_FEATURE_DEFAULT 0x00 | 78 | #define DASD_FEATURE_DEFAULT 0x00 |
78 | #define DASD_FEATURE_READONLY 0x01 | 79 | #define DASD_FEATURE_READONLY 0x01 |
@@ -80,6 +81,8 @@ typedef struct dasd_information2_t { | |||
80 | #define DASD_FEATURE_INITIAL_ONLINE 0x04 | 81 | #define DASD_FEATURE_INITIAL_ONLINE 0x04 |
81 | #define DASD_FEATURE_ERPLOG 0x08 | 82 | #define DASD_FEATURE_ERPLOG 0x08 |
82 | #define DASD_FEATURE_FAILFAST 0x10 | 83 | #define DASD_FEATURE_FAILFAST 0x10 |
84 | #define DASD_FEATURE_FAILONSLCK 0x20 | ||
85 | #define DASD_FEATURE_USERAW 0x40 | ||
83 | 86 | ||
84 | #define DASD_PARTN_BITS 2 | 87 | #define DASD_PARTN_BITS 2 |
85 | 88 | ||
@@ -217,6 +220,25 @@ typedef struct dasd_symmio_parms { | |||
217 | int rssd_result_len; | 220 | int rssd_result_len; |
218 | } __attribute__ ((packed)) dasd_symmio_parms_t; | 221 | } __attribute__ ((packed)) dasd_symmio_parms_t; |
219 | 222 | ||
223 | /* | ||
224 | * Data returned by Sense Path Group ID (SNID) | ||
225 | */ | ||
226 | struct dasd_snid_data { | ||
227 | struct { | ||
228 | __u8 group:2; | ||
229 | __u8 reserve:2; | ||
230 | __u8 mode:1; | ||
231 | __u8 res:3; | ||
232 | } __attribute__ ((packed)) path_state; | ||
233 | __u8 pgid[11]; | ||
234 | } __attribute__ ((packed)); | ||
235 | |||
236 | struct dasd_snid_ioctl_data { | ||
237 | struct dasd_snid_data data; | ||
238 | __u8 path_mask; | ||
239 | } __attribute__ ((packed)); | ||
240 | |||
241 | |||
220 | /******************************************************************************** | 242 | /******************************************************************************** |
221 | * SECTION: Definition of IOCTLs | 243 | * SECTION: Definition of IOCTLs |
222 | * | 244 | * |
@@ -261,25 +283,10 @@ typedef struct dasd_symmio_parms { | |||
261 | /* Set Attributes (cache operations) */ | 283 | /* Set Attributes (cache operations) */ |
262 | #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) | 284 | #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) |
263 | 285 | ||
286 | /* Get Sense Path Group ID (SNID) data */ | ||
287 | #define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data) | ||
288 | |||
264 | #define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t) | 289 | #define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t) |
265 | 290 | ||
266 | #endif /* DASD_H */ | 291 | #endif /* DASD_H */ |
267 | 292 | ||
268 | /* | ||
269 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
270 | * Emacs will notice this stuff at the end of the file and automatically | ||
271 | * adjust the settings for this buffer only. This must remain at the end | ||
272 | * of the file. | ||
273 | * --------------------------------------------------------------------------- | ||
274 | * Local variables: | ||
275 | * c-indent-level: 4 | ||
276 | * c-brace-imaginary-offset: 0 | ||
277 | * c-brace-offset: -4 | ||
278 | * c-argdecl-indent: 4 | ||
279 | * c-label-offset: -4 | ||
280 | * c-continued-statement-offset: 4 | ||
281 | * c-continued-brace-offset: 0 | ||
282 | * indent-tabs-mode: nil | ||
283 | * tab-width: 8 | ||
284 | * End: | ||
285 | */ | ||
diff --git a/arch/s390/include/asm/delay.h b/arch/s390/include/asm/delay.h index 8a096b83f51f..0e3b35f96be1 100644 --- a/arch/s390/include/asm/delay.h +++ b/arch/s390/include/asm/delay.h | |||
@@ -14,10 +14,12 @@ | |||
14 | #ifndef _S390_DELAY_H | 14 | #ifndef _S390_DELAY_H |
15 | #define _S390_DELAY_H | 15 | #define _S390_DELAY_H |
16 | 16 | ||
17 | extern void __udelay(unsigned long long usecs); | 17 | void __ndelay(unsigned long long nsecs); |
18 | extern void udelay_simple(unsigned long long usecs); | 18 | void __udelay(unsigned long long usecs); |
19 | extern void __delay(unsigned long loops); | 19 | void udelay_simple(unsigned long long usecs); |
20 | void __delay(unsigned long loops); | ||
20 | 21 | ||
22 | #define ndelay(n) __ndelay((unsigned long long) (n)) | ||
21 | #define udelay(n) __udelay((unsigned long long) (n)) | 23 | #define udelay(n) __udelay((unsigned long long) (n)) |
22 | #define mdelay(n) __udelay((unsigned long long) (n) * 1000) | 24 | #define mdelay(n) __udelay((unsigned long long) (n) * 1000) |
23 | 25 | ||
diff --git a/arch/s390/include/asm/diag.h b/arch/s390/include/asm/diag.h index 72b2e2f2d32d..7e91c58072e2 100644 --- a/arch/s390/include/asm/diag.h +++ b/arch/s390/include/asm/diag.h | |||
@@ -9,9 +9,22 @@ | |||
9 | #define _ASM_S390_DIAG_H | 9 | #define _ASM_S390_DIAG_H |
10 | 10 | ||
11 | /* | 11 | /* |
12 | * Diagnose 10: Release pages | 12 | * Diagnose 10: Release page range |
13 | */ | 13 | */ |
14 | extern void diag10(unsigned long addr); | 14 | static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn) |
15 | { | ||
16 | unsigned long start_addr, end_addr; | ||
17 | |||
18 | start_addr = start_pfn << PAGE_SHIFT; | ||
19 | end_addr = (start_pfn + num_pfn - 1) << PAGE_SHIFT; | ||
20 | |||
21 | asm volatile( | ||
22 | "0: diag %0,%1,0x10\n" | ||
23 | "1:\n" | ||
24 | EX_TABLE(0b, 1b) | ||
25 | EX_TABLE(1b, 1b) | ||
26 | : : "a" (start_addr), "a" (end_addr)); | ||
27 | } | ||
15 | 28 | ||
16 | /* | 29 | /* |
17 | * Diagnose 14: Input spool file manipulation | 30 | * Diagnose 14: Input spool file manipulation |
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 354d42616c7e..64b61bf72e93 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h | |||
@@ -161,7 +161,9 @@ extern unsigned int vdso_enabled; | |||
161 | use of this is to invoke "./ld.so someprog" to test out a new version of | 161 | use of this is to invoke "./ld.so someprog" to test out a new version of |
162 | the loader. We need to make sure that it is out of the way of the program | 162 | the loader. We need to make sure that it is out of the way of the program |
163 | that it will "exec", and that there is sufficient room for the brk. */ | 163 | that it will "exec", and that there is sufficient room for the brk. */ |
164 | #define ELF_ET_DYN_BASE (STACK_TOP / 3 * 2) | 164 | |
165 | extern unsigned long randomize_et_dyn(unsigned long base); | ||
166 | #define ELF_ET_DYN_BASE (randomize_et_dyn(STACK_TOP / 3 * 2)) | ||
165 | 167 | ||
166 | /* This yields a mask that user programs can use to figure out what | 168 | /* This yields a mask that user programs can use to figure out what |
167 | instruction set this CPU supports. */ | 169 | instruction set this CPU supports. */ |
@@ -194,17 +196,7 @@ do { \ | |||
194 | } while (0) | 196 | } while (0) |
195 | #endif /* __s390x__ */ | 197 | #endif /* __s390x__ */ |
196 | 198 | ||
197 | /* | 199 | #define STACK_RND_MASK 0x7ffUL |
198 | * An executable for which elf_read_implies_exec() returns TRUE will | ||
199 | * have the READ_IMPLIES_EXEC personality flag set automatically. | ||
200 | */ | ||
201 | #define elf_read_implies_exec(ex, executable_stack) \ | ||
202 | ({ \ | ||
203 | if (current->mm->context.noexec && \ | ||
204 | executable_stack != EXSTACK_DISABLE_X) \ | ||
205 | disable_noexec(current->mm, current); \ | ||
206 | current->mm->context.noexec == 0; \ | ||
207 | }) | ||
208 | 200 | ||
209 | #define ARCH_DLINFO \ | 201 | #define ARCH_DLINFO \ |
210 | do { \ | 202 | do { \ |
@@ -218,4 +210,7 @@ struct linux_binprm; | |||
218 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 | 210 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 |
219 | int arch_setup_additional_pages(struct linux_binprm *, int); | 211 | int arch_setup_additional_pages(struct linux_binprm *, int); |
220 | 212 | ||
213 | extern unsigned long arch_randomize_brk(struct mm_struct *mm); | ||
214 | #define arch_randomize_brk arch_randomize_brk | ||
215 | |||
221 | #endif | 216 | #endif |
diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h index 96c14a9102b8..b7931faaef6d 100644 --- a/arch/s390/include/asm/ftrace.h +++ b/arch/s390/include/asm/ftrace.h | |||
@@ -4,25 +4,20 @@ | |||
4 | #ifndef __ASSEMBLY__ | 4 | #ifndef __ASSEMBLY__ |
5 | 5 | ||
6 | extern void _mcount(void); | 6 | extern void _mcount(void); |
7 | extern unsigned long ftrace_dyn_func; | ||
8 | 7 | ||
9 | struct dyn_arch_ftrace { }; | 8 | struct dyn_arch_ftrace { }; |
10 | 9 | ||
11 | #define MCOUNT_ADDR ((long)_mcount) | 10 | #define MCOUNT_ADDR ((long)_mcount) |
12 | 11 | ||
13 | #ifdef CONFIG_64BIT | 12 | #ifdef CONFIG_64BIT |
14 | #define MCOUNT_OFFSET_RET 18 | 13 | #define MCOUNT_INSN_SIZE 12 |
15 | #define MCOUNT_INSN_SIZE 24 | ||
16 | #define MCOUNT_OFFSET 14 | ||
17 | #else | 14 | #else |
18 | #define MCOUNT_OFFSET_RET 26 | 15 | #define MCOUNT_INSN_SIZE 20 |
19 | #define MCOUNT_INSN_SIZE 30 | ||
20 | #define MCOUNT_OFFSET 8 | ||
21 | #endif | 16 | #endif |
22 | 17 | ||
23 | static inline unsigned long ftrace_call_adjust(unsigned long addr) | 18 | static inline unsigned long ftrace_call_adjust(unsigned long addr) |
24 | { | 19 | { |
25 | return addr - MCOUNT_OFFSET; | 20 | return addr; |
26 | } | 21 | } |
27 | 22 | ||
28 | #endif /* __ASSEMBLY__ */ | 23 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h index 5c5d02de49e9..81cf36b691f1 100644 --- a/arch/s390/include/asm/futex.h +++ b/arch/s390/include/asm/futex.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #include <linux/uaccess.h> | 7 | #include <linux/uaccess.h> |
8 | #include <asm/errno.h> | 8 | #include <asm/errno.h> |
9 | 9 | ||
10 | static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | 10 | static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) |
11 | { | 11 | { |
12 | int op = (encoded_op >> 28) & 7; | 12 | int op = (encoded_op >> 28) & 7; |
13 | int cmp = (encoded_op >> 24) & 15; | 13 | int cmp = (encoded_op >> 24) & 15; |
@@ -18,7 +18,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
21 | if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) | 21 | if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) |
22 | return -EFAULT; | 22 | return -EFAULT; |
23 | 23 | ||
24 | pagefault_disable(); | 24 | pagefault_disable(); |
@@ -39,13 +39,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
39 | return ret; | 39 | return ret; |
40 | } | 40 | } |
41 | 41 | ||
42 | static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, | 42 | static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
43 | int oldval, int newval) | 43 | u32 oldval, u32 newval) |
44 | { | 44 | { |
45 | if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) | 45 | if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) |
46 | return -EFAULT; | 46 | return -EFAULT; |
47 | 47 | ||
48 | return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval); | 48 | return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval); |
49 | } | 49 | } |
50 | 50 | ||
51 | #endif /* __KERNEL__ */ | 51 | #endif /* __KERNEL__ */ |
diff --git a/arch/s390/include/asm/hardirq.h b/arch/s390/include/asm/hardirq.h index 498bc3892385..e4155d3eb2cb 100644 --- a/arch/s390/include/asm/hardirq.h +++ b/arch/s390/include/asm/hardirq.h | |||
@@ -12,10 +12,6 @@ | |||
12 | #ifndef __ASM_HARDIRQ_H | 12 | #ifndef __ASM_HARDIRQ_H |
13 | #define __ASM_HARDIRQ_H | 13 | #define __ASM_HARDIRQ_H |
14 | 14 | ||
15 | #include <linux/threads.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/cache.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <asm/lowcore.h> | 15 | #include <asm/lowcore.h> |
20 | 16 | ||
21 | #define local_softirq_pending() (S390_lowcore.softirq_pending) | 17 | #define local_softirq_pending() (S390_lowcore.softirq_pending) |
@@ -25,20 +21,4 @@ | |||
25 | 21 | ||
26 | #define HARDIRQ_BITS 8 | 22 | #define HARDIRQ_BITS 8 |
27 | 23 | ||
28 | void clock_comparator_work(void); | ||
29 | |||
30 | static inline unsigned long long local_tick_disable(void) | ||
31 | { | ||
32 | unsigned long long old; | ||
33 | |||
34 | old = S390_lowcore.clock_comparator; | ||
35 | S390_lowcore.clock_comparator = -1ULL; | ||
36 | return old; | ||
37 | } | ||
38 | |||
39 | static inline void local_tick_enable(unsigned long long comp) | ||
40 | { | ||
41 | S390_lowcore.clock_comparator = comp; | ||
42 | } | ||
43 | |||
44 | #endif /* __ASM_HARDIRQ_H */ | 24 | #endif /* __ASM_HARDIRQ_H */ |
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h index bb8343d157bc..799ed0f1643d 100644 --- a/arch/s390/include/asm/hugetlb.h +++ b/arch/s390/include/asm/hugetlb.h | |||
@@ -37,32 +37,6 @@ static inline int prepare_hugepage_range(struct file *file, | |||
37 | int arch_prepare_hugepage(struct page *page); | 37 | int arch_prepare_hugepage(struct page *page); |
38 | void arch_release_hugepage(struct page *page); | 38 | void arch_release_hugepage(struct page *page); |
39 | 39 | ||
40 | static inline pte_t pte_mkhuge(pte_t pte) | ||
41 | { | ||
42 | /* | ||
43 | * PROT_NONE needs to be remapped from the pte type to the ste type. | ||
44 | * The HW invalid bit is also different for pte and ste. The pte | ||
45 | * invalid bit happens to be the same as the ste _SEGMENT_ENTRY_LARGE | ||
46 | * bit, so we don't have to clear it. | ||
47 | */ | ||
48 | if (pte_val(pte) & _PAGE_INVALID) { | ||
49 | if (pte_val(pte) & _PAGE_SWT) | ||
50 | pte_val(pte) |= _HPAGE_TYPE_NONE; | ||
51 | pte_val(pte) |= _SEGMENT_ENTRY_INV; | ||
52 | } | ||
53 | /* | ||
54 | * Clear SW pte bits SWT and SWX, there are no SW bits in a segment | ||
55 | * table entry. | ||
56 | */ | ||
57 | pte_val(pte) &= ~(_PAGE_SWT | _PAGE_SWX); | ||
58 | /* | ||
59 | * Also set the change-override bit because we don't need dirty bit | ||
60 | * tracking for hugetlbfs pages. | ||
61 | */ | ||
62 | pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO); | ||
63 | return pte; | ||
64 | } | ||
65 | |||
66 | static inline pte_t huge_pte_wrprotect(pte_t pte) | 40 | static inline pte_t huge_pte_wrprotect(pte_t pte) |
67 | { | 41 | { |
68 | pte_val(pte) |= _PAGE_RO; | 42 | pte_val(pte) |= _PAGE_RO; |
@@ -137,21 +111,10 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm, | |||
137 | { | 111 | { |
138 | pmd_t *pmdp = (pmd_t *) ptep; | 112 | pmd_t *pmdp = (pmd_t *) ptep; |
139 | 113 | ||
140 | if (!MACHINE_HAS_IDTE) { | 114 | if (MACHINE_HAS_IDTE) |
141 | __pmd_csp(pmdp); | ||
142 | if (mm->context.noexec) { | ||
143 | pmdp = get_shadow_table(pmdp); | ||
144 | __pmd_csp(pmdp); | ||
145 | } | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | __pmd_idte(address, pmdp); | ||
150 | if (mm->context.noexec) { | ||
151 | pmdp = get_shadow_table(pmdp); | ||
152 | __pmd_idte(address, pmdp); | 115 | __pmd_idte(address, pmdp); |
153 | } | 116 | else |
154 | return; | 117 | __pmd_csp(pmdp); |
155 | } | 118 | } |
156 | 119 | ||
157 | #define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ | 120 | #define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ |
diff --git a/arch/s390/include/asm/ioctls.h b/arch/s390/include/asm/ioctls.h index 2f3d8736361f..960a4c1ebdf1 100644 --- a/arch/s390/include/asm/ioctls.h +++ b/arch/s390/include/asm/ioctls.h | |||
@@ -1,94 +1,8 @@ | |||
1 | /* | ||
2 | * include/asm-s390/ioctls.h | ||
3 | * | ||
4 | * S390 version | ||
5 | * | ||
6 | * Derived from "include/asm-i386/ioctls.h" | ||
7 | */ | ||
8 | |||
9 | #ifndef __ARCH_S390_IOCTLS_H__ | 1 | #ifndef __ARCH_S390_IOCTLS_H__ |
10 | #define __ARCH_S390_IOCTLS_H__ | 2 | #define __ARCH_S390_IOCTLS_H__ |
11 | 3 | ||
12 | #include <asm/ioctl.h> | ||
13 | |||
14 | /* 0x54 is just a magic number to make these relatively unique ('T') */ | ||
15 | |||
16 | #define TCGETS 0x5401 | ||
17 | #define TCSETS 0x5402 | ||
18 | #define TCSETSW 0x5403 | ||
19 | #define TCSETSF 0x5404 | ||
20 | #define TCGETA 0x5405 | ||
21 | #define TCSETA 0x5406 | ||
22 | #define TCSETAW 0x5407 | ||
23 | #define TCSETAF 0x5408 | ||
24 | #define TCSBRK 0x5409 | ||
25 | #define TCXONC 0x540A | ||
26 | #define TCFLSH 0x540B | ||
27 | #define TIOCEXCL 0x540C | ||
28 | #define TIOCNXCL 0x540D | ||
29 | #define TIOCSCTTY 0x540E | ||
30 | #define TIOCGPGRP 0x540F | ||
31 | #define TIOCSPGRP 0x5410 | ||
32 | #define TIOCOUTQ 0x5411 | ||
33 | #define TIOCSTI 0x5412 | ||
34 | #define TIOCGWINSZ 0x5413 | ||
35 | #define TIOCSWINSZ 0x5414 | ||
36 | #define TIOCMGET 0x5415 | ||
37 | #define TIOCMBIS 0x5416 | ||
38 | #define TIOCMBIC 0x5417 | ||
39 | #define TIOCMSET 0x5418 | ||
40 | #define TIOCGSOFTCAR 0x5419 | ||
41 | #define TIOCSSOFTCAR 0x541A | ||
42 | #define FIONREAD 0x541B | ||
43 | #define TIOCINQ FIONREAD | ||
44 | #define TIOCLINUX 0x541C | ||
45 | #define TIOCCONS 0x541D | ||
46 | #define TIOCGSERIAL 0x541E | ||
47 | #define TIOCSSERIAL 0x541F | ||
48 | #define TIOCPKT 0x5420 | ||
49 | #define FIONBIO 0x5421 | ||
50 | #define TIOCNOTTY 0x5422 | ||
51 | #define TIOCSETD 0x5423 | ||
52 | #define TIOCGETD 0x5424 | ||
53 | #define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ | ||
54 | #define TIOCSBRK 0x5427 /* BSD compatibility */ | ||
55 | #define TIOCCBRK 0x5428 /* BSD compatibility */ | ||
56 | #define TIOCGSID 0x5429 /* Return the session ID of FD */ | ||
57 | #define TCGETS2 _IOR('T',0x2A, struct termios2) | ||
58 | #define TCSETS2 _IOW('T',0x2B, struct termios2) | ||
59 | #define TCSETSW2 _IOW('T',0x2C, struct termios2) | ||
60 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | ||
61 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | ||
62 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | ||
63 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
64 | |||
65 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ | ||
66 | #define FIOCLEX 0x5451 | ||
67 | #define FIOASYNC 0x5452 | ||
68 | #define TIOCSERCONFIG 0x5453 | ||
69 | #define TIOCSERGWILD 0x5454 | ||
70 | #define TIOCSERSWILD 0x5455 | ||
71 | #define TIOCGLCKTRMIOS 0x5456 | ||
72 | #define TIOCSLCKTRMIOS 0x5457 | ||
73 | #define TIOCSERGSTRUCT 0x5458 /* For debugging only */ | ||
74 | #define TIOCSERGETLSR 0x5459 /* Get line status register */ | ||
75 | #define TIOCSERGETMULTI 0x545A /* Get multiport config */ | ||
76 | #define TIOCSERSETMULTI 0x545B /* Set multiport config */ | ||
77 | |||
78 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ | ||
79 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | ||
80 | #define FIOQSIZE 0x545E | 4 | #define FIOQSIZE 0x545E |
81 | 5 | ||
82 | /* Used for packet mode */ | 6 | #include <asm-generic/ioctls.h> |
83 | #define TIOCPKT_DATA 0 | ||
84 | #define TIOCPKT_FLUSHREAD 1 | ||
85 | #define TIOCPKT_FLUSHWRITE 2 | ||
86 | #define TIOCPKT_STOP 4 | ||
87 | #define TIOCPKT_START 8 | ||
88 | #define TIOCPKT_NOSTOP 16 | ||
89 | #define TIOCPKT_DOSTOP 32 | ||
90 | #define TIOCPKT_IOCTL 64 | ||
91 | |||
92 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | ||
93 | 7 | ||
94 | #endif | 8 | #endif |
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index 7da991a858f8..ba7b01c726a3 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h | |||
@@ -1,23 +1,42 @@ | |||
1 | #ifndef _ASM_IRQ_H | 1 | #ifndef _ASM_IRQ_H |
2 | #define _ASM_IRQ_H | 2 | #define _ASM_IRQ_H |
3 | 3 | ||
4 | #ifdef __KERNEL__ | ||
5 | #include <linux/hardirq.h> | 4 | #include <linux/hardirq.h> |
6 | 5 | #include <linux/types.h> | |
7 | /* | ||
8 | * the definition of irqs has changed in 2.5.46: | ||
9 | * NR_IRQS is no longer the number of i/o | ||
10 | * interrupts (65536), but rather the number | ||
11 | * of interrupt classes (2). | ||
12 | * Only external and i/o interrupts make much sense here (CH). | ||
13 | */ | ||
14 | 6 | ||
15 | enum interruption_class { | 7 | enum interruption_class { |
16 | EXTERNAL_INTERRUPT, | 8 | EXTERNAL_INTERRUPT, |
17 | IO_INTERRUPT, | 9 | IO_INTERRUPT, |
18 | 10 | EXTINT_CLK, | |
11 | EXTINT_IPI, | ||
12 | EXTINT_TMR, | ||
13 | EXTINT_TLA, | ||
14 | EXTINT_PFL, | ||
15 | EXTINT_DSD, | ||
16 | EXTINT_VRT, | ||
17 | EXTINT_SCP, | ||
18 | EXTINT_IUC, | ||
19 | EXTINT_CPM, | ||
20 | IOINT_QAI, | ||
21 | IOINT_QDI, | ||
22 | IOINT_DAS, | ||
23 | IOINT_C15, | ||
24 | IOINT_C70, | ||
25 | IOINT_TAP, | ||
26 | IOINT_VMR, | ||
27 | IOINT_LCS, | ||
28 | IOINT_CLW, | ||
29 | IOINT_CTC, | ||
30 | IOINT_APB, | ||
31 | NMI_NMI, | ||
19 | NR_IRQS, | 32 | NR_IRQS, |
20 | }; | 33 | }; |
21 | 34 | ||
22 | #endif /* __KERNEL__ */ | 35 | typedef void (*ext_int_handler_t)(unsigned int, unsigned int, unsigned long); |
23 | #endif | 36 | |
37 | int register_external_interrupt(u16 code, ext_int_handler_t handler); | ||
38 | int unregister_external_interrupt(u16 code, ext_int_handler_t handler); | ||
39 | void service_subclass_irq_register(void); | ||
40 | void service_subclass_irq_unregister(void); | ||
41 | |||
42 | #endif /* _ASM_IRQ_H */ | ||
diff --git a/arch/s390/include/asm/irqflags.h b/arch/s390/include/asm/irqflags.h index 15b3ac253898..865d6d891ace 100644 --- a/arch/s390/include/asm/irqflags.h +++ b/arch/s390/include/asm/irqflags.h | |||
@@ -8,8 +8,8 @@ | |||
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | 10 | ||
11 | /* store then or system mask. */ | 11 | /* store then OR system mask. */ |
12 | #define __raw_local_irq_stosm(__or) \ | 12 | #define __arch_local_irq_stosm(__or) \ |
13 | ({ \ | 13 | ({ \ |
14 | unsigned long __mask; \ | 14 | unsigned long __mask; \ |
15 | asm volatile( \ | 15 | asm volatile( \ |
@@ -18,8 +18,8 @@ | |||
18 | __mask; \ | 18 | __mask; \ |
19 | }) | 19 | }) |
20 | 20 | ||
21 | /* store then and system mask. */ | 21 | /* store then AND system mask. */ |
22 | #define __raw_local_irq_stnsm(__and) \ | 22 | #define __arch_local_irq_stnsm(__and) \ |
23 | ({ \ | 23 | ({ \ |
24 | unsigned long __mask; \ | 24 | unsigned long __mask; \ |
25 | asm volatile( \ | 25 | asm volatile( \ |
@@ -29,39 +29,44 @@ | |||
29 | }) | 29 | }) |
30 | 30 | ||
31 | /* set system mask. */ | 31 | /* set system mask. */ |
32 | #define __raw_local_irq_ssm(__mask) \ | 32 | static inline void __arch_local_irq_ssm(unsigned long flags) |
33 | ({ \ | 33 | { |
34 | asm volatile("ssm %0" : : "Q" (__mask) : "memory"); \ | 34 | asm volatile("ssm %0" : : "Q" (flags) : "memory"); |
35 | }) | 35 | } |
36 | 36 | ||
37 | /* interrupt control.. */ | 37 | static inline unsigned long arch_local_save_flags(void) |
38 | static inline unsigned long raw_local_irq_enable(void) | ||
39 | { | 38 | { |
40 | return __raw_local_irq_stosm(0x03); | 39 | return __arch_local_irq_stosm(0x00); |
41 | } | 40 | } |
42 | 41 | ||
43 | static inline unsigned long raw_local_irq_disable(void) | 42 | static inline unsigned long arch_local_irq_save(void) |
44 | { | 43 | { |
45 | return __raw_local_irq_stnsm(0xfc); | 44 | return __arch_local_irq_stnsm(0xfc); |
46 | } | 45 | } |
47 | 46 | ||
48 | #define raw_local_save_flags(x) \ | 47 | static inline void arch_local_irq_disable(void) |
49 | do { \ | 48 | { |
50 | typecheck(unsigned long, x); \ | 49 | arch_local_irq_save(); |
51 | (x) = __raw_local_irq_stosm(0x00); \ | 50 | } |
52 | } while (0) | ||
53 | 51 | ||
54 | static inline void raw_local_irq_restore(unsigned long flags) | 52 | static inline void arch_local_irq_enable(void) |
55 | { | 53 | { |
56 | __raw_local_irq_ssm(flags); | 54 | __arch_local_irq_stosm(0x03); |
57 | } | 55 | } |
58 | 56 | ||
59 | static inline int raw_irqs_disabled_flags(unsigned long flags) | 57 | static inline void arch_local_irq_restore(unsigned long flags) |
58 | { | ||
59 | __arch_local_irq_ssm(flags); | ||
60 | } | ||
61 | |||
62 | static inline bool arch_irqs_disabled_flags(unsigned long flags) | ||
60 | { | 63 | { |
61 | return !(flags & (3UL << (BITS_PER_LONG - 8))); | 64 | return !(flags & (3UL << (BITS_PER_LONG - 8))); |
62 | } | 65 | } |
63 | 66 | ||
64 | /* For spinlocks etc */ | 67 | static inline bool arch_irqs_disabled(void) |
65 | #define raw_local_irq_save(x) ((x) = raw_local_irq_disable()) | 68 | { |
69 | return arch_irqs_disabled_flags(arch_local_save_flags()); | ||
70 | } | ||
66 | 71 | ||
67 | #endif /* __ASM_IRQFLAGS_H */ | 72 | #endif /* __ASM_IRQFLAGS_H */ |
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h new file mode 100644 index 000000000000..95a6cf2b5b67 --- /dev/null +++ b/arch/s390/include/asm/jump_label.h | |||
@@ -0,0 +1,37 @@ | |||
1 | #ifndef _ASM_S390_JUMP_LABEL_H | ||
2 | #define _ASM_S390_JUMP_LABEL_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | #define JUMP_LABEL_NOP_SIZE 6 | ||
7 | |||
8 | #ifdef CONFIG_64BIT | ||
9 | #define ASM_PTR ".quad" | ||
10 | #define ASM_ALIGN ".balign 8" | ||
11 | #else | ||
12 | #define ASM_PTR ".long" | ||
13 | #define ASM_ALIGN ".balign 4" | ||
14 | #endif | ||
15 | |||
16 | static __always_inline bool arch_static_branch(struct jump_label_key *key) | ||
17 | { | ||
18 | asm goto("0: brcl 0,0\n" | ||
19 | ".pushsection __jump_table, \"aw\"\n" | ||
20 | ASM_ALIGN "\n" | ||
21 | ASM_PTR " 0b, %l[label], %0\n" | ||
22 | ".popsection\n" | ||
23 | : : "X" (key) : : label); | ||
24 | return false; | ||
25 | label: | ||
26 | return true; | ||
27 | } | ||
28 | |||
29 | typedef unsigned long jump_label_t; | ||
30 | |||
31 | struct jump_entry { | ||
32 | jump_label_t code; | ||
33 | jump_label_t target; | ||
34 | jump_label_t key; | ||
35 | }; | ||
36 | |||
37 | #endif | ||
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h index 330f68caffe4..a231a9439c4b 100644 --- a/arch/s390/include/asm/kprobes.h +++ b/arch/s390/include/asm/kprobes.h | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/ptrace.h> | 31 | #include <linux/ptrace.h> |
32 | #include <linux/percpu.h> | 32 | #include <linux/percpu.h> |
33 | 33 | ||
34 | #define __ARCH_WANT_KPROBES_INSN_SLOT | ||
35 | struct pt_regs; | 34 | struct pt_regs; |
36 | struct kprobe; | 35 | struct kprobe; |
37 | 36 | ||
@@ -58,23 +57,12 @@ typedef u16 kprobe_opcode_t; | |||
58 | /* Architecture specific copy of original instruction */ | 57 | /* Architecture specific copy of original instruction */ |
59 | struct arch_specific_insn { | 58 | struct arch_specific_insn { |
60 | /* copy of original instruction */ | 59 | /* copy of original instruction */ |
61 | kprobe_opcode_t *insn; | 60 | kprobe_opcode_t insn[MAX_INSN_SIZE]; |
62 | int fixup; | ||
63 | int ilen; | ||
64 | int reg; | ||
65 | }; | 61 | }; |
66 | 62 | ||
67 | struct ins_replace_args { | ||
68 | kprobe_opcode_t *ptr; | ||
69 | kprobe_opcode_t old; | ||
70 | kprobe_opcode_t new; | ||
71 | }; | ||
72 | struct prev_kprobe { | 63 | struct prev_kprobe { |
73 | struct kprobe *kp; | 64 | struct kprobe *kp; |
74 | unsigned long status; | 65 | unsigned long status; |
75 | unsigned long saved_psw; | ||
76 | unsigned long kprobe_saved_imask; | ||
77 | unsigned long kprobe_saved_ctl[3]; | ||
78 | }; | 66 | }; |
79 | 67 | ||
80 | /* per-cpu kprobe control block */ | 68 | /* per-cpu kprobe control block */ |
@@ -82,17 +70,13 @@ struct kprobe_ctlblk { | |||
82 | unsigned long kprobe_status; | 70 | unsigned long kprobe_status; |
83 | unsigned long kprobe_saved_imask; | 71 | unsigned long kprobe_saved_imask; |
84 | unsigned long kprobe_saved_ctl[3]; | 72 | unsigned long kprobe_saved_ctl[3]; |
85 | struct pt_regs jprobe_saved_regs; | ||
86 | unsigned long jprobe_saved_r14; | ||
87 | unsigned long jprobe_saved_r15; | ||
88 | struct prev_kprobe prev_kprobe; | 73 | struct prev_kprobe prev_kprobe; |
74 | struct pt_regs jprobe_saved_regs; | ||
89 | kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; | 75 | kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; |
90 | }; | 76 | }; |
91 | 77 | ||
92 | void arch_remove_kprobe(struct kprobe *p); | 78 | void arch_remove_kprobe(struct kprobe *p); |
93 | void kretprobe_trampoline(void); | 79 | void kretprobe_trampoline(void); |
94 | int is_prohibited_opcode(kprobe_opcode_t *instruction); | ||
95 | void get_instruction_type(struct arch_specific_insn *ainsn); | ||
96 | 80 | ||
97 | int kprobe_fault_handler(struct pt_regs *regs, int trapnr); | 81 | int kprobe_fault_handler(struct pt_regs *regs, int trapnr); |
98 | int kprobe_exceptions_notify(struct notifier_block *self, | 82 | int kprobe_exceptions_notify(struct notifier_block *self, |
diff --git a/arch/s390/include/asm/kvm_virtio.h b/arch/s390/include/asm/kvm_virtio.h index acdfdff26611..72f614181eff 100644 --- a/arch/s390/include/asm/kvm_virtio.h +++ b/arch/s390/include/asm/kvm_virtio.h | |||
@@ -54,4 +54,11 @@ struct kvm_vqconfig { | |||
54 | * This is pagesize for historical reasons. */ | 54 | * This is pagesize for historical reasons. */ |
55 | #define KVM_S390_VIRTIO_RING_ALIGN 4096 | 55 | #define KVM_S390_VIRTIO_RING_ALIGN 4096 |
56 | 56 | ||
57 | |||
58 | /* These values are supposed to be in ext_params on an interrupt */ | ||
59 | #define VIRTIO_PARAM_MASK 0xff | ||
60 | #define VIRTIO_PARAM_VRING_INTERRUPT 0x0 | ||
61 | #define VIRTIO_PARAM_CONFIG_CHANGED 0x1 | ||
62 | #define VIRTIO_PARAM_DEV_ADD 0x2 | ||
63 | |||
57 | #endif | 64 | #endif |
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 0f97ef2d92ac..228cf0b295db 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h | |||
@@ -124,7 +124,7 @@ struct _lowcore { | |||
124 | /* Address space pointer. */ | 124 | /* Address space pointer. */ |
125 | __u32 kernel_asce; /* 0x02ac */ | 125 | __u32 kernel_asce; /* 0x02ac */ |
126 | __u32 user_asce; /* 0x02b0 */ | 126 | __u32 user_asce; /* 0x02b0 */ |
127 | __u32 user_exec_asce; /* 0x02b4 */ | 127 | __u32 current_pid; /* 0x02b4 */ |
128 | 128 | ||
129 | /* SMP info area */ | 129 | /* SMP info area */ |
130 | __u32 cpu_nr; /* 0x02b8 */ | 130 | __u32 cpu_nr; /* 0x02b8 */ |
@@ -150,9 +150,10 @@ struct _lowcore { | |||
150 | */ | 150 | */ |
151 | __u32 ipib; /* 0x0e00 */ | 151 | __u32 ipib; /* 0x0e00 */ |
152 | __u32 ipib_checksum; /* 0x0e04 */ | 152 | __u32 ipib_checksum; /* 0x0e04 */ |
153 | __u8 pad_0x0e08[0x0f00-0x0e08]; /* 0x0e08 */ | ||
153 | 154 | ||
154 | /* Align to the top 1k of prefix area */ | 155 | /* Extended facility list */ |
155 | __u8 pad_0x0e08[0x1000-0x0e08]; /* 0x0e08 */ | 156 | __u64 stfle_fac_list[32]; /* 0x0f00 */ |
156 | } __packed; | 157 | } __packed; |
157 | 158 | ||
158 | #else /* CONFIG_32BIT */ | 159 | #else /* CONFIG_32BIT */ |
@@ -254,7 +255,7 @@ struct _lowcore { | |||
254 | /* Address space pointer. */ | 255 | /* Address space pointer. */ |
255 | __u64 kernel_asce; /* 0x0310 */ | 256 | __u64 kernel_asce; /* 0x0310 */ |
256 | __u64 user_asce; /* 0x0318 */ | 257 | __u64 user_asce; /* 0x0318 */ |
257 | __u64 user_exec_asce; /* 0x0320 */ | 258 | __u64 current_pid; /* 0x0320 */ |
258 | 259 | ||
259 | /* SMP info area */ | 260 | /* SMP info area */ |
260 | __u32 cpu_nr; /* 0x0328 */ | 261 | __u32 cpu_nr; /* 0x0328 */ |
@@ -285,7 +286,11 @@ struct _lowcore { | |||
285 | */ | 286 | */ |
286 | __u64 ipib; /* 0x0e00 */ | 287 | __u64 ipib; /* 0x0e00 */ |
287 | __u32 ipib_checksum; /* 0x0e08 */ | 288 | __u32 ipib_checksum; /* 0x0e08 */ |
288 | __u8 pad_0x0e0c[0x11b8-0x0e0c]; /* 0x0e0c */ | 289 | __u8 pad_0x0e0c[0x0f00-0x0e0c]; /* 0x0e0c */ |
290 | |||
291 | /* Extended facility list */ | ||
292 | __u64 stfle_fac_list[32]; /* 0x0f00 */ | ||
293 | __u8 pad_0x1000[0x11b8-0x1000]; /* 0x1000 */ | ||
289 | 294 | ||
290 | /* 64 bit extparam used for pfault/diag 250: defined by architecture */ | 295 | /* 64 bit extparam used for pfault/diag 250: defined by architecture */ |
291 | __u64 ext_params2; /* 0x11B8 */ | 296 | __u64 ext_params2; /* 0x11B8 */ |
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h index 78522cdefdd4..82d0847896a0 100644 --- a/arch/s390/include/asm/mmu.h +++ b/arch/s390/include/asm/mmu.h | |||
@@ -5,19 +5,18 @@ typedef struct { | |||
5 | atomic_t attach_count; | 5 | atomic_t attach_count; |
6 | unsigned int flush_mm; | 6 | unsigned int flush_mm; |
7 | spinlock_t list_lock; | 7 | spinlock_t list_lock; |
8 | struct list_head crst_list; | ||
9 | struct list_head pgtable_list; | 8 | struct list_head pgtable_list; |
10 | unsigned long asce_bits; | 9 | unsigned long asce_bits; |
11 | unsigned long asce_limit; | 10 | unsigned long asce_limit; |
12 | unsigned long vdso_base; | 11 | unsigned long vdso_base; |
13 | int noexec; | 12 | /* Cloned contexts will be created with extended page tables. */ |
14 | int has_pgste; /* The mmu context has extended page tables */ | 13 | unsigned int alloc_pgste:1; |
15 | int alloc_pgste; /* cloned contexts will have extended page tables */ | 14 | /* The mmu context has extended page tables. */ |
15 | unsigned int has_pgste:1; | ||
16 | } mm_context_t; | 16 | } mm_context_t; |
17 | 17 | ||
18 | #define INIT_MM_CONTEXT(name) \ | 18 | #define INIT_MM_CONTEXT(name) \ |
19 | .context.list_lock = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \ | 19 | .context.list_lock = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \ |
20 | .context.crst_list = LIST_HEAD_INIT(name.context.crst_list), \ | ||
21 | .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), | 20 | .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), |
22 | 21 | ||
23 | #endif | 22 | #endif |
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index a6f0e7cc9cde..5682f160ff82 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h | |||
@@ -23,7 +23,7 @@ static inline int init_new_context(struct task_struct *tsk, | |||
23 | #ifdef CONFIG_64BIT | 23 | #ifdef CONFIG_64BIT |
24 | mm->context.asce_bits |= _ASCE_TYPE_REGION3; | 24 | mm->context.asce_bits |= _ASCE_TYPE_REGION3; |
25 | #endif | 25 | #endif |
26 | if (current->mm->context.alloc_pgste) { | 26 | if (current->mm && current->mm->context.alloc_pgste) { |
27 | /* | 27 | /* |
28 | * alloc_pgste indicates, that any NEW context will be created | 28 | * alloc_pgste indicates, that any NEW context will be created |
29 | * with extended page tables. The old context is unchanged. The | 29 | * with extended page tables. The old context is unchanged. The |
@@ -35,11 +35,9 @@ static inline int init_new_context(struct task_struct *tsk, | |||
35 | * and if has_pgste is set, it will create extended page | 35 | * and if has_pgste is set, it will create extended page |
36 | * tables. | 36 | * tables. |
37 | */ | 37 | */ |
38 | mm->context.noexec = 0; | ||
39 | mm->context.has_pgste = 1; | 38 | mm->context.has_pgste = 1; |
40 | mm->context.alloc_pgste = 1; | 39 | mm->context.alloc_pgste = 1; |
41 | } else { | 40 | } else { |
42 | mm->context.noexec = (user_mode == SECONDARY_SPACE_MODE); | ||
43 | mm->context.has_pgste = 0; | 41 | mm->context.has_pgste = 0; |
44 | mm->context.alloc_pgste = 0; | 42 | mm->context.alloc_pgste = 0; |
45 | } | 43 | } |
@@ -63,10 +61,8 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) | |||
63 | S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd); | 61 | S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd); |
64 | if (user_mode != HOME_SPACE_MODE) { | 62 | if (user_mode != HOME_SPACE_MODE) { |
65 | /* Load primary space page table origin. */ | 63 | /* Load primary space page table origin. */ |
66 | pgd = mm->context.noexec ? get_shadow_table(pgd) : pgd; | ||
67 | S390_lowcore.user_exec_asce = mm->context.asce_bits | __pa(pgd); | ||
68 | asm volatile(LCTL_OPCODE" 1,1,%0\n" | 64 | asm volatile(LCTL_OPCODE" 1,1,%0\n" |
69 | : : "m" (S390_lowcore.user_exec_asce) ); | 65 | : : "m" (S390_lowcore.user_asce) ); |
70 | } else | 66 | } else |
71 | /* Load home space page table origin. */ | 67 | /* Load home space page table origin. */ |
72 | asm volatile(LCTL_OPCODE" 13,13,%0" | 68 | asm volatile(LCTL_OPCODE" 13,13,%0" |
diff --git a/arch/s390/include/asm/mutex.h b/arch/s390/include/asm/mutex.h index 458c1f7fbc18..688271f5f2e4 100644 --- a/arch/s390/include/asm/mutex.h +++ b/arch/s390/include/asm/mutex.h | |||
@@ -7,3 +7,5 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <asm-generic/mutex-dec.h> | 9 | #include <asm-generic/mutex-dec.h> |
10 | |||
11 | #define arch_mutex_cpu_relax() barrier() | ||
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index af650fb47206..accb372ddc7e 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h | |||
@@ -90,6 +90,7 @@ static inline void copy_page(void *to, void *from) | |||
90 | */ | 90 | */ |
91 | 91 | ||
92 | typedef struct { unsigned long pgprot; } pgprot_t; | 92 | typedef struct { unsigned long pgprot; } pgprot_t; |
93 | typedef struct { unsigned long pgste; } pgste_t; | ||
93 | typedef struct { unsigned long pte; } pte_t; | 94 | typedef struct { unsigned long pte; } pte_t; |
94 | typedef struct { unsigned long pmd; } pmd_t; | 95 | typedef struct { unsigned long pmd; } pmd_t; |
95 | typedef struct { unsigned long pud; } pud_t; | 96 | typedef struct { unsigned long pud; } pud_t; |
@@ -97,35 +98,91 @@ typedef struct { unsigned long pgd; } pgd_t; | |||
97 | typedef pte_t *pgtable_t; | 98 | typedef pte_t *pgtable_t; |
98 | 99 | ||
99 | #define pgprot_val(x) ((x).pgprot) | 100 | #define pgprot_val(x) ((x).pgprot) |
101 | #define pgste_val(x) ((x).pgste) | ||
100 | #define pte_val(x) ((x).pte) | 102 | #define pte_val(x) ((x).pte) |
101 | #define pmd_val(x) ((x).pmd) | 103 | #define pmd_val(x) ((x).pmd) |
102 | #define pud_val(x) ((x).pud) | 104 | #define pud_val(x) ((x).pud) |
103 | #define pgd_val(x) ((x).pgd) | 105 | #define pgd_val(x) ((x).pgd) |
104 | 106 | ||
107 | #define __pgste(x) ((pgste_t) { (x) } ) | ||
105 | #define __pte(x) ((pte_t) { (x) } ) | 108 | #define __pte(x) ((pte_t) { (x) } ) |
106 | #define __pmd(x) ((pmd_t) { (x) } ) | 109 | #define __pmd(x) ((pmd_t) { (x) } ) |
110 | #define __pud(x) ((pud_t) { (x) } ) | ||
107 | #define __pgd(x) ((pgd_t) { (x) } ) | 111 | #define __pgd(x) ((pgd_t) { (x) } ) |
108 | #define __pgprot(x) ((pgprot_t) { (x) } ) | 112 | #define __pgprot(x) ((pgprot_t) { (x) } ) |
109 | 113 | ||
110 | static inline void | 114 | static inline void page_set_storage_key(unsigned long addr, |
111 | page_set_storage_key(unsigned long addr, unsigned int skey) | 115 | unsigned char skey, int mapped) |
112 | { | 116 | { |
113 | asm volatile("sske %0,%1" : : "d" (skey), "a" (addr)); | 117 | if (!mapped) |
118 | asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0" | ||
119 | : : "d" (skey), "a" (addr)); | ||
120 | else | ||
121 | asm volatile("sske %0,%1" : : "d" (skey), "a" (addr)); | ||
114 | } | 122 | } |
115 | 123 | ||
116 | static inline unsigned int | 124 | static inline unsigned char page_get_storage_key(unsigned long addr) |
117 | page_get_storage_key(unsigned long addr) | ||
118 | { | 125 | { |
119 | unsigned int skey; | 126 | unsigned char skey; |
120 | 127 | ||
121 | asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0)); | 128 | asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr)); |
122 | return skey; | 129 | return skey; |
123 | } | 130 | } |
124 | 131 | ||
132 | static inline int page_reset_referenced(unsigned long addr) | ||
133 | { | ||
134 | unsigned int ipm; | ||
135 | |||
136 | asm volatile( | ||
137 | " rrbe 0,%1\n" | ||
138 | " ipm %0\n" | ||
139 | : "=d" (ipm) : "a" (addr) : "cc"); | ||
140 | return !!(ipm & 0x20000000); | ||
141 | } | ||
142 | |||
143 | /* Bits int the storage key */ | ||
144 | #define _PAGE_CHANGED 0x02 /* HW changed bit */ | ||
145 | #define _PAGE_REFERENCED 0x04 /* HW referenced bit */ | ||
146 | #define _PAGE_FP_BIT 0x08 /* HW fetch protection bit */ | ||
147 | #define _PAGE_ACC_BITS 0xf0 /* HW access control bits */ | ||
148 | |||
149 | /* | ||
150 | * Test and clear dirty bit in storage key. | ||
151 | * We can't clear the changed bit atomically. This is a potential | ||
152 | * race against modification of the referenced bit. This function | ||
153 | * should therefore only be called if it is not mapped in any | ||
154 | * address space. | ||
155 | */ | ||
156 | #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY | ||
157 | static inline int page_test_and_clear_dirty(unsigned long pfn, int mapped) | ||
158 | { | ||
159 | unsigned char skey; | ||
160 | |||
161 | skey = page_get_storage_key(pfn << PAGE_SHIFT); | ||
162 | if (!(skey & _PAGE_CHANGED)) | ||
163 | return 0; | ||
164 | page_set_storage_key(pfn << PAGE_SHIFT, skey & ~_PAGE_CHANGED, mapped); | ||
165 | return 1; | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * Test and clear referenced bit in storage key. | ||
170 | */ | ||
171 | #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG | ||
172 | static inline int page_test_and_clear_young(unsigned long pfn) | ||
173 | { | ||
174 | return page_reset_referenced(pfn << PAGE_SHIFT); | ||
175 | } | ||
176 | |||
125 | struct page; | 177 | struct page; |
126 | void arch_free_page(struct page *page, int order); | 178 | void arch_free_page(struct page *page, int order); |
127 | void arch_alloc_page(struct page *page, int order); | 179 | void arch_alloc_page(struct page *page, int order); |
128 | 180 | ||
181 | static inline int devmem_is_allowed(unsigned long pfn) | ||
182 | { | ||
183 | return 0; | ||
184 | } | ||
185 | |||
129 | #define HAVE_ARCH_FREE_PAGE | 186 | #define HAVE_ARCH_FREE_PAGE |
130 | #define HAVE_ARCH_ALLOC_PAGE | 187 | #define HAVE_ARCH_ALLOC_PAGE |
131 | 188 | ||
diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h index f7ad8719d02d..5325c89a5843 100644 --- a/arch/s390/include/asm/percpu.h +++ b/arch/s390/include/asm/percpu.h | |||
@@ -1,6 +1,9 @@ | |||
1 | #ifndef __ARCH_S390_PERCPU__ | 1 | #ifndef __ARCH_S390_PERCPU__ |
2 | #define __ARCH_S390_PERCPU__ | 2 | #define __ARCH_S390_PERCPU__ |
3 | 3 | ||
4 | #include <linux/preempt.h> | ||
5 | #include <asm/cmpxchg.h> | ||
6 | |||
4 | /* | 7 | /* |
5 | * s390 uses its own implementation for per cpu data, the offset of | 8 | * s390 uses its own implementation for per cpu data, the offset of |
6 | * the cpu local data area is cached in the cpu's lowcore memory. | 9 | * the cpu local data area is cached in the cpu's lowcore memory. |
@@ -16,6 +19,71 @@ | |||
16 | #define ARCH_NEEDS_WEAK_PER_CPU | 19 | #define ARCH_NEEDS_WEAK_PER_CPU |
17 | #endif | 20 | #endif |
18 | 21 | ||
22 | #define arch_irqsafe_cpu_to_op(pcp, val, op) \ | ||
23 | do { \ | ||
24 | typedef typeof(pcp) pcp_op_T__; \ | ||
25 | pcp_op_T__ old__, new__, prev__; \ | ||
26 | pcp_op_T__ *ptr__; \ | ||
27 | preempt_disable(); \ | ||
28 | ptr__ = __this_cpu_ptr(&(pcp)); \ | ||
29 | prev__ = *ptr__; \ | ||
30 | do { \ | ||
31 | old__ = prev__; \ | ||
32 | new__ = old__ op (val); \ | ||
33 | switch (sizeof(*ptr__)) { \ | ||
34 | case 8: \ | ||
35 | prev__ = cmpxchg64(ptr__, old__, new__); \ | ||
36 | break; \ | ||
37 | default: \ | ||
38 | prev__ = cmpxchg(ptr__, old__, new__); \ | ||
39 | } \ | ||
40 | } while (prev__ != old__); \ | ||
41 | preempt_enable(); \ | ||
42 | } while (0) | ||
43 | |||
44 | #define irqsafe_cpu_add_1(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, +) | ||
45 | #define irqsafe_cpu_add_2(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, +) | ||
46 | #define irqsafe_cpu_add_4(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, +) | ||
47 | #define irqsafe_cpu_add_8(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, +) | ||
48 | |||
49 | #define irqsafe_cpu_and_1(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, &) | ||
50 | #define irqsafe_cpu_and_2(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, &) | ||
51 | #define irqsafe_cpu_and_4(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, &) | ||
52 | #define irqsafe_cpu_and_8(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, &) | ||
53 | |||
54 | #define irqsafe_cpu_or_1(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, |) | ||
55 | #define irqsafe_cpu_or_2(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, |) | ||
56 | #define irqsafe_cpu_or_4(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, |) | ||
57 | #define irqsafe_cpu_or_8(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, |) | ||
58 | |||
59 | #define irqsafe_cpu_xor_1(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, ^) | ||
60 | #define irqsafe_cpu_xor_2(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, ^) | ||
61 | #define irqsafe_cpu_xor_4(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, ^) | ||
62 | #define irqsafe_cpu_xor_8(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, ^) | ||
63 | |||
64 | #define arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) \ | ||
65 | ({ \ | ||
66 | typedef typeof(pcp) pcp_op_T__; \ | ||
67 | pcp_op_T__ ret__; \ | ||
68 | pcp_op_T__ *ptr__; \ | ||
69 | preempt_disable(); \ | ||
70 | ptr__ = __this_cpu_ptr(&(pcp)); \ | ||
71 | switch (sizeof(*ptr__)) { \ | ||
72 | case 8: \ | ||
73 | ret__ = cmpxchg64(ptr__, oval, nval); \ | ||
74 | break; \ | ||
75 | default: \ | ||
76 | ret__ = cmpxchg(ptr__, oval, nval); \ | ||
77 | } \ | ||
78 | preempt_enable(); \ | ||
79 | ret__; \ | ||
80 | }) | ||
81 | |||
82 | #define irqsafe_cpu_cmpxchg_1(pcp, oval, nval) arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) | ||
83 | #define irqsafe_cpu_cmpxchg_2(pcp, oval, nval) arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) | ||
84 | #define irqsafe_cpu_cmpxchg_4(pcp, oval, nval) arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) | ||
85 | #define irqsafe_cpu_cmpxchg_8(pcp, oval, nval) arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) | ||
86 | |||
19 | #include <asm-generic/percpu.h> | 87 | #include <asm-generic/percpu.h> |
20 | 88 | ||
21 | #endif /* __ARCH_S390_PERCPU__ */ | 89 | #endif /* __ARCH_S390_PERCPU__ */ |
diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h index 3840cbe77637..a75f168d2718 100644 --- a/arch/s390/include/asm/perf_event.h +++ b/arch/s390/include/asm/perf_event.h | |||
@@ -4,7 +4,6 @@ | |||
4 | * Copyright 2009 Martin Schwidefsky, IBM Corporation. | 4 | * Copyright 2009 Martin Schwidefsky, IBM Corporation. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | static inline void set_perf_event_pending(void) {} | 7 | /* Empty, just to avoid compiling error */ |
8 | static inline void clear_perf_event_pending(void) {} | ||
9 | 8 | ||
10 | #define PERF_EVENT_INDEX_OFFSET 0 | 9 | #define PERF_EVENT_INDEX_OFFSET 0 |
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index 68940d0bad91..38e71ebcd3c2 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h | |||
@@ -17,14 +17,15 @@ | |||
17 | #include <linux/gfp.h> | 17 | #include <linux/gfp.h> |
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | 19 | ||
20 | #define check_pgt_cache() do {} while (0) | 20 | unsigned long *crst_table_alloc(struct mm_struct *); |
21 | |||
22 | unsigned long *crst_table_alloc(struct mm_struct *, int); | ||
23 | void crst_table_free(struct mm_struct *, unsigned long *); | 21 | void crst_table_free(struct mm_struct *, unsigned long *); |
24 | 22 | ||
25 | unsigned long *page_table_alloc(struct mm_struct *); | 23 | unsigned long *page_table_alloc(struct mm_struct *); |
26 | void page_table_free(struct mm_struct *, unsigned long *); | 24 | void page_table_free(struct mm_struct *, unsigned long *); |
27 | void disable_noexec(struct mm_struct *, struct task_struct *); | 25 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE |
26 | void page_table_free_rcu(struct mmu_gather *, unsigned long *); | ||
27 | void __tlb_remove_table(void *_table); | ||
28 | #endif | ||
28 | 29 | ||
29 | static inline void clear_table(unsigned long *s, unsigned long val, size_t n) | 30 | static inline void clear_table(unsigned long *s, unsigned long val, size_t n) |
30 | { | 31 | { |
@@ -48,9 +49,6 @@ static inline void clear_table(unsigned long *s, unsigned long val, size_t n) | |||
48 | static inline void crst_table_init(unsigned long *crst, unsigned long entry) | 49 | static inline void crst_table_init(unsigned long *crst, unsigned long entry) |
49 | { | 50 | { |
50 | clear_table(crst, entry, sizeof(unsigned long)*2048); | 51 | clear_table(crst, entry, sizeof(unsigned long)*2048); |
51 | crst = get_shadow_table(crst); | ||
52 | if (crst) | ||
53 | clear_table(crst, entry, sizeof(unsigned long)*2048); | ||
54 | } | 52 | } |
55 | 53 | ||
56 | #ifndef __s390x__ | 54 | #ifndef __s390x__ |
@@ -67,10 +65,7 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm) | |||
67 | #define pmd_free(mm, x) do { } while (0) | 65 | #define pmd_free(mm, x) do { } while (0) |
68 | 66 | ||
69 | #define pgd_populate(mm, pgd, pud) BUG() | 67 | #define pgd_populate(mm, pgd, pud) BUG() |
70 | #define pgd_populate_kernel(mm, pgd, pud) BUG() | ||
71 | |||
72 | #define pud_populate(mm, pud, pmd) BUG() | 68 | #define pud_populate(mm, pud, pmd) BUG() |
73 | #define pud_populate_kernel(mm, pud, pmd) BUG() | ||
74 | 69 | ||
75 | #else /* __s390x__ */ | 70 | #else /* __s390x__ */ |
76 | 71 | ||
@@ -88,7 +83,7 @@ void crst_table_downgrade(struct mm_struct *, unsigned long limit); | |||
88 | 83 | ||
89 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) | 84 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) |
90 | { | 85 | { |
91 | unsigned long *table = crst_table_alloc(mm, mm->context.noexec); | 86 | unsigned long *table = crst_table_alloc(mm); |
92 | if (table) | 87 | if (table) |
93 | crst_table_init(table, _REGION3_ENTRY_EMPTY); | 88 | crst_table_init(table, _REGION3_ENTRY_EMPTY); |
94 | return (pud_t *) table; | 89 | return (pud_t *) table; |
@@ -97,43 +92,21 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) | |||
97 | 92 | ||
98 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) | 93 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) |
99 | { | 94 | { |
100 | unsigned long *table = crst_table_alloc(mm, mm->context.noexec); | 95 | unsigned long *table = crst_table_alloc(mm); |
101 | if (table) | 96 | if (table) |
102 | crst_table_init(table, _SEGMENT_ENTRY_EMPTY); | 97 | crst_table_init(table, _SEGMENT_ENTRY_EMPTY); |
103 | return (pmd_t *) table; | 98 | return (pmd_t *) table; |
104 | } | 99 | } |
105 | #define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd) | 100 | #define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd) |
106 | 101 | ||
107 | static inline void pgd_populate_kernel(struct mm_struct *mm, | ||
108 | pgd_t *pgd, pud_t *pud) | ||
109 | { | ||
110 | pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud); | ||
111 | } | ||
112 | |||
113 | static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) | 102 | static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) |
114 | { | 103 | { |
115 | pgd_populate_kernel(mm, pgd, pud); | 104 | pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud); |
116 | if (mm->context.noexec) { | ||
117 | pgd = get_shadow_table(pgd); | ||
118 | pud = get_shadow_table(pud); | ||
119 | pgd_populate_kernel(mm, pgd, pud); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | static inline void pud_populate_kernel(struct mm_struct *mm, | ||
124 | pud_t *pud, pmd_t *pmd) | ||
125 | { | ||
126 | pud_val(*pud) = _REGION3_ENTRY | __pa(pmd); | ||
127 | } | 105 | } |
128 | 106 | ||
129 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | 107 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) |
130 | { | 108 | { |
131 | pud_populate_kernel(mm, pud, pmd); | 109 | pud_val(*pud) = _REGION3_ENTRY | __pa(pmd); |
132 | if (mm->context.noexec) { | ||
133 | pud = get_shadow_table(pud); | ||
134 | pmd = get_shadow_table(pmd); | ||
135 | pud_populate_kernel(mm, pud, pmd); | ||
136 | } | ||
137 | } | 110 | } |
138 | 111 | ||
139 | #endif /* __s390x__ */ | 112 | #endif /* __s390x__ */ |
@@ -141,29 +114,19 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | |||
141 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | 114 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) |
142 | { | 115 | { |
143 | spin_lock_init(&mm->context.list_lock); | 116 | spin_lock_init(&mm->context.list_lock); |
144 | INIT_LIST_HEAD(&mm->context.crst_list); | ||
145 | INIT_LIST_HEAD(&mm->context.pgtable_list); | 117 | INIT_LIST_HEAD(&mm->context.pgtable_list); |
146 | return (pgd_t *) | 118 | return (pgd_t *) crst_table_alloc(mm); |
147 | crst_table_alloc(mm, user_mode == SECONDARY_SPACE_MODE); | ||
148 | } | 119 | } |
149 | #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) | 120 | #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) |
150 | 121 | ||
151 | static inline void pmd_populate_kernel(struct mm_struct *mm, | ||
152 | pmd_t *pmd, pte_t *pte) | ||
153 | { | ||
154 | pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte); | ||
155 | } | ||
156 | |||
157 | static inline void pmd_populate(struct mm_struct *mm, | 122 | static inline void pmd_populate(struct mm_struct *mm, |
158 | pmd_t *pmd, pgtable_t pte) | 123 | pmd_t *pmd, pgtable_t pte) |
159 | { | 124 | { |
160 | pmd_populate_kernel(mm, pmd, pte); | 125 | pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte); |
161 | if (mm->context.noexec) { | ||
162 | pmd = get_shadow_table(pmd); | ||
163 | pmd_populate_kernel(mm, pmd, pte + PTRS_PER_PTE); | ||
164 | } | ||
165 | } | 126 | } |
166 | 127 | ||
128 | #define pmd_populate_kernel(mm, pmd, pte) pmd_populate(mm, pmd, pte) | ||
129 | |||
167 | #define pmd_pgtable(pmd) \ | 130 | #define pmd_pgtable(pmd) \ |
168 | (pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE) | 131 | (pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE) |
169 | 132 | ||
@@ -176,4 +139,6 @@ static inline void pmd_populate(struct mm_struct *mm, | |||
176 | #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte) | 139 | #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte) |
177 | #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte) | 140 | #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte) |
178 | 141 | ||
142 | extern void rcu_table_freelist_finish(void); | ||
143 | |||
179 | #endif /* _S390_PGALLOC_H */ | 144 | #endif /* _S390_PGALLOC_H */ |
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 3157441ee1da..801fbe1d837d 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
@@ -31,13 +31,13 @@ | |||
31 | #ifndef __ASSEMBLY__ | 31 | #ifndef __ASSEMBLY__ |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/mm_types.h> | 33 | #include <linux/mm_types.h> |
34 | #include <asm/bitops.h> | ||
35 | #include <asm/bug.h> | 34 | #include <asm/bug.h> |
36 | #include <asm/processor.h> | 35 | #include <asm/page.h> |
37 | 36 | ||
38 | extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); | 37 | extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); |
39 | extern void paging_init(void); | 38 | extern void paging_init(void); |
40 | extern void vmem_map_init(void); | 39 | extern void vmem_map_init(void); |
40 | extern void fault_init(void); | ||
41 | 41 | ||
42 | /* | 42 | /* |
43 | * The S390 doesn't have any external MMU info: the kernel page | 43 | * The S390 doesn't have any external MMU info: the kernel page |
@@ -46,11 +46,27 @@ extern void vmem_map_init(void); | |||
46 | #define update_mmu_cache(vma, address, ptep) do { } while (0) | 46 | #define update_mmu_cache(vma, address, ptep) do { } while (0) |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * ZERO_PAGE is a global shared page that is always zero: used | 49 | * ZERO_PAGE is a global shared page that is always zero; used |
50 | * for zero-mapped memory areas etc.. | 50 | * for zero-mapped memory areas etc.. |
51 | */ | 51 | */ |
52 | extern char empty_zero_page[PAGE_SIZE]; | 52 | |
53 | #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) | 53 | extern unsigned long empty_zero_page; |
54 | extern unsigned long zero_page_mask; | ||
55 | |||
56 | #define ZERO_PAGE(vaddr) \ | ||
57 | (virt_to_page((void *)(empty_zero_page + \ | ||
58 | (((unsigned long)(vaddr)) &zero_page_mask)))) | ||
59 | |||
60 | #define is_zero_pfn is_zero_pfn | ||
61 | static inline int is_zero_pfn(unsigned long pfn) | ||
62 | { | ||
63 | extern unsigned long zero_pfn; | ||
64 | unsigned long offset_from_zero_pfn = pfn - zero_pfn; | ||
65 | return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT); | ||
66 | } | ||
67 | |||
68 | #define my_zero_pfn(addr) page_to_pfn(ZERO_PAGE(addr)) | ||
69 | |||
54 | #endif /* !__ASSEMBLY__ */ | 70 | #endif /* !__ASSEMBLY__ */ |
55 | 71 | ||
56 | /* | 72 | /* |
@@ -226,11 +242,13 @@ extern unsigned long VMALLOC_START; | |||
226 | /* Software bits in the page table entry */ | 242 | /* Software bits in the page table entry */ |
227 | #define _PAGE_SWT 0x001 /* SW pte type bit t */ | 243 | #define _PAGE_SWT 0x001 /* SW pte type bit t */ |
228 | #define _PAGE_SWX 0x002 /* SW pte type bit x */ | 244 | #define _PAGE_SWX 0x002 /* SW pte type bit x */ |
229 | #define _PAGE_SPECIAL 0x004 /* SW associated with special page */ | 245 | #define _PAGE_SWC 0x004 /* SW pte changed bit (for KVM) */ |
246 | #define _PAGE_SWR 0x008 /* SW pte referenced bit (for KVM) */ | ||
247 | #define _PAGE_SPECIAL 0x010 /* SW associated with special page */ | ||
230 | #define __HAVE_ARCH_PTE_SPECIAL | 248 | #define __HAVE_ARCH_PTE_SPECIAL |
231 | 249 | ||
232 | /* Set of bits not changed in pte_modify */ | 250 | /* Set of bits not changed in pte_modify */ |
233 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_SPECIAL) | 251 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_SPECIAL | _PAGE_SWC | _PAGE_SWR) |
234 | 252 | ||
235 | /* Six different types of pages. */ | 253 | /* Six different types of pages. */ |
236 | #define _PAGE_TYPE_EMPTY 0x400 | 254 | #define _PAGE_TYPE_EMPTY 0x400 |
@@ -239,8 +257,6 @@ extern unsigned long VMALLOC_START; | |||
239 | #define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ | 257 | #define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ |
240 | #define _PAGE_TYPE_RO 0x200 | 258 | #define _PAGE_TYPE_RO 0x200 |
241 | #define _PAGE_TYPE_RW 0x000 | 259 | #define _PAGE_TYPE_RW 0x000 |
242 | #define _PAGE_TYPE_EX_RO 0x202 | ||
243 | #define _PAGE_TYPE_EX_RW 0x002 | ||
244 | 260 | ||
245 | /* | 261 | /* |
246 | * Only four types for huge pages, using the invalid bit and protection bit | 262 | * Only four types for huge pages, using the invalid bit and protection bit |
@@ -270,8 +286,6 @@ extern unsigned long VMALLOC_START; | |||
270 | * _PAGE_TYPE_FILE 11?1 -> 11?1 | 286 | * _PAGE_TYPE_FILE 11?1 -> 11?1 |
271 | * _PAGE_TYPE_RO 0100 -> 1100 | 287 | * _PAGE_TYPE_RO 0100 -> 1100 |
272 | * _PAGE_TYPE_RW 0000 -> 1000 | 288 | * _PAGE_TYPE_RW 0000 -> 1000 |
273 | * _PAGE_TYPE_EX_RO 0110 -> 1110 | ||
274 | * _PAGE_TYPE_EX_RW 0010 -> 1010 | ||
275 | * | 289 | * |
276 | * pte_none is true for bits combinations 1000, 1010, 1100, 1110 | 290 | * pte_none is true for bits combinations 1000, 1010, 1100, 1110 |
277 | * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 | 291 | * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 |
@@ -279,16 +293,6 @@ extern unsigned long VMALLOC_START; | |||
279 | * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid. | 293 | * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid. |
280 | */ | 294 | */ |
281 | 295 | ||
282 | /* Page status table bits for virtualization */ | ||
283 | #define RCP_PCL_BIT 55 | ||
284 | #define RCP_HR_BIT 54 | ||
285 | #define RCP_HC_BIT 53 | ||
286 | #define RCP_GR_BIT 50 | ||
287 | #define RCP_GC_BIT 49 | ||
288 | |||
289 | /* User dirty bit for KVM's migration feature */ | ||
290 | #define KVM_UD_BIT 47 | ||
291 | |||
292 | #ifndef __s390x__ | 296 | #ifndef __s390x__ |
293 | 297 | ||
294 | /* Bits in the segment table address-space-control-element */ | 298 | /* Bits in the segment table address-space-control-element */ |
@@ -300,6 +304,7 @@ extern unsigned long VMALLOC_START; | |||
300 | 304 | ||
301 | /* Bits in the segment table entry */ | 305 | /* Bits in the segment table entry */ |
302 | #define _SEGMENT_ENTRY_ORIGIN 0x7fffffc0UL /* page table origin */ | 306 | #define _SEGMENT_ENTRY_ORIGIN 0x7fffffc0UL /* page table origin */ |
307 | #define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */ | ||
303 | #define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */ | 308 | #define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */ |
304 | #define _SEGMENT_ENTRY_COMMON 0x10 /* common segment bit */ | 309 | #define _SEGMENT_ENTRY_COMMON 0x10 /* common segment bit */ |
305 | #define _SEGMENT_ENTRY_PTL 0x0f /* page table length */ | 310 | #define _SEGMENT_ENTRY_PTL 0x0f /* page table length */ |
@@ -307,6 +312,19 @@ extern unsigned long VMALLOC_START; | |||
307 | #define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PTL) | 312 | #define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PTL) |
308 | #define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV) | 313 | #define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV) |
309 | 314 | ||
315 | /* Page status table bits for virtualization */ | ||
316 | #define RCP_ACC_BITS 0xf0000000UL | ||
317 | #define RCP_FP_BIT 0x08000000UL | ||
318 | #define RCP_PCL_BIT 0x00800000UL | ||
319 | #define RCP_HR_BIT 0x00400000UL | ||
320 | #define RCP_HC_BIT 0x00200000UL | ||
321 | #define RCP_GR_BIT 0x00040000UL | ||
322 | #define RCP_GC_BIT 0x00020000UL | ||
323 | |||
324 | /* User dirty / referenced bit for KVM's migration feature */ | ||
325 | #define KVM_UR_BIT 0x00008000UL | ||
326 | #define KVM_UC_BIT 0x00004000UL | ||
327 | |||
310 | #else /* __s390x__ */ | 328 | #else /* __s390x__ */ |
311 | 329 | ||
312 | /* Bits in the segment/region table address-space-control-element */ | 330 | /* Bits in the segment/region table address-space-control-element */ |
@@ -349,6 +367,19 @@ extern unsigned long VMALLOC_START; | |||
349 | #define _SEGMENT_ENTRY_LARGE 0x400 /* STE-format control, large page */ | 367 | #define _SEGMENT_ENTRY_LARGE 0x400 /* STE-format control, large page */ |
350 | #define _SEGMENT_ENTRY_CO 0x100 /* change-recording override */ | 368 | #define _SEGMENT_ENTRY_CO 0x100 /* change-recording override */ |
351 | 369 | ||
370 | /* Page status table bits for virtualization */ | ||
371 | #define RCP_ACC_BITS 0xf000000000000000UL | ||
372 | #define RCP_FP_BIT 0x0800000000000000UL | ||
373 | #define RCP_PCL_BIT 0x0080000000000000UL | ||
374 | #define RCP_HR_BIT 0x0040000000000000UL | ||
375 | #define RCP_HC_BIT 0x0020000000000000UL | ||
376 | #define RCP_GR_BIT 0x0004000000000000UL | ||
377 | #define RCP_GC_BIT 0x0002000000000000UL | ||
378 | |||
379 | /* User dirty / referenced bit for KVM's migration feature */ | ||
380 | #define KVM_UR_BIT 0x0000800000000000UL | ||
381 | #define KVM_UC_BIT 0x0000400000000000UL | ||
382 | |||
352 | #endif /* __s390x__ */ | 383 | #endif /* __s390x__ */ |
353 | 384 | ||
354 | /* | 385 | /* |
@@ -359,85 +390,54 @@ extern unsigned long VMALLOC_START; | |||
359 | #define _ASCE_USER_BITS (_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \ | 390 | #define _ASCE_USER_BITS (_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \ |
360 | _ASCE_ALT_EVENT) | 391 | _ASCE_ALT_EVENT) |
361 | 392 | ||
362 | /* Bits int the storage key */ | ||
363 | #define _PAGE_CHANGED 0x02 /* HW changed bit */ | ||
364 | #define _PAGE_REFERENCED 0x04 /* HW referenced bit */ | ||
365 | |||
366 | /* | 393 | /* |
367 | * Page protection definitions. | 394 | * Page protection definitions. |
368 | */ | 395 | */ |
369 | #define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) | 396 | #define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) |
370 | #define PAGE_RO __pgprot(_PAGE_TYPE_RO) | 397 | #define PAGE_RO __pgprot(_PAGE_TYPE_RO) |
371 | #define PAGE_RW __pgprot(_PAGE_TYPE_RW) | 398 | #define PAGE_RW __pgprot(_PAGE_TYPE_RW) |
372 | #define PAGE_EX_RO __pgprot(_PAGE_TYPE_EX_RO) | ||
373 | #define PAGE_EX_RW __pgprot(_PAGE_TYPE_EX_RW) | ||
374 | 399 | ||
375 | #define PAGE_KERNEL PAGE_RW | 400 | #define PAGE_KERNEL PAGE_RW |
376 | #define PAGE_COPY PAGE_RO | 401 | #define PAGE_COPY PAGE_RO |
377 | 402 | ||
378 | /* | 403 | /* |
379 | * Dependent on the EXEC_PROTECT option s390 can do execute protection. | 404 | * On s390 the page table entry has an invalid bit and a read-only bit. |
380 | * Write permission always implies read permission. In theory with a | 405 | * Read permission implies execute permission and write permission |
381 | * primary/secondary page table execute only can be implemented but | 406 | * implies read permission. |
382 | * it would cost an additional bit in the pte to distinguish all the | ||
383 | * different pte types. To avoid that execute permission currently | ||
384 | * implies read permission as well. | ||
385 | */ | 407 | */ |
386 | /*xwr*/ | 408 | /*xwr*/ |
387 | #define __P000 PAGE_NONE | 409 | #define __P000 PAGE_NONE |
388 | #define __P001 PAGE_RO | 410 | #define __P001 PAGE_RO |
389 | #define __P010 PAGE_RO | 411 | #define __P010 PAGE_RO |
390 | #define __P011 PAGE_RO | 412 | #define __P011 PAGE_RO |
391 | #define __P100 PAGE_EX_RO | 413 | #define __P100 PAGE_RO |
392 | #define __P101 PAGE_EX_RO | 414 | #define __P101 PAGE_RO |
393 | #define __P110 PAGE_EX_RO | 415 | #define __P110 PAGE_RO |
394 | #define __P111 PAGE_EX_RO | 416 | #define __P111 PAGE_RO |
395 | 417 | ||
396 | #define __S000 PAGE_NONE | 418 | #define __S000 PAGE_NONE |
397 | #define __S001 PAGE_RO | 419 | #define __S001 PAGE_RO |
398 | #define __S010 PAGE_RW | 420 | #define __S010 PAGE_RW |
399 | #define __S011 PAGE_RW | 421 | #define __S011 PAGE_RW |
400 | #define __S100 PAGE_EX_RO | 422 | #define __S100 PAGE_RO |
401 | #define __S101 PAGE_EX_RO | 423 | #define __S101 PAGE_RO |
402 | #define __S110 PAGE_EX_RW | 424 | #define __S110 PAGE_RW |
403 | #define __S111 PAGE_EX_RW | 425 | #define __S111 PAGE_RW |
404 | |||
405 | #ifndef __s390x__ | ||
406 | # define PxD_SHADOW_SHIFT 1 | ||
407 | #else /* __s390x__ */ | ||
408 | # define PxD_SHADOW_SHIFT 2 | ||
409 | #endif /* __s390x__ */ | ||
410 | 426 | ||
411 | static inline void *get_shadow_table(void *table) | 427 | static inline int mm_exclusive(struct mm_struct *mm) |
412 | { | 428 | { |
413 | unsigned long addr, offset; | 429 | return likely(mm == current->active_mm && |
414 | struct page *page; | 430 | atomic_read(&mm->context.attach_count) <= 1); |
415 | |||
416 | addr = (unsigned long) table; | ||
417 | offset = addr & ((PAGE_SIZE << PxD_SHADOW_SHIFT) - 1); | ||
418 | page = virt_to_page((void *)(addr ^ offset)); | ||
419 | return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL); | ||
420 | } | 431 | } |
421 | 432 | ||
422 | /* | 433 | static inline int mm_has_pgste(struct mm_struct *mm) |
423 | * Certain architectures need to do special things when PTEs | ||
424 | * within a page table are directly modified. Thus, the following | ||
425 | * hook is made available. | ||
426 | */ | ||
427 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
428 | pte_t *ptep, pte_t entry) | ||
429 | { | 434 | { |
430 | *ptep = entry; | 435 | #ifdef CONFIG_PGSTE |
431 | if (mm->context.noexec) { | 436 | if (unlikely(mm->context.has_pgste)) |
432 | if (!(pte_val(entry) & _PAGE_INVALID) && | 437 | return 1; |
433 | (pte_val(entry) & _PAGE_SWX)) | 438 | #endif |
434 | pte_val(entry) |= _PAGE_RO; | 439 | return 0; |
435 | else | ||
436 | pte_val(entry) = _PAGE_TYPE_EMPTY; | ||
437 | ptep[PTRS_PER_PTE] = entry; | ||
438 | } | ||
439 | } | 440 | } |
440 | |||
441 | /* | 441 | /* |
442 | * pgd/pmd/pte query functions | 442 | * pgd/pmd/pte query functions |
443 | */ | 443 | */ |
@@ -550,55 +550,130 @@ static inline int pte_special(pte_t pte) | |||
550 | } | 550 | } |
551 | 551 | ||
552 | #define __HAVE_ARCH_PTE_SAME | 552 | #define __HAVE_ARCH_PTE_SAME |
553 | #define pte_same(a,b) (pte_val(a) == pte_val(b)) | 553 | static inline int pte_same(pte_t a, pte_t b) |
554 | { | ||
555 | return pte_val(a) == pte_val(b); | ||
556 | } | ||
554 | 557 | ||
555 | static inline void rcp_lock(pte_t *ptep) | 558 | static inline pgste_t pgste_get_lock(pte_t *ptep) |
556 | { | 559 | { |
560 | unsigned long new = 0; | ||
557 | #ifdef CONFIG_PGSTE | 561 | #ifdef CONFIG_PGSTE |
558 | unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); | 562 | unsigned long old; |
563 | |||
559 | preempt_disable(); | 564 | preempt_disable(); |
560 | while (test_and_set_bit(RCP_PCL_BIT, pgste)) | 565 | asm( |
561 | ; | 566 | " lg %0,%2\n" |
567 | "0: lgr %1,%0\n" | ||
568 | " nihh %0,0xff7f\n" /* clear RCP_PCL_BIT in old */ | ||
569 | " oihh %1,0x0080\n" /* set RCP_PCL_BIT in new */ | ||
570 | " csg %0,%1,%2\n" | ||
571 | " jl 0b\n" | ||
572 | : "=&d" (old), "=&d" (new), "=Q" (ptep[PTRS_PER_PTE]) | ||
573 | : "Q" (ptep[PTRS_PER_PTE]) : "cc"); | ||
562 | #endif | 574 | #endif |
575 | return __pgste(new); | ||
563 | } | 576 | } |
564 | 577 | ||
565 | static inline void rcp_unlock(pte_t *ptep) | 578 | static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste) |
566 | { | 579 | { |
567 | #ifdef CONFIG_PGSTE | 580 | #ifdef CONFIG_PGSTE |
568 | unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); | 581 | asm( |
569 | clear_bit(RCP_PCL_BIT, pgste); | 582 | " nihh %1,0xff7f\n" /* clear RCP_PCL_BIT */ |
583 | " stg %1,%0\n" | ||
584 | : "=Q" (ptep[PTRS_PER_PTE]) | ||
585 | : "d" (pgste_val(pgste)), "Q" (ptep[PTRS_PER_PTE]) : "cc"); | ||
570 | preempt_enable(); | 586 | preempt_enable(); |
571 | #endif | 587 | #endif |
572 | } | 588 | } |
573 | 589 | ||
574 | /* forward declaration for SetPageUptodate in page-flags.h*/ | 590 | static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste) |
575 | static inline void page_clear_dirty(struct page *page); | ||
576 | #include <linux/page-flags.h> | ||
577 | |||
578 | static inline void ptep_rcp_copy(pte_t *ptep) | ||
579 | { | 591 | { |
580 | #ifdef CONFIG_PGSTE | 592 | #ifdef CONFIG_PGSTE |
581 | struct page *page = virt_to_page(pte_val(*ptep)); | 593 | unsigned long address, bits; |
582 | unsigned int skey; | 594 | unsigned char skey; |
583 | unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); | 595 | |
584 | 596 | address = pte_val(*ptep) & PAGE_MASK; | |
585 | skey = page_get_storage_key(page_to_phys(page)); | 597 | skey = page_get_storage_key(address); |
586 | if (skey & _PAGE_CHANGED) { | 598 | bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED); |
587 | set_bit_simple(RCP_GC_BIT, pgste); | 599 | /* Clear page changed & referenced bit in the storage key */ |
588 | set_bit_simple(KVM_UD_BIT, pgste); | 600 | if (bits) { |
589 | } | 601 | skey ^= bits; |
590 | if (skey & _PAGE_REFERENCED) | 602 | page_set_storage_key(address, skey, 1); |
591 | set_bit_simple(RCP_GR_BIT, pgste); | ||
592 | if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { | ||
593 | SetPageDirty(page); | ||
594 | set_bit_simple(KVM_UD_BIT, pgste); | ||
595 | } | 603 | } |
596 | if (test_and_clear_bit_simple(RCP_HR_BIT, pgste)) | 604 | /* Transfer page changed & referenced bit to guest bits in pgste */ |
597 | SetPageReferenced(page); | 605 | pgste_val(pgste) |= bits << 48; /* RCP_GR_BIT & RCP_GC_BIT */ |
606 | /* Get host changed & referenced bits from pgste */ | ||
607 | bits |= (pgste_val(pgste) & (RCP_HR_BIT | RCP_HC_BIT)) >> 52; | ||
608 | /* Clear host bits in pgste. */ | ||
609 | pgste_val(pgste) &= ~(RCP_HR_BIT | RCP_HC_BIT); | ||
610 | pgste_val(pgste) &= ~(RCP_ACC_BITS | RCP_FP_BIT); | ||
611 | /* Copy page access key and fetch protection bit to pgste */ | ||
612 | pgste_val(pgste) |= | ||
613 | (unsigned long) (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56; | ||
614 | /* Transfer changed and referenced to kvm user bits */ | ||
615 | pgste_val(pgste) |= bits << 45; /* KVM_UR_BIT & KVM_UC_BIT */ | ||
616 | /* Transfer changed & referenced to pte sofware bits */ | ||
617 | pte_val(*ptep) |= bits << 1; /* _PAGE_SWR & _PAGE_SWC */ | ||
618 | #endif | ||
619 | return pgste; | ||
620 | |||
621 | } | ||
622 | |||
623 | static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste) | ||
624 | { | ||
625 | #ifdef CONFIG_PGSTE | ||
626 | int young; | ||
627 | |||
628 | young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK); | ||
629 | /* Transfer page referenced bit to pte software bit (host view) */ | ||
630 | if (young || (pgste_val(pgste) & RCP_HR_BIT)) | ||
631 | pte_val(*ptep) |= _PAGE_SWR; | ||
632 | /* Clear host referenced bit in pgste. */ | ||
633 | pgste_val(pgste) &= ~RCP_HR_BIT; | ||
634 | /* Transfer page referenced bit to guest bit in pgste */ | ||
635 | pgste_val(pgste) |= (unsigned long) young << 50; /* set RCP_GR_BIT */ | ||
636 | #endif | ||
637 | return pgste; | ||
638 | |||
639 | } | ||
640 | |||
641 | static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste) | ||
642 | { | ||
643 | #ifdef CONFIG_PGSTE | ||
644 | unsigned long address; | ||
645 | unsigned long okey, nkey; | ||
646 | |||
647 | address = pte_val(*ptep) & PAGE_MASK; | ||
648 | okey = nkey = page_get_storage_key(address); | ||
649 | nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT); | ||
650 | /* Set page access key and fetch protection bit from pgste */ | ||
651 | nkey |= (pgste_val(pgste) & (RCP_ACC_BITS | RCP_FP_BIT)) >> 56; | ||
652 | if (okey != nkey) | ||
653 | page_set_storage_key(address, nkey, 1); | ||
598 | #endif | 654 | #endif |
599 | } | 655 | } |
600 | 656 | ||
601 | /* | 657 | /* |
658 | * Certain architectures need to do special things when PTEs | ||
659 | * within a page table are directly modified. Thus, the following | ||
660 | * hook is made available. | ||
661 | */ | ||
662 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
663 | pte_t *ptep, pte_t entry) | ||
664 | { | ||
665 | pgste_t pgste; | ||
666 | |||
667 | if (mm_has_pgste(mm)) { | ||
668 | pgste = pgste_get_lock(ptep); | ||
669 | pgste_set_pte(ptep, pgste); | ||
670 | *ptep = entry; | ||
671 | pgste_set_unlock(ptep, pgste); | ||
672 | } else | ||
673 | *ptep = entry; | ||
674 | } | ||
675 | |||
676 | /* | ||
602 | * query functions pte_write/pte_dirty/pte_young only work if | 677 | * query functions pte_write/pte_dirty/pte_young only work if |
603 | * pte_present() is true. Undefined behaviour if not.. | 678 | * pte_present() is true. Undefined behaviour if not.. |
604 | */ | 679 | */ |
@@ -609,19 +684,19 @@ static inline int pte_write(pte_t pte) | |||
609 | 684 | ||
610 | static inline int pte_dirty(pte_t pte) | 685 | static inline int pte_dirty(pte_t pte) |
611 | { | 686 | { |
612 | /* A pte is neither clean nor dirty on s/390. The dirty bit | 687 | #ifdef CONFIG_PGSTE |
613 | * is in the storage key. See page_test_and_clear_dirty for | 688 | if (pte_val(pte) & _PAGE_SWC) |
614 | * details. | 689 | return 1; |
615 | */ | 690 | #endif |
616 | return 0; | 691 | return 0; |
617 | } | 692 | } |
618 | 693 | ||
619 | static inline int pte_young(pte_t pte) | 694 | static inline int pte_young(pte_t pte) |
620 | { | 695 | { |
621 | /* A pte is neither young nor old on s/390. The young bit | 696 | #ifdef CONFIG_PGSTE |
622 | * is in the storage key. See page_test_and_clear_young for | 697 | if (pte_val(pte) & _PAGE_SWR) |
623 | * details. | 698 | return 1; |
624 | */ | 699 | #endif |
625 | return 0; | 700 | return 0; |
626 | } | 701 | } |
627 | 702 | ||
@@ -629,64 +704,30 @@ static inline int pte_young(pte_t pte) | |||
629 | * pgd/pmd/pte modification functions | 704 | * pgd/pmd/pte modification functions |
630 | */ | 705 | */ |
631 | 706 | ||
632 | #ifndef __s390x__ | 707 | static inline void pgd_clear(pgd_t *pgd) |
633 | |||
634 | #define pgd_clear(pgd) do { } while (0) | ||
635 | #define pud_clear(pud) do { } while (0) | ||
636 | |||
637 | #else /* __s390x__ */ | ||
638 | |||
639 | static inline void pgd_clear_kernel(pgd_t * pgd) | ||
640 | { | 708 | { |
709 | #ifdef __s390x__ | ||
641 | if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2) | 710 | if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2) |
642 | pgd_val(*pgd) = _REGION2_ENTRY_EMPTY; | 711 | pgd_val(*pgd) = _REGION2_ENTRY_EMPTY; |
712 | #endif | ||
643 | } | 713 | } |
644 | 714 | ||
645 | static inline void pgd_clear(pgd_t * pgd) | 715 | static inline void pud_clear(pud_t *pud) |
646 | { | ||
647 | pgd_t *shadow = get_shadow_table(pgd); | ||
648 | |||
649 | pgd_clear_kernel(pgd); | ||
650 | if (shadow) | ||
651 | pgd_clear_kernel(shadow); | ||
652 | } | ||
653 | |||
654 | static inline void pud_clear_kernel(pud_t *pud) | ||
655 | { | 716 | { |
717 | #ifdef __s390x__ | ||
656 | if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) | 718 | if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) |
657 | pud_val(*pud) = _REGION3_ENTRY_EMPTY; | 719 | pud_val(*pud) = _REGION3_ENTRY_EMPTY; |
720 | #endif | ||
658 | } | 721 | } |
659 | 722 | ||
660 | static inline void pud_clear(pud_t *pud) | 723 | static inline void pmd_clear(pmd_t *pmdp) |
661 | { | ||
662 | pud_t *shadow = get_shadow_table(pud); | ||
663 | |||
664 | pud_clear_kernel(pud); | ||
665 | if (shadow) | ||
666 | pud_clear_kernel(shadow); | ||
667 | } | ||
668 | |||
669 | #endif /* __s390x__ */ | ||
670 | |||
671 | static inline void pmd_clear_kernel(pmd_t * pmdp) | ||
672 | { | 724 | { |
673 | pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY; | 725 | pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY; |
674 | } | 726 | } |
675 | 727 | ||
676 | static inline void pmd_clear(pmd_t *pmd) | ||
677 | { | ||
678 | pmd_t *shadow = get_shadow_table(pmd); | ||
679 | |||
680 | pmd_clear_kernel(pmd); | ||
681 | if (shadow) | ||
682 | pmd_clear_kernel(shadow); | ||
683 | } | ||
684 | |||
685 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 728 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
686 | { | 729 | { |
687 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; | 730 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; |
688 | if (mm->context.noexec) | ||
689 | pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY; | ||
690 | } | 731 | } |
691 | 732 | ||
692 | /* | 733 | /* |
@@ -716,35 +757,27 @@ static inline pte_t pte_mkwrite(pte_t pte) | |||
716 | 757 | ||
717 | static inline pte_t pte_mkclean(pte_t pte) | 758 | static inline pte_t pte_mkclean(pte_t pte) |
718 | { | 759 | { |
719 | /* The only user of pte_mkclean is the fork() code. | 760 | #ifdef CONFIG_PGSTE |
720 | We must *not* clear the *physical* page dirty bit | 761 | pte_val(pte) &= ~_PAGE_SWC; |
721 | just because fork() wants to clear the dirty bit in | 762 | #endif |
722 | *one* of the page's mappings. So we just do nothing. */ | ||
723 | return pte; | 763 | return pte; |
724 | } | 764 | } |
725 | 765 | ||
726 | static inline pte_t pte_mkdirty(pte_t pte) | 766 | static inline pte_t pte_mkdirty(pte_t pte) |
727 | { | 767 | { |
728 | /* We do not explicitly set the dirty bit because the | ||
729 | * sske instruction is slow. It is faster to let the | ||
730 | * next instruction set the dirty bit. | ||
731 | */ | ||
732 | return pte; | 768 | return pte; |
733 | } | 769 | } |
734 | 770 | ||
735 | static inline pte_t pte_mkold(pte_t pte) | 771 | static inline pte_t pte_mkold(pte_t pte) |
736 | { | 772 | { |
737 | /* S/390 doesn't keep its dirty/referenced bit in the pte. | 773 | #ifdef CONFIG_PGSTE |
738 | * There is no point in clearing the real referenced bit. | 774 | pte_val(pte) &= ~_PAGE_SWR; |
739 | */ | 775 | #endif |
740 | return pte; | 776 | return pte; |
741 | } | 777 | } |
742 | 778 | ||
743 | static inline pte_t pte_mkyoung(pte_t pte) | 779 | static inline pte_t pte_mkyoung(pte_t pte) |
744 | { | 780 | { |
745 | /* S/390 doesn't keep its dirty/referenced bit in the pte. | ||
746 | * There is no point in setting the real referenced bit. | ||
747 | */ | ||
748 | return pte; | 781 | return pte; |
749 | } | 782 | } |
750 | 783 | ||
@@ -754,62 +787,88 @@ static inline pte_t pte_mkspecial(pte_t pte) | |||
754 | return pte; | 787 | return pte; |
755 | } | 788 | } |
756 | 789 | ||
757 | #ifdef CONFIG_PGSTE | 790 | #ifdef CONFIG_HUGETLB_PAGE |
791 | static inline pte_t pte_mkhuge(pte_t pte) | ||
792 | { | ||
793 | /* | ||
794 | * PROT_NONE needs to be remapped from the pte type to the ste type. | ||
795 | * The HW invalid bit is also different for pte and ste. The pte | ||
796 | * invalid bit happens to be the same as the ste _SEGMENT_ENTRY_LARGE | ||
797 | * bit, so we don't have to clear it. | ||
798 | */ | ||
799 | if (pte_val(pte) & _PAGE_INVALID) { | ||
800 | if (pte_val(pte) & _PAGE_SWT) | ||
801 | pte_val(pte) |= _HPAGE_TYPE_NONE; | ||
802 | pte_val(pte) |= _SEGMENT_ENTRY_INV; | ||
803 | } | ||
804 | /* | ||
805 | * Clear SW pte bits SWT and SWX, there are no SW bits in a segment | ||
806 | * table entry. | ||
807 | */ | ||
808 | pte_val(pte) &= ~(_PAGE_SWT | _PAGE_SWX); | ||
809 | /* | ||
810 | * Also set the change-override bit because we don't need dirty bit | ||
811 | * tracking for hugetlbfs pages. | ||
812 | */ | ||
813 | pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO); | ||
814 | return pte; | ||
815 | } | ||
816 | #endif | ||
817 | |||
758 | /* | 818 | /* |
759 | * Get (and clear) the user dirty bit for a PTE. | 819 | * Get (and clear) the user dirty bit for a pte. |
760 | */ | 820 | */ |
761 | static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm, | 821 | static inline int ptep_test_and_clear_user_dirty(struct mm_struct *mm, |
762 | pte_t *ptep) | 822 | pte_t *ptep) |
763 | { | 823 | { |
764 | int dirty; | 824 | pgste_t pgste; |
765 | unsigned long *pgste; | 825 | int dirty = 0; |
766 | struct page *page; | 826 | |
767 | unsigned int skey; | 827 | if (mm_has_pgste(mm)) { |
768 | 828 | pgste = pgste_get_lock(ptep); | |
769 | if (!mm->context.has_pgste) | 829 | pgste = pgste_update_all(ptep, pgste); |
770 | return -EINVAL; | 830 | dirty = !!(pgste_val(pgste) & KVM_UC_BIT); |
771 | rcp_lock(ptep); | 831 | pgste_val(pgste) &= ~KVM_UC_BIT; |
772 | pgste = (unsigned long *) (ptep + PTRS_PER_PTE); | 832 | pgste_set_unlock(ptep, pgste); |
773 | page = virt_to_page(pte_val(*ptep)); | 833 | return dirty; |
774 | skey = page_get_storage_key(page_to_phys(page)); | ||
775 | if (skey & _PAGE_CHANGED) { | ||
776 | set_bit_simple(RCP_GC_BIT, pgste); | ||
777 | set_bit_simple(KVM_UD_BIT, pgste); | ||
778 | } | 834 | } |
779 | if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { | ||
780 | SetPageDirty(page); | ||
781 | set_bit_simple(KVM_UD_BIT, pgste); | ||
782 | } | ||
783 | dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste); | ||
784 | if (skey & _PAGE_CHANGED) | ||
785 | page_clear_dirty(page); | ||
786 | rcp_unlock(ptep); | ||
787 | return dirty; | 835 | return dirty; |
788 | } | 836 | } |
789 | #endif | 837 | |
838 | /* | ||
839 | * Get (and clear) the user referenced bit for a pte. | ||
840 | */ | ||
841 | static inline int ptep_test_and_clear_user_young(struct mm_struct *mm, | ||
842 | pte_t *ptep) | ||
843 | { | ||
844 | pgste_t pgste; | ||
845 | int young = 0; | ||
846 | |||
847 | if (mm_has_pgste(mm)) { | ||
848 | pgste = pgste_get_lock(ptep); | ||
849 | pgste = pgste_update_young(ptep, pgste); | ||
850 | young = !!(pgste_val(pgste) & KVM_UR_BIT); | ||
851 | pgste_val(pgste) &= ~KVM_UR_BIT; | ||
852 | pgste_set_unlock(ptep, pgste); | ||
853 | } | ||
854 | return young; | ||
855 | } | ||
790 | 856 | ||
791 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG | 857 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG |
792 | static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, | 858 | static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, |
793 | unsigned long addr, pte_t *ptep) | 859 | unsigned long addr, pte_t *ptep) |
794 | { | 860 | { |
795 | #ifdef CONFIG_PGSTE | 861 | pgste_t pgste; |
796 | unsigned long physpage; | 862 | pte_t pte; |
797 | int young; | ||
798 | unsigned long *pgste; | ||
799 | 863 | ||
800 | if (!vma->vm_mm->context.has_pgste) | 864 | if (mm_has_pgste(vma->vm_mm)) { |
801 | return 0; | 865 | pgste = pgste_get_lock(ptep); |
802 | physpage = pte_val(*ptep) & PAGE_MASK; | 866 | pgste = pgste_update_young(ptep, pgste); |
803 | pgste = (unsigned long *) (ptep + PTRS_PER_PTE); | 867 | pte = *ptep; |
804 | 868 | *ptep = pte_mkold(pte); | |
805 | young = ((page_get_storage_key(physpage) & _PAGE_REFERENCED) != 0); | 869 | pgste_set_unlock(ptep, pgste); |
806 | rcp_lock(ptep); | 870 | return pte_young(pte); |
807 | if (young) | 871 | } |
808 | set_bit_simple(RCP_GR_BIT, pgste); | ||
809 | young |= test_and_clear_bit_simple(RCP_HR_BIT, pgste); | ||
810 | rcp_unlock(ptep); | ||
811 | return young; | ||
812 | #endif | ||
813 | return 0; | 872 | return 0; |
814 | } | 873 | } |
815 | 874 | ||
@@ -821,10 +880,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, | |||
821 | * On s390 reference bits are in storage key and never in TLB | 880 | * On s390 reference bits are in storage key and never in TLB |
822 | * With virtualization we handle the reference bit, without we | 881 | * With virtualization we handle the reference bit, without we |
823 | * we can simply return */ | 882 | * we can simply return */ |
824 | #ifdef CONFIG_PGSTE | ||
825 | return ptep_test_and_clear_young(vma, address, ptep); | 883 | return ptep_test_and_clear_young(vma, address, ptep); |
826 | #endif | ||
827 | return 0; | ||
828 | } | 884 | } |
829 | 885 | ||
830 | static inline void __ptep_ipte(unsigned long address, pte_t *ptep) | 886 | static inline void __ptep_ipte(unsigned long address, pte_t *ptep) |
@@ -844,25 +900,6 @@ static inline void __ptep_ipte(unsigned long address, pte_t *ptep) | |||
844 | } | 900 | } |
845 | } | 901 | } |
846 | 902 | ||
847 | static inline void ptep_invalidate(struct mm_struct *mm, | ||
848 | unsigned long address, pte_t *ptep) | ||
849 | { | ||
850 | if (mm->context.has_pgste) { | ||
851 | rcp_lock(ptep); | ||
852 | __ptep_ipte(address, ptep); | ||
853 | ptep_rcp_copy(ptep); | ||
854 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; | ||
855 | rcp_unlock(ptep); | ||
856 | return; | ||
857 | } | ||
858 | __ptep_ipte(address, ptep); | ||
859 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; | ||
860 | if (mm->context.noexec) { | ||
861 | __ptep_ipte(address, ptep + PTRS_PER_PTE); | ||
862 | pte_val(*(ptep + PTRS_PER_PTE)) = _PAGE_TYPE_EMPTY; | ||
863 | } | ||
864 | } | ||
865 | |||
866 | /* | 903 | /* |
867 | * This is hard to understand. ptep_get_and_clear and ptep_clear_flush | 904 | * This is hard to understand. ptep_get_and_clear and ptep_clear_flush |
868 | * both clear the TLB for the unmapped pte. The reason is that | 905 | * both clear the TLB for the unmapped pte. The reason is that |
@@ -877,24 +914,72 @@ static inline void ptep_invalidate(struct mm_struct *mm, | |||
877 | * is a nop. | 914 | * is a nop. |
878 | */ | 915 | */ |
879 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR | 916 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR |
880 | #define ptep_get_and_clear(__mm, __address, __ptep) \ | 917 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, |
881 | ({ \ | 918 | unsigned long address, pte_t *ptep) |
882 | pte_t __pte = *(__ptep); \ | 919 | { |
883 | (__mm)->context.flush_mm = 1; \ | 920 | pgste_t pgste; |
884 | if (atomic_read(&(__mm)->context.attach_count) > 1 || \ | 921 | pte_t pte; |
885 | (__mm) != current->active_mm) \ | 922 | |
886 | ptep_invalidate(__mm, __address, __ptep); \ | 923 | mm->context.flush_mm = 1; |
887 | else \ | 924 | if (mm_has_pgste(mm)) |
888 | pte_clear((__mm), (__address), (__ptep)); \ | 925 | pgste = pgste_get_lock(ptep); |
889 | __pte; \ | 926 | |
890 | }) | 927 | pte = *ptep; |
928 | if (!mm_exclusive(mm)) | ||
929 | __ptep_ipte(address, ptep); | ||
930 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; | ||
931 | |||
932 | if (mm_has_pgste(mm)) { | ||
933 | pgste = pgste_update_all(&pte, pgste); | ||
934 | pgste_set_unlock(ptep, pgste); | ||
935 | } | ||
936 | return pte; | ||
937 | } | ||
938 | |||
939 | #define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION | ||
940 | static inline pte_t ptep_modify_prot_start(struct mm_struct *mm, | ||
941 | unsigned long address, | ||
942 | pte_t *ptep) | ||
943 | { | ||
944 | pte_t pte; | ||
945 | |||
946 | mm->context.flush_mm = 1; | ||
947 | if (mm_has_pgste(mm)) | ||
948 | pgste_get_lock(ptep); | ||
949 | |||
950 | pte = *ptep; | ||
951 | if (!mm_exclusive(mm)) | ||
952 | __ptep_ipte(address, ptep); | ||
953 | return pte; | ||
954 | } | ||
955 | |||
956 | static inline void ptep_modify_prot_commit(struct mm_struct *mm, | ||
957 | unsigned long address, | ||
958 | pte_t *ptep, pte_t pte) | ||
959 | { | ||
960 | *ptep = pte; | ||
961 | if (mm_has_pgste(mm)) | ||
962 | pgste_set_unlock(ptep, *(pgste_t *)(ptep + PTRS_PER_PTE)); | ||
963 | } | ||
891 | 964 | ||
892 | #define __HAVE_ARCH_PTEP_CLEAR_FLUSH | 965 | #define __HAVE_ARCH_PTEP_CLEAR_FLUSH |
893 | static inline pte_t ptep_clear_flush(struct vm_area_struct *vma, | 966 | static inline pte_t ptep_clear_flush(struct vm_area_struct *vma, |
894 | unsigned long address, pte_t *ptep) | 967 | unsigned long address, pte_t *ptep) |
895 | { | 968 | { |
896 | pte_t pte = *ptep; | 969 | pgste_t pgste; |
897 | ptep_invalidate(vma->vm_mm, address, ptep); | 970 | pte_t pte; |
971 | |||
972 | if (mm_has_pgste(vma->vm_mm)) | ||
973 | pgste = pgste_get_lock(ptep); | ||
974 | |||
975 | pte = *ptep; | ||
976 | __ptep_ipte(address, ptep); | ||
977 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; | ||
978 | |||
979 | if (mm_has_pgste(vma->vm_mm)) { | ||
980 | pgste = pgste_update_all(&pte, pgste); | ||
981 | pgste_set_unlock(ptep, pgste); | ||
982 | } | ||
898 | return pte; | 983 | return pte; |
899 | } | 984 | } |
900 | 985 | ||
@@ -907,76 +992,67 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma, | |||
907 | */ | 992 | */ |
908 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL | 993 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL |
909 | static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, | 994 | static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, |
910 | unsigned long addr, | 995 | unsigned long address, |
911 | pte_t *ptep, int full) | 996 | pte_t *ptep, int full) |
912 | { | 997 | { |
913 | pte_t pte = *ptep; | 998 | pgste_t pgste; |
999 | pte_t pte; | ||
1000 | |||
1001 | if (mm_has_pgste(mm)) | ||
1002 | pgste = pgste_get_lock(ptep); | ||
914 | 1003 | ||
915 | if (full) | 1004 | pte = *ptep; |
916 | pte_clear(mm, addr, ptep); | 1005 | if (!full) |
917 | else | 1006 | __ptep_ipte(address, ptep); |
918 | ptep_invalidate(mm, addr, ptep); | 1007 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; |
1008 | |||
1009 | if (mm_has_pgste(mm)) { | ||
1010 | pgste = pgste_update_all(&pte, pgste); | ||
1011 | pgste_set_unlock(ptep, pgste); | ||
1012 | } | ||
919 | return pte; | 1013 | return pte; |
920 | } | 1014 | } |
921 | 1015 | ||
922 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT | 1016 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT |
923 | #define ptep_set_wrprotect(__mm, __addr, __ptep) \ | 1017 | static inline pte_t ptep_set_wrprotect(struct mm_struct *mm, |
924 | ({ \ | 1018 | unsigned long address, pte_t *ptep) |
925 | pte_t __pte = *(__ptep); \ | 1019 | { |
926 | if (pte_write(__pte)) { \ | 1020 | pgste_t pgste; |
927 | (__mm)->context.flush_mm = 1; \ | 1021 | pte_t pte = *ptep; |
928 | if (atomic_read(&(__mm)->context.attach_count) > 1 || \ | ||
929 | (__mm) != current->active_mm) \ | ||
930 | ptep_invalidate(__mm, __addr, __ptep); \ | ||
931 | set_pte_at(__mm, __addr, __ptep, pte_wrprotect(__pte)); \ | ||
932 | } \ | ||
933 | }) | ||
934 | 1022 | ||
935 | #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS | 1023 | if (pte_write(pte)) { |
936 | #define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ | 1024 | mm->context.flush_mm = 1; |
937 | ({ \ | 1025 | if (mm_has_pgste(mm)) |
938 | int __changed = !pte_same(*(__ptep), __entry); \ | 1026 | pgste = pgste_get_lock(ptep); |
939 | if (__changed) { \ | ||
940 | ptep_invalidate((__vma)->vm_mm, __addr, __ptep); \ | ||
941 | set_pte_at((__vma)->vm_mm, __addr, __ptep, __entry); \ | ||
942 | } \ | ||
943 | __changed; \ | ||
944 | }) | ||
945 | 1027 | ||
946 | /* | 1028 | if (!mm_exclusive(mm)) |
947 | * Test and clear dirty bit in storage key. | 1029 | __ptep_ipte(address, ptep); |
948 | * We can't clear the changed bit atomically. This is a potential | 1030 | *ptep = pte_wrprotect(pte); |
949 | * race against modification of the referenced bit. This function | ||
950 | * should therefore only be called if it is not mapped in any | ||
951 | * address space. | ||
952 | */ | ||
953 | #define __HAVE_ARCH_PAGE_TEST_DIRTY | ||
954 | static inline int page_test_dirty(struct page *page) | ||
955 | { | ||
956 | return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0; | ||
957 | } | ||
958 | 1031 | ||
959 | #define __HAVE_ARCH_PAGE_CLEAR_DIRTY | 1032 | if (mm_has_pgste(mm)) |
960 | static inline void page_clear_dirty(struct page *page) | 1033 | pgste_set_unlock(ptep, pgste); |
961 | { | 1034 | } |
962 | page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY); | 1035 | return pte; |
963 | } | 1036 | } |
964 | 1037 | ||
965 | /* | 1038 | #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS |
966 | * Test and clear referenced bit in storage key. | 1039 | static inline int ptep_set_access_flags(struct vm_area_struct *vma, |
967 | */ | 1040 | unsigned long address, pte_t *ptep, |
968 | #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG | 1041 | pte_t entry, int dirty) |
969 | static inline int page_test_and_clear_young(struct page *page) | ||
970 | { | 1042 | { |
971 | unsigned long physpage = page_to_phys(page); | 1043 | pgste_t pgste; |
972 | int ccode; | 1044 | |
973 | 1045 | if (pte_same(*ptep, entry)) | |
974 | asm volatile( | 1046 | return 0; |
975 | " rrbe 0,%1\n" | 1047 | if (mm_has_pgste(vma->vm_mm)) |
976 | " ipm %0\n" | 1048 | pgste = pgste_get_lock(ptep); |
977 | " srl %0,28\n" | 1049 | |
978 | : "=d" (ccode) : "a" (physpage) : "cc" ); | 1050 | __ptep_ipte(address, ptep); |
979 | return ccode & 2; | 1051 | *ptep = entry; |
1052 | |||
1053 | if (mm_has_pgste(vma->vm_mm)) | ||
1054 | pgste_set_unlock(ptep, pgste); | ||
1055 | return 1; | ||
980 | } | 1056 | } |
981 | 1057 | ||
982 | /* | 1058 | /* |
@@ -1048,9 +1124,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) | |||
1048 | #define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr)) | 1124 | #define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr)) |
1049 | #define pte_offset_kernel(pmd, address) pte_offset(pmd,address) | 1125 | #define pte_offset_kernel(pmd, address) pte_offset(pmd,address) |
1050 | #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) | 1126 | #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) |
1051 | #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address) | ||
1052 | #define pte_unmap(pte) do { } while (0) | 1127 | #define pte_unmap(pte) do { } while (0) |
1053 | #define pte_unmap_nested(pte) do { } while (0) | ||
1054 | 1128 | ||
1055 | /* | 1129 | /* |
1056 | * 31 bit swap entry format: | 1130 | * 31 bit swap entry format: |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 73e259834e10..1300c3025334 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -32,7 +32,6 @@ static inline void get_cpu_id(struct cpuid *ptr) | |||
32 | } | 32 | } |
33 | 33 | ||
34 | extern void s390_adjust_jiffies(void); | 34 | extern void s390_adjust_jiffies(void); |
35 | extern void print_cpu_info(void); | ||
36 | extern int get_cpu_capability(unsigned int *); | 35 | extern int get_cpu_capability(unsigned int *); |
37 | 36 | ||
38 | /* | 37 | /* |
@@ -81,11 +80,11 @@ struct thread_struct { | |||
81 | mm_segment_t mm_segment; | 80 | mm_segment_t mm_segment; |
82 | unsigned long prot_addr; /* address of protection-excep. */ | 81 | unsigned long prot_addr; /* address of protection-excep. */ |
83 | unsigned int trap_no; | 82 | unsigned int trap_no; |
84 | per_struct per_info; | 83 | struct per_regs per_user; /* User specified PER registers */ |
85 | /* Used to give failing instruction back to user for ieee exceptions */ | 84 | struct per_event per_event; /* Cause of the last PER trap */ |
86 | unsigned long ieee_instruction_pointer; | ||
87 | /* pfault_wait is used to block the process on a pfault event */ | 85 | /* pfault_wait is used to block the process on a pfault event */ |
88 | unsigned long pfault_wait; | 86 | unsigned long pfault_wait; |
87 | struct list_head list; | ||
89 | }; | 88 | }; |
90 | 89 | ||
91 | typedef struct thread_struct thread_struct; | 90 | typedef struct thread_struct thread_struct; |
@@ -150,11 +149,6 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |||
150 | */ | 149 | */ |
151 | extern unsigned long thread_saved_pc(struct task_struct *t); | 150 | extern unsigned long thread_saved_pc(struct task_struct *t); |
152 | 151 | ||
153 | /* | ||
154 | * Print register of task into buffer. Used in fs/proc/array.c. | ||
155 | */ | ||
156 | extern void task_show_regs(struct seq_file *m, struct task_struct *task); | ||
157 | |||
158 | extern void show_code(struct pt_regs *regs); | 152 | extern void show_code(struct pt_regs *regs); |
159 | 153 | ||
160 | unsigned long get_wchan(struct task_struct *p); | 154 | unsigned long get_wchan(struct task_struct *p); |
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index e2c218dc68a6..9ad628a8574a 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h | |||
@@ -331,10 +331,60 @@ struct pt_regs | |||
331 | unsigned short ilc; | 331 | unsigned short ilc; |
332 | unsigned short svcnr; | 332 | unsigned short svcnr; |
333 | }; | 333 | }; |
334 | |||
335 | /* | ||
336 | * Program event recording (PER) register set. | ||
337 | */ | ||
338 | struct per_regs { | ||
339 | unsigned long control; /* PER control bits */ | ||
340 | unsigned long start; /* PER starting address */ | ||
341 | unsigned long end; /* PER ending address */ | ||
342 | }; | ||
343 | |||
344 | /* | ||
345 | * PER event contains information about the cause of the last PER exception. | ||
346 | */ | ||
347 | struct per_event { | ||
348 | unsigned short cause; /* PER code, ATMID and AI */ | ||
349 | unsigned long address; /* PER address */ | ||
350 | unsigned char paid; /* PER access identification */ | ||
351 | }; | ||
352 | |||
353 | /* | ||
354 | * Simplified per_info structure used to decode the ptrace user space ABI. | ||
355 | */ | ||
356 | struct per_struct_kernel { | ||
357 | unsigned long cr9; /* PER control bits */ | ||
358 | unsigned long cr10; /* PER starting address */ | ||
359 | unsigned long cr11; /* PER ending address */ | ||
360 | unsigned long bits; /* Obsolete software bits */ | ||
361 | unsigned long starting_addr; /* User specified start address */ | ||
362 | unsigned long ending_addr; /* User specified end address */ | ||
363 | unsigned short perc_atmid; /* PER trap ATMID */ | ||
364 | unsigned long address; /* PER trap instruction address */ | ||
365 | unsigned char access_id; /* PER trap access identification */ | ||
366 | }; | ||
367 | |||
368 | #define PER_EVENT_MASK 0xE9000000UL | ||
369 | |||
370 | #define PER_EVENT_BRANCH 0x80000000UL | ||
371 | #define PER_EVENT_IFETCH 0x40000000UL | ||
372 | #define PER_EVENT_STORE 0x20000000UL | ||
373 | #define PER_EVENT_STORE_REAL 0x08000000UL | ||
374 | #define PER_EVENT_NULLIFICATION 0x01000000UL | ||
375 | |||
376 | #define PER_CONTROL_MASK 0x00a00000UL | ||
377 | |||
378 | #define PER_CONTROL_BRANCH_ADDRESS 0x00800000UL | ||
379 | #define PER_CONTROL_ALTERATION 0x00200000UL | ||
380 | |||
334 | #endif | 381 | #endif |
335 | 382 | ||
336 | /* | 383 | /* |
337 | * Now for the program event recording (trace) definitions. | 384 | * Now for the user space program event recording (trace) definitions. |
385 | * The following structures are used only for the ptrace interface, don't | ||
386 | * touch or even look at it if you don't want to modify the user-space | ||
387 | * ptrace interface. In particular stay away from it for in-kernel PER. | ||
338 | */ | 388 | */ |
339 | typedef struct | 389 | typedef struct |
340 | { | 390 | { |
@@ -481,8 +531,7 @@ struct user_regs_struct | |||
481 | * watchpoints. This is the way intel does it. | 531 | * watchpoints. This is the way intel does it. |
482 | */ | 532 | */ |
483 | per_struct per_info; | 533 | per_struct per_info; |
484 | unsigned long ieee_instruction_pointer; | 534 | unsigned long ieee_instruction_pointer; /* obsolete, always 0 */ |
485 | /* Used to give failing instruction back to user for ieee exceptions */ | ||
486 | }; | 535 | }; |
487 | 536 | ||
488 | #ifdef __KERNEL__ | 537 | #ifdef __KERNEL__ |
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 2ba630276295..15c97625df8d 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h | |||
@@ -139,110 +139,47 @@ struct slib { | |||
139 | struct slibe slibe[QDIO_MAX_BUFFERS_PER_Q]; | 139 | struct slibe slibe[QDIO_MAX_BUFFERS_PER_Q]; |
140 | } __attribute__ ((packed, aligned(2048))); | 140 | } __attribute__ ((packed, aligned(2048))); |
141 | 141 | ||
142 | /** | 142 | #define SBAL_EFLAGS_LAST_ENTRY 0x40 |
143 | * struct sbal_flags - storage block address list flags | 143 | #define SBAL_EFLAGS_CONTIGUOUS 0x20 |
144 | * @last: last entry | 144 | #define SBAL_EFLAGS_FIRST_FRAG 0x04 |
145 | * @cont: contiguous storage | 145 | #define SBAL_EFLAGS_MIDDLE_FRAG 0x08 |
146 | * @frag: fragmentation | 146 | #define SBAL_EFLAGS_LAST_FRAG 0x0c |
147 | */ | 147 | #define SBAL_EFLAGS_MASK 0x6f |
148 | struct sbal_flags { | ||
149 | u8 : 1; | ||
150 | u8 last : 1; | ||
151 | u8 cont : 1; | ||
152 | u8 : 1; | ||
153 | u8 frag : 2; | ||
154 | u8 : 2; | ||
155 | } __attribute__ ((packed)); | ||
156 | |||
157 | #define SBAL_FLAGS_FIRST_FRAG 0x04000000UL | ||
158 | #define SBAL_FLAGS_MIDDLE_FRAG 0x08000000UL | ||
159 | #define SBAL_FLAGS_LAST_FRAG 0x0c000000UL | ||
160 | #define SBAL_FLAGS_LAST_ENTRY 0x40000000UL | ||
161 | #define SBAL_FLAGS_CONTIGUOUS 0x20000000UL | ||
162 | 148 | ||
163 | #define SBAL_FLAGS0_DATA_CONTINUATION 0x20UL | 149 | #define SBAL_SFLAGS0_PCI_REQ 0x40 |
150 | #define SBAL_SFLAGS0_DATA_CONTINUATION 0x20 | ||
164 | 151 | ||
165 | /* Awesome OpenFCP extensions */ | 152 | /* Awesome OpenFCP extensions */ |
166 | #define SBAL_FLAGS0_TYPE_STATUS 0x00UL | 153 | #define SBAL_SFLAGS0_TYPE_STATUS 0x00 |
167 | #define SBAL_FLAGS0_TYPE_WRITE 0x08UL | 154 | #define SBAL_SFLAGS0_TYPE_WRITE 0x08 |
168 | #define SBAL_FLAGS0_TYPE_READ 0x10UL | 155 | #define SBAL_SFLAGS0_TYPE_READ 0x10 |
169 | #define SBAL_FLAGS0_TYPE_WRITE_READ 0x18UL | 156 | #define SBAL_SFLAGS0_TYPE_WRITE_READ 0x18 |
170 | #define SBAL_FLAGS0_MORE_SBALS 0x04UL | 157 | #define SBAL_SFLAGS0_MORE_SBALS 0x04 |
171 | #define SBAL_FLAGS0_COMMAND 0x02UL | 158 | #define SBAL_SFLAGS0_COMMAND 0x02 |
172 | #define SBAL_FLAGS0_LAST_SBAL 0x00UL | 159 | #define SBAL_SFLAGS0_LAST_SBAL 0x00 |
173 | #define SBAL_FLAGS0_ONLY_SBAL SBAL_FLAGS0_COMMAND | 160 | #define SBAL_SFLAGS0_ONLY_SBAL SBAL_SFLAGS0_COMMAND |
174 | #define SBAL_FLAGS0_MIDDLE_SBAL SBAL_FLAGS0_MORE_SBALS | 161 | #define SBAL_SFLAGS0_MIDDLE_SBAL SBAL_SFLAGS0_MORE_SBALS |
175 | #define SBAL_FLAGS0_FIRST_SBAL SBAL_FLAGS0_MORE_SBALS | SBAL_FLAGS0_COMMAND | 162 | #define SBAL_SFLAGS0_FIRST_SBAL (SBAL_SFLAGS0_MORE_SBALS | SBAL_SFLAGS0_COMMAND) |
176 | #define SBAL_FLAGS0_PCI 0x40 | ||
177 | |||
178 | /** | ||
179 | * struct sbal_sbalf_0 - sbal flags for sbale 0 | ||
180 | * @pci: PCI indicator | ||
181 | * @cont: data continuation | ||
182 | * @sbtype: storage-block type (FCP) | ||
183 | */ | ||
184 | struct sbal_sbalf_0 { | ||
185 | u8 : 1; | ||
186 | u8 pci : 1; | ||
187 | u8 cont : 1; | ||
188 | u8 sbtype : 2; | ||
189 | u8 : 3; | ||
190 | } __attribute__ ((packed)); | ||
191 | |||
192 | /** | ||
193 | * struct sbal_sbalf_1 - sbal flags for sbale 1 | ||
194 | * @key: storage key | ||
195 | */ | ||
196 | struct sbal_sbalf_1 { | ||
197 | u8 : 4; | ||
198 | u8 key : 4; | ||
199 | } __attribute__ ((packed)); | ||
200 | |||
201 | /** | ||
202 | * struct sbal_sbalf_14 - sbal flags for sbale 14 | ||
203 | * @erridx: error index | ||
204 | */ | ||
205 | struct sbal_sbalf_14 { | ||
206 | u8 : 4; | ||
207 | u8 erridx : 4; | ||
208 | } __attribute__ ((packed)); | ||
209 | |||
210 | /** | ||
211 | * struct sbal_sbalf_15 - sbal flags for sbale 15 | ||
212 | * @reason: reason for error state | ||
213 | */ | ||
214 | struct sbal_sbalf_15 { | ||
215 | u8 reason; | ||
216 | } __attribute__ ((packed)); | ||
217 | |||
218 | /** | ||
219 | * union sbal_sbalf - storage block address list flags | ||
220 | * @i0: sbalf0 | ||
221 | * @i1: sbalf1 | ||
222 | * @i14: sbalf14 | ||
223 | * @i15: sblaf15 | ||
224 | * @value: raw value | ||
225 | */ | ||
226 | union sbal_sbalf { | ||
227 | struct sbal_sbalf_0 i0; | ||
228 | struct sbal_sbalf_1 i1; | ||
229 | struct sbal_sbalf_14 i14; | ||
230 | struct sbal_sbalf_15 i15; | ||
231 | u8 value; | ||
232 | }; | ||
233 | 163 | ||
234 | /** | 164 | /** |
235 | * struct qdio_buffer_element - SBAL entry | 165 | * struct qdio_buffer_element - SBAL entry |
236 | * @flags: flags | 166 | * @eflags: SBAL entry flags |
167 | * @scount: SBAL count | ||
168 | * @sflags: whole SBAL flags | ||
237 | * @length: length | 169 | * @length: length |
238 | * @addr: address | 170 | * @addr: address |
239 | */ | 171 | */ |
240 | struct qdio_buffer_element { | 172 | struct qdio_buffer_element { |
241 | u32 flags; | 173 | u8 eflags; |
174 | /* private: */ | ||
175 | u8 res1; | ||
176 | /* public: */ | ||
177 | u8 scount; | ||
178 | u8 sflags; | ||
242 | u32 length; | 179 | u32 length; |
243 | #ifdef CONFIG_32BIT | 180 | #ifdef CONFIG_32BIT |
244 | /* private: */ | 181 | /* private: */ |
245 | void *reserved; | 182 | void *res2; |
246 | /* public: */ | 183 | /* public: */ |
247 | #endif | 184 | #endif |
248 | void *addr; | 185 | void *addr; |
@@ -360,6 +297,8 @@ struct qdio_initialize { | |||
360 | unsigned int no_output_qs; | 297 | unsigned int no_output_qs; |
361 | qdio_handler_t *input_handler; | 298 | qdio_handler_t *input_handler; |
362 | qdio_handler_t *output_handler; | 299 | qdio_handler_t *output_handler; |
300 | void (*queue_start_poll) (struct ccw_device *, int, unsigned long); | ||
301 | int scan_threshold; | ||
363 | unsigned long int_parm; | 302 | unsigned long int_parm; |
364 | void **input_sbal_addr_array; | 303 | void **input_sbal_addr_array; |
365 | void **output_sbal_addr_array; | 304 | void **output_sbal_addr_array; |
@@ -377,11 +316,13 @@ struct qdio_initialize { | |||
377 | extern int qdio_allocate(struct qdio_initialize *); | 316 | extern int qdio_allocate(struct qdio_initialize *); |
378 | extern int qdio_establish(struct qdio_initialize *); | 317 | extern int qdio_establish(struct qdio_initialize *); |
379 | extern int qdio_activate(struct ccw_device *); | 318 | extern int qdio_activate(struct ccw_device *); |
380 | 319 | extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int, | |
381 | extern int do_QDIO(struct ccw_device *cdev, unsigned int callflags, | 320 | unsigned int); |
382 | int q_nr, unsigned int bufnr, unsigned int count); | 321 | extern int qdio_start_irq(struct ccw_device *, int); |
383 | extern int qdio_shutdown(struct ccw_device*, int); | 322 | extern int qdio_stop_irq(struct ccw_device *, int); |
323 | extern int qdio_get_next_buffers(struct ccw_device *, int, int *, int *); | ||
324 | extern int qdio_shutdown(struct ccw_device *, int); | ||
384 | extern int qdio_free(struct ccw_device *); | 325 | extern int qdio_free(struct ccw_device *); |
385 | extern int qdio_get_ssqd_desc(struct ccw_device *dev, struct qdio_ssqd_desc*); | 326 | extern int qdio_get_ssqd_desc(struct ccw_device *, struct qdio_ssqd_desc *); |
386 | 327 | ||
387 | #endif /* __QDIO_H__ */ | 328 | #endif /* __QDIO_H__ */ |
diff --git a/arch/s390/include/asm/qeth.h b/arch/s390/include/asm/qeth.h index 06cbd1e8c943..90efda0b137d 100644 --- a/arch/s390/include/asm/qeth.h +++ b/arch/s390/include/asm/qeth.h | |||
@@ -28,39 +28,70 @@ struct qeth_arp_cache_entry { | |||
28 | __u8 reserved2[32]; | 28 | __u8 reserved2[32]; |
29 | } __attribute__ ((packed)); | 29 | } __attribute__ ((packed)); |
30 | 30 | ||
31 | enum qeth_arp_ipaddrtype { | ||
32 | QETHARP_IP_ADDR_V4 = 1, | ||
33 | QETHARP_IP_ADDR_V6 = 2, | ||
34 | }; | ||
35 | struct qeth_arp_entrytype { | ||
36 | __u8 mac; | ||
37 | __u8 ip; | ||
38 | } __attribute__((packed)); | ||
39 | |||
40 | #define QETH_QARP_MEDIASPECIFIC_BYTES 32 | ||
41 | #define QETH_QARP_MACADDRTYPE_BYTES 1 | ||
31 | struct qeth_arp_qi_entry7 { | 42 | struct qeth_arp_qi_entry7 { |
32 | __u8 media_specific[32]; | 43 | __u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES]; |
33 | __u8 macaddr_type; | 44 | struct qeth_arp_entrytype type; |
34 | __u8 ipaddr_type; | ||
35 | __u8 macaddr[6]; | 45 | __u8 macaddr[6]; |
36 | __u8 ipaddr[4]; | 46 | __u8 ipaddr[4]; |
37 | } __attribute__((packed)); | 47 | } __attribute__((packed)); |
38 | 48 | ||
49 | struct qeth_arp_qi_entry7_ipv6 { | ||
50 | __u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES]; | ||
51 | struct qeth_arp_entrytype type; | ||
52 | __u8 macaddr[6]; | ||
53 | __u8 ipaddr[16]; | ||
54 | } __attribute__((packed)); | ||
55 | |||
39 | struct qeth_arp_qi_entry7_short { | 56 | struct qeth_arp_qi_entry7_short { |
40 | __u8 macaddr_type; | 57 | struct qeth_arp_entrytype type; |
41 | __u8 ipaddr_type; | ||
42 | __u8 macaddr[6]; | 58 | __u8 macaddr[6]; |
43 | __u8 ipaddr[4]; | 59 | __u8 ipaddr[4]; |
44 | } __attribute__((packed)); | 60 | } __attribute__((packed)); |
45 | 61 | ||
62 | struct qeth_arp_qi_entry7_short_ipv6 { | ||
63 | struct qeth_arp_entrytype type; | ||
64 | __u8 macaddr[6]; | ||
65 | __u8 ipaddr[16]; | ||
66 | } __attribute__((packed)); | ||
67 | |||
46 | struct qeth_arp_qi_entry5 { | 68 | struct qeth_arp_qi_entry5 { |
47 | __u8 media_specific[32]; | 69 | __u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES]; |
48 | __u8 macaddr_type; | 70 | struct qeth_arp_entrytype type; |
49 | __u8 ipaddr_type; | ||
50 | __u8 ipaddr[4]; | 71 | __u8 ipaddr[4]; |
51 | } __attribute__((packed)); | 72 | } __attribute__((packed)); |
52 | 73 | ||
74 | struct qeth_arp_qi_entry5_ipv6 { | ||
75 | __u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES]; | ||
76 | struct qeth_arp_entrytype type; | ||
77 | __u8 ipaddr[16]; | ||
78 | } __attribute__((packed)); | ||
79 | |||
53 | struct qeth_arp_qi_entry5_short { | 80 | struct qeth_arp_qi_entry5_short { |
54 | __u8 macaddr_type; | 81 | struct qeth_arp_entrytype type; |
55 | __u8 ipaddr_type; | ||
56 | __u8 ipaddr[4]; | 82 | __u8 ipaddr[4]; |
57 | } __attribute__((packed)); | 83 | } __attribute__((packed)); |
58 | 84 | ||
85 | struct qeth_arp_qi_entry5_short_ipv6 { | ||
86 | struct qeth_arp_entrytype type; | ||
87 | __u8 ipaddr[16]; | ||
88 | } __attribute__((packed)); | ||
59 | /* | 89 | /* |
60 | * can be set by user if no "media specific information" is wanted | 90 | * can be set by user if no "media specific information" is wanted |
61 | * -> saves a lot of space in user space buffer | 91 | * -> saves a lot of space in user space buffer |
62 | */ | 92 | */ |
63 | #define QETH_QARP_STRIP_ENTRIES 0x8000 | 93 | #define QETH_QARP_STRIP_ENTRIES 0x8000 |
94 | #define QETH_QARP_WITH_IPV6 0x4000 | ||
64 | #define QETH_QARP_REQUEST_MASK 0x00ff | 95 | #define QETH_QARP_REQUEST_MASK 0x00ff |
65 | 96 | ||
66 | /* data sent to user space as result of query arp ioctl */ | 97 | /* data sent to user space as result of query arp ioctl */ |
diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h index 423fdda2322d..d0eb4653cebd 100644 --- a/arch/s390/include/asm/rwsem.h +++ b/arch/s390/include/asm/rwsem.h | |||
@@ -43,29 +43,6 @@ | |||
43 | 43 | ||
44 | #ifdef __KERNEL__ | 44 | #ifdef __KERNEL__ |
45 | 45 | ||
46 | #include <linux/list.h> | ||
47 | #include <linux/spinlock.h> | ||
48 | |||
49 | struct rwsem_waiter; | ||
50 | |||
51 | extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *); | ||
52 | extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *); | ||
53 | extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *); | ||
54 | extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *); | ||
55 | extern struct rw_semaphore *rwsem_downgrade_write(struct rw_semaphore *); | ||
56 | |||
57 | /* | ||
58 | * the semaphore definition | ||
59 | */ | ||
60 | struct rw_semaphore { | ||
61 | signed long count; | ||
62 | spinlock_t wait_lock; | ||
63 | struct list_head wait_list; | ||
64 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
65 | struct lockdep_map dep_map; | ||
66 | #endif | ||
67 | }; | ||
68 | |||
69 | #ifndef __s390x__ | 46 | #ifndef __s390x__ |
70 | #define RWSEM_UNLOCKED_VALUE 0x00000000 | 47 | #define RWSEM_UNLOCKED_VALUE 0x00000000 |
71 | #define RWSEM_ACTIVE_BIAS 0x00000001 | 48 | #define RWSEM_ACTIVE_BIAS 0x00000001 |
@@ -81,41 +58,6 @@ struct rw_semaphore { | |||
81 | #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) | 58 | #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) |
82 | 59 | ||
83 | /* | 60 | /* |
84 | * initialisation | ||
85 | */ | ||
86 | |||
87 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
88 | # define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname } | ||
89 | #else | ||
90 | # define __RWSEM_DEP_MAP_INIT(lockname) | ||
91 | #endif | ||
92 | |||
93 | #define __RWSEM_INITIALIZER(name) \ | ||
94 | { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait.lock), \ | ||
95 | LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) } | ||
96 | |||
97 | #define DECLARE_RWSEM(name) \ | ||
98 | struct rw_semaphore name = __RWSEM_INITIALIZER(name) | ||
99 | |||
100 | static inline void init_rwsem(struct rw_semaphore *sem) | ||
101 | { | ||
102 | sem->count = RWSEM_UNLOCKED_VALUE; | ||
103 | spin_lock_init(&sem->wait_lock); | ||
104 | INIT_LIST_HEAD(&sem->wait_list); | ||
105 | } | ||
106 | |||
107 | extern void __init_rwsem(struct rw_semaphore *sem, const char *name, | ||
108 | struct lock_class_key *key); | ||
109 | |||
110 | #define init_rwsem(sem) \ | ||
111 | do { \ | ||
112 | static struct lock_class_key __key; \ | ||
113 | \ | ||
114 | __init_rwsem((sem), #sem, &__key); \ | ||
115 | } while (0) | ||
116 | |||
117 | |||
118 | /* | ||
119 | * lock for reading | 61 | * lock for reading |
120 | */ | 62 | */ |
121 | static inline void __down_read(struct rw_semaphore *sem) | 63 | static inline void __down_read(struct rw_semaphore *sem) |
@@ -377,10 +319,5 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) | |||
377 | return new; | 319 | return new; |
378 | } | 320 | } |
379 | 321 | ||
380 | static inline int rwsem_is_locked(struct rw_semaphore *sem) | ||
381 | { | ||
382 | return (sem->count != 0); | ||
383 | } | ||
384 | |||
385 | #endif /* __KERNEL__ */ | 322 | #endif /* __KERNEL__ */ |
386 | #endif /* _S390_RWSEM_H */ | 323 | #endif /* _S390_RWSEM_H */ |
diff --git a/arch/s390/include/asm/s390_ext.h b/arch/s390/include/asm/s390_ext.h deleted file mode 100644 index 2afc060266a2..000000000000 --- a/arch/s390/include/asm/s390_ext.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | #ifndef _S390_EXTINT_H | ||
2 | #define _S390_EXTINT_H | ||
3 | |||
4 | /* | ||
5 | * include/asm-s390/s390_ext.h | ||
6 | * | ||
7 | * S390 version | ||
8 | * Copyright IBM Corp. 1999,2007 | ||
9 | * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com), | ||
10 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
11 | */ | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | |||
15 | typedef void (*ext_int_handler_t)(__u16 code); | ||
16 | |||
17 | typedef struct ext_int_info_t { | ||
18 | struct ext_int_info_t *next; | ||
19 | ext_int_handler_t handler; | ||
20 | __u16 code; | ||
21 | } ext_int_info_t; | ||
22 | |||
23 | extern ext_int_info_t *ext_int_hash[]; | ||
24 | |||
25 | int register_external_interrupt(__u16 code, ext_int_handler_t handler); | ||
26 | int register_early_external_interrupt(__u16 code, ext_int_handler_t handler, | ||
27 | ext_int_info_t *info); | ||
28 | int unregister_external_interrupt(__u16 code, ext_int_handler_t handler); | ||
29 | int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler, | ||
30 | ext_int_info_t *info); | ||
31 | |||
32 | #endif | ||
diff --git a/arch/s390/include/asm/scatterlist.h b/arch/s390/include/asm/scatterlist.h index 35d786fe93ae..6d45ef6c12a7 100644 --- a/arch/s390/include/asm/scatterlist.h +++ b/arch/s390/include/asm/scatterlist.h | |||
@@ -1 +1,3 @@ | |||
1 | #include <asm-generic/scatterlist.h> | 1 | #include <asm-generic/scatterlist.h> |
2 | |||
3 | #define ARCH_HAS_SG_CHAIN | ||
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 25e831d58e1e..d5e2ef10537d 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h | |||
@@ -73,6 +73,7 @@ extern unsigned int user_mode; | |||
73 | #define MACHINE_FLAG_PFMF (1UL << 11) | 73 | #define MACHINE_FLAG_PFMF (1UL << 11) |
74 | #define MACHINE_FLAG_LPAR (1UL << 12) | 74 | #define MACHINE_FLAG_LPAR (1UL << 12) |
75 | #define MACHINE_FLAG_SPP (1UL << 13) | 75 | #define MACHINE_FLAG_SPP (1UL << 13) |
76 | #define MACHINE_FLAG_TOPOLOGY (1UL << 14) | ||
76 | 77 | ||
77 | #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) | 78 | #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) |
78 | #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) | 79 | #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) |
@@ -90,6 +91,7 @@ extern unsigned int user_mode; | |||
90 | #define MACHINE_HAS_HPAGE (0) | 91 | #define MACHINE_HAS_HPAGE (0) |
91 | #define MACHINE_HAS_PFMF (0) | 92 | #define MACHINE_HAS_PFMF (0) |
92 | #define MACHINE_HAS_SPP (0) | 93 | #define MACHINE_HAS_SPP (0) |
94 | #define MACHINE_HAS_TOPOLOGY (0) | ||
93 | #else /* __s390x__ */ | 95 | #else /* __s390x__ */ |
94 | #define MACHINE_HAS_IEEE (1) | 96 | #define MACHINE_HAS_IEEE (1) |
95 | #define MACHINE_HAS_CSP (1) | 97 | #define MACHINE_HAS_CSP (1) |
@@ -100,6 +102,7 @@ extern unsigned int user_mode; | |||
100 | #define MACHINE_HAS_HPAGE (S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE) | 102 | #define MACHINE_HAS_HPAGE (S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE) |
101 | #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) | 103 | #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) |
102 | #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) | 104 | #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) |
105 | #define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) | ||
103 | #endif /* __s390x__ */ | 106 | #endif /* __s390x__ */ |
104 | 107 | ||
105 | #define ZFCPDUMP_HSA_SIZE (32UL<<20) | 108 | #define ZFCPDUMP_HSA_SIZE (32UL<<20) |
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index edc03cb9cd79..045e009fc164 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h | |||
@@ -20,7 +20,6 @@ extern void machine_power_off_smp(void); | |||
20 | 20 | ||
21 | extern int __cpu_disable (void); | 21 | extern int __cpu_disable (void); |
22 | extern void __cpu_die (unsigned int cpu); | 22 | extern void __cpu_die (unsigned int cpu); |
23 | extern void cpu_die (void) __attribute__ ((noreturn)); | ||
24 | extern int __cpu_up (unsigned int cpu); | 23 | extern int __cpu_up (unsigned int cpu); |
25 | 24 | ||
26 | extern struct mutex smp_cpu_state_mutex; | 25 | extern struct mutex smp_cpu_state_mutex; |
@@ -71,8 +70,10 @@ static inline void smp_switch_to_ipl_cpu(void (*func)(void *), void *data) | |||
71 | 70 | ||
72 | #ifdef CONFIG_HOTPLUG_CPU | 71 | #ifdef CONFIG_HOTPLUG_CPU |
73 | extern int smp_rescan_cpus(void); | 72 | extern int smp_rescan_cpus(void); |
73 | extern void __noreturn cpu_die(void); | ||
74 | #else | 74 | #else |
75 | static inline int smp_rescan_cpus(void) { return 0; } | 75 | static inline int smp_rescan_cpus(void) { return 0; } |
76 | static inline void cpu_die(void) { } | ||
76 | #endif | 77 | #endif |
77 | 78 | ||
78 | #endif /* __ASM_SMP_H */ | 79 | #endif /* __ASM_SMP_H */ |
diff --git a/arch/s390/include/asm/suspend.h b/arch/s390/include/asm/suspend.h deleted file mode 100644 index dc75c616eafe..000000000000 --- a/arch/s390/include/asm/suspend.h +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | #ifndef __ASM_S390_SUSPEND_H | ||
2 | #define __ASM_S390_SUSPEND_H | ||
3 | |||
4 | static inline int arch_prepare_suspend(void) | ||
5 | { | ||
6 | return 0; | ||
7 | } | ||
8 | |||
9 | #endif | ||
10 | |||
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index 8429686951f9..5c0246b955d8 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h | |||
@@ -65,8 +65,6 @@ static inline void syscall_get_arguments(struct task_struct *task, | |||
65 | if (test_tsk_thread_flag(task, TIF_31BIT)) | 65 | if (test_tsk_thread_flag(task, TIF_31BIT)) |
66 | mask = 0xffffffff; | 66 | mask = 0xffffffff; |
67 | #endif | 67 | #endif |
68 | if (i + n == 6) | ||
69 | args[--n] = regs->args[0] & mask; | ||
70 | while (n-- > 0) | 68 | while (n-- > 0) |
71 | if (i + n > 0) | 69 | if (i + n > 0) |
72 | args[n] = regs->gprs[2 + i + n] & mask; | 70 | args[n] = regs->gprs[2 + i + n] & mask; |
@@ -80,8 +78,6 @@ static inline void syscall_set_arguments(struct task_struct *task, | |||
80 | const unsigned long *args) | 78 | const unsigned long *args) |
81 | { | 79 | { |
82 | BUG_ON(i + n > 6); | 80 | BUG_ON(i + n > 6); |
83 | if (i + n == 6) | ||
84 | regs->args[0] = args[--n]; | ||
85 | while (n-- > 0) | 81 | while (n-- > 0) |
86 | if (i + n > 0) | 82 | if (i + n > 0) |
87 | regs->gprs[2 + i + n] = args[n]; | 83 | regs->gprs[2 + i + n] = args[n]; |
diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index 22bdb2a0ee5f..79d3d6e2e9c5 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h | |||
@@ -14,8 +14,13 @@ | |||
14 | #ifndef __ASM_S390_SYSINFO_H | 14 | #ifndef __ASM_S390_SYSINFO_H |
15 | #define __ASM_S390_SYSINFO_H | 15 | #define __ASM_S390_SYSINFO_H |
16 | 16 | ||
17 | #include <asm/bitsperlong.h> | ||
18 | |||
17 | struct sysinfo_1_1_1 { | 19 | struct sysinfo_1_1_1 { |
18 | char reserved_0[32]; | 20 | unsigned short :16; |
21 | unsigned char ccr; | ||
22 | unsigned char cai; | ||
23 | char reserved_0[28]; | ||
19 | char manufacturer[16]; | 24 | char manufacturer[16]; |
20 | char type[4]; | 25 | char type[4]; |
21 | char reserved_1[12]; | 26 | char reserved_1[12]; |
@@ -104,6 +109,39 @@ struct sysinfo_3_2_2 { | |||
104 | char reserved_544[3552]; | 109 | char reserved_544[3552]; |
105 | }; | 110 | }; |
106 | 111 | ||
112 | #define TOPOLOGY_CPU_BITS 64 | ||
113 | #define TOPOLOGY_NR_MAG 6 | ||
114 | |||
115 | struct topology_cpu { | ||
116 | unsigned char reserved0[4]; | ||
117 | unsigned char :6; | ||
118 | unsigned char pp:2; | ||
119 | unsigned char reserved1; | ||
120 | unsigned short origin; | ||
121 | unsigned long mask[TOPOLOGY_CPU_BITS / BITS_PER_LONG]; | ||
122 | }; | ||
123 | |||
124 | struct topology_container { | ||
125 | unsigned char reserved[7]; | ||
126 | unsigned char id; | ||
127 | }; | ||
128 | |||
129 | union topology_entry { | ||
130 | unsigned char nl; | ||
131 | struct topology_cpu cpu; | ||
132 | struct topology_container container; | ||
133 | }; | ||
134 | |||
135 | struct sysinfo_15_1_x { | ||
136 | unsigned char reserved0[2]; | ||
137 | unsigned short length; | ||
138 | unsigned char mag[TOPOLOGY_NR_MAG]; | ||
139 | unsigned char reserved1; | ||
140 | unsigned char mnest; | ||
141 | unsigned char reserved2[4]; | ||
142 | union topology_entry tle[0]; | ||
143 | }; | ||
144 | |||
107 | static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) | 145 | static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) |
108 | { | 146 | { |
109 | register int r0 asm("0") = (fc << 28) | sel1; | 147 | register int r0 asm("0") = (fc << 28) | sel1; |
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h index cef66210c846..d382629a0172 100644 --- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h | |||
@@ -14,12 +14,14 @@ | |||
14 | #include <asm/setup.h> | 14 | #include <asm/setup.h> |
15 | #include <asm/processor.h> | 15 | #include <asm/processor.h> |
16 | #include <asm/lowcore.h> | 16 | #include <asm/lowcore.h> |
17 | #include <asm/cmpxchg.h> | ||
17 | 18 | ||
18 | #ifdef __KERNEL__ | 19 | #ifdef __KERNEL__ |
19 | 20 | ||
20 | struct task_struct; | 21 | struct task_struct; |
21 | 22 | ||
22 | extern struct task_struct *__switch_to(void *, void *); | 23 | extern struct task_struct *__switch_to(void *, void *); |
24 | extern void update_per_regs(struct task_struct *task); | ||
23 | 25 | ||
24 | static inline void save_fp_regs(s390_fp_regs *fpregs) | 26 | static inline void save_fp_regs(s390_fp_regs *fpregs) |
25 | { | 27 | { |
@@ -85,26 +87,26 @@ static inline void restore_access_regs(unsigned int *acrs) | |||
85 | asm volatile("lam 0,15,%0" : : "Q" (*acrs)); | 87 | asm volatile("lam 0,15,%0" : : "Q" (*acrs)); |
86 | } | 88 | } |
87 | 89 | ||
88 | #define switch_to(prev,next,last) do { \ | 90 | #define switch_to(prev,next,last) do { \ |
89 | if (prev == next) \ | 91 | if (prev->mm) { \ |
90 | break; \ | 92 | save_fp_regs(&prev->thread.fp_regs); \ |
91 | save_fp_regs(&prev->thread.fp_regs); \ | 93 | save_access_regs(&prev->thread.acrs[0]); \ |
92 | restore_fp_regs(&next->thread.fp_regs); \ | 94 | } \ |
93 | save_access_regs(&prev->thread.acrs[0]); \ | 95 | if (next->mm) { \ |
94 | restore_access_regs(&next->thread.acrs[0]); \ | 96 | restore_fp_regs(&next->thread.fp_regs); \ |
95 | prev = __switch_to(prev,next); \ | 97 | restore_access_regs(&next->thread.acrs[0]); \ |
98 | update_per_regs(next); \ | ||
99 | } \ | ||
100 | prev = __switch_to(prev,next); \ | ||
96 | } while (0) | 101 | } while (0) |
97 | 102 | ||
98 | extern void account_vtime(struct task_struct *, struct task_struct *); | 103 | extern void account_vtime(struct task_struct *, struct task_struct *); |
99 | extern void account_tick_vtime(struct task_struct *); | 104 | extern void account_tick_vtime(struct task_struct *); |
100 | extern void account_system_vtime(struct task_struct *); | ||
101 | 105 | ||
102 | #ifdef CONFIG_PFAULT | 106 | #ifdef CONFIG_PFAULT |
103 | extern void pfault_irq_init(void); | ||
104 | extern int pfault_init(void); | 107 | extern int pfault_init(void); |
105 | extern void pfault_fini(void); | 108 | extern void pfault_fini(void); |
106 | #else /* CONFIG_PFAULT */ | 109 | #else /* CONFIG_PFAULT */ |
107 | #define pfault_irq_init() do { } while (0) | ||
108 | #define pfault_init() ({-1;}) | 110 | #define pfault_init() ({-1;}) |
109 | #define pfault_fini() do { } while (0) | 111 | #define pfault_fini() do { } while (0) |
110 | #endif /* CONFIG_PFAULT */ | 112 | #endif /* CONFIG_PFAULT */ |
@@ -119,161 +121,6 @@ extern int memcpy_real(void *, void *, size_t); | |||
119 | 121 | ||
120 | #define nop() asm volatile("nop") | 122 | #define nop() asm volatile("nop") |
121 | 123 | ||
122 | #define xchg(ptr,x) \ | ||
123 | ({ \ | ||
124 | __typeof__(*(ptr)) __ret; \ | ||
125 | __ret = (__typeof__(*(ptr))) \ | ||
126 | __xchg((unsigned long)(x), (void *)(ptr),sizeof(*(ptr))); \ | ||
127 | __ret; \ | ||
128 | }) | ||
129 | |||
130 | extern void __xchg_called_with_bad_pointer(void); | ||
131 | |||
132 | static inline unsigned long __xchg(unsigned long x, void * ptr, int size) | ||
133 | { | ||
134 | unsigned long addr, old; | ||
135 | int shift; | ||
136 | |||
137 | switch (size) { | ||
138 | case 1: | ||
139 | addr = (unsigned long) ptr; | ||
140 | shift = (3 ^ (addr & 3)) << 3; | ||
141 | addr ^= addr & 3; | ||
142 | asm volatile( | ||
143 | " l %0,%4\n" | ||
144 | "0: lr 0,%0\n" | ||
145 | " nr 0,%3\n" | ||
146 | " or 0,%2\n" | ||
147 | " cs %0,0,%4\n" | ||
148 | " jl 0b\n" | ||
149 | : "=&d" (old), "=Q" (*(int *) addr) | ||
150 | : "d" (x << shift), "d" (~(255 << shift)), | ||
151 | "Q" (*(int *) addr) : "memory", "cc", "0"); | ||
152 | return old >> shift; | ||
153 | case 2: | ||
154 | addr = (unsigned long) ptr; | ||
155 | shift = (2 ^ (addr & 2)) << 3; | ||
156 | addr ^= addr & 2; | ||
157 | asm volatile( | ||
158 | " l %0,%4\n" | ||
159 | "0: lr 0,%0\n" | ||
160 | " nr 0,%3\n" | ||
161 | " or 0,%2\n" | ||
162 | " cs %0,0,%4\n" | ||
163 | " jl 0b\n" | ||
164 | : "=&d" (old), "=Q" (*(int *) addr) | ||
165 | : "d" (x << shift), "d" (~(65535 << shift)), | ||
166 | "Q" (*(int *) addr) : "memory", "cc", "0"); | ||
167 | return old >> shift; | ||
168 | case 4: | ||
169 | asm volatile( | ||
170 | " l %0,%3\n" | ||
171 | "0: cs %0,%2,%3\n" | ||
172 | " jl 0b\n" | ||
173 | : "=&d" (old), "=Q" (*(int *) ptr) | ||
174 | : "d" (x), "Q" (*(int *) ptr) | ||
175 | : "memory", "cc"); | ||
176 | return old; | ||
177 | #ifdef __s390x__ | ||
178 | case 8: | ||
179 | asm volatile( | ||
180 | " lg %0,%3\n" | ||
181 | "0: csg %0,%2,%3\n" | ||
182 | " jl 0b\n" | ||
183 | : "=&d" (old), "=m" (*(long *) ptr) | ||
184 | : "d" (x), "Q" (*(long *) ptr) | ||
185 | : "memory", "cc"); | ||
186 | return old; | ||
187 | #endif /* __s390x__ */ | ||
188 | } | ||
189 | __xchg_called_with_bad_pointer(); | ||
190 | return x; | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * Atomic compare and exchange. Compare OLD with MEM, if identical, | ||
195 | * store NEW in MEM. Return the initial value in MEM. Success is | ||
196 | * indicated by comparing RETURN with OLD. | ||
197 | */ | ||
198 | |||
199 | #define __HAVE_ARCH_CMPXCHG 1 | ||
200 | |||
201 | #define cmpxchg(ptr, o, n) \ | ||
202 | ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ | ||
203 | (unsigned long)(n), sizeof(*(ptr)))) | ||
204 | |||
205 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
206 | |||
207 | static inline unsigned long | ||
208 | __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | ||
209 | { | ||
210 | unsigned long addr, prev, tmp; | ||
211 | int shift; | ||
212 | |||
213 | switch (size) { | ||
214 | case 1: | ||
215 | addr = (unsigned long) ptr; | ||
216 | shift = (3 ^ (addr & 3)) << 3; | ||
217 | addr ^= addr & 3; | ||
218 | asm volatile( | ||
219 | " l %0,%2\n" | ||
220 | "0: nr %0,%5\n" | ||
221 | " lr %1,%0\n" | ||
222 | " or %0,%3\n" | ||
223 | " or %1,%4\n" | ||
224 | " cs %0,%1,%2\n" | ||
225 | " jnl 1f\n" | ||
226 | " xr %1,%0\n" | ||
227 | " nr %1,%5\n" | ||
228 | " jnz 0b\n" | ||
229 | "1:" | ||
230 | : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) | ||
231 | : "d" (old << shift), "d" (new << shift), | ||
232 | "d" (~(255 << shift)), "Q" (*(int *) ptr) | ||
233 | : "memory", "cc"); | ||
234 | return prev >> shift; | ||
235 | case 2: | ||
236 | addr = (unsigned long) ptr; | ||
237 | shift = (2 ^ (addr & 2)) << 3; | ||
238 | addr ^= addr & 2; | ||
239 | asm volatile( | ||
240 | " l %0,%2\n" | ||
241 | "0: nr %0,%5\n" | ||
242 | " lr %1,%0\n" | ||
243 | " or %0,%3\n" | ||
244 | " or %1,%4\n" | ||
245 | " cs %0,%1,%2\n" | ||
246 | " jnl 1f\n" | ||
247 | " xr %1,%0\n" | ||
248 | " nr %1,%5\n" | ||
249 | " jnz 0b\n" | ||
250 | "1:" | ||
251 | : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) | ||
252 | : "d" (old << shift), "d" (new << shift), | ||
253 | "d" (~(65535 << shift)), "Q" (*(int *) ptr) | ||
254 | : "memory", "cc"); | ||
255 | return prev >> shift; | ||
256 | case 4: | ||
257 | asm volatile( | ||
258 | " cs %0,%3,%1\n" | ||
259 | : "=&d" (prev), "=Q" (*(int *) ptr) | ||
260 | : "0" (old), "d" (new), "Q" (*(int *) ptr) | ||
261 | : "memory", "cc"); | ||
262 | return prev; | ||
263 | #ifdef __s390x__ | ||
264 | case 8: | ||
265 | asm volatile( | ||
266 | " csg %0,%3,%1\n" | ||
267 | : "=&d" (prev), "=Q" (*(long *) ptr) | ||
268 | : "0" (old), "d" (new), "Q" (*(long *) ptr) | ||
269 | : "memory", "cc"); | ||
270 | return prev; | ||
271 | #endif /* __s390x__ */ | ||
272 | } | ||
273 | __cmpxchg_called_with_bad_pointer(); | ||
274 | return old; | ||
275 | } | ||
276 | |||
277 | /* | 124 | /* |
278 | * Force strict CPU ordering. | 125 | * Force strict CPU ordering. |
279 | * And yes, this is required on UP too when we're talking | 126 | * And yes, this is required on UP too when we're talking |
@@ -352,46 +199,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | |||
352 | __ctl_load(__dummy, cr, cr); \ | 199 | __ctl_load(__dummy, cr, cr); \ |
353 | }) | 200 | }) |
354 | 201 | ||
355 | #include <linux/irqflags.h> | ||
356 | |||
357 | #include <asm-generic/cmpxchg-local.h> | ||
358 | |||
359 | static inline unsigned long __cmpxchg_local(volatile void *ptr, | ||
360 | unsigned long old, | ||
361 | unsigned long new, int size) | ||
362 | { | ||
363 | switch (size) { | ||
364 | case 1: | ||
365 | case 2: | ||
366 | case 4: | ||
367 | #ifdef __s390x__ | ||
368 | case 8: | ||
369 | #endif | ||
370 | return __cmpxchg(ptr, old, new, size); | ||
371 | default: | ||
372 | return __cmpxchg_local_generic(ptr, old, new, size); | ||
373 | } | ||
374 | |||
375 | return old; | ||
376 | } | ||
377 | |||
378 | /* | ||
379 | * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make | ||
380 | * them available. | ||
381 | */ | ||
382 | #define cmpxchg_local(ptr, o, n) \ | ||
383 | ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ | ||
384 | (unsigned long)(n), sizeof(*(ptr)))) | ||
385 | #ifdef __s390x__ | ||
386 | #define cmpxchg64_local(ptr, o, n) \ | ||
387 | ({ \ | ||
388 | BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ | ||
389 | cmpxchg_local((ptr), (o), (n)); \ | ||
390 | }) | ||
391 | #else | ||
392 | #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) | ||
393 | #endif | ||
394 | |||
395 | /* | 202 | /* |
396 | * Use to set psw mask except for the first byte which | 203 | * Use to set psw mask except for the first byte which |
397 | * won't be changed by this function. | 204 | * won't be changed by this function. |
@@ -399,7 +206,7 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, | |||
399 | static inline void | 206 | static inline void |
400 | __set_psw_mask(unsigned long mask) | 207 | __set_psw_mask(unsigned long mask) |
401 | { | 208 | { |
402 | __load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8))); | 209 | __load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8))); |
403 | } | 210 | } |
404 | 211 | ||
405 | #define local_mcck_enable() __set_psw_mask(psw_kernel_bits) | 212 | #define local_mcck_enable() __set_psw_mask(psw_kernel_bits) |
@@ -419,30 +226,21 @@ extern void smp_ctl_clear_bit(int cr, int bit); | |||
419 | 226 | ||
420 | #endif /* CONFIG_SMP */ | 227 | #endif /* CONFIG_SMP */ |
421 | 228 | ||
422 | static inline unsigned int stfl(void) | 229 | #define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */ |
423 | { | ||
424 | asm volatile( | ||
425 | " .insn s,0xb2b10000,0(0)\n" /* stfl */ | ||
426 | "0:\n" | ||
427 | EX_TABLE(0b,0b)); | ||
428 | return S390_lowcore.stfl_fac_list; | ||
429 | } | ||
430 | 230 | ||
431 | static inline int __stfle(unsigned long long *list, int doublewords) | 231 | /* |
232 | * The test_facility function uses the bit odering where the MSB is bit 0. | ||
233 | * That makes it easier to query facility bits with the bit number as | ||
234 | * documented in the Principles of Operation. | ||
235 | */ | ||
236 | static inline int test_facility(unsigned long nr) | ||
432 | { | 237 | { |
433 | typedef struct { unsigned long long _[doublewords]; } addrtype; | 238 | unsigned char *ptr; |
434 | register unsigned long __nr asm("0") = doublewords - 1; | ||
435 | 239 | ||
436 | asm volatile(".insn s,0xb2b00000,%0" /* stfle */ | 240 | if (nr >= MAX_FACILITY_BIT) |
437 | : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc"); | 241 | return 0; |
438 | return __nr + 1; | 242 | ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3); |
439 | } | 243 | return (*ptr & (0x80 >> (nr & 7))) != 0; |
440 | |||
441 | static inline int stfle(unsigned long long *list, int doublewords) | ||
442 | { | ||
443 | if (!(stfl() & (1UL << 24))) | ||
444 | return -EOPNOTSUPP; | ||
445 | return __stfle(list, doublewords); | ||
446 | } | 244 | } |
447 | 245 | ||
448 | static inline unsigned short stap(void) | 246 | static inline unsigned short stap(void) |
@@ -457,7 +255,7 @@ extern void (*_machine_restart)(char *command); | |||
457 | extern void (*_machine_halt)(void); | 255 | extern void (*_machine_halt)(void); |
458 | extern void (*_machine_power_off)(void); | 256 | extern void (*_machine_power_off)(void); |
459 | 257 | ||
460 | #define arch_align_stack(x) (x) | 258 | extern unsigned long arch_align_stack(unsigned long sp); |
461 | 259 | ||
462 | static inline int tprot(unsigned long addr) | 260 | static inline int tprot(unsigned long addr) |
463 | { | 261 | { |
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 5baf0230b29b..ad1382f7932e 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h | |||
@@ -74,7 +74,7 @@ struct thread_info { | |||
74 | /* how to get the thread information struct from C */ | 74 | /* how to get the thread information struct from C */ |
75 | static inline struct thread_info *current_thread_info(void) | 75 | static inline struct thread_info *current_thread_info(void) |
76 | { | 76 | { |
77 | return (struct thread_info *)(S390_lowcore.kernel_stack - THREAD_SIZE); | 77 | return (struct thread_info *) S390_lowcore.thread_info; |
78 | } | 78 | } |
79 | 79 | ||
80 | #define THREAD_SIZE_ORDER THREAD_ORDER | 80 | #define THREAD_SIZE_ORDER THREAD_ORDER |
@@ -88,7 +88,7 @@ static inline struct thread_info *current_thread_info(void) | |||
88 | #define TIF_SIGPENDING 2 /* signal pending */ | 88 | #define TIF_SIGPENDING 2 /* signal pending */ |
89 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ | 89 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ |
90 | #define TIF_RESTART_SVC 4 /* restart svc with new svc number */ | 90 | #define TIF_RESTART_SVC 4 /* restart svc with new svc number */ |
91 | #define TIF_SINGLE_STEP 6 /* deliver sigtrap on return to user */ | 91 | #define TIF_PER_TRAP 6 /* deliver sigtrap on return to user */ |
92 | #define TIF_MCCK_PENDING 7 /* machine check handling is pending */ | 92 | #define TIF_MCCK_PENDING 7 /* machine check handling is pending */ |
93 | #define TIF_SYSCALL_TRACE 8 /* syscall trace active */ | 93 | #define TIF_SYSCALL_TRACE 8 /* syscall trace active */ |
94 | #define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */ | 94 | #define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */ |
@@ -99,14 +99,15 @@ static inline struct thread_info *current_thread_info(void) | |||
99 | #define TIF_31BIT 17 /* 32bit process */ | 99 | #define TIF_31BIT 17 /* 32bit process */ |
100 | #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ | 100 | #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ |
101 | #define TIF_RESTORE_SIGMASK 19 /* restore signal mask in do_signal() */ | 101 | #define TIF_RESTORE_SIGMASK 19 /* restore signal mask in do_signal() */ |
102 | #define TIF_FREEZE 20 /* thread is freezing for suspend */ | 102 | #define TIF_SINGLE_STEP 20 /* This task is single stepped */ |
103 | #define TIF_FREEZE 21 /* thread is freezing for suspend */ | ||
103 | 104 | ||
104 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) | 105 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) |
105 | #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) | 106 | #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) |
106 | #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) | 107 | #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) |
107 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) | 108 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) |
108 | #define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC) | 109 | #define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC) |
109 | #define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP) | 110 | #define _TIF_PER_TRAP (1<<TIF_PER_TRAP) |
110 | #define _TIF_MCCK_PENDING (1<<TIF_MCCK_PENDING) | 111 | #define _TIF_MCCK_PENDING (1<<TIF_MCCK_PENDING) |
111 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 112 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
112 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) | 113 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) |
@@ -114,8 +115,15 @@ static inline struct thread_info *current_thread_info(void) | |||
114 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) | 115 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) |
115 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) | 116 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) |
116 | #define _TIF_31BIT (1<<TIF_31BIT) | 117 | #define _TIF_31BIT (1<<TIF_31BIT) |
118 | #define _TIF_SINGLE_STEP (1<<TIF_FREEZE) | ||
117 | #define _TIF_FREEZE (1<<TIF_FREEZE) | 119 | #define _TIF_FREEZE (1<<TIF_FREEZE) |
118 | 120 | ||
121 | #ifdef CONFIG_64BIT | ||
122 | #define is_32bit_task() (test_thread_flag(TIF_31BIT)) | ||
123 | #else | ||
124 | #define is_32bit_task() (1) | ||
125 | #endif | ||
126 | |||
119 | #endif /* __KERNEL__ */ | 127 | #endif /* __KERNEL__ */ |
120 | 128 | ||
121 | #define PREEMPT_ACTIVE 0x4000000 | 129 | #define PREEMPT_ACTIVE 0x4000000 |
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index 09d345a701dc..88829a40af6f 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h | |||
@@ -11,6 +11,8 @@ | |||
11 | #ifndef _ASM_S390_TIMEX_H | 11 | #ifndef _ASM_S390_TIMEX_H |
12 | #define _ASM_S390_TIMEX_H | 12 | #define _ASM_S390_TIMEX_H |
13 | 13 | ||
14 | #include <asm/lowcore.h> | ||
15 | |||
14 | /* The value of the TOD clock for 1.1.1970. */ | 16 | /* The value of the TOD clock for 1.1.1970. */ |
15 | #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL | 17 | #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL |
16 | 18 | ||
@@ -49,6 +51,24 @@ static inline void store_clock_comparator(__u64 *time) | |||
49 | asm volatile("stckc %0" : "=Q" (*time)); | 51 | asm volatile("stckc %0" : "=Q" (*time)); |
50 | } | 52 | } |
51 | 53 | ||
54 | void clock_comparator_work(void); | ||
55 | |||
56 | static inline unsigned long long local_tick_disable(void) | ||
57 | { | ||
58 | unsigned long long old; | ||
59 | |||
60 | old = S390_lowcore.clock_comparator; | ||
61 | S390_lowcore.clock_comparator = -1ULL; | ||
62 | set_clock_comparator(S390_lowcore.clock_comparator); | ||
63 | return old; | ||
64 | } | ||
65 | |||
66 | static inline void local_tick_enable(unsigned long long comp) | ||
67 | { | ||
68 | S390_lowcore.clock_comparator = comp; | ||
69 | set_clock_comparator(S390_lowcore.clock_comparator); | ||
70 | } | ||
71 | |||
52 | #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ | 72 | #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ |
53 | 73 | ||
54 | typedef unsigned long long cycles_t; | 74 | typedef unsigned long long cycles_t; |
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h index fd1c00d08bf5..c687a2c83462 100644 --- a/arch/s390/include/asm/tlb.h +++ b/arch/s390/include/asm/tlb.h | |||
@@ -22,70 +22,77 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
25 | #include <linux/pagemap.h> | ||
25 | #include <linux/swap.h> | 26 | #include <linux/swap.h> |
26 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
27 | #include <asm/pgalloc.h> | 28 | #include <asm/pgalloc.h> |
28 | #include <asm/smp.h> | ||
29 | #include <asm/tlbflush.h> | 29 | #include <asm/tlbflush.h> |
30 | 30 | ||
31 | #ifndef CONFIG_SMP | ||
32 | #define TLB_NR_PTRS 1 | ||
33 | #else | ||
34 | #define TLB_NR_PTRS 508 | ||
35 | #endif | ||
36 | |||
37 | struct mmu_gather { | 31 | struct mmu_gather { |
38 | struct mm_struct *mm; | 32 | struct mm_struct *mm; |
33 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE | ||
34 | struct mmu_table_batch *batch; | ||
35 | #endif | ||
39 | unsigned int fullmm; | 36 | unsigned int fullmm; |
40 | unsigned int nr_ptes; | 37 | unsigned int need_flush; |
41 | unsigned int nr_pxds; | ||
42 | void *array[TLB_NR_PTRS]; | ||
43 | }; | 38 | }; |
44 | 39 | ||
45 | DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); | 40 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE |
41 | struct mmu_table_batch { | ||
42 | struct rcu_head rcu; | ||
43 | unsigned int nr; | ||
44 | void *tables[0]; | ||
45 | }; | ||
46 | 46 | ||
47 | static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, | 47 | #define MAX_TABLE_BATCH \ |
48 | unsigned int full_mm_flush) | 48 | ((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *)) |
49 | { | ||
50 | struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); | ||
51 | 49 | ||
50 | extern void tlb_table_flush(struct mmu_gather *tlb); | ||
51 | extern void tlb_remove_table(struct mmu_gather *tlb, void *table); | ||
52 | #endif | ||
53 | |||
54 | static inline void tlb_gather_mmu(struct mmu_gather *tlb, | ||
55 | struct mm_struct *mm, | ||
56 | unsigned int full_mm_flush) | ||
57 | { | ||
52 | tlb->mm = mm; | 58 | tlb->mm = mm; |
53 | tlb->fullmm = full_mm_flush; | 59 | tlb->fullmm = full_mm_flush; |
54 | tlb->nr_ptes = 0; | 60 | tlb->need_flush = 0; |
55 | tlb->nr_pxds = TLB_NR_PTRS; | 61 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE |
62 | tlb->batch = NULL; | ||
63 | #endif | ||
56 | if (tlb->fullmm) | 64 | if (tlb->fullmm) |
57 | __tlb_flush_mm(mm); | 65 | __tlb_flush_mm(mm); |
58 | return tlb; | ||
59 | } | 66 | } |
60 | 67 | ||
61 | static inline void tlb_flush_mmu(struct mmu_gather *tlb, | 68 | static inline void tlb_flush_mmu(struct mmu_gather *tlb) |
62 | unsigned long start, unsigned long end) | ||
63 | { | 69 | { |
64 | if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < TLB_NR_PTRS)) | 70 | if (!tlb->need_flush) |
65 | __tlb_flush_mm(tlb->mm); | 71 | return; |
66 | while (tlb->nr_ptes > 0) | 72 | tlb->need_flush = 0; |
67 | pte_free(tlb->mm, tlb->array[--tlb->nr_ptes]); | 73 | __tlb_flush_mm(tlb->mm); |
68 | while (tlb->nr_pxds < TLB_NR_PTRS) | 74 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE |
69 | /* pgd_free frees the pointer as region or segment table */ | 75 | tlb_table_flush(tlb); |
70 | pgd_free(tlb->mm, tlb->array[tlb->nr_pxds++]); | 76 | #endif |
71 | } | 77 | } |
72 | 78 | ||
73 | static inline void tlb_finish_mmu(struct mmu_gather *tlb, | 79 | static inline void tlb_finish_mmu(struct mmu_gather *tlb, |
74 | unsigned long start, unsigned long end) | 80 | unsigned long start, unsigned long end) |
75 | { | 81 | { |
76 | tlb_flush_mmu(tlb, start, end); | 82 | tlb_flush_mmu(tlb); |
77 | |||
78 | /* keep the page table cache within bounds */ | ||
79 | check_pgt_cache(); | ||
80 | |||
81 | put_cpu_var(mmu_gathers); | ||
82 | } | 83 | } |
83 | 84 | ||
84 | /* | 85 | /* |
85 | * Release the page cache reference for a pte removed by | 86 | * Release the page cache reference for a pte removed by |
86 | * tlb_ptep_clear_flush. In both flush modes the tlb fo a page cache page | 87 | * tlb_ptep_clear_flush. In both flush modes the tlb for a page cache page |
87 | * has already been freed, so just do free_page_and_swap_cache. | 88 | * has already been freed, so just do free_page_and_swap_cache. |
88 | */ | 89 | */ |
90 | static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) | ||
91 | { | ||
92 | free_page_and_swap_cache(page); | ||
93 | return 1; /* avoid calling tlb_flush_mmu */ | ||
94 | } | ||
95 | |||
89 | static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) | 96 | static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) |
90 | { | 97 | { |
91 | free_page_and_swap_cache(page); | 98 | free_page_and_swap_cache(page); |
@@ -98,12 +105,11 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) | |||
98 | static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | 105 | static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, |
99 | unsigned long address) | 106 | unsigned long address) |
100 | { | 107 | { |
101 | if (!tlb->fullmm) { | 108 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE |
102 | tlb->array[tlb->nr_ptes++] = pte; | 109 | if (!tlb->fullmm) |
103 | if (tlb->nr_ptes >= tlb->nr_pxds) | 110 | return page_table_free_rcu(tlb, (unsigned long *) pte); |
104 | tlb_flush_mmu(tlb, 0, 0); | 111 | #endif |
105 | } else | 112 | page_table_free(tlb->mm, (unsigned long *) pte); |
106 | pte_free(tlb->mm, pte); | ||
107 | } | 113 | } |
108 | 114 | ||
109 | /* | 115 | /* |
@@ -119,12 +125,11 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, | |||
119 | #ifdef __s390x__ | 125 | #ifdef __s390x__ |
120 | if (tlb->mm->context.asce_limit <= (1UL << 31)) | 126 | if (tlb->mm->context.asce_limit <= (1UL << 31)) |
121 | return; | 127 | return; |
122 | if (!tlb->fullmm) { | 128 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE |
123 | tlb->array[--tlb->nr_pxds] = pmd; | 129 | if (!tlb->fullmm) |
124 | if (tlb->nr_ptes >= tlb->nr_pxds) | 130 | return tlb_remove_table(tlb, pmd); |
125 | tlb_flush_mmu(tlb, 0, 0); | 131 | #endif |
126 | } else | 132 | crst_table_free(tlb->mm, (unsigned long *) pmd); |
127 | pmd_free(tlb->mm, pmd); | ||
128 | #endif | 133 | #endif |
129 | } | 134 | } |
130 | 135 | ||
@@ -141,12 +146,11 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, | |||
141 | #ifdef __s390x__ | 146 | #ifdef __s390x__ |
142 | if (tlb->mm->context.asce_limit <= (1UL << 42)) | 147 | if (tlb->mm->context.asce_limit <= (1UL << 42)) |
143 | return; | 148 | return; |
144 | if (!tlb->fullmm) { | 149 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE |
145 | tlb->array[--tlb->nr_pxds] = pud; | 150 | if (!tlb->fullmm) |
146 | if (tlb->nr_ptes >= tlb->nr_pxds) | 151 | return tlb_remove_table(tlb, pud); |
147 | tlb_flush_mmu(tlb, 0, 0); | 152 | #endif |
148 | } else | 153 | crst_table_free(tlb->mm, (unsigned long *) pud); |
149 | pud_free(tlb->mm, pud); | ||
150 | #endif | 154 | #endif |
151 | } | 155 | } |
152 | 156 | ||
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index 29d5d6d4becc..b7a4f2eb0057 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h | |||
@@ -50,7 +50,7 @@ static inline void __tlb_flush_full(struct mm_struct *mm) | |||
50 | /* | 50 | /* |
51 | * If the process only ran on the local cpu, do a local flush. | 51 | * If the process only ran on the local cpu, do a local flush. |
52 | */ | 52 | */ |
53 | local_cpumask = cpumask_of_cpu(smp_processor_id()); | 53 | cpumask_copy(&local_cpumask, cpumask_of(smp_processor_id())); |
54 | if (cpumask_equal(mm_cpumask(mm), &local_cpumask)) | 54 | if (cpumask_equal(mm_cpumask(mm), &local_cpumask)) |
55 | __tlb_flush_local(); | 55 | __tlb_flush_local(); |
56 | else | 56 | else |
@@ -80,16 +80,11 @@ static inline void __tlb_flush_mm(struct mm_struct * mm) | |||
80 | * on all cpus instead of doing a local flush if the mm | 80 | * on all cpus instead of doing a local flush if the mm |
81 | * only ran on the local cpu. | 81 | * only ran on the local cpu. |
82 | */ | 82 | */ |
83 | if (MACHINE_HAS_IDTE) { | 83 | if (MACHINE_HAS_IDTE) |
84 | if (mm->context.noexec) | ||
85 | __tlb_flush_idte((unsigned long) | ||
86 | get_shadow_table(mm->pgd) | | ||
87 | mm->context.asce_bits); | ||
88 | __tlb_flush_idte((unsigned long) mm->pgd | | 84 | __tlb_flush_idte((unsigned long) mm->pgd | |
89 | mm->context.asce_bits); | 85 | mm->context.asce_bits); |
90 | return; | 86 | else |
91 | } | 87 | __tlb_flush_full(mm); |
92 | __tlb_flush_full(mm); | ||
93 | } | 88 | } |
94 | 89 | ||
95 | static inline void __tlb_flush_mm_cond(struct mm_struct * mm) | 90 | static inline void __tlb_flush_mm_cond(struct mm_struct * mm) |
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index 831bd033ea77..005d77d8ae2a 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h | |||
@@ -2,19 +2,38 @@ | |||
2 | #define _ASM_S390_TOPOLOGY_H | 2 | #define _ASM_S390_TOPOLOGY_H |
3 | 3 | ||
4 | #include <linux/cpumask.h> | 4 | #include <linux/cpumask.h> |
5 | 5 | #include <asm/sysinfo.h> | |
6 | #define mc_capable() (1) | ||
7 | |||
8 | const struct cpumask *cpu_coregroup_mask(unsigned int cpu); | ||
9 | 6 | ||
10 | extern unsigned char cpu_core_id[NR_CPUS]; | 7 | extern unsigned char cpu_core_id[NR_CPUS]; |
11 | extern cpumask_t cpu_core_map[NR_CPUS]; | 8 | extern cpumask_t cpu_core_map[NR_CPUS]; |
12 | 9 | ||
10 | static inline const struct cpumask *cpu_coregroup_mask(int cpu) | ||
11 | { | ||
12 | return &cpu_core_map[cpu]; | ||
13 | } | ||
14 | |||
13 | #define topology_core_id(cpu) (cpu_core_id[cpu]) | 15 | #define topology_core_id(cpu) (cpu_core_id[cpu]) |
14 | #define topology_core_cpumask(cpu) (&cpu_core_map[cpu]) | 16 | #define topology_core_cpumask(cpu) (&cpu_core_map[cpu]) |
17 | #define mc_capable() (1) | ||
18 | |||
19 | #ifdef CONFIG_SCHED_BOOK | ||
20 | |||
21 | extern unsigned char cpu_book_id[NR_CPUS]; | ||
22 | extern cpumask_t cpu_book_map[NR_CPUS]; | ||
23 | |||
24 | static inline const struct cpumask *cpu_book_mask(int cpu) | ||
25 | { | ||
26 | return &cpu_book_map[cpu]; | ||
27 | } | ||
28 | |||
29 | #define topology_book_id(cpu) (cpu_book_id[cpu]) | ||
30 | #define topology_book_cpumask(cpu) (&cpu_book_map[cpu]) | ||
31 | |||
32 | #endif /* CONFIG_SCHED_BOOK */ | ||
15 | 33 | ||
16 | int topology_set_cpu_management(int fc); | 34 | int topology_set_cpu_management(int fc); |
17 | void topology_schedule_update(void); | 35 | void topology_schedule_update(void); |
36 | void store_topology(struct sysinfo_15_1_x *info); | ||
18 | 37 | ||
19 | #define POLARIZATION_UNKNWN (-1) | 38 | #define POLARIZATION_UNKNWN (-1) |
20 | #define POLARIZATION_HRZ (0) | 39 | #define POLARIZATION_HRZ (0) |
@@ -30,6 +49,8 @@ static inline void s390_init_cpu_topology(void) | |||
30 | }; | 49 | }; |
31 | #endif | 50 | #endif |
32 | 51 | ||
52 | #define SD_BOOK_INIT SD_CPU_INIT | ||
53 | |||
33 | #include <asm-generic/topology.h> | 54 | #include <asm-generic/topology.h> |
34 | 55 | ||
35 | #endif /* _ASM_S390_TOPOLOGY_H */ | 56 | #endif /* _ASM_S390_TOPOLOGY_H */ |
diff --git a/arch/s390/include/asm/types.h b/arch/s390/include/asm/types.h index 04d6b95a89c6..eeb52ccf499f 100644 --- a/arch/s390/include/asm/types.h +++ b/arch/s390/include/asm/types.h | |||
@@ -30,14 +30,6 @@ typedef __signed__ long saddr_t; | |||
30 | 30 | ||
31 | #ifndef __ASSEMBLY__ | 31 | #ifndef __ASSEMBLY__ |
32 | 32 | ||
33 | typedef u64 dma64_addr_t; | ||
34 | #ifdef __s390x__ | ||
35 | /* DMA addresses come in 32-bit and 64-bit flavours. */ | ||
36 | typedef u64 dma_addr_t; | ||
37 | #else | ||
38 | typedef u32 dma_addr_t; | ||
39 | #endif | ||
40 | |||
41 | #ifndef __s390x__ | 33 | #ifndef __s390x__ |
42 | typedef union { | 34 | typedef union { |
43 | unsigned long long pair; | 35 | unsigned long long pair; |
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index d6b1ed0ec52b..2b23885e81e9 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h | |||
@@ -49,12 +49,13 @@ | |||
49 | 49 | ||
50 | #define segment_eq(a,b) ((a).ar4 == (b).ar4) | 50 | #define segment_eq(a,b) ((a).ar4 == (b).ar4) |
51 | 51 | ||
52 | #define __access_ok(addr, size) \ | ||
53 | ({ \ | ||
54 | __chk_user_ptr(addr); \ | ||
55 | 1; \ | ||
56 | }) | ||
52 | 57 | ||
53 | static inline int __access_ok(const void __user *addr, unsigned long size) | 58 | #define access_ok(type, addr, size) __access_ok(addr, size) |
54 | { | ||
55 | return 1; | ||
56 | } | ||
57 | #define access_ok(type,addr,size) __access_ok(addr,size) | ||
58 | 59 | ||
59 | /* | 60 | /* |
60 | * The exception table consists of pairs of addresses: the first is the | 61 | * The exception table consists of pairs of addresses: the first is the |
@@ -83,8 +84,8 @@ struct uaccess_ops { | |||
83 | size_t (*clear_user)(size_t, void __user *); | 84 | size_t (*clear_user)(size_t, void __user *); |
84 | size_t (*strnlen_user)(size_t, const char __user *); | 85 | size_t (*strnlen_user)(size_t, const char __user *); |
85 | size_t (*strncpy_from_user)(size_t, const char __user *, char *); | 86 | size_t (*strncpy_from_user)(size_t, const char __user *, char *); |
86 | int (*futex_atomic_op)(int op, int __user *, int oparg, int *old); | 87 | int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old); |
87 | int (*futex_atomic_cmpxchg)(int __user *, int old, int new); | 88 | int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new); |
88 | }; | 89 | }; |
89 | 90 | ||
90 | extern struct uaccess_ops uaccess; | 91 | extern struct uaccess_ops uaccess; |
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 1049ef27c15e..404bdb9671b4 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h | |||
@@ -272,7 +272,12 @@ | |||
272 | #define __NR_fanotify_init 332 | 272 | #define __NR_fanotify_init 332 |
273 | #define __NR_fanotify_mark 333 | 273 | #define __NR_fanotify_mark 333 |
274 | #define __NR_prlimit64 334 | 274 | #define __NR_prlimit64 334 |
275 | #define NR_syscalls 335 | 275 | #define __NR_name_to_handle_at 335 |
276 | #define __NR_open_by_handle_at 336 | ||
277 | #define __NR_clock_adjtime 337 | ||
278 | #define __NR_syncfs 338 | ||
279 | #define __NR_setns 339 | ||
280 | #define NR_syscalls 340 | ||
276 | 281 | ||
277 | /* | 282 | /* |
278 | * There are some system calls that are not present on 64 bit, some | 283 | * There are some system calls that are not present on 64 bit, some |
@@ -381,6 +386,7 @@ | |||
381 | 386 | ||
382 | /* Ignore system calls that are also reachable via sys_socket */ | 387 | /* Ignore system calls that are also reachable via sys_socket */ |
383 | #define __IGNORE_recvmmsg | 388 | #define __IGNORE_recvmmsg |
389 | #define __IGNORE_sendmmsg | ||
384 | 390 | ||
385 | #define __ARCH_WANT_IPC_PARSE_VERSION | 391 | #define __ARCH_WANT_IPC_PARSE_VERSION |
386 | #define __ARCH_WANT_OLD_READDIR | 392 | #define __ARCH_WANT_OLD_READDIR |
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 64230bc392fa..df3732249baa 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
@@ -20,10 +20,10 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' | |||
20 | 20 | ||
21 | CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w | 21 | CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w |
22 | 22 | ||
23 | obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ | 23 | obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \ |
24 | processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ | 24 | processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \ |
25 | s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ | 25 | debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \ |
26 | vdso.o vtime.o sysinfo.o nmi.o sclp.o | 26 | sysinfo.o jump_label.o |
27 | 27 | ||
28 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) | 28 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) |
29 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) | 29 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 5232278d79ad..edfbd17d7082 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
@@ -23,14 +23,16 @@ int main(void) | |||
23 | { | 23 | { |
24 | DEFINE(__THREAD_info, offsetof(struct task_struct, stack)); | 24 | DEFINE(__THREAD_info, offsetof(struct task_struct, stack)); |
25 | DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp)); | 25 | DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp)); |
26 | DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info)); | ||
27 | DEFINE(__THREAD_mm_segment, offsetof(struct task_struct, thread.mm_segment)); | 26 | DEFINE(__THREAD_mm_segment, offsetof(struct task_struct, thread.mm_segment)); |
28 | BLANK(); | 27 | BLANK(); |
29 | DEFINE(__TASK_pid, offsetof(struct task_struct, pid)); | 28 | DEFINE(__TASK_pid, offsetof(struct task_struct, pid)); |
30 | BLANK(); | 29 | BLANK(); |
31 | DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid)); | 30 | DEFINE(__THREAD_per_cause, |
32 | DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address)); | 31 | offsetof(struct task_struct, thread.per_event.cause)); |
33 | DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id)); | 32 | DEFINE(__THREAD_per_address, |
33 | offsetof(struct task_struct, thread.per_event.address)); | ||
34 | DEFINE(__THREAD_per_paid, | ||
35 | offsetof(struct task_struct, thread.per_event.paid)); | ||
34 | BLANK(); | 36 | BLANK(); |
35 | DEFINE(__TI_task, offsetof(struct thread_info, task)); | 37 | DEFINE(__TI_task, offsetof(struct thread_info, task)); |
36 | DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain)); | 38 | DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain)); |
@@ -66,9 +68,9 @@ int main(void) | |||
66 | DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base)); | 68 | DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base)); |
67 | DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time)); | 69 | DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time)); |
68 | /* constants used by the vdso */ | 70 | /* constants used by the vdso */ |
69 | DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); | 71 | DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME); |
70 | DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); | 72 | DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC); |
71 | DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); | 73 | DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); |
72 | BLANK(); | 74 | BLANK(); |
73 | /* constants for SIGP */ | 75 | /* constants for SIGP */ |
74 | DEFINE(__SIGP_STOP, sigp_stop); | 76 | DEFINE(__SIGP_STOP, sigp_stop); |
@@ -84,9 +86,10 @@ int main(void) | |||
84 | DEFINE(__LC_SVC_INT_CODE, offsetof(struct _lowcore, svc_code)); | 86 | DEFINE(__LC_SVC_INT_CODE, offsetof(struct _lowcore, svc_code)); |
85 | DEFINE(__LC_PGM_ILC, offsetof(struct _lowcore, pgm_ilc)); | 87 | DEFINE(__LC_PGM_ILC, offsetof(struct _lowcore, pgm_ilc)); |
86 | DEFINE(__LC_PGM_INT_CODE, offsetof(struct _lowcore, pgm_code)); | 88 | DEFINE(__LC_PGM_INT_CODE, offsetof(struct _lowcore, pgm_code)); |
87 | DEFINE(__LC_PER_ATMID, offsetof(struct _lowcore, per_perc_atmid)); | 89 | DEFINE(__LC_TRANS_EXC_CODE, offsetof(struct _lowcore, trans_exc_code)); |
90 | DEFINE(__LC_PER_CAUSE, offsetof(struct _lowcore, per_perc_atmid)); | ||
88 | DEFINE(__LC_PER_ADDRESS, offsetof(struct _lowcore, per_address)); | 91 | DEFINE(__LC_PER_ADDRESS, offsetof(struct _lowcore, per_address)); |
89 | DEFINE(__LC_PER_ACCESS_ID, offsetof(struct _lowcore, per_access_id)); | 92 | DEFINE(__LC_PER_PAID, offsetof(struct _lowcore, per_access_id)); |
90 | DEFINE(__LC_AR_MODE_ID, offsetof(struct _lowcore, ar_access_id)); | 93 | DEFINE(__LC_AR_MODE_ID, offsetof(struct _lowcore, ar_access_id)); |
91 | DEFINE(__LC_SUBCHANNEL_ID, offsetof(struct _lowcore, subchannel_id)); | 94 | DEFINE(__LC_SUBCHANNEL_ID, offsetof(struct _lowcore, subchannel_id)); |
92 | DEFINE(__LC_SUBCHANNEL_NR, offsetof(struct _lowcore, subchannel_nr)); | 95 | DEFINE(__LC_SUBCHANNEL_NR, offsetof(struct _lowcore, subchannel_nr)); |
@@ -121,13 +124,11 @@ int main(void) | |||
121 | DEFINE(__LC_LAST_UPDATE_TIMER, offsetof(struct _lowcore, last_update_timer)); | 124 | DEFINE(__LC_LAST_UPDATE_TIMER, offsetof(struct _lowcore, last_update_timer)); |
122 | DEFINE(__LC_LAST_UPDATE_CLOCK, offsetof(struct _lowcore, last_update_clock)); | 125 | DEFINE(__LC_LAST_UPDATE_CLOCK, offsetof(struct _lowcore, last_update_clock)); |
123 | DEFINE(__LC_CURRENT, offsetof(struct _lowcore, current_task)); | 126 | DEFINE(__LC_CURRENT, offsetof(struct _lowcore, current_task)); |
127 | DEFINE(__LC_CURRENT_PID, offsetof(struct _lowcore, current_pid)); | ||
124 | DEFINE(__LC_THREAD_INFO, offsetof(struct _lowcore, thread_info)); | 128 | DEFINE(__LC_THREAD_INFO, offsetof(struct _lowcore, thread_info)); |
125 | DEFINE(__LC_KERNEL_STACK, offsetof(struct _lowcore, kernel_stack)); | 129 | DEFINE(__LC_KERNEL_STACK, offsetof(struct _lowcore, kernel_stack)); |
126 | DEFINE(__LC_ASYNC_STACK, offsetof(struct _lowcore, async_stack)); | 130 | DEFINE(__LC_ASYNC_STACK, offsetof(struct _lowcore, async_stack)); |
127 | DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack)); | 131 | DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack)); |
128 | DEFINE(__LC_KERNEL_ASCE, offsetof(struct _lowcore, kernel_asce)); | ||
129 | DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); | ||
130 | DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce)); | ||
131 | DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); | 132 | DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); |
132 | DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); | 133 | DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); |
133 | DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); | 134 | DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); |
@@ -142,10 +143,8 @@ int main(void) | |||
142 | DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area)); | 143 | DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area)); |
143 | DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area)); | 144 | DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area)); |
144 | #ifdef CONFIG_32BIT | 145 | #ifdef CONFIG_32BIT |
145 | DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params)); | ||
146 | DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr)); | 146 | DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr)); |
147 | #else /* CONFIG_32BIT */ | 147 | #else /* CONFIG_32BIT */ |
148 | DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params2)); | ||
149 | DEFINE(__LC_EXT_PARAMS2, offsetof(struct _lowcore, ext_params2)); | 148 | DEFINE(__LC_EXT_PARAMS2, offsetof(struct _lowcore, ext_params2)); |
150 | DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area)); | 149 | DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area)); |
151 | DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste)); | 150 | DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste)); |
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 1e6449c79ab6..53acaa86dd94 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/resource.h> | 25 | #include <linux/resource.h> |
26 | #include <linux/times.h> | 26 | #include <linux/times.h> |
27 | #include <linux/smp.h> | 27 | #include <linux/smp.h> |
28 | #include <linux/smp_lock.h> | ||
29 | #include <linux/sem.h> | 28 | #include <linux/sem.h> |
30 | #include <linux/msg.h> | 29 | #include <linux/msg.h> |
31 | #include <linux/shm.h> | 30 | #include <linux/shm.h> |
diff --git a/arch/s390/kernel/compat_ptrace.h b/arch/s390/kernel/compat_ptrace.h index 123dd660d7fb..12b823833510 100644 --- a/arch/s390/kernel/compat_ptrace.h +++ b/arch/s390/kernel/compat_ptrace.h | |||
@@ -4,40 +4,19 @@ | |||
4 | #include <asm/ptrace.h> /* needed for NUM_CR_WORDS */ | 4 | #include <asm/ptrace.h> /* needed for NUM_CR_WORDS */ |
5 | #include "compat_linux.h" /* needed for psw_compat_t */ | 5 | #include "compat_linux.h" /* needed for psw_compat_t */ |
6 | 6 | ||
7 | typedef struct { | 7 | struct compat_per_struct_kernel { |
8 | __u32 cr[NUM_CR_WORDS]; | 8 | __u32 cr9; /* PER control bits */ |
9 | } per_cr_words32; | 9 | __u32 cr10; /* PER starting address */ |
10 | 10 | __u32 cr11; /* PER ending address */ | |
11 | typedef struct { | 11 | __u32 bits; /* Obsolete software bits */ |
12 | __u16 perc_atmid; /* 0x096 */ | 12 | __u32 starting_addr; /* User specified start address */ |
13 | __u32 address; /* 0x098 */ | 13 | __u32 ending_addr; /* User specified end address */ |
14 | __u8 access_id; /* 0x0a1 */ | 14 | __u16 perc_atmid; /* PER trap ATMID */ |
15 | } per_lowcore_words32; | 15 | __u32 address; /* PER trap instruction address */ |
16 | 16 | __u8 access_id; /* PER trap access identification */ | |
17 | typedef struct { | 17 | }; |
18 | union { | ||
19 | per_cr_words32 words; | ||
20 | } control_regs; | ||
21 | /* | ||
22 | * Use these flags instead of setting em_instruction_fetch | ||
23 | * directly they are used so that single stepping can be | ||
24 | * switched on & off while not affecting other tracing | ||
25 | */ | ||
26 | unsigned single_step : 1; | ||
27 | unsigned instruction_fetch : 1; | ||
28 | unsigned : 30; | ||
29 | /* | ||
30 | * These addresses are copied into cr10 & cr11 if single | ||
31 | * stepping is switched off | ||
32 | */ | ||
33 | __u32 starting_addr; | ||
34 | __u32 ending_addr; | ||
35 | union { | ||
36 | per_lowcore_words32 words; | ||
37 | } lowcore; | ||
38 | } per_struct32; | ||
39 | 18 | ||
40 | struct user_regs_struct32 | 19 | struct compat_user_regs_struct |
41 | { | 20 | { |
42 | psw_compat_t psw; | 21 | psw_compat_t psw; |
43 | u32 gprs[NUM_GPRS]; | 22 | u32 gprs[NUM_GPRS]; |
@@ -50,15 +29,14 @@ struct user_regs_struct32 | |||
50 | * itself as there is no "official" ptrace interface for hardware | 29 | * itself as there is no "official" ptrace interface for hardware |
51 | * watchpoints. This is the way intel does it. | 30 | * watchpoints. This is the way intel does it. |
52 | */ | 31 | */ |
53 | per_struct32 per_info; | 32 | struct compat_per_struct_kernel per_info; |
54 | u32 ieee_instruction_pointer; | 33 | u32 ieee_instruction_pointer; /* obsolete, always 0 */ |
55 | /* Used to give failing instruction back to user for ieee exceptions */ | ||
56 | }; | 34 | }; |
57 | 35 | ||
58 | struct user32 { | 36 | struct compat_user { |
59 | /* We start with the registers, to mimic the way that "memory" | 37 | /* We start with the registers, to mimic the way that "memory" |
60 | is returned from the ptrace(3,...) function. */ | 38 | is returned from the ptrace(3,...) function. */ |
61 | struct user_regs_struct32 regs; /* Where the registers are actually stored */ | 39 | struct compat_user_regs_struct regs; |
62 | /* The rest of this junk is to help gdb figure out what goes where */ | 40 | /* The rest of this junk is to help gdb figure out what goes where */ |
63 | u32 u_tsize; /* Text segment size (pages). */ | 41 | u32 u_tsize; /* Text segment size (pages). */ |
64 | u32 u_dsize; /* Data segment size (pages). */ | 42 | u32 u_dsize; /* Data segment size (pages). */ |
@@ -80,6 +58,6 @@ typedef struct | |||
80 | __u32 len; | 58 | __u32 len; |
81 | __u32 kernel_addr; | 59 | __u32 kernel_addr; |
82 | __u32 process_addr; | 60 | __u32 process_addr; |
83 | } ptrace_area_emu31; | 61 | } compat_ptrace_area; |
84 | 62 | ||
85 | #endif /* _PTRACE32_H */ | 63 | #endif /* _PTRACE32_H */ |
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 8e60fb23b90d..1f5eb789c3a7 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
@@ -1877,3 +1877,36 @@ sys_prlimit64_wrapper: | |||
1877 | llgtr %r4,%r4 # const struct rlimit64 __user * | 1877 | llgtr %r4,%r4 # const struct rlimit64 __user * |
1878 | llgtr %r5,%r5 # struct rlimit64 __user * | 1878 | llgtr %r5,%r5 # struct rlimit64 __user * |
1879 | jg sys_prlimit64 # branch to system call | 1879 | jg sys_prlimit64 # branch to system call |
1880 | |||
1881 | .globl sys_name_to_handle_at_wrapper | ||
1882 | sys_name_to_handle_at_wrapper: | ||
1883 | lgfr %r2,%r2 # int | ||
1884 | llgtr %r3,%r3 # const char __user * | ||
1885 | llgtr %r4,%r4 # struct file_handle __user * | ||
1886 | llgtr %r5,%r5 # int __user * | ||
1887 | lgfr %r6,%r6 # int | ||
1888 | jg sys_name_to_handle_at | ||
1889 | |||
1890 | .globl compat_sys_open_by_handle_at_wrapper | ||
1891 | compat_sys_open_by_handle_at_wrapper: | ||
1892 | lgfr %r2,%r2 # int | ||
1893 | llgtr %r3,%r3 # struct file_handle __user * | ||
1894 | lgfr %r4,%r4 # int | ||
1895 | jg compat_sys_open_by_handle_at | ||
1896 | |||
1897 | .globl compat_sys_clock_adjtime_wrapper | ||
1898 | compat_sys_clock_adjtime_wrapper: | ||
1899 | lgfr %r2,%r2 # clockid_t (int) | ||
1900 | llgtr %r3,%r3 # struct compat_timex __user * | ||
1901 | jg compat_sys_clock_adjtime | ||
1902 | |||
1903 | .globl sys_syncfs_wrapper | ||
1904 | sys_syncfs_wrapper: | ||
1905 | lgfr %r2,%r2 # int | ||
1906 | jg sys_syncfs | ||
1907 | |||
1908 | .globl sys_setns_wrapper | ||
1909 | sys_setns_wrapper: | ||
1910 | lgfr %r2,%r2 # int | ||
1911 | lgfr %r3,%r3 # int | ||
1912 | jg sys_setns | ||
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 98192261491d..5ad6bc078bfd 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c | |||
@@ -174,6 +174,7 @@ static const struct file_operations debug_file_ops = { | |||
174 | .write = debug_input, | 174 | .write = debug_input, |
175 | .open = debug_open, | 175 | .open = debug_open, |
176 | .release = debug_close, | 176 | .release = debug_close, |
177 | .llseek = no_llseek, | ||
177 | }; | 178 | }; |
178 | 179 | ||
179 | static struct dentry *debug_debugfs_root_entry; | 180 | static struct dentry *debug_debugfs_root_entry; |
diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c index c032d11da8a1..8237fc07ac79 100644 --- a/arch/s390/kernel/diag.c +++ b/arch/s390/kernel/diag.c | |||
@@ -9,27 +9,6 @@ | |||
9 | #include <asm/diag.h> | 9 | #include <asm/diag.h> |
10 | 10 | ||
11 | /* | 11 | /* |
12 | * Diagnose 10: Release pages | ||
13 | */ | ||
14 | void diag10(unsigned long addr) | ||
15 | { | ||
16 | if (addr >= 0x7ff00000) | ||
17 | return; | ||
18 | asm volatile( | ||
19 | #ifdef CONFIG_64BIT | ||
20 | " sam31\n" | ||
21 | " diag %0,%0,0x10\n" | ||
22 | "0: sam64\n" | ||
23 | #else | ||
24 | " diag %0,%0,0x10\n" | ||
25 | "0:\n" | ||
26 | #endif | ||
27 | EX_TABLE(0b, 0b) | ||
28 | : : "a" (addr)); | ||
29 | } | ||
30 | EXPORT_SYMBOL(diag10); | ||
31 | |||
32 | /* | ||
33 | * Diagnose 14: Input spool file manipulation | 12 | * Diagnose 14: Input spool file manipulation |
34 | */ | 13 | */ |
35 | int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode) | 14 | int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode) |
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index b39b27d68b45..1ca3d1d6a86c 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c | |||
@@ -30,9 +30,9 @@ | |||
30 | #include <asm/atomic.h> | 30 | #include <asm/atomic.h> |
31 | #include <asm/mathemu.h> | 31 | #include <asm/mathemu.h> |
32 | #include <asm/cpcmd.h> | 32 | #include <asm/cpcmd.h> |
33 | #include <asm/s390_ext.h> | ||
34 | #include <asm/lowcore.h> | 33 | #include <asm/lowcore.h> |
35 | #include <asm/debug.h> | 34 | #include <asm/debug.h> |
35 | #include <asm/irq.h> | ||
36 | 36 | ||
37 | #ifndef CONFIG_64BIT | 37 | #ifndef CONFIG_64BIT |
38 | #define ONELONG "%08lx: " | 38 | #define ONELONG "%08lx: " |
@@ -113,7 +113,7 @@ enum { | |||
113 | INSTR_INVALID, | 113 | INSTR_INVALID, |
114 | INSTR_E, | 114 | INSTR_E, |
115 | INSTR_RIE_R0IU, INSTR_RIE_R0UU, INSTR_RIE_RRP, INSTR_RIE_RRPU, | 115 | INSTR_RIE_R0IU, INSTR_RIE_R0UU, INSTR_RIE_RRP, INSTR_RIE_RRPU, |
116 | INSTR_RIE_RRUUU, INSTR_RIE_RUPI, INSTR_RIE_RUPU, | 116 | INSTR_RIE_RRUUU, INSTR_RIE_RUPI, INSTR_RIE_RUPU, INSTR_RIE_RRI0, |
117 | INSTR_RIL_RI, INSTR_RIL_RP, INSTR_RIL_RU, INSTR_RIL_UP, | 117 | INSTR_RIL_RI, INSTR_RIL_RP, INSTR_RIL_RU, INSTR_RIL_UP, |
118 | INSTR_RIS_R0RDU, INSTR_RIS_R0UU, INSTR_RIS_RURDI, INSTR_RIS_RURDU, | 118 | INSTR_RIS_R0RDU, INSTR_RIS_R0UU, INSTR_RIS_RURDI, INSTR_RIS_RURDU, |
119 | INSTR_RI_RI, INSTR_RI_RP, INSTR_RI_RU, INSTR_RI_UP, | 119 | INSTR_RI_RI, INSTR_RI_RP, INSTR_RI_RU, INSTR_RI_UP, |
@@ -122,13 +122,14 @@ enum { | |||
122 | INSTR_RRE_RR, INSTR_RRE_RR_OPT, | 122 | INSTR_RRE_RR, INSTR_RRE_RR_OPT, |
123 | INSTR_RRF_0UFF, INSTR_RRF_F0FF, INSTR_RRF_F0FF2, INSTR_RRF_F0FR, | 123 | INSTR_RRF_0UFF, INSTR_RRF_F0FF, INSTR_RRF_F0FF2, INSTR_RRF_F0FR, |
124 | INSTR_RRF_FFRU, INSTR_RRF_FUFF, INSTR_RRF_M0RR, INSTR_RRF_R0RR, | 124 | INSTR_RRF_FFRU, INSTR_RRF_FUFF, INSTR_RRF_M0RR, INSTR_RRF_R0RR, |
125 | INSTR_RRF_RURR, INSTR_RRF_U0FF, INSTR_RRF_U0RF, INSTR_RRF_U0RR, | 125 | INSTR_RRF_R0RR2, INSTR_RRF_RURR, INSTR_RRF_U0FF, INSTR_RRF_U0RF, |
126 | INSTR_RRF_UUFF, INSTR_RRR_F0FF, INSTR_RRS_RRRDU, | 126 | INSTR_RRF_U0RR, INSTR_RRF_UUFF, INSTR_RRR_F0FF, INSTR_RRS_RRRDU, |
127 | INSTR_RR_FF, INSTR_RR_R0, INSTR_RR_RR, INSTR_RR_U0, INSTR_RR_UR, | 127 | INSTR_RR_FF, INSTR_RR_R0, INSTR_RR_RR, INSTR_RR_U0, INSTR_RR_UR, |
128 | INSTR_RSE_CCRD, INSTR_RSE_RRRD, INSTR_RSE_RURD, | 128 | INSTR_RSE_CCRD, INSTR_RSE_RRRD, INSTR_RSE_RURD, |
129 | INSTR_RSI_RRP, | 129 | INSTR_RSI_RRP, |
130 | INSTR_RSL_R0RD, | 130 | INSTR_RSL_R0RD, |
131 | INSTR_RSY_AARD, INSTR_RSY_CCRD, INSTR_RSY_RRRD, INSTR_RSY_RURD, | 131 | INSTR_RSY_AARD, INSTR_RSY_CCRD, INSTR_RSY_RRRD, INSTR_RSY_RURD, |
132 | INSTR_RSY_RDRM, | ||
132 | INSTR_RS_AARD, INSTR_RS_CCRD, INSTR_RS_R0RD, INSTR_RS_RRRD, | 133 | INSTR_RS_AARD, INSTR_RS_CCRD, INSTR_RS_R0RD, INSTR_RS_RRRD, |
133 | INSTR_RS_RURD, | 134 | INSTR_RS_RURD, |
134 | INSTR_RXE_FRRD, INSTR_RXE_RRRD, | 135 | INSTR_RXE_FRRD, INSTR_RXE_RRRD, |
@@ -139,7 +140,7 @@ enum { | |||
139 | INSTR_SIY_IRD, INSTR_SIY_URD, | 140 | INSTR_SIY_IRD, INSTR_SIY_URD, |
140 | INSTR_SI_URD, | 141 | INSTR_SI_URD, |
141 | INSTR_SSE_RDRD, | 142 | INSTR_SSE_RDRD, |
142 | INSTR_SSF_RRDRD, | 143 | INSTR_SSF_RRDRD, INSTR_SSF_RRDRD2, |
143 | INSTR_SS_L0RDRD, INSTR_SS_LIRDRD, INSTR_SS_LLRDRD, INSTR_SS_RRRDRD, | 144 | INSTR_SS_L0RDRD, INSTR_SS_LIRDRD, INSTR_SS_LLRDRD, INSTR_SS_RRRDRD, |
144 | INSTR_SS_RRRDRD2, INSTR_SS_RRRDRD3, | 145 | INSTR_SS_RRRDRD2, INSTR_SS_RRRDRD3, |
145 | INSTR_S_00, INSTR_S_RD, | 146 | INSTR_S_00, INSTR_S_RD, |
@@ -152,7 +153,7 @@ struct operand { | |||
152 | }; | 153 | }; |
153 | 154 | ||
154 | struct insn { | 155 | struct insn { |
155 | const char name[6]; | 156 | const char name[5]; |
156 | unsigned char opfrag; | 157 | unsigned char opfrag; |
157 | unsigned char format; | 158 | unsigned char format; |
158 | }; | 159 | }; |
@@ -217,6 +218,7 @@ static const unsigned char formats[][7] = { | |||
217 | [INSTR_RIE_RRP] = { 0xff, R_8,R_12,J16_16,0,0,0 }, | 218 | [INSTR_RIE_RRP] = { 0xff, R_8,R_12,J16_16,0,0,0 }, |
218 | [INSTR_RIE_RRUUU] = { 0xff, R_8,R_12,U8_16,U8_24,U8_32,0 }, | 219 | [INSTR_RIE_RRUUU] = { 0xff, R_8,R_12,U8_16,U8_24,U8_32,0 }, |
219 | [INSTR_RIE_RUPI] = { 0xff, R_8,I8_32,U4_12,J16_16,0,0 }, | 220 | [INSTR_RIE_RUPI] = { 0xff, R_8,I8_32,U4_12,J16_16,0,0 }, |
221 | [INSTR_RIE_RRI0] = { 0xff, R_8,R_12,I16_16,0,0,0 }, | ||
220 | [INSTR_RIL_RI] = { 0x0f, R_8,I32_16,0,0,0,0 }, | 222 | [INSTR_RIL_RI] = { 0x0f, R_8,I32_16,0,0,0,0 }, |
221 | [INSTR_RIL_RP] = { 0x0f, R_8,J32_16,0,0,0,0 }, | 223 | [INSTR_RIL_RP] = { 0x0f, R_8,J32_16,0,0,0,0 }, |
222 | [INSTR_RIL_RU] = { 0x0f, R_8,U32_16,0,0,0,0 }, | 224 | [INSTR_RIL_RU] = { 0x0f, R_8,U32_16,0,0,0,0 }, |
@@ -248,6 +250,7 @@ static const unsigned char formats[][7] = { | |||
248 | [INSTR_RRF_FUFF] = { 0xff, F_24,F_16,F_28,U4_20,0,0 }, | 250 | [INSTR_RRF_FUFF] = { 0xff, F_24,F_16,F_28,U4_20,0,0 }, |
249 | [INSTR_RRF_M0RR] = { 0xff, R_24,R_28,M_16,0,0,0 }, | 251 | [INSTR_RRF_M0RR] = { 0xff, R_24,R_28,M_16,0,0,0 }, |
250 | [INSTR_RRF_R0RR] = { 0xff, R_24,R_16,R_28,0,0,0 }, | 252 | [INSTR_RRF_R0RR] = { 0xff, R_24,R_16,R_28,0,0,0 }, |
253 | [INSTR_RRF_R0RR2] = { 0xff, R_24,R_28,R_16,0,0,0 }, | ||
251 | [INSTR_RRF_RURR] = { 0xff, R_24,R_28,R_16,U4_20,0,0 }, | 254 | [INSTR_RRF_RURR] = { 0xff, R_24,R_28,R_16,U4_20,0,0 }, |
252 | [INSTR_RRF_U0FF] = { 0xff, F_24,U4_16,F_28,0,0,0 }, | 255 | [INSTR_RRF_U0FF] = { 0xff, F_24,U4_16,F_28,0,0,0 }, |
253 | [INSTR_RRF_U0RF] = { 0xff, R_24,U4_16,F_28,0,0,0 }, | 256 | [INSTR_RRF_U0RF] = { 0xff, R_24,U4_16,F_28,0,0,0 }, |
@@ -269,6 +272,7 @@ static const unsigned char formats[][7] = { | |||
269 | [INSTR_RSY_CCRD] = { 0xff, C_8,C_12,D20_20,B_16,0,0 }, | 272 | [INSTR_RSY_CCRD] = { 0xff, C_8,C_12,D20_20,B_16,0,0 }, |
270 | [INSTR_RSY_RRRD] = { 0xff, R_8,R_12,D20_20,B_16,0,0 }, | 273 | [INSTR_RSY_RRRD] = { 0xff, R_8,R_12,D20_20,B_16,0,0 }, |
271 | [INSTR_RSY_RURD] = { 0xff, R_8,U4_12,D20_20,B_16,0,0 }, | 274 | [INSTR_RSY_RURD] = { 0xff, R_8,U4_12,D20_20,B_16,0,0 }, |
275 | [INSTR_RSY_RDRM] = { 0xff, R_8,D20_20,B_16,U4_12,0,0 }, | ||
272 | [INSTR_RS_AARD] = { 0xff, A_8,A_12,D_20,B_16,0,0 }, | 276 | [INSTR_RS_AARD] = { 0xff, A_8,A_12,D_20,B_16,0,0 }, |
273 | [INSTR_RS_CCRD] = { 0xff, C_8,C_12,D_20,B_16,0,0 }, | 277 | [INSTR_RS_CCRD] = { 0xff, C_8,C_12,D_20,B_16,0,0 }, |
274 | [INSTR_RS_R0RD] = { 0xff, R_8,D_20,B_16,0,0,0 }, | 278 | [INSTR_RS_R0RD] = { 0xff, R_8,D_20,B_16,0,0,0 }, |
@@ -290,6 +294,7 @@ static const unsigned char formats[][7] = { | |||
290 | [INSTR_SI_URD] = { 0xff, D_20,B_16,U8_8,0,0,0 }, | 294 | [INSTR_SI_URD] = { 0xff, D_20,B_16,U8_8,0,0,0 }, |
291 | [INSTR_SSE_RDRD] = { 0xff, D_20,B_16,D_36,B_32,0,0 }, | 295 | [INSTR_SSE_RDRD] = { 0xff, D_20,B_16,D_36,B_32,0,0 }, |
292 | [INSTR_SSF_RRDRD] = { 0x00, D_20,B_16,D_36,B_32,R_8,0 }, | 296 | [INSTR_SSF_RRDRD] = { 0x00, D_20,B_16,D_36,B_32,R_8,0 }, |
297 | [INSTR_SSF_RRDRD2]= { 0x00, R_8,D_20,B_16,D_36,B_32,0 }, | ||
293 | [INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 }, | 298 | [INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 }, |
294 | [INSTR_SS_LIRDRD] = { 0xff, D_20,L4_8,B_16,D_36,B_32,U4_12 }, | 299 | [INSTR_SS_LIRDRD] = { 0xff, D_20,L4_8,B_16,D_36,B_32,U4_12 }, |
295 | [INSTR_SS_LLRDRD] = { 0xff, D_20,L4_8,B_16,D_36,L4_12,B_32 }, | 300 | [INSTR_SS_LLRDRD] = { 0xff, D_20,L4_8,B_16,D_36,L4_12,B_32 }, |
@@ -300,6 +305,36 @@ static const unsigned char formats[][7] = { | |||
300 | [INSTR_S_RD] = { 0xff, D_20,B_16,0,0,0,0 }, | 305 | [INSTR_S_RD] = { 0xff, D_20,B_16,0,0,0,0 }, |
301 | }; | 306 | }; |
302 | 307 | ||
308 | enum { | ||
309 | LONG_INSN_ALGHSIK, | ||
310 | LONG_INSN_ALHSIK, | ||
311 | LONG_INSN_CLFHSI, | ||
312 | LONG_INSN_CLGFRL, | ||
313 | LONG_INSN_CLGHRL, | ||
314 | LONG_INSN_CLGHSI, | ||
315 | LONG_INSN_CLHHSI, | ||
316 | LONG_INSN_LLGFRL, | ||
317 | LONG_INSN_LLGHRL, | ||
318 | LONG_INSN_POPCNT, | ||
319 | LONG_INSN_RISBHG, | ||
320 | LONG_INSN_RISBLG, | ||
321 | }; | ||
322 | |||
323 | static char *long_insn_name[] = { | ||
324 | [LONG_INSN_ALGHSIK] = "alghsik", | ||
325 | [LONG_INSN_ALHSIK] = "alhsik", | ||
326 | [LONG_INSN_CLFHSI] = "clfhsi", | ||
327 | [LONG_INSN_CLGFRL] = "clgfrl", | ||
328 | [LONG_INSN_CLGHRL] = "clghrl", | ||
329 | [LONG_INSN_CLGHSI] = "clghsi", | ||
330 | [LONG_INSN_CLHHSI] = "clhhsi", | ||
331 | [LONG_INSN_LLGFRL] = "llgfrl", | ||
332 | [LONG_INSN_LLGHRL] = "llghrl", | ||
333 | [LONG_INSN_POPCNT] = "popcnt", | ||
334 | [LONG_INSN_RISBHG] = "risbhg", | ||
335 | [LONG_INSN_RISBLG] = "risblk", | ||
336 | }; | ||
337 | |||
303 | static struct insn opcode[] = { | 338 | static struct insn opcode[] = { |
304 | #ifdef CONFIG_64BIT | 339 | #ifdef CONFIG_64BIT |
305 | { "lmd", 0xef, INSTR_SS_RRRDRD3 }, | 340 | { "lmd", 0xef, INSTR_SS_RRRDRD3 }, |
@@ -637,6 +672,7 @@ static struct insn opcode_b2[] = { | |||
637 | { "rp", 0x77, INSTR_S_RD }, | 672 | { "rp", 0x77, INSTR_S_RD }, |
638 | { "stcke", 0x78, INSTR_S_RD }, | 673 | { "stcke", 0x78, INSTR_S_RD }, |
639 | { "sacf", 0x79, INSTR_S_RD }, | 674 | { "sacf", 0x79, INSTR_S_RD }, |
675 | { "spp", 0x80, INSTR_S_RD }, | ||
640 | { "stsi", 0x7d, INSTR_S_RD }, | 676 | { "stsi", 0x7d, INSTR_S_RD }, |
641 | { "srnm", 0x99, INSTR_S_RD }, | 677 | { "srnm", 0x99, INSTR_S_RD }, |
642 | { "stfpc", 0x9c, INSTR_S_RD }, | 678 | { "stfpc", 0x9c, INSTR_S_RD }, |
@@ -881,6 +917,35 @@ static struct insn opcode_b9[] = { | |||
881 | { "pfmf", 0xaf, INSTR_RRE_RR }, | 917 | { "pfmf", 0xaf, INSTR_RRE_RR }, |
882 | { "trte", 0xbf, INSTR_RRF_M0RR }, | 918 | { "trte", 0xbf, INSTR_RRF_M0RR }, |
883 | { "trtre", 0xbd, INSTR_RRF_M0RR }, | 919 | { "trtre", 0xbd, INSTR_RRF_M0RR }, |
920 | { "ahhhr", 0xc8, INSTR_RRF_R0RR2 }, | ||
921 | { "shhhr", 0xc9, INSTR_RRF_R0RR2 }, | ||
922 | { "alhhh", 0xca, INSTR_RRF_R0RR2 }, | ||
923 | { "alhhl", 0xca, INSTR_RRF_R0RR2 }, | ||
924 | { "slhhh", 0xcb, INSTR_RRF_R0RR2 }, | ||
925 | { "chhr ", 0xcd, INSTR_RRE_RR }, | ||
926 | { "clhhr", 0xcf, INSTR_RRE_RR }, | ||
927 | { "ahhlr", 0xd8, INSTR_RRF_R0RR2 }, | ||
928 | { "shhlr", 0xd9, INSTR_RRF_R0RR2 }, | ||
929 | { "slhhl", 0xdb, INSTR_RRF_R0RR2 }, | ||
930 | { "chlr", 0xdd, INSTR_RRE_RR }, | ||
931 | { "clhlr", 0xdf, INSTR_RRE_RR }, | ||
932 | { { 0, LONG_INSN_POPCNT }, 0xe1, INSTR_RRE_RR }, | ||
933 | { "locgr", 0xe2, INSTR_RRF_M0RR }, | ||
934 | { "ngrk", 0xe4, INSTR_RRF_R0RR2 }, | ||
935 | { "ogrk", 0xe6, INSTR_RRF_R0RR2 }, | ||
936 | { "xgrk", 0xe7, INSTR_RRF_R0RR2 }, | ||
937 | { "agrk", 0xe8, INSTR_RRF_R0RR2 }, | ||
938 | { "sgrk", 0xe9, INSTR_RRF_R0RR2 }, | ||
939 | { "algrk", 0xea, INSTR_RRF_R0RR2 }, | ||
940 | { "slgrk", 0xeb, INSTR_RRF_R0RR2 }, | ||
941 | { "locr", 0xf2, INSTR_RRF_M0RR }, | ||
942 | { "nrk", 0xf4, INSTR_RRF_R0RR2 }, | ||
943 | { "ork", 0xf6, INSTR_RRF_R0RR2 }, | ||
944 | { "xrk", 0xf7, INSTR_RRF_R0RR2 }, | ||
945 | { "ark", 0xf8, INSTR_RRF_R0RR2 }, | ||
946 | { "srk", 0xf9, INSTR_RRF_R0RR2 }, | ||
947 | { "alrk", 0xfa, INSTR_RRF_R0RR2 }, | ||
948 | { "slrk", 0xfb, INSTR_RRF_R0RR2 }, | ||
884 | #endif | 949 | #endif |
885 | { "kmac", 0x1e, INSTR_RRE_RR }, | 950 | { "kmac", 0x1e, INSTR_RRE_RR }, |
886 | { "lrvr", 0x1f, INSTR_RRE_RR }, | 951 | { "lrvr", 0x1f, INSTR_RRE_RR }, |
@@ -949,9 +1014,9 @@ static struct insn opcode_c4[] = { | |||
949 | { "lgfrl", 0x0c, INSTR_RIL_RP }, | 1014 | { "lgfrl", 0x0c, INSTR_RIL_RP }, |
950 | { "lhrl", 0x05, INSTR_RIL_RP }, | 1015 | { "lhrl", 0x05, INSTR_RIL_RP }, |
951 | { "lghrl", 0x04, INSTR_RIL_RP }, | 1016 | { "lghrl", 0x04, INSTR_RIL_RP }, |
952 | { "llgfrl", 0x0e, INSTR_RIL_RP }, | 1017 | { { 0, LONG_INSN_LLGFRL }, 0x0e, INSTR_RIL_RP }, |
953 | { "llhrl", 0x02, INSTR_RIL_RP }, | 1018 | { "llhrl", 0x02, INSTR_RIL_RP }, |
954 | { "llghrl", 0x06, INSTR_RIL_RP }, | 1019 | { { 0, LONG_INSN_LLGHRL }, 0x06, INSTR_RIL_RP }, |
955 | { "strl", 0x0f, INSTR_RIL_RP }, | 1020 | { "strl", 0x0f, INSTR_RIL_RP }, |
956 | { "stgrl", 0x0b, INSTR_RIL_RP }, | 1021 | { "stgrl", 0x0b, INSTR_RIL_RP }, |
957 | { "sthrl", 0x07, INSTR_RIL_RP }, | 1022 | { "sthrl", 0x07, INSTR_RIL_RP }, |
@@ -968,9 +1033,9 @@ static struct insn opcode_c6[] = { | |||
968 | { "cghrl", 0x04, INSTR_RIL_RP }, | 1033 | { "cghrl", 0x04, INSTR_RIL_RP }, |
969 | { "clrl", 0x0f, INSTR_RIL_RP }, | 1034 | { "clrl", 0x0f, INSTR_RIL_RP }, |
970 | { "clgrl", 0x0a, INSTR_RIL_RP }, | 1035 | { "clgrl", 0x0a, INSTR_RIL_RP }, |
971 | { "clgfrl", 0x0e, INSTR_RIL_RP }, | 1036 | { { 0, LONG_INSN_CLGFRL }, 0x0e, INSTR_RIL_RP }, |
972 | { "clhrl", 0x07, INSTR_RIL_RP }, | 1037 | { "clhrl", 0x07, INSTR_RIL_RP }, |
973 | { "clghrl", 0x06, INSTR_RIL_RP }, | 1038 | { { 0, LONG_INSN_CLGHRL }, 0x06, INSTR_RIL_RP }, |
974 | { "pfdrl", 0x02, INSTR_RIL_UP }, | 1039 | { "pfdrl", 0x02, INSTR_RIL_UP }, |
975 | { "exrl", 0x00, INSTR_RIL_RP }, | 1040 | { "exrl", 0x00, INSTR_RIL_RP }, |
976 | #endif | 1041 | #endif |
@@ -982,6 +1047,20 @@ static struct insn opcode_c8[] = { | |||
982 | { "mvcos", 0x00, INSTR_SSF_RRDRD }, | 1047 | { "mvcos", 0x00, INSTR_SSF_RRDRD }, |
983 | { "ectg", 0x01, INSTR_SSF_RRDRD }, | 1048 | { "ectg", 0x01, INSTR_SSF_RRDRD }, |
984 | { "csst", 0x02, INSTR_SSF_RRDRD }, | 1049 | { "csst", 0x02, INSTR_SSF_RRDRD }, |
1050 | { "lpd", 0x04, INSTR_SSF_RRDRD2 }, | ||
1051 | { "lpdg ", 0x05, INSTR_SSF_RRDRD2 }, | ||
1052 | #endif | ||
1053 | { "", 0, INSTR_INVALID } | ||
1054 | }; | ||
1055 | |||
1056 | static struct insn opcode_cc[] = { | ||
1057 | #ifdef CONFIG_64BIT | ||
1058 | { "brcth", 0x06, INSTR_RIL_RP }, | ||
1059 | { "aih", 0x08, INSTR_RIL_RI }, | ||
1060 | { "alsih", 0x0a, INSTR_RIL_RI }, | ||
1061 | { "alsih", 0x0b, INSTR_RIL_RI }, | ||
1062 | { "cih", 0x0d, INSTR_RIL_RI }, | ||
1063 | { "clih ", 0x0f, INSTR_RIL_RI }, | ||
985 | #endif | 1064 | #endif |
986 | { "", 0, INSTR_INVALID } | 1065 | { "", 0, INSTR_INVALID } |
987 | }; | 1066 | }; |
@@ -1063,6 +1142,16 @@ static struct insn opcode_e3[] = { | |||
1063 | { "mfy", 0x5c, INSTR_RXY_RRRD }, | 1142 | { "mfy", 0x5c, INSTR_RXY_RRRD }, |
1064 | { "mhy", 0x7c, INSTR_RXY_RRRD }, | 1143 | { "mhy", 0x7c, INSTR_RXY_RRRD }, |
1065 | { "pfd", 0x36, INSTR_RXY_URRD }, | 1144 | { "pfd", 0x36, INSTR_RXY_URRD }, |
1145 | { "lbh", 0xc0, INSTR_RXY_RRRD }, | ||
1146 | { "llch", 0xc2, INSTR_RXY_RRRD }, | ||
1147 | { "stch", 0xc3, INSTR_RXY_RRRD }, | ||
1148 | { "lhh", 0xc4, INSTR_RXY_RRRD }, | ||
1149 | { "llhh", 0xc6, INSTR_RXY_RRRD }, | ||
1150 | { "sthh", 0xc7, INSTR_RXY_RRRD }, | ||
1151 | { "lfh", 0xca, INSTR_RXY_RRRD }, | ||
1152 | { "stfh", 0xcb, INSTR_RXY_RRRD }, | ||
1153 | { "chf", 0xcd, INSTR_RXY_RRRD }, | ||
1154 | { "clhf", 0xcf, INSTR_RXY_RRRD }, | ||
1066 | #endif | 1155 | #endif |
1067 | { "lrv", 0x1e, INSTR_RXY_RRRD }, | 1156 | { "lrv", 0x1e, INSTR_RXY_RRRD }, |
1068 | { "lrvh", 0x1f, INSTR_RXY_RRRD }, | 1157 | { "lrvh", 0x1f, INSTR_RXY_RRRD }, |
@@ -1080,9 +1169,9 @@ static struct insn opcode_e5[] = { | |||
1080 | { "chhsi", 0x54, INSTR_SIL_RDI }, | 1169 | { "chhsi", 0x54, INSTR_SIL_RDI }, |
1081 | { "chsi", 0x5c, INSTR_SIL_RDI }, | 1170 | { "chsi", 0x5c, INSTR_SIL_RDI }, |
1082 | { "cghsi", 0x58, INSTR_SIL_RDI }, | 1171 | { "cghsi", 0x58, INSTR_SIL_RDI }, |
1083 | { "clhhsi", 0x55, INSTR_SIL_RDU }, | 1172 | { { 0, LONG_INSN_CLHHSI }, 0x55, INSTR_SIL_RDU }, |
1084 | { "clfhsi", 0x5d, INSTR_SIL_RDU }, | 1173 | { { 0, LONG_INSN_CLFHSI }, 0x5d, INSTR_SIL_RDU }, |
1085 | { "clghsi", 0x59, INSTR_SIL_RDU }, | 1174 | { { 0, LONG_INSN_CLGHSI }, 0x59, INSTR_SIL_RDU }, |
1086 | { "mvhhi", 0x44, INSTR_SIL_RDI }, | 1175 | { "mvhhi", 0x44, INSTR_SIL_RDI }, |
1087 | { "mvhi", 0x4c, INSTR_SIL_RDI }, | 1176 | { "mvhi", 0x4c, INSTR_SIL_RDI }, |
1088 | { "mvghi", 0x48, INSTR_SIL_RDI }, | 1177 | { "mvghi", 0x48, INSTR_SIL_RDI }, |
@@ -1137,6 +1226,24 @@ static struct insn opcode_eb[] = { | |||
1137 | { "alsi", 0x6e, INSTR_SIY_IRD }, | 1226 | { "alsi", 0x6e, INSTR_SIY_IRD }, |
1138 | { "algsi", 0x7e, INSTR_SIY_IRD }, | 1227 | { "algsi", 0x7e, INSTR_SIY_IRD }, |
1139 | { "ecag", 0x4c, INSTR_RSY_RRRD }, | 1228 | { "ecag", 0x4c, INSTR_RSY_RRRD }, |
1229 | { "srak", 0xdc, INSTR_RSY_RRRD }, | ||
1230 | { "slak", 0xdd, INSTR_RSY_RRRD }, | ||
1231 | { "srlk", 0xde, INSTR_RSY_RRRD }, | ||
1232 | { "sllk", 0xdf, INSTR_RSY_RRRD }, | ||
1233 | { "locg", 0xe2, INSTR_RSY_RDRM }, | ||
1234 | { "stocg", 0xe3, INSTR_RSY_RDRM }, | ||
1235 | { "lang", 0xe4, INSTR_RSY_RRRD }, | ||
1236 | { "laog", 0xe6, INSTR_RSY_RRRD }, | ||
1237 | { "laxg", 0xe7, INSTR_RSY_RRRD }, | ||
1238 | { "laag", 0xe8, INSTR_RSY_RRRD }, | ||
1239 | { "laalg", 0xea, INSTR_RSY_RRRD }, | ||
1240 | { "loc", 0xf2, INSTR_RSY_RDRM }, | ||
1241 | { "stoc", 0xf3, INSTR_RSY_RDRM }, | ||
1242 | { "lan", 0xf4, INSTR_RSY_RRRD }, | ||
1243 | { "lao", 0xf6, INSTR_RSY_RRRD }, | ||
1244 | { "lax", 0xf7, INSTR_RSY_RRRD }, | ||
1245 | { "laa", 0xf8, INSTR_RSY_RRRD }, | ||
1246 | { "laal", 0xfa, INSTR_RSY_RRRD }, | ||
1140 | #endif | 1247 | #endif |
1141 | { "rll", 0x1d, INSTR_RSY_RRRD }, | 1248 | { "rll", 0x1d, INSTR_RSY_RRRD }, |
1142 | { "mvclu", 0x8e, INSTR_RSY_RRRD }, | 1249 | { "mvclu", 0x8e, INSTR_RSY_RRRD }, |
@@ -1172,6 +1279,12 @@ static struct insn opcode_ec[] = { | |||
1172 | { "rxsbg", 0x57, INSTR_RIE_RRUUU }, | 1279 | { "rxsbg", 0x57, INSTR_RIE_RRUUU }, |
1173 | { "rosbg", 0x56, INSTR_RIE_RRUUU }, | 1280 | { "rosbg", 0x56, INSTR_RIE_RRUUU }, |
1174 | { "risbg", 0x55, INSTR_RIE_RRUUU }, | 1281 | { "risbg", 0x55, INSTR_RIE_RRUUU }, |
1282 | { { 0, LONG_INSN_RISBLG }, 0x51, INSTR_RIE_RRUUU }, | ||
1283 | { { 0, LONG_INSN_RISBHG }, 0x5D, INSTR_RIE_RRUUU }, | ||
1284 | { "ahik", 0xd8, INSTR_RIE_RRI0 }, | ||
1285 | { "aghik", 0xd9, INSTR_RIE_RRI0 }, | ||
1286 | { { 0, LONG_INSN_ALHSIK }, 0xda, INSTR_RIE_RRI0 }, | ||
1287 | { { 0, LONG_INSN_ALGHSIK }, 0xdb, INSTR_RIE_RRI0 }, | ||
1175 | #endif | 1288 | #endif |
1176 | { "", 0, INSTR_INVALID } | 1289 | { "", 0, INSTR_INVALID } |
1177 | }; | 1290 | }; |
@@ -1321,6 +1434,9 @@ static struct insn *find_insn(unsigned char *code) | |||
1321 | case 0xc8: | 1434 | case 0xc8: |
1322 | table = opcode_c8; | 1435 | table = opcode_c8; |
1323 | break; | 1436 | break; |
1437 | case 0xcc: | ||
1438 | table = opcode_cc; | ||
1439 | break; | ||
1324 | case 0xe3: | 1440 | case 0xe3: |
1325 | table = opcode_e3; | 1441 | table = opcode_e3; |
1326 | opfrag = code[5]; | 1442 | opfrag = code[5]; |
@@ -1367,7 +1483,11 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr) | |||
1367 | ptr = buffer; | 1483 | ptr = buffer; |
1368 | insn = find_insn(code); | 1484 | insn = find_insn(code); |
1369 | if (insn) { | 1485 | if (insn) { |
1370 | ptr += sprintf(ptr, "%.5s\t", insn->name); | 1486 | if (insn->name[0] == '\0') |
1487 | ptr += sprintf(ptr, "%s\t", | ||
1488 | long_insn_name[(int) insn->name[1]]); | ||
1489 | else | ||
1490 | ptr += sprintf(ptr, "%.5s\t", insn->name); | ||
1371 | /* Extract the operands. */ | 1491 | /* Extract the operands. */ |
1372 | separator = 0; | 1492 | separator = 0; |
1373 | for (ops = formats[insn->format] + 1, i = 0; | 1493 | for (ops = formats[insn->format] + 1, i = 0; |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index c00856ad4e5a..068f8465c4ee 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -94,6 +94,7 @@ static noinline __init void create_kernel_nss(void) | |||
94 | unsigned int sinitrd_pfn, einitrd_pfn; | 94 | unsigned int sinitrd_pfn, einitrd_pfn; |
95 | #endif | 95 | #endif |
96 | int response; | 96 | int response; |
97 | int hlen; | ||
97 | size_t len; | 98 | size_t len; |
98 | char *savesys_ptr; | 99 | char *savesys_ptr; |
99 | char defsys_cmd[DEFSYS_CMD_SIZE]; | 100 | char defsys_cmd[DEFSYS_CMD_SIZE]; |
@@ -124,24 +125,27 @@ static noinline __init void create_kernel_nss(void) | |||
124 | end_pfn = PFN_UP(__pa(&_end)); | 125 | end_pfn = PFN_UP(__pa(&_end)); |
125 | min_size = end_pfn << 2; | 126 | min_size = end_pfn << 2; |
126 | 127 | ||
127 | sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X", | 128 | hlen = snprintf(defsys_cmd, DEFSYS_CMD_SIZE, |
128 | kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1, | 129 | "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X", |
129 | eshared_pfn, end_pfn); | 130 | kernel_nss_name, stext_pfn - 1, stext_pfn, |
131 | eshared_pfn - 1, eshared_pfn, end_pfn); | ||
130 | 132 | ||
131 | #ifdef CONFIG_BLK_DEV_INITRD | 133 | #ifdef CONFIG_BLK_DEV_INITRD |
132 | if (INITRD_START && INITRD_SIZE) { | 134 | if (INITRD_START && INITRD_SIZE) { |
133 | sinitrd_pfn = PFN_DOWN(__pa(INITRD_START)); | 135 | sinitrd_pfn = PFN_DOWN(__pa(INITRD_START)); |
134 | einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE)); | 136 | einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE)); |
135 | min_size = einitrd_pfn << 2; | 137 | min_size = einitrd_pfn << 2; |
136 | sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd, | 138 | hlen += snprintf(defsys_cmd + hlen, DEFSYS_CMD_SIZE - hlen, |
137 | sinitrd_pfn, einitrd_pfn); | 139 | " EW %.5X-%.5X", sinitrd_pfn, einitrd_pfn); |
138 | } | 140 | } |
139 | #endif | 141 | #endif |
140 | 142 | ||
141 | sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK PARMREGS=0-13", | 143 | snprintf(defsys_cmd + hlen, DEFSYS_CMD_SIZE - hlen, |
142 | defsys_cmd, min_size); | 144 | " EW MINSIZE=%.7iK PARMREGS=0-13", min_size); |
143 | sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", | 145 | defsys_cmd[DEFSYS_CMD_SIZE - 1] = '\0'; |
144 | kernel_nss_name, kernel_nss_name); | 146 | snprintf(savesys_cmd, SAVESYS_CMD_SIZE, "SAVESYS %s \n IPL %s", |
147 | kernel_nss_name, kernel_nss_name); | ||
148 | savesys_cmd[SAVESYS_CMD_SIZE - 1] = '\0'; | ||
145 | 149 | ||
146 | __cpcmd(defsys_cmd, NULL, 0, &response); | 150 | __cpcmd(defsys_cmd, NULL, 0, &response); |
147 | 151 | ||
@@ -208,7 +212,8 @@ static noinline __init void init_kernel_storage_key(void) | |||
208 | end_pfn = PFN_UP(__pa(&_end)); | 212 | end_pfn = PFN_UP(__pa(&_end)); |
209 | 213 | ||
210 | for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++) | 214 | for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++) |
211 | page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); | 215 | page_set_storage_key(init_pfn << PAGE_SHIFT, |
216 | PAGE_DEFAULT_KEY, 0); | ||
212 | } | 217 | } |
213 | 218 | ||
214 | static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE); | 219 | static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE); |
@@ -255,13 +260,33 @@ static noinline __init void setup_lowcore_early(void) | |||
255 | s390_base_pgm_handler_fn = early_pgm_check_handler; | 260 | s390_base_pgm_handler_fn = early_pgm_check_handler; |
256 | } | 261 | } |
257 | 262 | ||
263 | static noinline __init void setup_facility_list(void) | ||
264 | { | ||
265 | unsigned long nr; | ||
266 | |||
267 | S390_lowcore.stfl_fac_list = 0; | ||
268 | asm volatile( | ||
269 | " .insn s,0xb2b10000,0(0)\n" /* stfl */ | ||
270 | "0:\n" | ||
271 | EX_TABLE(0b,0b) : "=m" (S390_lowcore.stfl_fac_list)); | ||
272 | memcpy(&S390_lowcore.stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); | ||
273 | nr = 4; /* # bytes stored by stfl */ | ||
274 | if (test_facility(7)) { | ||
275 | /* More facility bits available with stfle */ | ||
276 | register unsigned long reg0 asm("0") = MAX_FACILITY_BIT/64 - 1; | ||
277 | asm volatile(".insn s,0xb2b00000,%0" /* stfle */ | ||
278 | : "=m" (S390_lowcore.stfle_fac_list), "+d" (reg0) | ||
279 | : : "cc"); | ||
280 | nr = (reg0 + 1) * 8; /* # bytes stored by stfle */ | ||
281 | } | ||
282 | memset((char *) S390_lowcore.stfle_fac_list + nr, 0, | ||
283 | MAX_FACILITY_BIT/8 - nr); | ||
284 | } | ||
285 | |||
258 | static noinline __init void setup_hpage(void) | 286 | static noinline __init void setup_hpage(void) |
259 | { | 287 | { |
260 | #ifndef CONFIG_DEBUG_PAGEALLOC | 288 | #ifndef CONFIG_DEBUG_PAGEALLOC |
261 | unsigned int facilities; | 289 | if (!test_facility(2) || !test_facility(8)) |
262 | |||
263 | facilities = stfl(); | ||
264 | if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29))) | ||
265 | return; | 290 | return; |
266 | S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; | 291 | S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; |
267 | __ctl_set_bit(0, 23); | 292 | __ctl_set_bit(0, 23); |
@@ -355,18 +380,15 @@ static __init void detect_diag44(void) | |||
355 | static __init void detect_machine_facilities(void) | 380 | static __init void detect_machine_facilities(void) |
356 | { | 381 | { |
357 | #ifdef CONFIG_64BIT | 382 | #ifdef CONFIG_64BIT |
358 | unsigned int facilities; | 383 | if (test_facility(3)) |
359 | unsigned long long facility_bits; | ||
360 | |||
361 | facilities = stfl(); | ||
362 | if (facilities & (1 << 28)) | ||
363 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; | 384 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; |
364 | if (facilities & (1 << 23)) | 385 | if (test_facility(8)) |
365 | S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; | 386 | S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; |
366 | if (facilities & (1 << 4)) | 387 | if (test_facility(11)) |
388 | S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY; | ||
389 | if (test_facility(27)) | ||
367 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; | 390 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; |
368 | if ((stfle(&facility_bits, 1) > 0) && | 391 | if (test_facility(40)) |
369 | (facility_bits & (1ULL << (63 - 40)))) | ||
370 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; | 392 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; |
371 | #endif | 393 | #endif |
372 | } | 394 | } |
@@ -447,6 +469,7 @@ void __init startup_init(void) | |||
447 | lockdep_off(); | 469 | lockdep_off(); |
448 | sort_main_extable(); | 470 | sort_main_extable(); |
449 | setup_lowcore_early(); | 471 | setup_lowcore_early(); |
472 | setup_facility_list(); | ||
450 | detect_machine_type(); | 473 | detect_machine_type(); |
451 | ipl_update_parameters(); | 474 | ipl_update_parameters(); |
452 | setup_boot_command_line(); | 475 | setup_boot_command_line(); |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index bea9ee37ac9d..0476174dfff5 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -9,7 +9,6 @@ | |||
9 | * Heiko Carstens <heiko.carstens@de.ibm.com> | 9 | * Heiko Carstens <heiko.carstens@de.ibm.com> |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/sys.h> | ||
13 | #include <linux/linkage.h> | 12 | #include <linux/linkage.h> |
14 | #include <linux/init.h> | 13 | #include <linux/init.h> |
15 | #include <asm/cache.h> | 14 | #include <asm/cache.h> |
@@ -49,7 +48,7 @@ SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR | |||
49 | SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE | 48 | SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE |
50 | 49 | ||
51 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | 50 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
52 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) | 51 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP ) |
53 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | 52 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
54 | _TIF_MCCK_PENDING) | 53 | _TIF_MCCK_PENDING) |
55 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | 54 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ |
@@ -72,25 +71,9 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
72 | l %r1,BASED(.Ltrace_irq_off_caller) | 71 | l %r1,BASED(.Ltrace_irq_off_caller) |
73 | basr %r14,%r1 | 72 | basr %r14,%r1 |
74 | .endm | 73 | .endm |
75 | |||
76 | .macro TRACE_IRQS_CHECK_ON | ||
77 | tm SP_PSW(%r15),0x03 # irqs enabled? | ||
78 | bz BASED(0f) | ||
79 | TRACE_IRQS_ON | ||
80 | 0: | ||
81 | .endm | ||
82 | |||
83 | .macro TRACE_IRQS_CHECK_OFF | ||
84 | tm SP_PSW(%r15),0x03 # irqs enabled? | ||
85 | bz BASED(0f) | ||
86 | TRACE_IRQS_OFF | ||
87 | 0: | ||
88 | .endm | ||
89 | #else | 74 | #else |
90 | #define TRACE_IRQS_ON | 75 | #define TRACE_IRQS_ON |
91 | #define TRACE_IRQS_OFF | 76 | #define TRACE_IRQS_OFF |
92 | #define TRACE_IRQS_CHECK_ON | ||
93 | #define TRACE_IRQS_CHECK_OFF | ||
94 | #endif | 77 | #endif |
95 | 78 | ||
96 | #ifdef CONFIG_LOCKDEP | 79 | #ifdef CONFIG_LOCKDEP |
@@ -126,31 +109,36 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
126 | 1: stm %r10,%r11,\lc_sum | 109 | 1: stm %r10,%r11,\lc_sum |
127 | .endm | 110 | .endm |
128 | 111 | ||
129 | .macro SAVE_ALL_BASE savearea | 112 | .macro SAVE_ALL_SVC psworg,savearea |
130 | stm %r12,%r15,\savearea | 113 | stm %r12,%r15,\savearea |
131 | l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 | 114 | l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 |
115 | l %r15,__LC_KERNEL_STACK # problem state -> load ksp | ||
116 | s %r15,BASED(.Lc_spsize) # make room for registers & psw | ||
132 | .endm | 117 | .endm |
133 | 118 | ||
134 | .macro SAVE_ALL_SVC psworg,savearea | 119 | .macro SAVE_ALL_BASE savearea |
135 | la %r12,\psworg | 120 | stm %r12,%r15,\savearea |
136 | l %r15,__LC_KERNEL_STACK # problem state -> load ksp | 121 | l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 |
137 | .endm | 122 | .endm |
138 | 123 | ||
139 | .macro SAVE_ALL_SYNC psworg,savearea | 124 | .macro SAVE_ALL_PGM psworg,savearea |
140 | la %r12,\psworg | ||
141 | tm \psworg+1,0x01 # test problem state bit | 125 | tm \psworg+1,0x01 # test problem state bit |
142 | bz BASED(2f) # skip stack setup save | ||
143 | l %r15,__LC_KERNEL_STACK # problem state -> load ksp | ||
144 | #ifdef CONFIG_CHECK_STACK | 126 | #ifdef CONFIG_CHECK_STACK |
145 | b BASED(3f) | 127 | bnz BASED(1f) |
146 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | 128 | tml %r15,STACK_SIZE - CONFIG_STACK_GUARD |
147 | bz BASED(stack_overflow) | 129 | bnz BASED(2f) |
148 | 3: | 130 | la %r12,\psworg |
131 | b BASED(stack_overflow) | ||
132 | #else | ||
133 | bz BASED(2f) | ||
149 | #endif | 134 | #endif |
150 | 2: | 135 | 1: l %r15,__LC_KERNEL_STACK # problem state -> load ksp |
136 | 2: s %r15,BASED(.Lc_spsize) # make room for registers & psw | ||
151 | .endm | 137 | .endm |
152 | 138 | ||
153 | .macro SAVE_ALL_ASYNC psworg,savearea | 139 | .macro SAVE_ALL_ASYNC psworg,savearea |
140 | stm %r12,%r15,\savearea | ||
141 | l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 | ||
154 | la %r12,\psworg | 142 | la %r12,\psworg |
155 | tm \psworg+1,0x01 # test problem state bit | 143 | tm \psworg+1,0x01 # test problem state bit |
156 | bnz BASED(1f) # from user -> load async stack | 144 | bnz BASED(1f) # from user -> load async stack |
@@ -165,27 +153,23 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
165 | 0: l %r14,__LC_ASYNC_STACK # are we already on the async stack ? | 153 | 0: l %r14,__LC_ASYNC_STACK # are we already on the async stack ? |
166 | slr %r14,%r15 | 154 | slr %r14,%r15 |
167 | sra %r14,STACK_SHIFT | 155 | sra %r14,STACK_SHIFT |
168 | be BASED(2f) | ||
169 | 1: l %r15,__LC_ASYNC_STACK | ||
170 | #ifdef CONFIG_CHECK_STACK | 156 | #ifdef CONFIG_CHECK_STACK |
171 | b BASED(3f) | 157 | bnz BASED(1f) |
172 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | 158 | tml %r15,STACK_SIZE - CONFIG_STACK_GUARD |
173 | bz BASED(stack_overflow) | 159 | bnz BASED(2f) |
174 | 3: | 160 | b BASED(stack_overflow) |
161 | #else | ||
162 | bz BASED(2f) | ||
175 | #endif | 163 | #endif |
176 | 2: | 164 | 1: l %r15,__LC_ASYNC_STACK |
165 | 2: s %r15,BASED(.Lc_spsize) # make room for registers & psw | ||
177 | .endm | 166 | .endm |
178 | 167 | ||
179 | .macro CREATE_STACK_FRAME psworg,savearea | 168 | .macro CREATE_STACK_FRAME savearea |
180 | s %r15,BASED(.Lc_spsize) # make room for registers & psw | 169 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
181 | mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack | ||
182 | st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 | 170 | st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 |
183 | icm %r12,12,__LC_SVC_ILC | ||
184 | stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack | ||
185 | st %r12,SP_ILC(%r15) | ||
186 | mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack | 171 | mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack |
187 | la %r12,0 | 172 | stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack |
188 | st %r12,__SF_BACKCHAIN(%r15) # clear back chain | ||
189 | .endm | 173 | .endm |
190 | 174 | ||
191 | .macro RESTORE_ALL psworg,sync | 175 | .macro RESTORE_ALL psworg,sync |
@@ -198,6 +182,14 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
198 | lpsw \psworg # back to caller | 182 | lpsw \psworg # back to caller |
199 | .endm | 183 | .endm |
200 | 184 | ||
185 | .macro REENABLE_IRQS | ||
186 | mvc __SF_EMPTY(1,%r15),SP_PSW(%r15) | ||
187 | ni __SF_EMPTY(%r15),0xbf | ||
188 | ssm __SF_EMPTY(%r15) | ||
189 | .endm | ||
190 | |||
191 | .section .kprobes.text, "ax" | ||
192 | |||
201 | /* | 193 | /* |
202 | * Scheduler resume function, called by switch_to | 194 | * Scheduler resume function, called by switch_to |
203 | * gpr2 = (task_struct *) prev | 195 | * gpr2 = (task_struct *) prev |
@@ -208,31 +200,22 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
208 | .globl __switch_to | 200 | .globl __switch_to |
209 | __switch_to: | 201 | __switch_to: |
210 | basr %r1,0 | 202 | basr %r1,0 |
211 | __switch_to_base: | 203 | 0: l %r4,__THREAD_info(%r2) # get thread_info of prev |
212 | tm __THREAD_per(%r3),0xe8 # new process is using per ? | 204 | l %r5,__THREAD_info(%r3) # get thread_info of next |
213 | bz __switch_to_noper-__switch_to_base(%r1) # if not we're fine | ||
214 | stctl %c9,%c11,__SF_EMPTY(%r15) # We are using per stuff | ||
215 | clc __THREAD_per(12,%r3),__SF_EMPTY(%r15) | ||
216 | be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's | ||
217 | lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't | ||
218 | __switch_to_noper: | ||
219 | l %r4,__THREAD_info(%r2) # get thread_info of prev | ||
220 | tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending? | 205 | tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending? |
221 | bz __switch_to_no_mcck-__switch_to_base(%r1) | 206 | bz 1f-0b(%r1) |
222 | ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev | 207 | ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev |
223 | l %r4,__THREAD_info(%r3) # get thread_info of next | 208 | oi __TI_flags+3(%r5),_TIF_MCCK_PENDING # set it in next |
224 | oi __TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next | 209 | 1: stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task |
225 | __switch_to_no_mcck: | 210 | st %r15,__THREAD_ksp(%r2) # store kernel stack of prev |
226 | stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task | 211 | l %r15,__THREAD_ksp(%r3) # load kernel stack of next |
227 | st %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp | 212 | lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 |
228 | l %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp | 213 | lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task |
229 | lm %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task | 214 | st %r3,__LC_CURRENT # store task struct of next |
230 | st %r3,__LC_CURRENT # __LC_CURRENT = current task struct | 215 | mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next |
231 | lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 | 216 | st %r5,__LC_THREAD_INFO # store thread info of next |
232 | l %r3,__THREAD_info(%r3) # load thread_info from task struct | 217 | ahi %r5,STACK_SIZE # end of kernel stack of next |
233 | st %r3,__LC_THREAD_INFO | 218 | st %r5,__LC_KERNEL_STACK # store end of kernel stack |
234 | ahi %r3,STACK_SIZE | ||
235 | st %r3,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack | ||
236 | br %r14 | 219 | br %r14 |
237 | 220 | ||
238 | __critical_start: | 221 | __critical_start: |
@@ -245,10 +228,11 @@ __critical_start: | |||
245 | system_call: | 228 | system_call: |
246 | stpt __LC_SYNC_ENTER_TIMER | 229 | stpt __LC_SYNC_ENTER_TIMER |
247 | sysc_saveall: | 230 | sysc_saveall: |
248 | SAVE_ALL_BASE __LC_SAVE_AREA | ||
249 | SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 231 | SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
250 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 232 | CREATE_STACK_FRAME __LC_SAVE_AREA |
251 | lh %r7,0x8a # get svc number from lowcore | 233 | mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW |
234 | mvc SP_ILC(4,%r15),__LC_SVC_ILC | ||
235 | l %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
252 | sysc_vtime: | 236 | sysc_vtime: |
253 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 237 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
254 | sysc_stime: | 238 | sysc_stime: |
@@ -256,21 +240,20 @@ sysc_stime: | |||
256 | sysc_update: | 240 | sysc_update: |
257 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 241 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
258 | sysc_do_svc: | 242 | sysc_do_svc: |
259 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 243 | xr %r7,%r7 |
260 | ltr %r7,%r7 # test for svc 0 | 244 | icm %r7,3,SP_SVCNR(%r15) # load svc number and test for svc 0 |
261 | bnz BASED(sysc_nr_ok) # svc number > 0 | 245 | bnz BASED(sysc_nr_ok) # svc number > 0 |
262 | # svc 0: system call number in %r1 | 246 | # svc 0: system call number in %r1 |
263 | cl %r1,BASED(.Lnr_syscalls) | 247 | cl %r1,BASED(.Lnr_syscalls) |
264 | bnl BASED(sysc_nr_ok) | 248 | bnl BASED(sysc_nr_ok) |
249 | sth %r1,SP_SVCNR(%r15) | ||
265 | lr %r7,%r1 # copy svc number to %r7 | 250 | lr %r7,%r1 # copy svc number to %r7 |
266 | sysc_nr_ok: | 251 | sysc_nr_ok: |
267 | mvc SP_ARGS(4,%r15),SP_R7(%r15) | ||
268 | sysc_do_restart: | ||
269 | sth %r7,SP_SVCNR(%r15) | ||
270 | sll %r7,2 # svc number *4 | 252 | sll %r7,2 # svc number *4 |
271 | l %r8,BASED(.Lsysc_table) | 253 | l %r10,BASED(.Lsysc_table) |
272 | tm __TI_flags+2(%r9),_TIF_SYSCALL | 254 | tm __TI_flags+2(%r12),_TIF_SYSCALL |
273 | l %r8,0(%r7,%r8) # get system call addr. | 255 | mvc SP_ARGS(4,%r15),SP_R7(%r15) |
256 | l %r8,0(%r7,%r10) # get system call addr. | ||
274 | bnz BASED(sysc_tracesys) | 257 | bnz BASED(sysc_tracesys) |
275 | basr %r14,%r8 # call sys_xxxx | 258 | basr %r14,%r8 # call sys_xxxx |
276 | st %r2,SP_R2(%r15) # store return value (change R2 on stack) | 259 | st %r2,SP_R2(%r15) # store return value (change R2 on stack) |
@@ -278,7 +261,7 @@ sysc_do_restart: | |||
278 | sysc_return: | 261 | sysc_return: |
279 | LOCKDEP_SYS_EXIT | 262 | LOCKDEP_SYS_EXIT |
280 | sysc_tif: | 263 | sysc_tif: |
281 | tm __TI_flags+3(%r9),_TIF_WORK_SVC | 264 | tm __TI_flags+3(%r12),_TIF_WORK_SVC |
282 | bnz BASED(sysc_work) # there is work to do (signals etc.) | 265 | bnz BASED(sysc_work) # there is work to do (signals etc.) |
283 | sysc_restore: | 266 | sysc_restore: |
284 | RESTORE_ALL __LC_RETURN_PSW,1 | 267 | RESTORE_ALL __LC_RETURN_PSW,1 |
@@ -295,17 +278,17 @@ sysc_work: | |||
295 | # One of the work bits is on. Find out which one. | 278 | # One of the work bits is on. Find out which one. |
296 | # | 279 | # |
297 | sysc_work_tif: | 280 | sysc_work_tif: |
298 | tm __TI_flags+3(%r9),_TIF_MCCK_PENDING | 281 | tm __TI_flags+3(%r12),_TIF_MCCK_PENDING |
299 | bo BASED(sysc_mcck_pending) | 282 | bo BASED(sysc_mcck_pending) |
300 | tm __TI_flags+3(%r9),_TIF_NEED_RESCHED | 283 | tm __TI_flags+3(%r12),_TIF_NEED_RESCHED |
301 | bo BASED(sysc_reschedule) | 284 | bo BASED(sysc_reschedule) |
302 | tm __TI_flags+3(%r9),_TIF_SIGPENDING | 285 | tm __TI_flags+3(%r12),_TIF_SIGPENDING |
303 | bo BASED(sysc_sigpending) | 286 | bo BASED(sysc_sigpending) |
304 | tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME | 287 | tm __TI_flags+3(%r12),_TIF_NOTIFY_RESUME |
305 | bo BASED(sysc_notify_resume) | 288 | bo BASED(sysc_notify_resume) |
306 | tm __TI_flags+3(%r9),_TIF_RESTART_SVC | 289 | tm __TI_flags+3(%r12),_TIF_RESTART_SVC |
307 | bo BASED(sysc_restart) | 290 | bo BASED(sysc_restart) |
308 | tm __TI_flags+3(%r9),_TIF_SINGLE_STEP | 291 | tm __TI_flags+3(%r12),_TIF_PER_TRAP |
309 | bo BASED(sysc_singlestep) | 292 | bo BASED(sysc_singlestep) |
310 | b BASED(sysc_return) # beware of critical section cleanup | 293 | b BASED(sysc_return) # beware of critical section cleanup |
311 | 294 | ||
@@ -329,13 +312,13 @@ sysc_mcck_pending: | |||
329 | # _TIF_SIGPENDING is set, call do_signal | 312 | # _TIF_SIGPENDING is set, call do_signal |
330 | # | 313 | # |
331 | sysc_sigpending: | 314 | sysc_sigpending: |
332 | ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP | 315 | ni __TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP |
333 | la %r2,SP_PTREGS(%r15) # load pt_regs | 316 | la %r2,SP_PTREGS(%r15) # load pt_regs |
334 | l %r1,BASED(.Ldo_signal) | 317 | l %r1,BASED(.Ldo_signal) |
335 | basr %r14,%r1 # call do_signal | 318 | basr %r14,%r1 # call do_signal |
336 | tm __TI_flags+3(%r9),_TIF_RESTART_SVC | 319 | tm __TI_flags+3(%r12),_TIF_RESTART_SVC |
337 | bo BASED(sysc_restart) | 320 | bo BASED(sysc_restart) |
338 | tm __TI_flags+3(%r9),_TIF_SINGLE_STEP | 321 | tm __TI_flags+3(%r12),_TIF_PER_TRAP |
339 | bo BASED(sysc_singlestep) | 322 | bo BASED(sysc_singlestep) |
340 | b BASED(sysc_return) | 323 | b BASED(sysc_return) |
341 | 324 | ||
@@ -353,23 +336,23 @@ sysc_notify_resume: | |||
353 | # _TIF_RESTART_SVC is set, set up registers and restart svc | 336 | # _TIF_RESTART_SVC is set, set up registers and restart svc |
354 | # | 337 | # |
355 | sysc_restart: | 338 | sysc_restart: |
356 | ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC | 339 | ni __TI_flags+3(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC |
357 | l %r7,SP_R2(%r15) # load new svc number | 340 | l %r7,SP_R2(%r15) # load new svc number |
358 | mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument | 341 | mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument |
359 | lm %r2,%r6,SP_R2(%r15) # load svc arguments | 342 | lm %r2,%r6,SP_R2(%r15) # load svc arguments |
360 | b BASED(sysc_do_restart) # restart svc | 343 | sth %r7,SP_SVCNR(%r15) |
344 | b BASED(sysc_nr_ok) # restart svc | ||
361 | 345 | ||
362 | # | 346 | # |
363 | # _TIF_SINGLE_STEP is set, call do_single_step | 347 | # _TIF_PER_TRAP is set, call do_per_trap |
364 | # | 348 | # |
365 | sysc_singlestep: | 349 | sysc_singlestep: |
366 | ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP | 350 | ni __TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP |
367 | mvi SP_SVCNR(%r15),0xff # set trap indication to pgm check | 351 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number |
368 | mvi SP_SVCNR+1(%r15),0xff | ||
369 | la %r2,SP_PTREGS(%r15) # address of register-save area | 352 | la %r2,SP_PTREGS(%r15) # address of register-save area |
370 | l %r1,BASED(.Lhandle_per) # load adr. of per handler | 353 | l %r1,BASED(.Lhandle_per) # load adr. of per handler |
371 | la %r14,BASED(sysc_return) # load adr. of system return | 354 | la %r14,BASED(sysc_return) # load adr. of system return |
372 | br %r1 # branch to do_single_step | 355 | br %r1 # branch to do_per_trap |
373 | 356 | ||
374 | # | 357 | # |
375 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before | 358 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before |
@@ -379,22 +362,23 @@ sysc_tracesys: | |||
379 | l %r1,BASED(.Ltrace_entry) | 362 | l %r1,BASED(.Ltrace_entry) |
380 | la %r2,SP_PTREGS(%r15) # load pt_regs | 363 | la %r2,SP_PTREGS(%r15) # load pt_regs |
381 | la %r3,0 | 364 | la %r3,0 |
382 | srl %r7,2 | 365 | xr %r0,%r0 |
383 | st %r7,SP_R2(%r15) | 366 | icm %r0,3,SP_SVCNR(%r15) |
367 | st %r0,SP_R2(%r15) | ||
384 | basr %r14,%r1 | 368 | basr %r14,%r1 |
385 | cl %r2,BASED(.Lnr_syscalls) | 369 | cl %r2,BASED(.Lnr_syscalls) |
386 | bnl BASED(sysc_tracenogo) | 370 | bnl BASED(sysc_tracenogo) |
387 | l %r8,BASED(.Lsysc_table) | ||
388 | lr %r7,%r2 | 371 | lr %r7,%r2 |
389 | sll %r7,2 # svc number *4 | 372 | sll %r7,2 # svc number *4 |
390 | l %r8,0(%r7,%r8) | 373 | l %r8,0(%r7,%r10) |
391 | sysc_tracego: | 374 | sysc_tracego: |
392 | lm %r3,%r6,SP_R3(%r15) | 375 | lm %r3,%r6,SP_R3(%r15) |
376 | mvc SP_ARGS(4,%r15),SP_R7(%r15) | ||
393 | l %r2,SP_ORIG_R2(%r15) | 377 | l %r2,SP_ORIG_R2(%r15) |
394 | basr %r14,%r8 # call sys_xxx | 378 | basr %r14,%r8 # call sys_xxx |
395 | st %r2,SP_R2(%r15) # store return value | 379 | st %r2,SP_R2(%r15) # store return value |
396 | sysc_tracenogo: | 380 | sysc_tracenogo: |
397 | tm __TI_flags+2(%r9),_TIF_SYSCALL | 381 | tm __TI_flags+2(%r12),_TIF_SYSCALL |
398 | bz BASED(sysc_return) | 382 | bz BASED(sysc_return) |
399 | l %r1,BASED(.Ltrace_exit) | 383 | l %r1,BASED(.Ltrace_exit) |
400 | la %r2,SP_PTREGS(%r15) # load pt_regs | 384 | la %r2,SP_PTREGS(%r15) # load pt_regs |
@@ -407,7 +391,7 @@ sysc_tracenogo: | |||
407 | .globl ret_from_fork | 391 | .globl ret_from_fork |
408 | ret_from_fork: | 392 | ret_from_fork: |
409 | l %r13,__LC_SVC_NEW_PSW+4 | 393 | l %r13,__LC_SVC_NEW_PSW+4 |
410 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 394 | l %r12,__LC_THREAD_INFO # load pointer to thread_info struct |
411 | tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? | 395 | tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? |
412 | bo BASED(0f) | 396 | bo BASED(0f) |
413 | st %r15,SP_R15(%r15) # store stack pointer for new kthread | 397 | st %r15,SP_R15(%r15) # store stack pointer for new kthread |
@@ -440,13 +424,11 @@ kernel_execve: | |||
440 | br %r14 | 424 | br %r14 |
441 | # execve succeeded. | 425 | # execve succeeded. |
442 | 0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts | 426 | 0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts |
443 | TRACE_IRQS_OFF | ||
444 | l %r15,__LC_KERNEL_STACK # load ksp | 427 | l %r15,__LC_KERNEL_STACK # load ksp |
445 | s %r15,BASED(.Lc_spsize) # make room for registers & psw | 428 | s %r15,BASED(.Lc_spsize) # make room for registers & psw |
446 | l %r9,__LC_THREAD_INFO | ||
447 | mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs | 429 | mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs |
430 | l %r12,__LC_THREAD_INFO | ||
448 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | 431 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
449 | TRACE_IRQS_ON | ||
450 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 432 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
451 | l %r1,BASED(.Lexecve_tail) | 433 | l %r1,BASED(.Lexecve_tail) |
452 | basr %r14,%r1 | 434 | basr %r14,%r1 |
@@ -475,27 +457,28 @@ pgm_check_handler: | |||
475 | SAVE_ALL_BASE __LC_SAVE_AREA | 457 | SAVE_ALL_BASE __LC_SAVE_AREA |
476 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception | 458 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception |
477 | bnz BASED(pgm_per) # got per exception -> special case | 459 | bnz BASED(pgm_per) # got per exception -> special case |
478 | SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 460 | SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
479 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 461 | CREATE_STACK_FRAME __LC_SAVE_AREA |
462 | xc SP_ILC(4,%r15),SP_ILC(%r15) | ||
463 | mvc SP_PSW(8,%r15),__LC_PGM_OLD_PSW | ||
464 | l %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
480 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 465 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
481 | bz BASED(pgm_no_vtime) | 466 | bz BASED(pgm_no_vtime) |
482 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 467 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
483 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 468 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
484 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 469 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
485 | pgm_no_vtime: | 470 | pgm_no_vtime: |
486 | TRACE_IRQS_CHECK_OFF | ||
487 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | ||
488 | l %r3,__LC_PGM_ILC # load program interruption code | 471 | l %r3,__LC_PGM_ILC # load program interruption code |
472 | l %r4,__LC_TRANS_EXC_CODE | ||
473 | REENABLE_IRQS | ||
489 | la %r8,0x7f | 474 | la %r8,0x7f |
490 | nr %r8,%r3 | 475 | nr %r8,%r3 |
491 | pgm_do_call: | ||
492 | l %r7,BASED(.Ljump_table) | ||
493 | sll %r8,2 | 476 | sll %r8,2 |
494 | l %r7,0(%r8,%r7) # load address of handler routine | 477 | l %r1,BASED(.Ljump_table) |
478 | l %r1,0(%r8,%r1) # load address of handler routine | ||
495 | la %r2,SP_PTREGS(%r15) # address of register-save area | 479 | la %r2,SP_PTREGS(%r15) # address of register-save area |
496 | basr %r14,%r7 # branch to interrupt-handler | 480 | basr %r14,%r1 # branch to interrupt-handler |
497 | pgm_exit: | 481 | pgm_exit: |
498 | TRACE_IRQS_CHECK_ON | ||
499 | b BASED(sysc_return) | 482 | b BASED(sysc_return) |
500 | 483 | ||
501 | # | 484 | # |
@@ -515,55 +498,54 @@ pgm_per: | |||
515 | # Normal per exception | 498 | # Normal per exception |
516 | # | 499 | # |
517 | pgm_per_std: | 500 | pgm_per_std: |
518 | SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 501 | SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
519 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 502 | CREATE_STACK_FRAME __LC_SAVE_AREA |
503 | mvc SP_PSW(8,%r15),__LC_PGM_OLD_PSW | ||
504 | l %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
520 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 505 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
521 | bz BASED(pgm_no_vtime2) | 506 | bz BASED(pgm_no_vtime2) |
522 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 507 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
523 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 508 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
524 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 509 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
525 | pgm_no_vtime2: | 510 | pgm_no_vtime2: |
526 | TRACE_IRQS_CHECK_OFF | 511 | l %r1,__TI_task(%r12) |
527 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | ||
528 | l %r1,__TI_task(%r9) | ||
529 | tm SP_PSW+1(%r15),0x01 # kernel per event ? | 512 | tm SP_PSW+1(%r15),0x01 # kernel per event ? |
530 | bz BASED(kernel_per) | 513 | bz BASED(kernel_per) |
531 | mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID | 514 | mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE |
532 | mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS | 515 | mvc __THREAD_per_address(4,%r1),__LC_PER_ADDRESS |
533 | mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID | 516 | mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID |
534 | oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP | 517 | oi __TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP |
535 | l %r3,__LC_PGM_ILC # load program interruption code | 518 | l %r3,__LC_PGM_ILC # load program interruption code |
519 | l %r4,__LC_TRANS_EXC_CODE | ||
520 | REENABLE_IRQS | ||
536 | la %r8,0x7f | 521 | la %r8,0x7f |
537 | nr %r8,%r3 # clear per-event-bit and ilc | 522 | nr %r8,%r3 # clear per-event-bit and ilc |
538 | be BASED(pgm_exit2) # only per or per+check ? | 523 | be BASED(pgm_exit2) # only per or per+check ? |
539 | l %r7,BASED(.Ljump_table) | ||
540 | sll %r8,2 | 524 | sll %r8,2 |
541 | l %r7,0(%r8,%r7) # load address of handler routine | 525 | l %r1,BASED(.Ljump_table) |
526 | l %r1,0(%r8,%r1) # load address of handler routine | ||
542 | la %r2,SP_PTREGS(%r15) # address of register-save area | 527 | la %r2,SP_PTREGS(%r15) # address of register-save area |
543 | basr %r14,%r7 # branch to interrupt-handler | 528 | basr %r14,%r1 # branch to interrupt-handler |
544 | pgm_exit2: | 529 | pgm_exit2: |
545 | TRACE_IRQS_ON | ||
546 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | ||
547 | b BASED(sysc_return) | 530 | b BASED(sysc_return) |
548 | 531 | ||
549 | # | 532 | # |
550 | # it was a single stepped SVC that is causing all the trouble | 533 | # it was a single stepped SVC that is causing all the trouble |
551 | # | 534 | # |
552 | pgm_svcper: | 535 | pgm_svcper: |
553 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 536 | SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
554 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 537 | CREATE_STACK_FRAME __LC_SAVE_AREA |
538 | mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW | ||
539 | mvc SP_ILC(4,%r15),__LC_SVC_ILC | ||
540 | l %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
555 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 541 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
556 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 542 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
557 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 543 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
558 | lh %r7,0x8a # get svc number from lowcore | 544 | l %r8,__TI_task(%r12) |
559 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 545 | mvc __THREAD_per_cause(2,%r8),__LC_PER_CAUSE |
560 | TRACE_IRQS_OFF | 546 | mvc __THREAD_per_address(4,%r8),__LC_PER_ADDRESS |
561 | l %r8,__TI_task(%r9) | 547 | mvc __THREAD_per_paid(1,%r8),__LC_PER_PAID |
562 | mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID | 548 | oi __TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP |
563 | mvc __THREAD_per+__PER_address(4,%r8),__LC_PER_ADDRESS | ||
564 | mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID | ||
565 | oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP | ||
566 | TRACE_IRQS_ON | ||
567 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 549 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
568 | lm %r2,%r6,SP_R2(%r15) # load svc arguments | 550 | lm %r2,%r6,SP_R2(%r15) # load svc arguments |
569 | b BASED(sysc_do_svc) | 551 | b BASED(sysc_do_svc) |
@@ -572,8 +554,8 @@ pgm_svcper: | |||
572 | # per was called from kernel, must be kprobes | 554 | # per was called from kernel, must be kprobes |
573 | # | 555 | # |
574 | kernel_per: | 556 | kernel_per: |
575 | mvi SP_SVCNR(%r15),0xff # set trap indication to pgm check | 557 | REENABLE_IRQS |
576 | mvi SP_SVCNR+1(%r15),0xff | 558 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) |
577 | la %r2,SP_PTREGS(%r15) # address of register-save area | 559 | la %r2,SP_PTREGS(%r15) # address of register-save area |
578 | l %r1,BASED(.Lhandle_per) # load adr. of per handler | 560 | l %r1,BASED(.Lhandle_per) # load adr. of per handler |
579 | basr %r14,%r1 # branch to do_single_step | 561 | basr %r14,%r1 # branch to do_single_step |
@@ -587,9 +569,10 @@ kernel_per: | |||
587 | io_int_handler: | 569 | io_int_handler: |
588 | stck __LC_INT_CLOCK | 570 | stck __LC_INT_CLOCK |
589 | stpt __LC_ASYNC_ENTER_TIMER | 571 | stpt __LC_ASYNC_ENTER_TIMER |
590 | SAVE_ALL_BASE __LC_SAVE_AREA+16 | ||
591 | SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 | 572 | SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 |
592 | CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 | 573 | CREATE_STACK_FRAME __LC_SAVE_AREA+16 |
574 | mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack | ||
575 | l %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
593 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 576 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
594 | bz BASED(io_no_vtime) | 577 | bz BASED(io_no_vtime) |
595 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 578 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER |
@@ -597,7 +580,6 @@ io_int_handler: | |||
597 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | 580 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER |
598 | io_no_vtime: | 581 | io_no_vtime: |
599 | TRACE_IRQS_OFF | 582 | TRACE_IRQS_OFF |
600 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | ||
601 | l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ | 583 | l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ |
602 | la %r2,SP_PTREGS(%r15) # address of register-save area | 584 | la %r2,SP_PTREGS(%r15) # address of register-save area |
603 | basr %r14,%r1 # branch to standard irq handler | 585 | basr %r14,%r1 # branch to standard irq handler |
@@ -605,7 +587,7 @@ io_return: | |||
605 | LOCKDEP_SYS_EXIT | 587 | LOCKDEP_SYS_EXIT |
606 | TRACE_IRQS_ON | 588 | TRACE_IRQS_ON |
607 | io_tif: | 589 | io_tif: |
608 | tm __TI_flags+3(%r9),_TIF_WORK_INT | 590 | tm __TI_flags+3(%r12),_TIF_WORK_INT |
609 | bnz BASED(io_work) # there is work to do (signals etc.) | 591 | bnz BASED(io_work) # there is work to do (signals etc.) |
610 | io_restore: | 592 | io_restore: |
611 | RESTORE_ALL __LC_RETURN_PSW,0 | 593 | RESTORE_ALL __LC_RETURN_PSW,0 |
@@ -623,9 +605,9 @@ io_work: | |||
623 | bo BASED(io_work_user) # yes -> do resched & signal | 605 | bo BASED(io_work_user) # yes -> do resched & signal |
624 | #ifdef CONFIG_PREEMPT | 606 | #ifdef CONFIG_PREEMPT |
625 | # check for preemptive scheduling | 607 | # check for preemptive scheduling |
626 | icm %r0,15,__TI_precount(%r9) | 608 | icm %r0,15,__TI_precount(%r12) |
627 | bnz BASED(io_restore) # preemption disabled | 609 | bnz BASED(io_restore) # preemption disabled |
628 | tm __TI_flags+3(%r9),_TIF_NEED_RESCHED | 610 | tm __TI_flags+3(%r12),_TIF_NEED_RESCHED |
629 | bno BASED(io_restore) | 611 | bno BASED(io_restore) |
630 | # switch to kernel stack | 612 | # switch to kernel stack |
631 | l %r1,SP_R15(%r15) | 613 | l %r1,SP_R15(%r15) |
@@ -659,13 +641,13 @@ io_work_user: | |||
659 | # and _TIF_MCCK_PENDING | 641 | # and _TIF_MCCK_PENDING |
660 | # | 642 | # |
661 | io_work_tif: | 643 | io_work_tif: |
662 | tm __TI_flags+3(%r9),_TIF_MCCK_PENDING | 644 | tm __TI_flags+3(%r12),_TIF_MCCK_PENDING |
663 | bo BASED(io_mcck_pending) | 645 | bo BASED(io_mcck_pending) |
664 | tm __TI_flags+3(%r9),_TIF_NEED_RESCHED | 646 | tm __TI_flags+3(%r12),_TIF_NEED_RESCHED |
665 | bo BASED(io_reschedule) | 647 | bo BASED(io_reschedule) |
666 | tm __TI_flags+3(%r9),_TIF_SIGPENDING | 648 | tm __TI_flags+3(%r12),_TIF_SIGPENDING |
667 | bo BASED(io_sigpending) | 649 | bo BASED(io_sigpending) |
668 | tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME | 650 | tm __TI_flags+3(%r12),_TIF_NOTIFY_RESUME |
669 | bo BASED(io_notify_resume) | 651 | bo BASED(io_notify_resume) |
670 | b BASED(io_return) # beware of critical section cleanup | 652 | b BASED(io_return) # beware of critical section cleanup |
671 | 653 | ||
@@ -725,19 +707,20 @@ io_notify_resume: | |||
725 | ext_int_handler: | 707 | ext_int_handler: |
726 | stck __LC_INT_CLOCK | 708 | stck __LC_INT_CLOCK |
727 | stpt __LC_ASYNC_ENTER_TIMER | 709 | stpt __LC_ASYNC_ENTER_TIMER |
728 | SAVE_ALL_BASE __LC_SAVE_AREA+16 | ||
729 | SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 | 710 | SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 |
730 | CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 | 711 | CREATE_STACK_FRAME __LC_SAVE_AREA+16 |
712 | mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack | ||
713 | l %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
731 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 714 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
732 | bz BASED(ext_no_vtime) | 715 | bz BASED(ext_no_vtime) |
733 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 716 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER |
734 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 717 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
735 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | 718 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER |
736 | ext_no_vtime: | 719 | ext_no_vtime: |
737 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | ||
738 | TRACE_IRQS_OFF | 720 | TRACE_IRQS_OFF |
739 | la %r2,SP_PTREGS(%r15) # address of register-save area | 721 | la %r2,SP_PTREGS(%r15) # address of register-save area |
740 | lh %r3,__LC_EXT_INT_CODE # get interruption code | 722 | l %r3,__LC_CPU_ADDRESS # get cpu address + interruption code |
723 | l %r4,__LC_EXT_PARAMS # get external parameters | ||
741 | l %r1,BASED(.Ldo_extint) | 724 | l %r1,BASED(.Ldo_extint) |
742 | basr %r14,%r1 | 725 | basr %r14,%r1 |
743 | b BASED(io_return) | 726 | b BASED(io_return) |
@@ -788,7 +771,10 @@ mcck_int_main: | |||
788 | sra %r14,PAGE_SHIFT | 771 | sra %r14,PAGE_SHIFT |
789 | be BASED(0f) | 772 | be BASED(0f) |
790 | l %r15,__LC_PANIC_STACK # load panic stack | 773 | l %r15,__LC_PANIC_STACK # load panic stack |
791 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32 | 774 | 0: s %r15,BASED(.Lc_spsize) # make room for registers & psw |
775 | CREATE_STACK_FRAME __LC_SAVE_AREA+32 | ||
776 | mvc SP_PSW(8,%r15),0(%r12) | ||
777 | l %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
792 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | 778 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? |
793 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical | 779 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical |
794 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 780 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -797,7 +783,6 @@ mcck_int_main: | |||
797 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 783 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
798 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER | 784 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER |
799 | mcck_no_vtime: | 785 | mcck_no_vtime: |
800 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | ||
801 | la %r2,SP_PTREGS(%r15) # load pt_regs | 786 | la %r2,SP_PTREGS(%r15) # load pt_regs |
802 | l %r1,BASED(.Ls390_mcck) | 787 | l %r1,BASED(.Ls390_mcck) |
803 | basr %r14,%r1 # call machine check handler | 788 | basr %r14,%r1 # call machine check handler |
@@ -809,7 +794,7 @@ mcck_no_vtime: | |||
809 | xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain | 794 | xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain |
810 | lr %r15,%r1 | 795 | lr %r15,%r1 |
811 | stosm __SF_EMPTY(%r15),0x04 # turn dat on | 796 | stosm __SF_EMPTY(%r15),0x04 # turn dat on |
812 | tm __TI_flags+3(%r9),_TIF_MCCK_PENDING | 797 | tm __TI_flags+3(%r12),_TIF_MCCK_PENDING |
813 | bno BASED(mcck_return) | 798 | bno BASED(mcck_return) |
814 | TRACE_IRQS_OFF | 799 | TRACE_IRQS_OFF |
815 | l %r1,BASED(.Ls390_handle_mcck) | 800 | l %r1,BASED(.Ls390_handle_mcck) |
@@ -852,7 +837,7 @@ restart_base: | |||
852 | stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on | 837 | stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on |
853 | basr %r14,0 | 838 | basr %r14,0 |
854 | l %r14,restart_addr-.(%r14) | 839 | l %r14,restart_addr-.(%r14) |
855 | br %r14 # branch to start_secondary | 840 | basr %r14,%r14 # branch to start_secondary |
856 | restart_addr: | 841 | restart_addr: |
857 | .long start_secondary | 842 | .long start_secondary |
858 | .align 8 | 843 | .align 8 |
@@ -874,6 +859,8 @@ restart_crash: | |||
874 | restart_go: | 859 | restart_go: |
875 | #endif | 860 | #endif |
876 | 861 | ||
862 | .section .kprobes.text, "ax" | ||
863 | |||
877 | #ifdef CONFIG_CHECK_STACK | 864 | #ifdef CONFIG_CHECK_STACK |
878 | /* | 865 | /* |
879 | * The synchronous or the asynchronous stack overflowed. We are dead. | 866 | * The synchronous or the asynchronous stack overflowed. We are dead. |
@@ -956,12 +943,13 @@ cleanup_system_call: | |||
956 | bh BASED(0f) | 943 | bh BASED(0f) |
957 | mvc __LC_SAVE_AREA(16),0(%r12) | 944 | mvc __LC_SAVE_AREA(16),0(%r12) |
958 | 0: st %r13,4(%r12) | 945 | 0: st %r13,4(%r12) |
959 | st %r12,__LC_SAVE_AREA+48 # argh | 946 | l %r15,__LC_KERNEL_STACK # problem state -> load ksp |
960 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 947 | s %r15,BASED(.Lc_spsize) # make room for registers & psw |
961 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | ||
962 | l %r12,__LC_SAVE_AREA+48 # argh | ||
963 | st %r15,12(%r12) | 948 | st %r15,12(%r12) |
964 | lh %r7,0x8a | 949 | CREATE_STACK_FRAME __LC_SAVE_AREA |
950 | mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW | ||
951 | mvc SP_ILC(4,%r15),__LC_SVC_ILC | ||
952 | mvc 0(4,%r12),__LC_THREAD_INFO | ||
965 | cleanup_vtime: | 953 | cleanup_vtime: |
966 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12) | 954 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12) |
967 | bhe BASED(cleanup_stime) | 955 | bhe BASED(cleanup_stime) |
@@ -1059,7 +1047,7 @@ cleanup_io_restore_insn: | |||
1059 | .Ldo_signal: .long do_signal | 1047 | .Ldo_signal: .long do_signal |
1060 | .Ldo_notify_resume: | 1048 | .Ldo_notify_resume: |
1061 | .long do_notify_resume | 1049 | .long do_notify_resume |
1062 | .Lhandle_per: .long do_single_step | 1050 | .Lhandle_per: .long do_per_trap |
1063 | .Ldo_execve: .long do_execve | 1051 | .Ldo_execve: .long do_execve |
1064 | .Lexecve_tail: .long execve_tail | 1052 | .Lexecve_tail: .long execve_tail |
1065 | .Ljump_table: .long pgm_check_table | 1053 | .Ljump_table: .long pgm_check_table |
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index ff579b6bde06..17a6f83a2d67 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
@@ -5,21 +5,21 @@ | |||
5 | #include <linux/signal.h> | 5 | #include <linux/signal.h> |
6 | #include <asm/ptrace.h> | 6 | #include <asm/ptrace.h> |
7 | 7 | ||
8 | typedef void pgm_check_handler_t(struct pt_regs *, long); | 8 | typedef void pgm_check_handler_t(struct pt_regs *, long, unsigned long); |
9 | extern pgm_check_handler_t *pgm_check_table[128]; | 9 | extern pgm_check_handler_t *pgm_check_table[128]; |
10 | pgm_check_handler_t do_protection_exception; | 10 | pgm_check_handler_t do_protection_exception; |
11 | pgm_check_handler_t do_dat_exception; | 11 | pgm_check_handler_t do_dat_exception; |
12 | 12 | ||
13 | extern int sysctl_userprocess_debug; | 13 | extern int sysctl_userprocess_debug; |
14 | 14 | ||
15 | void do_single_step(struct pt_regs *regs); | 15 | void do_per_trap(struct pt_regs *regs); |
16 | void syscall_trace(struct pt_regs *regs, int entryexit); | 16 | void syscall_trace(struct pt_regs *regs, int entryexit); |
17 | void kernel_stack_overflow(struct pt_regs * regs); | 17 | void kernel_stack_overflow(struct pt_regs * regs); |
18 | void do_signal(struct pt_regs *regs); | 18 | void do_signal(struct pt_regs *regs); |
19 | int handle_signal32(unsigned long sig, struct k_sigaction *ka, | 19 | int handle_signal32(unsigned long sig, struct k_sigaction *ka, |
20 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs); | 20 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs); |
21 | 21 | ||
22 | void do_extint(struct pt_regs *regs, unsigned short code); | 22 | void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long); |
23 | int __cpuinit start_secondary(void *cpuvoid); | 23 | int __cpuinit start_secondary(void *cpuvoid); |
24 | void __init startup_init(void); | 24 | void __init startup_init(void); |
25 | void die(const char * str, struct pt_regs * regs, long err); | 25 | void die(const char * str, struct pt_regs * regs, long err); |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 8bccec15ea90..d61967e2eab0 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -51,7 +51,7 @@ STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER | |||
51 | STACK_SIZE = 1 << STACK_SHIFT | 51 | STACK_SIZE = 1 << STACK_SHIFT |
52 | 52 | ||
53 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | 53 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
54 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) | 54 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP ) |
55 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | 55 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
56 | _TIF_MCCK_PENDING) | 56 | _TIF_MCCK_PENDING) |
57 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | 57 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ |
@@ -79,25 +79,9 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | |||
79 | basr %r2,%r0 | 79 | basr %r2,%r0 |
80 | brasl %r14,trace_hardirqs_off_caller | 80 | brasl %r14,trace_hardirqs_off_caller |
81 | .endm | 81 | .endm |
82 | |||
83 | .macro TRACE_IRQS_CHECK_ON | ||
84 | tm SP_PSW(%r15),0x03 # irqs enabled? | ||
85 | jz 0f | ||
86 | TRACE_IRQS_ON | ||
87 | 0: | ||
88 | .endm | ||
89 | |||
90 | .macro TRACE_IRQS_CHECK_OFF | ||
91 | tm SP_PSW(%r15),0x03 # irqs enabled? | ||
92 | jz 0f | ||
93 | TRACE_IRQS_OFF | ||
94 | 0: | ||
95 | .endm | ||
96 | #else | 82 | #else |
97 | #define TRACE_IRQS_ON | 83 | #define TRACE_IRQS_ON |
98 | #define TRACE_IRQS_OFF | 84 | #define TRACE_IRQS_OFF |
99 | #define TRACE_IRQS_CHECK_ON | ||
100 | #define TRACE_IRQS_CHECK_OFF | ||
101 | #endif | 85 | #endif |
102 | 86 | ||
103 | #ifdef CONFIG_LOCKDEP | 87 | #ifdef CONFIG_LOCKDEP |
@@ -207,6 +191,14 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | |||
207 | 0: | 191 | 0: |
208 | .endm | 192 | .endm |
209 | 193 | ||
194 | .macro REENABLE_IRQS | ||
195 | mvc __SF_EMPTY(1,%r15),SP_PSW(%r15) | ||
196 | ni __SF_EMPTY(%r15),0xbf | ||
197 | ssm __SF_EMPTY(%r15) | ||
198 | .endm | ||
199 | |||
200 | .section .kprobes.text, "ax" | ||
201 | |||
210 | /* | 202 | /* |
211 | * Scheduler resume function, called by switch_to | 203 | * Scheduler resume function, called by switch_to |
212 | * gpr2 = (task_struct *) prev | 204 | * gpr2 = (task_struct *) prev |
@@ -216,30 +208,22 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | |||
216 | */ | 208 | */ |
217 | .globl __switch_to | 209 | .globl __switch_to |
218 | __switch_to: | 210 | __switch_to: |
219 | tm __THREAD_per+4(%r3),0xe8 # is the new process using per ? | 211 | lg %r4,__THREAD_info(%r2) # get thread_info of prev |
220 | jz __switch_to_noper # if not we're fine | 212 | lg %r5,__THREAD_info(%r3) # get thread_info of next |
221 | stctg %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff | ||
222 | clc __THREAD_per(24,%r3),__SF_EMPTY(%r15) | ||
223 | je __switch_to_noper # we got away without bashing TLB's | ||
224 | lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't | ||
225 | __switch_to_noper: | ||
226 | lg %r4,__THREAD_info(%r2) # get thread_info of prev | ||
227 | tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending? | 213 | tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending? |
228 | jz __switch_to_no_mcck | 214 | jz 0f |
229 | ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev | 215 | ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev |
230 | lg %r4,__THREAD_info(%r3) # get thread_info of next | 216 | oi __TI_flags+7(%r5),_TIF_MCCK_PENDING # set it in next |
231 | oi __TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next | 217 | 0: stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task |
232 | __switch_to_no_mcck: | 218 | stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev |
233 | stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task | 219 | lg %r15,__THREAD_ksp(%r3) # load kernel stack of next |
234 | stg %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp | 220 | lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 |
235 | lg %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp | 221 | lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task |
236 | lmg %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task | 222 | stg %r3,__LC_CURRENT # store task struct of next |
237 | stg %r3,__LC_CURRENT # __LC_CURRENT = current task struct | 223 | mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next |
238 | lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 | 224 | stg %r5,__LC_THREAD_INFO # store thread info of next |
239 | lg %r3,__THREAD_info(%r3) # load thread_info from task struct | 225 | aghi %r5,STACK_SIZE # end of kernel stack of next |
240 | stg %r3,__LC_THREAD_INFO | 226 | stg %r5,__LC_KERNEL_STACK # store end of kernel stack |
241 | aghi %r3,STACK_SIZE | ||
242 | stg %r3,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack | ||
243 | br %r14 | 227 | br %r14 |
244 | 228 | ||
245 | __critical_start: | 229 | __critical_start: |
@@ -256,7 +240,6 @@ sysc_saveall: | |||
256 | CREATE_STACK_FRAME __LC_SAVE_AREA | 240 | CREATE_STACK_FRAME __LC_SAVE_AREA |
257 | mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW | 241 | mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW |
258 | mvc SP_ILC(4,%r15),__LC_SVC_ILC | 242 | mvc SP_ILC(4,%r15),__LC_SVC_ILC |
259 | stg %r7,SP_ARGS(%r15) | ||
260 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct | 243 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct |
261 | sysc_vtime: | 244 | sysc_vtime: |
262 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 245 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
@@ -284,6 +267,7 @@ sysc_nr_ok: | |||
284 | sysc_noemu: | 267 | sysc_noemu: |
285 | #endif | 268 | #endif |
286 | tm __TI_flags+6(%r12),_TIF_SYSCALL | 269 | tm __TI_flags+6(%r12),_TIF_SYSCALL |
270 | mvc SP_ARGS(8,%r15),SP_R7(%r15) | ||
287 | lgf %r8,0(%r7,%r10) # load address of system call routine | 271 | lgf %r8,0(%r7,%r10) # load address of system call routine |
288 | jnz sysc_tracesys | 272 | jnz sysc_tracesys |
289 | basr %r14,%r8 # call sys_xxxx | 273 | basr %r14,%r8 # call sys_xxxx |
@@ -319,7 +303,7 @@ sysc_work_tif: | |||
319 | jo sysc_notify_resume | 303 | jo sysc_notify_resume |
320 | tm __TI_flags+7(%r12),_TIF_RESTART_SVC | 304 | tm __TI_flags+7(%r12),_TIF_RESTART_SVC |
321 | jo sysc_restart | 305 | jo sysc_restart |
322 | tm __TI_flags+7(%r12),_TIF_SINGLE_STEP | 306 | tm __TI_flags+7(%r12),_TIF_PER_TRAP |
323 | jo sysc_singlestep | 307 | jo sysc_singlestep |
324 | j sysc_return # beware of critical section cleanup | 308 | j sysc_return # beware of critical section cleanup |
325 | 309 | ||
@@ -341,12 +325,12 @@ sysc_mcck_pending: | |||
341 | # _TIF_SIGPENDING is set, call do_signal | 325 | # _TIF_SIGPENDING is set, call do_signal |
342 | # | 326 | # |
343 | sysc_sigpending: | 327 | sysc_sigpending: |
344 | ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP | 328 | ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP |
345 | la %r2,SP_PTREGS(%r15) # load pt_regs | 329 | la %r2,SP_PTREGS(%r15) # load pt_regs |
346 | brasl %r14,do_signal # call do_signal | 330 | brasl %r14,do_signal # call do_signal |
347 | tm __TI_flags+7(%r12),_TIF_RESTART_SVC | 331 | tm __TI_flags+7(%r12),_TIF_RESTART_SVC |
348 | jo sysc_restart | 332 | jo sysc_restart |
349 | tm __TI_flags+7(%r12),_TIF_SINGLE_STEP | 333 | tm __TI_flags+7(%r12),_TIF_PER_TRAP |
350 | jo sysc_singlestep | 334 | jo sysc_singlestep |
351 | j sysc_return | 335 | j sysc_return |
352 | 336 | ||
@@ -371,14 +355,14 @@ sysc_restart: | |||
371 | j sysc_nr_ok # restart svc | 355 | j sysc_nr_ok # restart svc |
372 | 356 | ||
373 | # | 357 | # |
374 | # _TIF_SINGLE_STEP is set, call do_single_step | 358 | # _TIF_PER_TRAP is set, call do_per_trap |
375 | # | 359 | # |
376 | sysc_singlestep: | 360 | sysc_singlestep: |
377 | ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP | 361 | ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP |
378 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number | 362 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number |
379 | la %r2,SP_PTREGS(%r15) # address of register-save area | 363 | la %r2,SP_PTREGS(%r15) # address of register-save area |
380 | larl %r14,sysc_return # load adr. of system return | 364 | larl %r14,sysc_return # load adr. of system return |
381 | jg do_single_step # branch to do_sigtrap | 365 | jg do_per_trap |
382 | 366 | ||
383 | # | 367 | # |
384 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before | 368 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before |
@@ -397,6 +381,7 @@ sysc_tracesys: | |||
397 | lgf %r8,0(%r7,%r10) | 381 | lgf %r8,0(%r7,%r10) |
398 | sysc_tracego: | 382 | sysc_tracego: |
399 | lmg %r3,%r6,SP_R3(%r15) | 383 | lmg %r3,%r6,SP_R3(%r15) |
384 | mvc SP_ARGS(8,%r15),SP_R7(%r15) | ||
400 | lg %r2,SP_ORIG_R2(%r15) | 385 | lg %r2,SP_ORIG_R2(%r15) |
401 | basr %r14,%r8 # call sys_xxx | 386 | basr %r14,%r8 # call sys_xxx |
402 | stg %r2,SP_R2(%r15) # store return value | 387 | stg %r2,SP_R2(%r15) # store return value |
@@ -443,14 +428,12 @@ kernel_execve: | |||
443 | br %r14 | 428 | br %r14 |
444 | # execve succeeded. | 429 | # execve succeeded. |
445 | 0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts | 430 | 0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts |
446 | # TRACE_IRQS_OFF | ||
447 | lg %r15,__LC_KERNEL_STACK # load ksp | 431 | lg %r15,__LC_KERNEL_STACK # load ksp |
448 | aghi %r15,-SP_SIZE # make room for registers & psw | 432 | aghi %r15,-SP_SIZE # make room for registers & psw |
449 | lg %r13,__LC_SVC_NEW_PSW+8 | 433 | lg %r13,__LC_SVC_NEW_PSW+8 |
450 | mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs | 434 | mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs |
451 | lg %r12,__LC_THREAD_INFO | 435 | lg %r12,__LC_THREAD_INFO |
452 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 436 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
453 | # TRACE_IRQS_ON | ||
454 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 437 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
455 | brasl %r14,execve_tail | 438 | brasl %r14,execve_tail |
456 | j sysc_return | 439 | j sysc_return |
@@ -490,19 +473,18 @@ pgm_check_handler: | |||
490 | LAST_BREAK | 473 | LAST_BREAK |
491 | pgm_no_vtime: | 474 | pgm_no_vtime: |
492 | HANDLE_SIE_INTERCEPT | 475 | HANDLE_SIE_INTERCEPT |
493 | TRACE_IRQS_CHECK_OFF | ||
494 | stg %r11,SP_ARGS(%r15) | 476 | stg %r11,SP_ARGS(%r15) |
495 | lgf %r3,__LC_PGM_ILC # load program interruption code | 477 | lgf %r3,__LC_PGM_ILC # load program interruption code |
478 | lg %r4,__LC_TRANS_EXC_CODE | ||
479 | REENABLE_IRQS | ||
496 | lghi %r8,0x7f | 480 | lghi %r8,0x7f |
497 | ngr %r8,%r3 | 481 | ngr %r8,%r3 |
498 | pgm_do_call: | ||
499 | sll %r8,3 | 482 | sll %r8,3 |
500 | larl %r1,pgm_check_table | 483 | larl %r1,pgm_check_table |
501 | lg %r1,0(%r8,%r1) # load address of handler routine | 484 | lg %r1,0(%r8,%r1) # load address of handler routine |
502 | la %r2,SP_PTREGS(%r15) # address of register-save area | 485 | la %r2,SP_PTREGS(%r15) # address of register-save area |
503 | basr %r14,%r1 # branch to interrupt-handler | 486 | basr %r14,%r1 # branch to interrupt-handler |
504 | pgm_exit: | 487 | pgm_exit: |
505 | TRACE_IRQS_CHECK_ON | ||
506 | j sysc_return | 488 | j sysc_return |
507 | 489 | ||
508 | # | 490 | # |
@@ -533,15 +515,16 @@ pgm_per_std: | |||
533 | LAST_BREAK | 515 | LAST_BREAK |
534 | pgm_no_vtime2: | 516 | pgm_no_vtime2: |
535 | HANDLE_SIE_INTERCEPT | 517 | HANDLE_SIE_INTERCEPT |
536 | TRACE_IRQS_CHECK_OFF | ||
537 | lg %r1,__TI_task(%r12) | 518 | lg %r1,__TI_task(%r12) |
538 | tm SP_PSW+1(%r15),0x01 # kernel per event ? | 519 | tm SP_PSW+1(%r15),0x01 # kernel per event ? |
539 | jz kernel_per | 520 | jz kernel_per |
540 | mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID | 521 | mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE |
541 | mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS | 522 | mvc __THREAD_per_address(8,%r1),__LC_PER_ADDRESS |
542 | mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID | 523 | mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID |
543 | oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP | 524 | oi __TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP |
544 | lgf %r3,__LC_PGM_ILC # load program interruption code | 525 | lgf %r3,__LC_PGM_ILC # load program interruption code |
526 | lg %r4,__LC_TRANS_EXC_CODE | ||
527 | REENABLE_IRQS | ||
545 | lghi %r8,0x7f | 528 | lghi %r8,0x7f |
546 | ngr %r8,%r3 # clear per-event-bit and ilc | 529 | ngr %r8,%r3 # clear per-event-bit and ilc |
547 | je pgm_exit2 | 530 | je pgm_exit2 |
@@ -551,8 +534,6 @@ pgm_no_vtime2: | |||
551 | la %r2,SP_PTREGS(%r15) # address of register-save area | 534 | la %r2,SP_PTREGS(%r15) # address of register-save area |
552 | basr %r14,%r1 # branch to interrupt-handler | 535 | basr %r14,%r1 # branch to interrupt-handler |
553 | pgm_exit2: | 536 | pgm_exit2: |
554 | TRACE_IRQS_ON | ||
555 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | ||
556 | j sysc_return | 537 | j sysc_return |
557 | 538 | ||
558 | # | 539 | # |
@@ -568,13 +549,11 @@ pgm_svcper: | |||
568 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 549 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
569 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 550 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
570 | LAST_BREAK | 551 | LAST_BREAK |
571 | TRACE_IRQS_OFF | ||
572 | lg %r8,__TI_task(%r12) | 552 | lg %r8,__TI_task(%r12) |
573 | mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID | 553 | mvc __THREAD_per_cause(2,%r8),__LC_PER_CAUSE |
574 | mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS | 554 | mvc __THREAD_per_address(8,%r8),__LC_PER_ADDRESS |
575 | mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID | 555 | mvc __THREAD_per_paid(1,%r8),__LC_PER_PAID |
576 | oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP | 556 | oi __TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP |
577 | TRACE_IRQS_ON | ||
578 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 557 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
579 | lmg %r2,%r6,SP_R2(%r15) # load svc arguments | 558 | lmg %r2,%r6,SP_R2(%r15) # load svc arguments |
580 | j sysc_do_svc | 559 | j sysc_do_svc |
@@ -583,9 +562,10 @@ pgm_svcper: | |||
583 | # per was called from kernel, must be kprobes | 562 | # per was called from kernel, must be kprobes |
584 | # | 563 | # |
585 | kernel_per: | 564 | kernel_per: |
565 | REENABLE_IRQS | ||
586 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number | 566 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number |
587 | la %r2,SP_PTREGS(%r15) # address of register-save area | 567 | la %r2,SP_PTREGS(%r15) # address of register-save area |
588 | brasl %r14,do_single_step | 568 | brasl %r14,do_per_trap |
589 | j pgm_exit | 569 | j pgm_exit |
590 | 570 | ||
591 | /* | 571 | /* |
@@ -743,8 +723,11 @@ ext_int_handler: | |||
743 | ext_no_vtime: | 723 | ext_no_vtime: |
744 | HANDLE_SIE_INTERCEPT | 724 | HANDLE_SIE_INTERCEPT |
745 | TRACE_IRQS_OFF | 725 | TRACE_IRQS_OFF |
726 | lghi %r1,4096 | ||
746 | la %r2,SP_PTREGS(%r15) # address of register-save area | 727 | la %r2,SP_PTREGS(%r15) # address of register-save area |
747 | llgh %r3,__LC_EXT_INT_CODE # get interruption code | 728 | llgf %r3,__LC_CPU_ADDRESS # get cpu address + interruption code |
729 | llgf %r4,__LC_EXT_PARAMS # get external parameter | ||
730 | lg %r5,__LC_EXT_PARAMS2-4096(%r1) # get 64 bit external parameter | ||
748 | brasl %r14,do_extint | 731 | brasl %r14,do_extint |
749 | j io_return | 732 | j io_return |
750 | 733 | ||
@@ -859,7 +842,7 @@ restart_base: | |||
859 | mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1) | 842 | mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1) |
860 | xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER | 843 | xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER |
861 | stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on | 844 | stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on |
862 | jg start_secondary | 845 | brasl %r14,start_secondary |
863 | .align 8 | 846 | .align 8 |
864 | restart_vtime: | 847 | restart_vtime: |
865 | .long 0x7fffffff,0xffffffff | 848 | .long 0x7fffffff,0xffffffff |
@@ -879,6 +862,8 @@ restart_crash: | |||
879 | restart_go: | 862 | restart_go: |
880 | #endif | 863 | #endif |
881 | 864 | ||
865 | .section .kprobes.text, "ax" | ||
866 | |||
882 | #ifdef CONFIG_CHECK_STACK | 867 | #ifdef CONFIG_CHECK_STACK |
883 | /* | 868 | /* |
884 | * The synchronous or the asynchronous stack overflowed. We are dead. | 869 | * The synchronous or the asynchronous stack overflowed. We are dead. |
@@ -966,7 +951,6 @@ cleanup_system_call: | |||
966 | CREATE_STACK_FRAME __LC_SAVE_AREA | 951 | CREATE_STACK_FRAME __LC_SAVE_AREA |
967 | mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW | 952 | mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW |
968 | mvc SP_ILC(4,%r15),__LC_SVC_ILC | 953 | mvc SP_ILC(4,%r15),__LC_SVC_ILC |
969 | stg %r7,SP_ARGS(%r15) | ||
970 | mvc 8(8,%r12),__LC_THREAD_INFO | 954 | mvc 8(8,%r12),__LC_THREAD_INFO |
971 | cleanup_vtime: | 955 | cleanup_vtime: |
972 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) | 956 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) |
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 6a83d0581317..78bdf0e5dff7 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright IBM Corp. 2009 | 4 | * Copyright IBM Corp. 2009 |
5 | * | 5 | * |
6 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>, | 6 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>, |
7 | * | 7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/hardirq.h> | 10 | #include <linux/hardirq.h> |
@@ -12,176 +12,144 @@ | |||
12 | #include <linux/ftrace.h> | 12 | #include <linux/ftrace.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/kprobes.h> | ||
15 | #include <trace/syscall.h> | 16 | #include <trace/syscall.h> |
16 | #include <asm/asm-offsets.h> | 17 | #include <asm/asm-offsets.h> |
17 | 18 | ||
19 | #ifdef CONFIG_64BIT | ||
20 | #define MCOUNT_OFFSET_RET 12 | ||
21 | #else | ||
22 | #define MCOUNT_OFFSET_RET 22 | ||
23 | #endif | ||
24 | |||
18 | #ifdef CONFIG_DYNAMIC_FTRACE | 25 | #ifdef CONFIG_DYNAMIC_FTRACE |
19 | 26 | ||
20 | void ftrace_disable_code(void); | 27 | void ftrace_disable_code(void); |
21 | void ftrace_disable_return(void); | 28 | void ftrace_enable_insn(void); |
22 | void ftrace_call_code(void); | ||
23 | void ftrace_nop_code(void); | ||
24 | |||
25 | #define FTRACE_INSN_SIZE 4 | ||
26 | 29 | ||
27 | #ifdef CONFIG_64BIT | 30 | #ifdef CONFIG_64BIT |
28 | 31 | /* | |
32 | * The 64-bit mcount code looks like this: | ||
33 | * stg %r14,8(%r15) # offset 0 | ||
34 | * > larl %r1,<&counter> # offset 6 | ||
35 | * > brasl %r14,_mcount # offset 12 | ||
36 | * lg %r14,8(%r15) # offset 18 | ||
37 | * Total length is 24 bytes. The middle two instructions of the mcount | ||
38 | * block get overwritten by ftrace_make_nop / ftrace_make_call. | ||
39 | * The 64-bit enabled ftrace code block looks like this: | ||
40 | * stg %r14,8(%r15) # offset 0 | ||
41 | * > lg %r1,__LC_FTRACE_FUNC # offset 6 | ||
42 | * > lgr %r0,%r0 # offset 12 | ||
43 | * > basr %r14,%r1 # offset 16 | ||
44 | * lg %r14,8(%15) # offset 18 | ||
45 | * The return points of the mcount/ftrace function have the same offset 18. | ||
46 | * The 64-bit disable ftrace code block looks like this: | ||
47 | * stg %r14,8(%r15) # offset 0 | ||
48 | * > jg .+18 # offset 6 | ||
49 | * > lgr %r0,%r0 # offset 12 | ||
50 | * > basr %r14,%r1 # offset 16 | ||
51 | * lg %r14,8(%15) # offset 18 | ||
52 | * The jg instruction branches to offset 24 to skip as many instructions | ||
53 | * as possible. | ||
54 | */ | ||
29 | asm( | 55 | asm( |
30 | " .align 4\n" | 56 | " .align 4\n" |
31 | "ftrace_disable_code:\n" | 57 | "ftrace_disable_code:\n" |
32 | " j 0f\n" | 58 | " jg 0f\n" |
33 | " .word 0x0024\n" | ||
34 | " lg %r1,"__stringify(__LC_FTRACE_FUNC)"\n" | ||
35 | " basr %r14,%r1\n" | ||
36 | "ftrace_disable_return:\n" | ||
37 | " lg %r14,8(15)\n" | ||
38 | " lgr %r0,%r0\n" | 59 | " lgr %r0,%r0\n" |
39 | "0:\n"); | 60 | " basr %r14,%r1\n" |
40 | 61 | "0:\n" | |
41 | asm( | ||
42 | " .align 4\n" | 62 | " .align 4\n" |
43 | "ftrace_nop_code:\n" | 63 | "ftrace_enable_insn:\n" |
44 | " j .+"__stringify(MCOUNT_INSN_SIZE)"\n"); | 64 | " lg %r1,"__stringify(__LC_FTRACE_FUNC)"\n"); |
45 | 65 | ||
46 | asm( | 66 | #define FTRACE_INSN_SIZE 6 |
47 | " .align 4\n" | ||
48 | "ftrace_call_code:\n" | ||
49 | " stg %r14,8(%r15)\n"); | ||
50 | 67 | ||
51 | #else /* CONFIG_64BIT */ | 68 | #else /* CONFIG_64BIT */ |
52 | 69 | /* | |
70 | * The 31-bit mcount code looks like this: | ||
71 | * st %r14,4(%r15) # offset 0 | ||
72 | * > bras %r1,0f # offset 4 | ||
73 | * > .long _mcount # offset 8 | ||
74 | * > .long <&counter> # offset 12 | ||
75 | * > 0: l %r14,0(%r1) # offset 16 | ||
76 | * > l %r1,4(%r1) # offset 20 | ||
77 | * basr %r14,%r14 # offset 24 | ||
78 | * l %r14,4(%r15) # offset 26 | ||
79 | * Total length is 30 bytes. The twenty bytes starting from offset 4 | ||
80 | * to offset 24 get overwritten by ftrace_make_nop / ftrace_make_call. | ||
81 | * The 31-bit enabled ftrace code block looks like this: | ||
82 | * st %r14,4(%r15) # offset 0 | ||
83 | * > l %r14,__LC_FTRACE_FUNC # offset 4 | ||
84 | * > j 0f # offset 8 | ||
85 | * > .fill 12,1,0x07 # offset 12 | ||
86 | * 0: basr %r14,%r14 # offset 24 | ||
87 | * l %r14,4(%r14) # offset 26 | ||
88 | * The return points of the mcount/ftrace function have the same offset 26. | ||
89 | * The 31-bit disabled ftrace code block looks like this: | ||
90 | * st %r14,4(%r15) # offset 0 | ||
91 | * > j .+26 # offset 4 | ||
92 | * > j 0f # offset 8 | ||
93 | * > .fill 12,1,0x07 # offset 12 | ||
94 | * 0: basr %r14,%r14 # offset 24 | ||
95 | * l %r14,4(%r14) # offset 26 | ||
96 | * The j instruction branches to offset 30 to skip as many instructions | ||
97 | * as possible. | ||
98 | */ | ||
53 | asm( | 99 | asm( |
54 | " .align 4\n" | 100 | " .align 4\n" |
55 | "ftrace_disable_code:\n" | 101 | "ftrace_disable_code:\n" |
102 | " j 1f\n" | ||
56 | " j 0f\n" | 103 | " j 0f\n" |
57 | " l %r1,"__stringify(__LC_FTRACE_FUNC)"\n" | 104 | " .fill 12,1,0x07\n" |
58 | " basr %r14,%r1\n" | 105 | "0: basr %r14,%r14\n" |
59 | "ftrace_disable_return:\n" | 106 | "1:\n" |
60 | " l %r14,4(%r15)\n" | ||
61 | " j 0f\n" | ||
62 | " bcr 0,%r7\n" | ||
63 | " bcr 0,%r7\n" | ||
64 | " bcr 0,%r7\n" | ||
65 | " bcr 0,%r7\n" | ||
66 | " bcr 0,%r7\n" | ||
67 | " bcr 0,%r7\n" | ||
68 | "0:\n"); | ||
69 | |||
70 | asm( | ||
71 | " .align 4\n" | 107 | " .align 4\n" |
72 | "ftrace_nop_code:\n" | 108 | "ftrace_enable_insn:\n" |
73 | " j .+"__stringify(MCOUNT_INSN_SIZE)"\n"); | 109 | " l %r14,"__stringify(__LC_FTRACE_FUNC)"\n"); |
74 | 110 | ||
75 | asm( | 111 | #define FTRACE_INSN_SIZE 4 |
76 | " .align 4\n" | ||
77 | "ftrace_call_code:\n" | ||
78 | " st %r14,4(%r15)\n"); | ||
79 | 112 | ||
80 | #endif /* CONFIG_64BIT */ | 113 | #endif /* CONFIG_64BIT */ |
81 | 114 | ||
82 | static int ftrace_modify_code(unsigned long ip, | ||
83 | void *old_code, int old_size, | ||
84 | void *new_code, int new_size) | ||
85 | { | ||
86 | unsigned char replaced[MCOUNT_INSN_SIZE]; | ||
87 | |||
88 | /* | ||
89 | * Note: Due to modules code can disappear and change. | ||
90 | * We need to protect against faulting as well as code | ||
91 | * changing. We do this by using the probe_kernel_* | ||
92 | * functions. | ||
93 | * This however is just a simple sanity check. | ||
94 | */ | ||
95 | if (probe_kernel_read(replaced, (void *)ip, old_size)) | ||
96 | return -EFAULT; | ||
97 | if (memcmp(replaced, old_code, old_size) != 0) | ||
98 | return -EINVAL; | ||
99 | if (probe_kernel_write((void *)ip, new_code, new_size)) | ||
100 | return -EPERM; | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int ftrace_make_initial_nop(struct module *mod, struct dyn_ftrace *rec, | ||
105 | unsigned long addr) | ||
106 | { | ||
107 | return ftrace_modify_code(rec->ip, | ||
108 | ftrace_call_code, FTRACE_INSN_SIZE, | ||
109 | ftrace_disable_code, MCOUNT_INSN_SIZE); | ||
110 | } | ||
111 | 115 | ||
112 | int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, | 116 | int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, |
113 | unsigned long addr) | 117 | unsigned long addr) |
114 | { | 118 | { |
115 | if (addr == MCOUNT_ADDR) | 119 | if (probe_kernel_write((void *) rec->ip, ftrace_disable_code, |
116 | return ftrace_make_initial_nop(mod, rec, addr); | 120 | MCOUNT_INSN_SIZE)) |
117 | return ftrace_modify_code(rec->ip, | 121 | return -EPERM; |
118 | ftrace_call_code, FTRACE_INSN_SIZE, | 122 | return 0; |
119 | ftrace_nop_code, FTRACE_INSN_SIZE); | ||
120 | } | 123 | } |
121 | 124 | ||
122 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | 125 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) |
123 | { | 126 | { |
124 | return ftrace_modify_code(rec->ip, | 127 | if (probe_kernel_write((void *) rec->ip, ftrace_enable_insn, |
125 | ftrace_nop_code, FTRACE_INSN_SIZE, | 128 | FTRACE_INSN_SIZE)) |
126 | ftrace_call_code, FTRACE_INSN_SIZE); | 129 | return -EPERM; |
130 | return 0; | ||
127 | } | 131 | } |
128 | 132 | ||
129 | int ftrace_update_ftrace_func(ftrace_func_t func) | 133 | int ftrace_update_ftrace_func(ftrace_func_t func) |
130 | { | 134 | { |
131 | ftrace_dyn_func = (unsigned long)func; | ||
132 | return 0; | 135 | return 0; |
133 | } | 136 | } |
134 | 137 | ||
135 | int __init ftrace_dyn_arch_init(void *data) | 138 | int __init ftrace_dyn_arch_init(void *data) |
136 | { | 139 | { |
137 | *(unsigned long *)data = 0; | 140 | *(unsigned long *) data = 0; |
138 | return 0; | 141 | return 0; |
139 | } | 142 | } |
140 | 143 | ||
141 | #endif /* CONFIG_DYNAMIC_FTRACE */ | 144 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
142 | 145 | ||
143 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 146 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
144 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
145 | /* | ||
146 | * Patch the kernel code at ftrace_graph_caller location: | ||
147 | * The instruction there is branch relative on condition. The condition mask | ||
148 | * is either all ones (always branch aka disable ftrace_graph_caller) or all | ||
149 | * zeroes (nop aka enable ftrace_graph_caller). | ||
150 | * Instruction format for brc is a7m4xxxx where m is the condition mask. | ||
151 | */ | ||
152 | int ftrace_enable_ftrace_graph_caller(void) | ||
153 | { | ||
154 | unsigned short opcode = 0xa704; | ||
155 | |||
156 | return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode)); | ||
157 | } | ||
158 | |||
159 | int ftrace_disable_ftrace_graph_caller(void) | ||
160 | { | ||
161 | unsigned short opcode = 0xa7f4; | ||
162 | |||
163 | return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode)); | ||
164 | } | ||
165 | |||
166 | static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr) | ||
167 | { | ||
168 | return addr - (ftrace_disable_return - ftrace_disable_code); | ||
169 | } | ||
170 | |||
171 | #else /* CONFIG_DYNAMIC_FTRACE */ | ||
172 | |||
173 | static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr) | ||
174 | { | ||
175 | return addr - MCOUNT_OFFSET_RET; | ||
176 | } | ||
177 | |||
178 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
179 | |||
180 | /* | 147 | /* |
181 | * Hook the return address and push it in the stack of return addresses | 148 | * Hook the return address and push it in the stack of return addresses |
182 | * in current thread info. | 149 | * in current thread info. |
183 | */ | 150 | */ |
184 | unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent) | 151 | unsigned long __kprobes prepare_ftrace_return(unsigned long parent, |
152 | unsigned long ip) | ||
185 | { | 153 | { |
186 | struct ftrace_graph_ent trace; | 154 | struct ftrace_graph_ent trace; |
187 | 155 | ||
@@ -189,14 +157,42 @@ unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent) | |||
189 | goto out; | 157 | goto out; |
190 | if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY) | 158 | if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY) |
191 | goto out; | 159 | goto out; |
192 | trace.func = ftrace_mcount_call_adjust(ip) & PSW_ADDR_INSN; | 160 | trace.func = (ip & PSW_ADDR_INSN) - MCOUNT_OFFSET_RET; |
193 | /* Only trace if the calling function expects to. */ | 161 | /* Only trace if the calling function expects to. */ |
194 | if (!ftrace_graph_entry(&trace)) { | 162 | if (!ftrace_graph_entry(&trace)) { |
195 | current->curr_ret_stack--; | 163 | current->curr_ret_stack--; |
196 | goto out; | 164 | goto out; |
197 | } | 165 | } |
198 | parent = (unsigned long)return_to_handler; | 166 | parent = (unsigned long) return_to_handler; |
199 | out: | 167 | out: |
200 | return parent; | 168 | return parent; |
201 | } | 169 | } |
170 | |||
171 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
172 | /* | ||
173 | * Patch the kernel code at ftrace_graph_caller location. The instruction | ||
174 | * there is branch relative and save to prepare_ftrace_return. To disable | ||
175 | * the call to prepare_ftrace_return we patch the bras offset to point | ||
176 | * directly after the instructions. To enable the call we calculate | ||
177 | * the original offset to prepare_ftrace_return and put it back. | ||
178 | */ | ||
179 | int ftrace_enable_ftrace_graph_caller(void) | ||
180 | { | ||
181 | unsigned short offset; | ||
182 | |||
183 | offset = ((void *) prepare_ftrace_return - | ||
184 | (void *) ftrace_graph_caller) / 2; | ||
185 | return probe_kernel_write(ftrace_graph_caller + 2, | ||
186 | &offset, sizeof(offset)); | ||
187 | } | ||
188 | |||
189 | int ftrace_disable_ftrace_graph_caller(void) | ||
190 | { | ||
191 | static unsigned short offset = 0x0002; | ||
192 | |||
193 | return probe_kernel_write(ftrace_graph_caller + 2, | ||
194 | &offset, sizeof(offset)); | ||
195 | } | ||
196 | |||
197 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
202 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 198 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index db1696e210af..fb317bf2c378 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S | |||
@@ -460,7 +460,7 @@ startup: | |||
460 | #ifndef CONFIG_MARCH_G5 | 460 | #ifndef CONFIG_MARCH_G5 |
461 | # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} | 461 | # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} |
462 | xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST | 462 | xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST |
463 | stfl __LC_STFL_FAC_LIST # store facility list | 463 | .insn s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list |
464 | tm __LC_STFL_FAC_LIST,0x01 # stfle available ? | 464 | tm __LC_STFL_FAC_LIST,0x01 # stfle available ? |
465 | jz 0f | 465 | jz 0f |
466 | la %r0,0 | 466 | la %r0,0 |
@@ -488,7 +488,9 @@ startup: | |||
488 | .align 16 | 488 | .align 16 |
489 | 2: .long 0x000a0000,0x8badcccc | 489 | 2: .long 0x000a0000,0x8badcccc |
490 | #if defined(CONFIG_64BIT) | 490 | #if defined(CONFIG_64BIT) |
491 | #if defined(CONFIG_MARCH_Z10) | 491 | #if defined(CONFIG_MARCH_Z196) |
492 | .long 0xc100efe3, 0xf46c0000 | ||
493 | #elif defined(CONFIG_MARCH_Z10) | ||
492 | .long 0xc100efe3, 0xf0680000 | 494 | .long 0xc100efe3, 0xf0680000 |
493 | #elif defined(CONFIG_MARCH_Z9_109) | 495 | #elif defined(CONFIG_MARCH_Z9_109) |
494 | .long 0xc100efc3, 0x00000000 | 496 | .long 0xc100efc3, 0x00000000 |
@@ -498,7 +500,9 @@ startup: | |||
498 | .long 0xc0000000, 0x00000000 | 500 | .long 0xc0000000, 0x00000000 |
499 | #endif | 501 | #endif |
500 | #else | 502 | #else |
501 | #if defined(CONFIG_MARCH_Z10) | 503 | #if defined(CONFIG_MARCH_Z196) |
504 | .long 0x8100c880, 0x00000000 | ||
505 | #elif defined(CONFIG_MARCH_Z10) | ||
502 | .long 0x8100c880, 0x00000000 | 506 | .long 0x8100c880, 0x00000000 |
503 | #elif defined(CONFIG_MARCH_Z9_109) | 507 | #elif defined(CONFIG_MARCH_Z9_109) |
504 | .long 0x8100c880, 0x00000000 | 508 | .long 0x8100c880, 0x00000000 |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 026a37a94fc9..e3264f6a9720 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -1,28 +1,66 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/irq.c | 2 | * Copyright IBM Corp. 2004,2011 |
3 | * | 3 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, |
4 | * Copyright IBM Corp. 2004,2007 | 4 | * Holger Smolinski <Holger.Smolinski@de.ibm.com>, |
5 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), | 5 | * Thomas Spatzier <tspat@de.ibm.com>, |
6 | * Thomas Spatzier (tspat@de.ibm.com) | ||
7 | * | 6 | * |
8 | * This file contains interrupt related functions. | 7 | * This file contains interrupt related functions. |
9 | */ | 8 | */ |
10 | 9 | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/kernel_stat.h> | 10 | #include <linux/kernel_stat.h> |
14 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
15 | #include <linux/seq_file.h> | 12 | #include <linux/seq_file.h> |
16 | #include <linux/cpu.h> | ||
17 | #include <linux/proc_fs.h> | 13 | #include <linux/proc_fs.h> |
18 | #include <linux/profile.h> | 14 | #include <linux/profile.h> |
15 | #include <linux/module.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/ftrace.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/cpu.h> | ||
21 | #include <asm/irq_regs.h> | ||
22 | #include <asm/cputime.h> | ||
23 | #include <asm/lowcore.h> | ||
24 | #include <asm/irq.h> | ||
25 | #include "entry.h" | ||
26 | |||
27 | struct irq_class { | ||
28 | char *name; | ||
29 | char *desc; | ||
30 | }; | ||
31 | |||
32 | static const struct irq_class intrclass_names[] = { | ||
33 | {.name = "EXT" }, | ||
34 | {.name = "I/O" }, | ||
35 | {.name = "CLK", .desc = "[EXT] Clock Comparator" }, | ||
36 | {.name = "IPI", .desc = "[EXT] Signal Processor" }, | ||
37 | {.name = "TMR", .desc = "[EXT] CPU Timer" }, | ||
38 | {.name = "TAL", .desc = "[EXT] Timing Alert" }, | ||
39 | {.name = "PFL", .desc = "[EXT] Pseudo Page Fault" }, | ||
40 | {.name = "DSD", .desc = "[EXT] DASD Diag" }, | ||
41 | {.name = "VRT", .desc = "[EXT] Virtio" }, | ||
42 | {.name = "SCP", .desc = "[EXT] Service Call" }, | ||
43 | {.name = "IUC", .desc = "[EXT] IUCV" }, | ||
44 | {.name = "CPM", .desc = "[EXT] CPU Measurement" }, | ||
45 | {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" }, | ||
46 | {.name = "QDI", .desc = "[I/O] QDIO Interrupt" }, | ||
47 | {.name = "DAS", .desc = "[I/O] DASD" }, | ||
48 | {.name = "C15", .desc = "[I/O] 3215" }, | ||
49 | {.name = "C70", .desc = "[I/O] 3270" }, | ||
50 | {.name = "TAP", .desc = "[I/O] Tape" }, | ||
51 | {.name = "VMR", .desc = "[I/O] Unit Record Devices" }, | ||
52 | {.name = "LCS", .desc = "[I/O] LCS" }, | ||
53 | {.name = "CLW", .desc = "[I/O] CLAW" }, | ||
54 | {.name = "CTC", .desc = "[I/O] CTC" }, | ||
55 | {.name = "APB", .desc = "[I/O] AP Bus" }, | ||
56 | {.name = "NMI", .desc = "[NMI] Machine Check" }, | ||
57 | }; | ||
19 | 58 | ||
20 | /* | 59 | /* |
21 | * show_interrupts is needed by /proc/interrupts. | 60 | * show_interrupts is needed by /proc/interrupts. |
22 | */ | 61 | */ |
23 | int show_interrupts(struct seq_file *p, void *v) | 62 | int show_interrupts(struct seq_file *p, void *v) |
24 | { | 63 | { |
25 | static const char *intrclass_names[] = { "EXT", "I/O", }; | ||
26 | int i = *(loff_t *) v, j; | 64 | int i = *(loff_t *) v, j; |
27 | 65 | ||
28 | get_online_cpus(); | 66 | get_online_cpus(); |
@@ -34,15 +72,16 @@ int show_interrupts(struct seq_file *p, void *v) | |||
34 | } | 72 | } |
35 | 73 | ||
36 | if (i < NR_IRQS) { | 74 | if (i < NR_IRQS) { |
37 | seq_printf(p, "%s: ", intrclass_names[i]); | 75 | seq_printf(p, "%s: ", intrclass_names[i].name); |
38 | #ifndef CONFIG_SMP | 76 | #ifndef CONFIG_SMP |
39 | seq_printf(p, "%10u ", kstat_irqs(i)); | 77 | seq_printf(p, "%10u ", kstat_irqs(i)); |
40 | #else | 78 | #else |
41 | for_each_online_cpu(j) | 79 | for_each_online_cpu(j) |
42 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); | 80 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); |
43 | #endif | 81 | #endif |
82 | if (intrclass_names[i].desc) | ||
83 | seq_printf(p, " %s", intrclass_names[i].desc); | ||
44 | seq_putc(p, '\n'); | 84 | seq_putc(p, '\n'); |
45 | |||
46 | } | 85 | } |
47 | put_online_cpus(); | 86 | put_online_cpus(); |
48 | return 0; | 87 | return 0; |
@@ -52,8 +91,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
52 | * For compatibilty only. S/390 specific setup of interrupts et al. is done | 91 | * For compatibilty only. S/390 specific setup of interrupts et al. is done |
53 | * much later in init_channel_subsystem(). | 92 | * much later in init_channel_subsystem(). |
54 | */ | 93 | */ |
55 | void __init | 94 | void __init init_IRQ(void) |
56 | init_IRQ(void) | ||
57 | { | 95 | { |
58 | /* nothing... */ | 96 | /* nothing... */ |
59 | } | 97 | } |
@@ -104,3 +142,116 @@ void init_irq_proc(void) | |||
104 | create_prof_cpu_mask(root_irq_dir); | 142 | create_prof_cpu_mask(root_irq_dir); |
105 | } | 143 | } |
106 | #endif | 144 | #endif |
145 | |||
146 | /* | ||
147 | * ext_int_hash[index] is the start of the list for all external interrupts | ||
148 | * that hash to this index. With the current set of external interrupts | ||
149 | * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000 | ||
150 | * iucv and 0x2603 pfault) this is always the first element. | ||
151 | */ | ||
152 | |||
153 | struct ext_int_info { | ||
154 | struct ext_int_info *next; | ||
155 | ext_int_handler_t handler; | ||
156 | u16 code; | ||
157 | }; | ||
158 | |||
159 | static struct ext_int_info *ext_int_hash[256]; | ||
160 | |||
161 | static inline int ext_hash(u16 code) | ||
162 | { | ||
163 | return (code + (code >> 9)) & 0xff; | ||
164 | } | ||
165 | |||
166 | int register_external_interrupt(u16 code, ext_int_handler_t handler) | ||
167 | { | ||
168 | struct ext_int_info *p; | ||
169 | int index; | ||
170 | |||
171 | p = kmalloc(sizeof(*p), GFP_ATOMIC); | ||
172 | if (!p) | ||
173 | return -ENOMEM; | ||
174 | p->code = code; | ||
175 | p->handler = handler; | ||
176 | index = ext_hash(code); | ||
177 | p->next = ext_int_hash[index]; | ||
178 | ext_int_hash[index] = p; | ||
179 | return 0; | ||
180 | } | ||
181 | EXPORT_SYMBOL(register_external_interrupt); | ||
182 | |||
183 | int unregister_external_interrupt(u16 code, ext_int_handler_t handler) | ||
184 | { | ||
185 | struct ext_int_info *p, *q; | ||
186 | int index; | ||
187 | |||
188 | index = ext_hash(code); | ||
189 | q = NULL; | ||
190 | p = ext_int_hash[index]; | ||
191 | while (p) { | ||
192 | if (p->code == code && p->handler == handler) | ||
193 | break; | ||
194 | q = p; | ||
195 | p = p->next; | ||
196 | } | ||
197 | if (!p) | ||
198 | return -ENOENT; | ||
199 | if (q) | ||
200 | q->next = p->next; | ||
201 | else | ||
202 | ext_int_hash[index] = p->next; | ||
203 | kfree(p); | ||
204 | return 0; | ||
205 | } | ||
206 | EXPORT_SYMBOL(unregister_external_interrupt); | ||
207 | |||
208 | void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code, | ||
209 | unsigned int param32, unsigned long param64) | ||
210 | { | ||
211 | struct pt_regs *old_regs; | ||
212 | unsigned short code; | ||
213 | struct ext_int_info *p; | ||
214 | int index; | ||
215 | |||
216 | code = (unsigned short) ext_int_code; | ||
217 | old_regs = set_irq_regs(regs); | ||
218 | s390_idle_check(regs, S390_lowcore.int_clock, | ||
219 | S390_lowcore.async_enter_timer); | ||
220 | irq_enter(); | ||
221 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) | ||
222 | /* Serve timer interrupts first. */ | ||
223 | clock_comparator_work(); | ||
224 | kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; | ||
225 | if (code != 0x1004) | ||
226 | __get_cpu_var(s390_idle).nohz_delay = 1; | ||
227 | index = ext_hash(code); | ||
228 | for (p = ext_int_hash[index]; p; p = p->next) { | ||
229 | if (likely(p->code == code)) | ||
230 | p->handler(ext_int_code, param32, param64); | ||
231 | } | ||
232 | irq_exit(); | ||
233 | set_irq_regs(old_regs); | ||
234 | } | ||
235 | |||
236 | static DEFINE_SPINLOCK(sc_irq_lock); | ||
237 | static int sc_irq_refcount; | ||
238 | |||
239 | void service_subclass_irq_register(void) | ||
240 | { | ||
241 | spin_lock(&sc_irq_lock); | ||
242 | if (!sc_irq_refcount) | ||
243 | ctl_set_bit(0, 9); | ||
244 | sc_irq_refcount++; | ||
245 | spin_unlock(&sc_irq_lock); | ||
246 | } | ||
247 | EXPORT_SYMBOL(service_subclass_irq_register); | ||
248 | |||
249 | void service_subclass_irq_unregister(void) | ||
250 | { | ||
251 | spin_lock(&sc_irq_lock); | ||
252 | sc_irq_refcount--; | ||
253 | if (!sc_irq_refcount) | ||
254 | ctl_clear_bit(0, 9); | ||
255 | spin_unlock(&sc_irq_lock); | ||
256 | } | ||
257 | EXPORT_SYMBOL(service_subclass_irq_unregister); | ||
diff --git a/arch/s390/kernel/jump_label.c b/arch/s390/kernel/jump_label.c new file mode 100644 index 000000000000..44cc06bedf77 --- /dev/null +++ b/arch/s390/kernel/jump_label.c | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Jump label s390 support | ||
3 | * | ||
4 | * Copyright IBM Corp. 2011 | ||
5 | * Author(s): Jan Glauber <jang@linux.vnet.ibm.com> | ||
6 | */ | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/uaccess.h> | ||
9 | #include <linux/stop_machine.h> | ||
10 | #include <linux/jump_label.h> | ||
11 | #include <asm/ipl.h> | ||
12 | |||
13 | #ifdef HAVE_JUMP_LABEL | ||
14 | |||
15 | struct insn { | ||
16 | u16 opcode; | ||
17 | s32 offset; | ||
18 | } __packed; | ||
19 | |||
20 | struct insn_args { | ||
21 | unsigned long *target; | ||
22 | struct insn *insn; | ||
23 | ssize_t size; | ||
24 | }; | ||
25 | |||
26 | static int __arch_jump_label_transform(void *data) | ||
27 | { | ||
28 | struct insn_args *args = data; | ||
29 | int rc; | ||
30 | |||
31 | rc = probe_kernel_write(args->target, args->insn, args->size); | ||
32 | WARN_ON_ONCE(rc < 0); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | void arch_jump_label_transform(struct jump_entry *entry, | ||
37 | enum jump_label_type type) | ||
38 | { | ||
39 | struct insn_args args; | ||
40 | struct insn insn; | ||
41 | |||
42 | if (type == JUMP_LABEL_ENABLE) { | ||
43 | /* brcl 15,offset */ | ||
44 | insn.opcode = 0xc0f4; | ||
45 | insn.offset = (entry->target - entry->code) >> 1; | ||
46 | } else { | ||
47 | /* brcl 0,0 */ | ||
48 | insn.opcode = 0xc004; | ||
49 | insn.offset = 0; | ||
50 | } | ||
51 | |||
52 | args.target = (void *) entry->code; | ||
53 | args.insn = &insn; | ||
54 | args.size = JUMP_LABEL_NOP_SIZE; | ||
55 | |||
56 | stop_machine(__arch_jump_label_transform, &args, NULL); | ||
57 | } | ||
58 | |||
59 | #endif | ||
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 2a3d2bf6f083..1d05d669107c 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -30,35 +30,16 @@ | |||
30 | #include <asm/sections.h> | 30 | #include <asm/sections.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/hardirq.h> | ||
33 | 34 | ||
34 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 35 | DEFINE_PER_CPU(struct kprobe *, current_kprobe); |
35 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 36 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
36 | 37 | ||
37 | struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; | 38 | struct kretprobe_blackpoint kretprobe_blacklist[] = { }; |
38 | 39 | ||
39 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 40 | static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn) |
40 | { | 41 | { |
41 | /* Make sure the probe isn't going on a difficult instruction */ | 42 | switch (insn[0] >> 8) { |
42 | if (is_prohibited_opcode((kprobe_opcode_t *) p->addr)) | ||
43 | return -EINVAL; | ||
44 | |||
45 | if ((unsigned long)p->addr & 0x01) | ||
46 | return -EINVAL; | ||
47 | |||
48 | /* Use the get_insn_slot() facility for correctness */ | ||
49 | if (!(p->ainsn.insn = get_insn_slot())) | ||
50 | return -ENOMEM; | ||
51 | |||
52 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | ||
53 | |||
54 | get_instruction_type(&p->ainsn); | ||
55 | p->opcode = *p->addr; | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | int __kprobes is_prohibited_opcode(kprobe_opcode_t *instruction) | ||
60 | { | ||
61 | switch (*(__u8 *) instruction) { | ||
62 | case 0x0c: /* bassm */ | 43 | case 0x0c: /* bassm */ |
63 | case 0x0b: /* bsm */ | 44 | case 0x0b: /* bsm */ |
64 | case 0x83: /* diag */ | 45 | case 0x83: /* diag */ |
@@ -67,7 +48,7 @@ int __kprobes is_prohibited_opcode(kprobe_opcode_t *instruction) | |||
67 | case 0xad: /* stosm */ | 48 | case 0xad: /* stosm */ |
68 | return -EINVAL; | 49 | return -EINVAL; |
69 | } | 50 | } |
70 | switch (*(__u16 *) instruction) { | 51 | switch (insn[0]) { |
71 | case 0x0101: /* pr */ | 52 | case 0x0101: /* pr */ |
72 | case 0xb25a: /* bsa */ | 53 | case 0xb25a: /* bsa */ |
73 | case 0xb240: /* bakr */ | 54 | case 0xb240: /* bakr */ |
@@ -80,93 +61,92 @@ int __kprobes is_prohibited_opcode(kprobe_opcode_t *instruction) | |||
80 | return 0; | 61 | return 0; |
81 | } | 62 | } |
82 | 63 | ||
83 | void __kprobes get_instruction_type(struct arch_specific_insn *ainsn) | 64 | static int __kprobes get_fixup_type(kprobe_opcode_t *insn) |
84 | { | 65 | { |
85 | /* default fixup method */ | 66 | /* default fixup method */ |
86 | ainsn->fixup = FIXUP_PSW_NORMAL; | 67 | int fixup = FIXUP_PSW_NORMAL; |
87 | |||
88 | /* save r1 operand */ | ||
89 | ainsn->reg = (*ainsn->insn & 0xf0) >> 4; | ||
90 | |||
91 | /* save the instruction length (pop 5-5) in bytes */ | ||
92 | switch (*(__u8 *) (ainsn->insn) >> 6) { | ||
93 | case 0: | ||
94 | ainsn->ilen = 2; | ||
95 | break; | ||
96 | case 1: | ||
97 | case 2: | ||
98 | ainsn->ilen = 4; | ||
99 | break; | ||
100 | case 3: | ||
101 | ainsn->ilen = 6; | ||
102 | break; | ||
103 | } | ||
104 | 68 | ||
105 | switch (*(__u8 *) ainsn->insn) { | 69 | switch (insn[0] >> 8) { |
106 | case 0x05: /* balr */ | 70 | case 0x05: /* balr */ |
107 | case 0x0d: /* basr */ | 71 | case 0x0d: /* basr */ |
108 | ainsn->fixup = FIXUP_RETURN_REGISTER; | 72 | fixup = FIXUP_RETURN_REGISTER; |
109 | /* if r2 = 0, no branch will be taken */ | 73 | /* if r2 = 0, no branch will be taken */ |
110 | if ((*ainsn->insn & 0x0f) == 0) | 74 | if ((insn[0] & 0x0f) == 0) |
111 | ainsn->fixup |= FIXUP_BRANCH_NOT_TAKEN; | 75 | fixup |= FIXUP_BRANCH_NOT_TAKEN; |
112 | break; | 76 | break; |
113 | case 0x06: /* bctr */ | 77 | case 0x06: /* bctr */ |
114 | case 0x07: /* bcr */ | 78 | case 0x07: /* bcr */ |
115 | ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN; | 79 | fixup = FIXUP_BRANCH_NOT_TAKEN; |
116 | break; | 80 | break; |
117 | case 0x45: /* bal */ | 81 | case 0x45: /* bal */ |
118 | case 0x4d: /* bas */ | 82 | case 0x4d: /* bas */ |
119 | ainsn->fixup = FIXUP_RETURN_REGISTER; | 83 | fixup = FIXUP_RETURN_REGISTER; |
120 | break; | 84 | break; |
121 | case 0x47: /* bc */ | 85 | case 0x47: /* bc */ |
122 | case 0x46: /* bct */ | 86 | case 0x46: /* bct */ |
123 | case 0x86: /* bxh */ | 87 | case 0x86: /* bxh */ |
124 | case 0x87: /* bxle */ | 88 | case 0x87: /* bxle */ |
125 | ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN; | 89 | fixup = FIXUP_BRANCH_NOT_TAKEN; |
126 | break; | 90 | break; |
127 | case 0x82: /* lpsw */ | 91 | case 0x82: /* lpsw */ |
128 | ainsn->fixup = FIXUP_NOT_REQUIRED; | 92 | fixup = FIXUP_NOT_REQUIRED; |
129 | break; | 93 | break; |
130 | case 0xb2: /* lpswe */ | 94 | case 0xb2: /* lpswe */ |
131 | if (*(((__u8 *) ainsn->insn) + 1) == 0xb2) { | 95 | if ((insn[0] & 0xff) == 0xb2) |
132 | ainsn->fixup = FIXUP_NOT_REQUIRED; | 96 | fixup = FIXUP_NOT_REQUIRED; |
133 | } | ||
134 | break; | 97 | break; |
135 | case 0xa7: /* bras */ | 98 | case 0xa7: /* bras */ |
136 | if ((*ainsn->insn & 0x0f) == 0x05) { | 99 | if ((insn[0] & 0x0f) == 0x05) |
137 | ainsn->fixup |= FIXUP_RETURN_REGISTER; | 100 | fixup |= FIXUP_RETURN_REGISTER; |
138 | } | ||
139 | break; | 101 | break; |
140 | case 0xc0: | 102 | case 0xc0: |
141 | if ((*ainsn->insn & 0x0f) == 0x00 /* larl */ | 103 | if ((insn[0] & 0x0f) == 0x00 || /* larl */ |
142 | || (*ainsn->insn & 0x0f) == 0x05) /* brasl */ | 104 | (insn[0] & 0x0f) == 0x05) /* brasl */ |
143 | ainsn->fixup |= FIXUP_RETURN_REGISTER; | 105 | fixup |= FIXUP_RETURN_REGISTER; |
144 | break; | 106 | break; |
145 | case 0xeb: | 107 | case 0xeb: |
146 | if (*(((__u8 *) ainsn->insn) + 5 ) == 0x44 || /* bxhg */ | 108 | if ((insn[2] & 0xff) == 0x44 || /* bxhg */ |
147 | *(((__u8 *) ainsn->insn) + 5) == 0x45) {/* bxleg */ | 109 | (insn[2] & 0xff) == 0x45) /* bxleg */ |
148 | ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN; | 110 | fixup = FIXUP_BRANCH_NOT_TAKEN; |
149 | } | ||
150 | break; | 111 | break; |
151 | case 0xe3: /* bctg */ | 112 | case 0xe3: /* bctg */ |
152 | if (*(((__u8 *) ainsn->insn) + 5) == 0x46) { | 113 | if ((insn[2] & 0xff) == 0x46) |
153 | ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN; | 114 | fixup = FIXUP_BRANCH_NOT_TAKEN; |
154 | } | ||
155 | break; | 115 | break; |
156 | } | 116 | } |
117 | return fixup; | ||
157 | } | 118 | } |
158 | 119 | ||
120 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | ||
121 | { | ||
122 | if ((unsigned long) p->addr & 0x01) | ||
123 | return -EINVAL; | ||
124 | |||
125 | /* Make sure the probe isn't going on a difficult instruction */ | ||
126 | if (is_prohibited_opcode(p->addr)) | ||
127 | return -EINVAL; | ||
128 | |||
129 | p->opcode = *p->addr; | ||
130 | memcpy(p->ainsn.insn, p->addr, ((p->opcode >> 14) + 3) & -2); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | struct ins_replace_args { | ||
136 | kprobe_opcode_t *ptr; | ||
137 | kprobe_opcode_t opcode; | ||
138 | }; | ||
139 | |||
159 | static int __kprobes swap_instruction(void *aref) | 140 | static int __kprobes swap_instruction(void *aref) |
160 | { | 141 | { |
161 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 142 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
162 | unsigned long status = kcb->kprobe_status; | 143 | unsigned long status = kcb->kprobe_status; |
163 | struct ins_replace_args *args = aref; | 144 | struct ins_replace_args *args = aref; |
164 | int rc; | ||
165 | 145 | ||
166 | kcb->kprobe_status = KPROBE_SWAP_INST; | 146 | kcb->kprobe_status = KPROBE_SWAP_INST; |
167 | rc = probe_kernel_write(args->ptr, &args->new, sizeof(args->new)); | 147 | probe_kernel_write(args->ptr, &args->opcode, sizeof(args->opcode)); |
168 | kcb->kprobe_status = status; | 148 | kcb->kprobe_status = status; |
169 | return rc; | 149 | return 0; |
170 | } | 150 | } |
171 | 151 | ||
172 | void __kprobes arch_arm_kprobe(struct kprobe *p) | 152 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
@@ -174,8 +154,7 @@ void __kprobes arch_arm_kprobe(struct kprobe *p) | |||
174 | struct ins_replace_args args; | 154 | struct ins_replace_args args; |
175 | 155 | ||
176 | args.ptr = p->addr; | 156 | args.ptr = p->addr; |
177 | args.old = p->opcode; | 157 | args.opcode = BREAKPOINT_INSTRUCTION; |
178 | args.new = BREAKPOINT_INSTRUCTION; | ||
179 | stop_machine(swap_instruction, &args, NULL); | 158 | stop_machine(swap_instruction, &args, NULL); |
180 | } | 159 | } |
181 | 160 | ||
@@ -184,64 +163,69 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) | |||
184 | struct ins_replace_args args; | 163 | struct ins_replace_args args; |
185 | 164 | ||
186 | args.ptr = p->addr; | 165 | args.ptr = p->addr; |
187 | args.old = BREAKPOINT_INSTRUCTION; | 166 | args.opcode = p->opcode; |
188 | args.new = p->opcode; | ||
189 | stop_machine(swap_instruction, &args, NULL); | 167 | stop_machine(swap_instruction, &args, NULL); |
190 | } | 168 | } |
191 | 169 | ||
192 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 170 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
193 | { | 171 | { |
194 | if (p->ainsn.insn) { | ||
195 | free_insn_slot(p->ainsn.insn, 0); | ||
196 | p->ainsn.insn = NULL; | ||
197 | } | ||
198 | } | 172 | } |
199 | 173 | ||
200 | static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | 174 | static void __kprobes enable_singlestep(struct kprobe_ctlblk *kcb, |
175 | struct pt_regs *regs, | ||
176 | unsigned long ip) | ||
201 | { | 177 | { |
202 | per_cr_bits kprobe_per_regs[1]; | 178 | struct per_regs per_kprobe; |
203 | 179 | ||
204 | memset(kprobe_per_regs, 0, sizeof(per_cr_bits)); | 180 | /* Set up the PER control registers %cr9-%cr11 */ |
205 | regs->psw.addr = (unsigned long)p->ainsn.insn | PSW_ADDR_AMODE; | 181 | per_kprobe.control = PER_EVENT_IFETCH; |
182 | per_kprobe.start = ip; | ||
183 | per_kprobe.end = ip; | ||
206 | 184 | ||
207 | /* Set up the per control reg info, will pass to lctl */ | 185 | /* Save control regs and psw mask */ |
208 | kprobe_per_regs[0].em_instruction_fetch = 1; | 186 | __ctl_store(kcb->kprobe_saved_ctl, 9, 11); |
209 | kprobe_per_regs[0].starting_addr = (unsigned long)p->ainsn.insn; | 187 | kcb->kprobe_saved_imask = regs->psw.mask & |
210 | kprobe_per_regs[0].ending_addr = (unsigned long)p->ainsn.insn + 1; | 188 | (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT); |
211 | 189 | ||
212 | /* Set the PER control regs, turns on single step for this address */ | 190 | /* Set PER control regs, turns on single step for the given address */ |
213 | __ctl_load(kprobe_per_regs, 9, 11); | 191 | __ctl_load(per_kprobe, 9, 11); |
214 | regs->psw.mask |= PSW_MASK_PER; | 192 | regs->psw.mask |= PSW_MASK_PER; |
215 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK); | 193 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT); |
194 | regs->psw.addr = ip | PSW_ADDR_AMODE; | ||
216 | } | 195 | } |
217 | 196 | ||
218 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) | 197 | static void __kprobes disable_singlestep(struct kprobe_ctlblk *kcb, |
198 | struct pt_regs *regs, | ||
199 | unsigned long ip) | ||
219 | { | 200 | { |
220 | kcb->prev_kprobe.kp = kprobe_running(); | 201 | /* Restore control regs and psw mask, set new psw address */ |
221 | kcb->prev_kprobe.status = kcb->kprobe_status; | 202 | __ctl_load(kcb->kprobe_saved_ctl, 9, 11); |
222 | kcb->prev_kprobe.kprobe_saved_imask = kcb->kprobe_saved_imask; | 203 | regs->psw.mask &= ~PSW_MASK_PER; |
223 | memcpy(kcb->prev_kprobe.kprobe_saved_ctl, kcb->kprobe_saved_ctl, | 204 | regs->psw.mask |= kcb->kprobe_saved_imask; |
224 | sizeof(kcb->kprobe_saved_ctl)); | 205 | regs->psw.addr = ip | PSW_ADDR_AMODE; |
225 | } | 206 | } |
226 | 207 | ||
227 | static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) | 208 | /* |
209 | * Activate a kprobe by storing its pointer to current_kprobe. The | ||
210 | * previous kprobe is stored in kcb->prev_kprobe. A stack of up to | ||
211 | * two kprobes can be active, see KPROBE_REENTER. | ||
212 | */ | ||
213 | static void __kprobes push_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p) | ||
228 | { | 214 | { |
229 | __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; | 215 | kcb->prev_kprobe.kp = __get_cpu_var(current_kprobe); |
230 | kcb->kprobe_status = kcb->prev_kprobe.status; | 216 | kcb->prev_kprobe.status = kcb->kprobe_status; |
231 | kcb->kprobe_saved_imask = kcb->prev_kprobe.kprobe_saved_imask; | 217 | __get_cpu_var(current_kprobe) = p; |
232 | memcpy(kcb->kprobe_saved_ctl, kcb->prev_kprobe.kprobe_saved_ctl, | ||
233 | sizeof(kcb->kprobe_saved_ctl)); | ||
234 | } | 218 | } |
235 | 219 | ||
236 | static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, | 220 | /* |
237 | struct kprobe_ctlblk *kcb) | 221 | * Deactivate a kprobe by backing up to the previous state. If the |
222 | * current state is KPROBE_REENTER prev_kprobe.kp will be non-NULL, | ||
223 | * for any other state prev_kprobe.kp will be NULL. | ||
224 | */ | ||
225 | static void __kprobes pop_kprobe(struct kprobe_ctlblk *kcb) | ||
238 | { | 226 | { |
239 | __get_cpu_var(current_kprobe) = p; | 227 | __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; |
240 | /* Save the interrupt and per flags */ | 228 | kcb->kprobe_status = kcb->prev_kprobe.status; |
241 | kcb->kprobe_saved_imask = regs->psw.mask & | ||
242 | (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK); | ||
243 | /* Save the control regs that govern PER */ | ||
244 | __ctl_store(kcb->kprobe_saved_ctl, 9, 11); | ||
245 | } | 229 | } |
246 | 230 | ||
247 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 231 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
@@ -250,79 +234,104 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | |||
250 | ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14]; | 234 | ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14]; |
251 | 235 | ||
252 | /* Replace the return addr with trampoline addr */ | 236 | /* Replace the return addr with trampoline addr */ |
253 | regs->gprs[14] = (unsigned long)&kretprobe_trampoline; | 237 | regs->gprs[14] = (unsigned long) &kretprobe_trampoline; |
238 | } | ||
239 | |||
240 | static void __kprobes kprobe_reenter_check(struct kprobe_ctlblk *kcb, | ||
241 | struct kprobe *p) | ||
242 | { | ||
243 | switch (kcb->kprobe_status) { | ||
244 | case KPROBE_HIT_SSDONE: | ||
245 | case KPROBE_HIT_ACTIVE: | ||
246 | kprobes_inc_nmissed_count(p); | ||
247 | break; | ||
248 | case KPROBE_HIT_SS: | ||
249 | case KPROBE_REENTER: | ||
250 | default: | ||
251 | /* | ||
252 | * A kprobe on the code path to single step an instruction | ||
253 | * is a BUG. The code path resides in the .kprobes.text | ||
254 | * section and is executed with interrupts disabled. | ||
255 | */ | ||
256 | printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr); | ||
257 | dump_kprobe(p); | ||
258 | BUG(); | ||
259 | } | ||
254 | } | 260 | } |
255 | 261 | ||
256 | static int __kprobes kprobe_handler(struct pt_regs *regs) | 262 | static int __kprobes kprobe_handler(struct pt_regs *regs) |
257 | { | 263 | { |
258 | struct kprobe *p; | ||
259 | int ret = 0; | ||
260 | unsigned long *addr = (unsigned long *) | ||
261 | ((regs->psw.addr & PSW_ADDR_INSN) - 2); | ||
262 | struct kprobe_ctlblk *kcb; | 264 | struct kprobe_ctlblk *kcb; |
265 | struct kprobe *p; | ||
263 | 266 | ||
264 | /* | 267 | /* |
265 | * We don't want to be preempted for the entire | 268 | * We want to disable preemption for the entire duration of kprobe |
266 | * duration of kprobe processing | 269 | * processing. That includes the calls to the pre/post handlers |
270 | * and single stepping the kprobe instruction. | ||
267 | */ | 271 | */ |
268 | preempt_disable(); | 272 | preempt_disable(); |
269 | kcb = get_kprobe_ctlblk(); | 273 | kcb = get_kprobe_ctlblk(); |
274 | p = get_kprobe((void *)((regs->psw.addr & PSW_ADDR_INSN) - 2)); | ||
270 | 275 | ||
271 | /* Check we're not actually recursing */ | 276 | if (p) { |
272 | if (kprobe_running()) { | 277 | if (kprobe_running()) { |
273 | p = get_kprobe(addr); | 278 | /* |
274 | if (p) { | 279 | * We have hit a kprobe while another is still |
275 | if (kcb->kprobe_status == KPROBE_HIT_SS && | 280 | * active. This can happen in the pre and post |
276 | *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { | 281 | * handler. Single step the instruction of the |
277 | regs->psw.mask &= ~PSW_MASK_PER; | 282 | * new probe but do not call any handler function |
278 | regs->psw.mask |= kcb->kprobe_saved_imask; | 283 | * of this secondary kprobe. |
279 | goto no_kprobe; | 284 | * push_kprobe and pop_kprobe saves and restores |
280 | } | 285 | * the currently active kprobe. |
281 | /* We have reentered the kprobe_handler(), since | ||
282 | * another probe was hit while within the handler. | ||
283 | * We here save the original kprobes variables and | ||
284 | * just single step on the instruction of the new probe | ||
285 | * without calling any user handlers. | ||
286 | */ | 286 | */ |
287 | save_previous_kprobe(kcb); | 287 | kprobe_reenter_check(kcb, p); |
288 | set_current_kprobe(p, regs, kcb); | 288 | push_kprobe(kcb, p); |
289 | kprobes_inc_nmissed_count(p); | ||
290 | prepare_singlestep(p, regs); | ||
291 | kcb->kprobe_status = KPROBE_REENTER; | 289 | kcb->kprobe_status = KPROBE_REENTER; |
292 | return 1; | ||
293 | } else { | 290 | } else { |
294 | p = __get_cpu_var(current_kprobe); | 291 | /* |
295 | if (p->break_handler && p->break_handler(p, regs)) { | 292 | * If we have no pre-handler or it returned 0, we |
296 | goto ss_probe; | 293 | * continue with single stepping. If we have a |
297 | } | 294 | * pre-handler and it returned non-zero, it prepped |
295 | * for calling the break_handler below on re-entry | ||
296 | * for jprobe processing, so get out doing nothing | ||
297 | * more here. | ||
298 | */ | ||
299 | push_kprobe(kcb, p); | ||
300 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
301 | if (p->pre_handler && p->pre_handler(p, regs)) | ||
302 | return 1; | ||
303 | kcb->kprobe_status = KPROBE_HIT_SS; | ||
298 | } | 304 | } |
299 | goto no_kprobe; | 305 | enable_singlestep(kcb, regs, (unsigned long) p->ainsn.insn); |
300 | } | ||
301 | |||
302 | p = get_kprobe(addr); | ||
303 | if (!p) | ||
304 | /* | ||
305 | * No kprobe at this address. The fault has not been | ||
306 | * caused by a kprobe breakpoint. The race of breakpoint | ||
307 | * vs. kprobe remove does not exist because on s390 we | ||
308 | * use stop_machine to arm/disarm the breakpoints. | ||
309 | */ | ||
310 | goto no_kprobe; | ||
311 | |||
312 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
313 | set_current_kprobe(p, regs, kcb); | ||
314 | if (p->pre_handler && p->pre_handler(p, regs)) | ||
315 | /* handler has already set things up, so skip ss setup */ | ||
316 | return 1; | 306 | return 1; |
317 | 307 | } else if (kprobe_running()) { | |
318 | ss_probe: | 308 | p = __get_cpu_var(current_kprobe); |
319 | prepare_singlestep(p, regs); | 309 | if (p->break_handler && p->break_handler(p, regs)) { |
320 | kcb->kprobe_status = KPROBE_HIT_SS; | 310 | /* |
321 | return 1; | 311 | * Continuation after the jprobe completed and |
322 | 312 | * caused the jprobe_return trap. The jprobe | |
323 | no_kprobe: | 313 | * break_handler "returns" to the original |
314 | * function that still has the kprobe breakpoint | ||
315 | * installed. We continue with single stepping. | ||
316 | */ | ||
317 | kcb->kprobe_status = KPROBE_HIT_SS; | ||
318 | enable_singlestep(kcb, regs, | ||
319 | (unsigned long) p->ainsn.insn); | ||
320 | return 1; | ||
321 | } /* else: | ||
322 | * No kprobe at this address and the current kprobe | ||
323 | * has no break handler (no jprobe!). The kernel just | ||
324 | * exploded, let the standard trap handler pick up the | ||
325 | * pieces. | ||
326 | */ | ||
327 | } /* else: | ||
328 | * No kprobe at this address and no active kprobe. The trap has | ||
329 | * not been caused by a kprobe breakpoint. The race of breakpoint | ||
330 | * vs. kprobe remove does not exist because on s390 as we use | ||
331 | * stop_machine to arm/disarm the breakpoints. | ||
332 | */ | ||
324 | preempt_enable_no_resched(); | 333 | preempt_enable_no_resched(); |
325 | return ret; | 334 | return 0; |
326 | } | 335 | } |
327 | 336 | ||
328 | /* | 337 | /* |
@@ -343,11 +352,12 @@ static void __used kretprobe_trampoline_holder(void) | |||
343 | static int __kprobes trampoline_probe_handler(struct kprobe *p, | 352 | static int __kprobes trampoline_probe_handler(struct kprobe *p, |
344 | struct pt_regs *regs) | 353 | struct pt_regs *regs) |
345 | { | 354 | { |
346 | struct kretprobe_instance *ri = NULL; | 355 | struct kretprobe_instance *ri; |
347 | struct hlist_head *head, empty_rp; | 356 | struct hlist_head *head, empty_rp; |
348 | struct hlist_node *node, *tmp; | 357 | struct hlist_node *node, *tmp; |
349 | unsigned long flags, orig_ret_address = 0; | 358 | unsigned long flags, orig_ret_address; |
350 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; | 359 | unsigned long trampoline_address; |
360 | kprobe_opcode_t *correct_ret_addr; | ||
351 | 361 | ||
352 | INIT_HLIST_HEAD(&empty_rp); | 362 | INIT_HLIST_HEAD(&empty_rp); |
353 | kretprobe_hash_lock(current, &head, &flags); | 363 | kretprobe_hash_lock(current, &head, &flags); |
@@ -365,30 +375,55 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
365 | * real return address, and all the rest will point to | 375 | * real return address, and all the rest will point to |
366 | * kretprobe_trampoline | 376 | * kretprobe_trampoline |
367 | */ | 377 | */ |
378 | ri = NULL; | ||
379 | orig_ret_address = 0; | ||
380 | correct_ret_addr = NULL; | ||
381 | trampoline_address = (unsigned long) &kretprobe_trampoline; | ||
368 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | 382 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { |
369 | if (ri->task != current) | 383 | if (ri->task != current) |
370 | /* another task is sharing our hash bucket */ | 384 | /* another task is sharing our hash bucket */ |
371 | continue; | 385 | continue; |
372 | 386 | ||
373 | if (ri->rp && ri->rp->handler) | 387 | orig_ret_address = (unsigned long) ri->ret_addr; |
388 | |||
389 | if (orig_ret_address != trampoline_address) | ||
390 | /* | ||
391 | * This is the real return address. Any other | ||
392 | * instances associated with this task are for | ||
393 | * other calls deeper on the call stack | ||
394 | */ | ||
395 | break; | ||
396 | } | ||
397 | |||
398 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | ||
399 | |||
400 | correct_ret_addr = ri->ret_addr; | ||
401 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | ||
402 | if (ri->task != current) | ||
403 | /* another task is sharing our hash bucket */ | ||
404 | continue; | ||
405 | |||
406 | orig_ret_address = (unsigned long) ri->ret_addr; | ||
407 | |||
408 | if (ri->rp && ri->rp->handler) { | ||
409 | ri->ret_addr = correct_ret_addr; | ||
374 | ri->rp->handler(ri, regs); | 410 | ri->rp->handler(ri, regs); |
411 | } | ||
375 | 412 | ||
376 | orig_ret_address = (unsigned long)ri->ret_addr; | ||
377 | recycle_rp_inst(ri, &empty_rp); | 413 | recycle_rp_inst(ri, &empty_rp); |
378 | 414 | ||
379 | if (orig_ret_address != trampoline_address) { | 415 | if (orig_ret_address != trampoline_address) |
380 | /* | 416 | /* |
381 | * This is the real return address. Any other | 417 | * This is the real return address. Any other |
382 | * instances associated with this task are for | 418 | * instances associated with this task are for |
383 | * other calls deeper on the call stack | 419 | * other calls deeper on the call stack |
384 | */ | 420 | */ |
385 | break; | 421 | break; |
386 | } | ||
387 | } | 422 | } |
388 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | 423 | |
389 | regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE; | 424 | regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE; |
390 | 425 | ||
391 | reset_current_kprobe(); | 426 | pop_kprobe(get_kprobe_ctlblk()); |
392 | kretprobe_hash_unlock(current, &flags); | 427 | kretprobe_hash_unlock(current, &flags); |
393 | preempt_enable_no_resched(); | 428 | preempt_enable_no_resched(); |
394 | 429 | ||
@@ -415,55 +450,42 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
415 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) | 450 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) |
416 | { | 451 | { |
417 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 452 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
453 | unsigned long ip = regs->psw.addr & PSW_ADDR_INSN; | ||
454 | int fixup = get_fixup_type(p->ainsn.insn); | ||
418 | 455 | ||
419 | regs->psw.addr &= PSW_ADDR_INSN; | 456 | if (fixup & FIXUP_PSW_NORMAL) |
420 | 457 | ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn; | |
421 | if (p->ainsn.fixup & FIXUP_PSW_NORMAL) | ||
422 | regs->psw.addr = (unsigned long)p->addr + | ||
423 | ((unsigned long)regs->psw.addr - | ||
424 | (unsigned long)p->ainsn.insn); | ||
425 | 458 | ||
426 | if (p->ainsn.fixup & FIXUP_BRANCH_NOT_TAKEN) | 459 | if (fixup & FIXUP_BRANCH_NOT_TAKEN) { |
427 | if ((unsigned long)regs->psw.addr - | 460 | int ilen = ((p->ainsn.insn[0] >> 14) + 3) & -2; |
428 | (unsigned long)p->ainsn.insn == p->ainsn.ilen) | 461 | if (ip - (unsigned long) p->ainsn.insn == ilen) |
429 | regs->psw.addr = (unsigned long)p->addr + p->ainsn.ilen; | 462 | ip = (unsigned long) p->addr + ilen; |
463 | } | ||
430 | 464 | ||
431 | if (p->ainsn.fixup & FIXUP_RETURN_REGISTER) | 465 | if (fixup & FIXUP_RETURN_REGISTER) { |
432 | regs->gprs[p->ainsn.reg] = ((unsigned long)p->addr + | 466 | int reg = (p->ainsn.insn[0] & 0xf0) >> 4; |
433 | (regs->gprs[p->ainsn.reg] - | 467 | regs->gprs[reg] += (unsigned long) p->addr - |
434 | (unsigned long)p->ainsn.insn)) | 468 | (unsigned long) p->ainsn.insn; |
435 | | PSW_ADDR_AMODE; | 469 | } |
436 | 470 | ||
437 | regs->psw.addr |= PSW_ADDR_AMODE; | 471 | disable_singlestep(kcb, regs, ip); |
438 | /* turn off PER mode */ | ||
439 | regs->psw.mask &= ~PSW_MASK_PER; | ||
440 | /* Restore the original per control regs */ | ||
441 | __ctl_load(kcb->kprobe_saved_ctl, 9, 11); | ||
442 | regs->psw.mask |= kcb->kprobe_saved_imask; | ||
443 | } | 472 | } |
444 | 473 | ||
445 | static int __kprobes post_kprobe_handler(struct pt_regs *regs) | 474 | static int __kprobes post_kprobe_handler(struct pt_regs *regs) |
446 | { | 475 | { |
447 | struct kprobe *cur = kprobe_running(); | ||
448 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 476 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
477 | struct kprobe *p = kprobe_running(); | ||
449 | 478 | ||
450 | if (!cur) | 479 | if (!p) |
451 | return 0; | 480 | return 0; |
452 | 481 | ||
453 | if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { | 482 | if (kcb->kprobe_status != KPROBE_REENTER && p->post_handler) { |
454 | kcb->kprobe_status = KPROBE_HIT_SSDONE; | 483 | kcb->kprobe_status = KPROBE_HIT_SSDONE; |
455 | cur->post_handler(cur, regs, 0); | 484 | p->post_handler(p, regs, 0); |
456 | } | 485 | } |
457 | 486 | ||
458 | resume_execution(cur, regs); | 487 | resume_execution(p, regs); |
459 | 488 | pop_kprobe(kcb); | |
460 | /*Restore back the original saved kprobes variables and continue. */ | ||
461 | if (kcb->kprobe_status == KPROBE_REENTER) { | ||
462 | restore_previous_kprobe(kcb); | ||
463 | goto out; | ||
464 | } | ||
465 | reset_current_kprobe(); | ||
466 | out: | ||
467 | preempt_enable_no_resched(); | 489 | preempt_enable_no_resched(); |
468 | 490 | ||
469 | /* | 491 | /* |
@@ -471,17 +493,16 @@ out: | |||
471 | * will have PER set, in which case, continue the remaining processing | 493 | * will have PER set, in which case, continue the remaining processing |
472 | * of do_single_step, as if this is not a probe hit. | 494 | * of do_single_step, as if this is not a probe hit. |
473 | */ | 495 | */ |
474 | if (regs->psw.mask & PSW_MASK_PER) { | 496 | if (regs->psw.mask & PSW_MASK_PER) |
475 | return 0; | 497 | return 0; |
476 | } | ||
477 | 498 | ||
478 | return 1; | 499 | return 1; |
479 | } | 500 | } |
480 | 501 | ||
481 | int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | 502 | static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr) |
482 | { | 503 | { |
483 | struct kprobe *cur = kprobe_running(); | ||
484 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 504 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
505 | struct kprobe *p = kprobe_running(); | ||
485 | const struct exception_table_entry *entry; | 506 | const struct exception_table_entry *entry; |
486 | 507 | ||
487 | switch(kcb->kprobe_status) { | 508 | switch(kcb->kprobe_status) { |
@@ -497,13 +518,8 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
497 | * and allow the page fault handler to continue as a | 518 | * and allow the page fault handler to continue as a |
498 | * normal page fault. | 519 | * normal page fault. |
499 | */ | 520 | */ |
500 | regs->psw.addr = (unsigned long)cur->addr | PSW_ADDR_AMODE; | 521 | disable_singlestep(kcb, regs, (unsigned long) p->addr); |
501 | regs->psw.mask &= ~PSW_MASK_PER; | 522 | pop_kprobe(kcb); |
502 | regs->psw.mask |= kcb->kprobe_saved_imask; | ||
503 | if (kcb->kprobe_status == KPROBE_REENTER) | ||
504 | restore_previous_kprobe(kcb); | ||
505 | else | ||
506 | reset_current_kprobe(); | ||
507 | preempt_enable_no_resched(); | 523 | preempt_enable_no_resched(); |
508 | break; | 524 | break; |
509 | case KPROBE_HIT_ACTIVE: | 525 | case KPROBE_HIT_ACTIVE: |
@@ -513,7 +529,7 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
513 | * we can also use npre/npostfault count for accouting | 529 | * we can also use npre/npostfault count for accouting |
514 | * these specific fault cases. | 530 | * these specific fault cases. |
515 | */ | 531 | */ |
516 | kprobes_inc_nmissed_count(cur); | 532 | kprobes_inc_nmissed_count(p); |
517 | 533 | ||
518 | /* | 534 | /* |
519 | * We come here because instructions in the pre/post | 535 | * We come here because instructions in the pre/post |
@@ -522,7 +538,7 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
522 | * copy_from_user(), get_user() etc. Let the | 538 | * copy_from_user(), get_user() etc. Let the |
523 | * user-specified handler try to fix it first. | 539 | * user-specified handler try to fix it first. |
524 | */ | 540 | */ |
525 | if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) | 541 | if (p->fault_handler && p->fault_handler(p, regs, trapnr)) |
526 | return 1; | 542 | return 1; |
527 | 543 | ||
528 | /* | 544 | /* |
@@ -546,57 +562,71 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
546 | return 0; | 562 | return 0; |
547 | } | 563 | } |
548 | 564 | ||
565 | int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | ||
566 | { | ||
567 | int ret; | ||
568 | |||
569 | if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT)) | ||
570 | local_irq_disable(); | ||
571 | ret = kprobe_trap_handler(regs, trapnr); | ||
572 | if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT)) | ||
573 | local_irq_restore(regs->psw.mask & ~PSW_MASK_PER); | ||
574 | return ret; | ||
575 | } | ||
576 | |||
549 | /* | 577 | /* |
550 | * Wrapper routine to for handling exceptions. | 578 | * Wrapper routine to for handling exceptions. |
551 | */ | 579 | */ |
552 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | 580 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, |
553 | unsigned long val, void *data) | 581 | unsigned long val, void *data) |
554 | { | 582 | { |
555 | struct die_args *args = (struct die_args *)data; | 583 | struct die_args *args = (struct die_args *) data; |
584 | struct pt_regs *regs = args->regs; | ||
556 | int ret = NOTIFY_DONE; | 585 | int ret = NOTIFY_DONE; |
557 | 586 | ||
587 | if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT)) | ||
588 | local_irq_disable(); | ||
589 | |||
558 | switch (val) { | 590 | switch (val) { |
559 | case DIE_BPT: | 591 | case DIE_BPT: |
560 | if (kprobe_handler(args->regs)) | 592 | if (kprobe_handler(regs)) |
561 | ret = NOTIFY_STOP; | 593 | ret = NOTIFY_STOP; |
562 | break; | 594 | break; |
563 | case DIE_SSTEP: | 595 | case DIE_SSTEP: |
564 | if (post_kprobe_handler(args->regs)) | 596 | if (post_kprobe_handler(regs)) |
565 | ret = NOTIFY_STOP; | 597 | ret = NOTIFY_STOP; |
566 | break; | 598 | break; |
567 | case DIE_TRAP: | 599 | case DIE_TRAP: |
568 | /* kprobe_running() needs smp_processor_id() */ | 600 | if (!preemptible() && kprobe_running() && |
569 | preempt_disable(); | 601 | kprobe_trap_handler(regs, args->trapnr)) |
570 | if (kprobe_running() && | ||
571 | kprobe_fault_handler(args->regs, args->trapnr)) | ||
572 | ret = NOTIFY_STOP; | 602 | ret = NOTIFY_STOP; |
573 | preempt_enable(); | ||
574 | break; | 603 | break; |
575 | default: | 604 | default: |
576 | break; | 605 | break; |
577 | } | 606 | } |
607 | |||
608 | if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT)) | ||
609 | local_irq_restore(regs->psw.mask & ~PSW_MASK_PER); | ||
610 | |||
578 | return ret; | 611 | return ret; |
579 | } | 612 | } |
580 | 613 | ||
581 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 614 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
582 | { | 615 | { |
583 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 616 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
584 | unsigned long addr; | ||
585 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 617 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
618 | unsigned long stack; | ||
586 | 619 | ||
587 | memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs)); | 620 | memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs)); |
588 | 621 | ||
589 | /* setup return addr to the jprobe handler routine */ | 622 | /* setup return addr to the jprobe handler routine */ |
590 | regs->psw.addr = (unsigned long)(jp->entry) | PSW_ADDR_AMODE; | 623 | regs->psw.addr = (unsigned long) jp->entry | PSW_ADDR_AMODE; |
624 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT); | ||
591 | 625 | ||
592 | /* r14 is the function return address */ | ||
593 | kcb->jprobe_saved_r14 = (unsigned long)regs->gprs[14]; | ||
594 | /* r15 is the stack pointer */ | 626 | /* r15 is the stack pointer */ |
595 | kcb->jprobe_saved_r15 = (unsigned long)regs->gprs[15]; | 627 | stack = (unsigned long) regs->gprs[15]; |
596 | addr = (unsigned long)kcb->jprobe_saved_r15; | ||
597 | 628 | ||
598 | memcpy(kcb->jprobes_stack, (kprobe_opcode_t *) addr, | 629 | memcpy(kcb->jprobes_stack, (void *) stack, MIN_STACK_SIZE(stack)); |
599 | MIN_STACK_SIZE(addr)); | ||
600 | return 1; | 630 | return 1; |
601 | } | 631 | } |
602 | 632 | ||
@@ -613,30 +643,29 @@ void __kprobes jprobe_return_end(void) | |||
613 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 643 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
614 | { | 644 | { |
615 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 645 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
616 | unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_r15); | 646 | unsigned long stack; |
647 | |||
648 | stack = (unsigned long) kcb->jprobe_saved_regs.gprs[15]; | ||
617 | 649 | ||
618 | /* Put the regs back */ | 650 | /* Put the regs back */ |
619 | memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); | 651 | memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); |
620 | /* put the stack back */ | 652 | /* put the stack back */ |
621 | memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, | 653 | memcpy((void *) stack, kcb->jprobes_stack, MIN_STACK_SIZE(stack)); |
622 | MIN_STACK_SIZE(stack_addr)); | ||
623 | preempt_enable_no_resched(); | 654 | preempt_enable_no_resched(); |
624 | return 1; | 655 | return 1; |
625 | } | 656 | } |
626 | 657 | ||
627 | static struct kprobe trampoline_p = { | 658 | static struct kprobe trampoline = { |
628 | .addr = (kprobe_opcode_t *) & kretprobe_trampoline, | 659 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, |
629 | .pre_handler = trampoline_probe_handler | 660 | .pre_handler = trampoline_probe_handler |
630 | }; | 661 | }; |
631 | 662 | ||
632 | int __init arch_init_kprobes(void) | 663 | int __init arch_init_kprobes(void) |
633 | { | 664 | { |
634 | return register_kprobe(&trampoline_p); | 665 | return register_kprobe(&trampoline); |
635 | } | 666 | } |
636 | 667 | ||
637 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | 668 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) |
638 | { | 669 | { |
639 | if (p->addr == (kprobe_opcode_t *) & kretprobe_trampoline) | 670 | return p->addr == (kprobe_opcode_t *) &kretprobe_trampoline; |
640 | return 1; | ||
641 | return 0; | ||
642 | } | 671 | } |
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index a922d51df6bf..b09b9c62573e 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/kexec.h> | 12 | #include <linux/kexec.h> |
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/reboot.h> | 14 | #include <linux/reboot.h> |
15 | #include <linux/ftrace.h> | ||
15 | #include <asm/cio.h> | 16 | #include <asm/cio.h> |
16 | #include <asm/setup.h> | 17 | #include <asm/setup.h> |
17 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
@@ -71,6 +72,7 @@ static void __machine_kexec(void *data) | |||
71 | 72 | ||
72 | void machine_kexec(struct kimage *image) | 73 | void machine_kexec(struct kimage *image) |
73 | { | 74 | { |
75 | tracer_disable(); | ||
74 | smp_send_stop(); | 76 | smp_send_stop(); |
75 | smp_switch_to_ipl_cpu(__machine_kexec, image); | 77 | smp_switch_to_ipl_cpu(__machine_kexec, image); |
76 | } | 78 | } |
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index dfe015d7398c..1e6a55795628 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S | |||
@@ -7,6 +7,8 @@ | |||
7 | 7 | ||
8 | #include <asm/asm-offsets.h> | 8 | #include <asm/asm-offsets.h> |
9 | 9 | ||
10 | .section .kprobes.text, "ax" | ||
11 | |||
10 | .globl ftrace_stub | 12 | .globl ftrace_stub |
11 | ftrace_stub: | 13 | ftrace_stub: |
12 | br %r14 | 14 | br %r14 |
@@ -16,22 +18,12 @@ _mcount: | |||
16 | #ifdef CONFIG_DYNAMIC_FTRACE | 18 | #ifdef CONFIG_DYNAMIC_FTRACE |
17 | br %r14 | 19 | br %r14 |
18 | 20 | ||
19 | .data | ||
20 | .globl ftrace_dyn_func | ||
21 | ftrace_dyn_func: | ||
22 | .long ftrace_stub | ||
23 | .previous | ||
24 | |||
25 | .globl ftrace_caller | 21 | .globl ftrace_caller |
26 | ftrace_caller: | 22 | ftrace_caller: |
27 | #endif | 23 | #endif |
28 | stm %r2,%r5,16(%r15) | 24 | stm %r2,%r5,16(%r15) |
29 | bras %r1,2f | 25 | bras %r1,2f |
30 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
31 | 0: .long ftrace_dyn_func | ||
32 | #else | ||
33 | 0: .long ftrace_trace_function | 26 | 0: .long ftrace_trace_function |
34 | #endif | ||
35 | 1: .long function_trace_stop | 27 | 1: .long function_trace_stop |
36 | 2: l %r2,1b-0b(%r1) | 28 | 2: l %r2,1b-0b(%r1) |
37 | icm %r2,0xf,0(%r2) | 29 | icm %r2,0xf,0(%r2) |
@@ -47,21 +39,15 @@ ftrace_caller: | |||
47 | l %r14,0(%r14) | 39 | l %r14,0(%r14) |
48 | basr %r14,%r14 | 40 | basr %r14,%r14 |
49 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 41 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
50 | #ifdef CONFIG_DYNAMIC_FTRACE | 42 | l %r2,100(%r15) |
43 | l %r3,152(%r15) | ||
51 | .globl ftrace_graph_caller | 44 | .globl ftrace_graph_caller |
52 | ftrace_graph_caller: | 45 | ftrace_graph_caller: |
53 | # This unconditional branch gets runtime patched. Change only if | 46 | # The bras instruction gets runtime patched to call prepare_ftrace_return. |
54 | # you know what you are doing. See ftrace_enable_graph_caller(). | 47 | # See ftrace_enable_ftrace_graph_caller. The patched instruction is: |
55 | j 1f | 48 | # bras %r14,prepare_ftrace_return |
56 | #endif | 49 | bras %r14,0f |
57 | bras %r1,0f | 50 | 0: st %r2,100(%r15) |
58 | .long prepare_ftrace_return | ||
59 | 0: l %r2,152(%r15) | ||
60 | l %r4,0(%r1) | ||
61 | l %r3,100(%r15) | ||
62 | basr %r14,%r4 | ||
63 | st %r2,100(%r15) | ||
64 | 1: | ||
65 | #endif | 51 | #endif |
66 | ahi %r15,96 | 52 | ahi %r15,96 |
67 | l %r14,56(%r15) | 53 | l %r14,56(%r15) |
diff --git a/arch/s390/kernel/mcount64.S b/arch/s390/kernel/mcount64.S index c37211c6092b..e73667286ac0 100644 --- a/arch/s390/kernel/mcount64.S +++ b/arch/s390/kernel/mcount64.S | |||
@@ -7,6 +7,8 @@ | |||
7 | 7 | ||
8 | #include <asm/asm-offsets.h> | 8 | #include <asm/asm-offsets.h> |
9 | 9 | ||
10 | .section .kprobes.text, "ax" | ||
11 | |||
10 | .globl ftrace_stub | 12 | .globl ftrace_stub |
11 | ftrace_stub: | 13 | ftrace_stub: |
12 | br %r14 | 14 | br %r14 |
@@ -16,12 +18,6 @@ _mcount: | |||
16 | #ifdef CONFIG_DYNAMIC_FTRACE | 18 | #ifdef CONFIG_DYNAMIC_FTRACE |
17 | br %r14 | 19 | br %r14 |
18 | 20 | ||
19 | .data | ||
20 | .globl ftrace_dyn_func | ||
21 | ftrace_dyn_func: | ||
22 | .quad ftrace_stub | ||
23 | .previous | ||
24 | |||
25 | .globl ftrace_caller | 21 | .globl ftrace_caller |
26 | ftrace_caller: | 22 | ftrace_caller: |
27 | #endif | 23 | #endif |
@@ -35,26 +31,19 @@ ftrace_caller: | |||
35 | stg %r1,__SF_BACKCHAIN(%r15) | 31 | stg %r1,__SF_BACKCHAIN(%r15) |
36 | lgr %r2,%r14 | 32 | lgr %r2,%r14 |
37 | lg %r3,168(%r15) | 33 | lg %r3,168(%r15) |
38 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
39 | larl %r14,ftrace_dyn_func | ||
40 | #else | ||
41 | larl %r14,ftrace_trace_function | 34 | larl %r14,ftrace_trace_function |
42 | #endif | ||
43 | lg %r14,0(%r14) | 35 | lg %r14,0(%r14) |
44 | basr %r14,%r14 | 36 | basr %r14,%r14 |
45 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 37 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
46 | #ifdef CONFIG_DYNAMIC_FTRACE | 38 | lg %r2,168(%r15) |
39 | lg %r3,272(%r15) | ||
47 | .globl ftrace_graph_caller | 40 | .globl ftrace_graph_caller |
48 | ftrace_graph_caller: | 41 | ftrace_graph_caller: |
49 | # This unconditional branch gets runtime patched. Change only if | 42 | # The bras instruction gets runtime patched to call prepare_ftrace_return. |
50 | # you know what you are doing. See ftrace_enable_graph_caller(). | 43 | # See ftrace_enable_ftrace_graph_caller. The patched instruction is: |
51 | j 0f | 44 | # bras %r14,prepare_ftrace_return |
52 | #endif | 45 | bras %r14,0f |
53 | lg %r2,272(%r15) | 46 | 0: stg %r2,168(%r15) |
54 | lg %r3,168(%r15) | ||
55 | brasl %r14,prepare_ftrace_return | ||
56 | stg %r2,168(%r15) | ||
57 | 0: | ||
58 | #endif | 47 | #endif |
59 | aghi %r15,160 | 48 | aghi %r15,160 |
60 | lmg %r2,%r5,32(%r15) | 49 | lmg %r2,%r5,32(%r15) |
diff --git a/arch/s390/kernel/mem_detect.c b/arch/s390/kernel/mem_detect.c index 559af0d07878..0fbe4e32f7ba 100644 --- a/arch/s390/kernel/mem_detect.c +++ b/arch/s390/kernel/mem_detect.c | |||
@@ -54,11 +54,11 @@ void detect_memory_layout(struct mem_chunk chunk[]) | |||
54 | * right thing and we don't get scheduled away with low address | 54 | * right thing and we don't get scheduled away with low address |
55 | * protection disabled. | 55 | * protection disabled. |
56 | */ | 56 | */ |
57 | flags = __raw_local_irq_stnsm(0xf8); | 57 | flags = __arch_local_irq_stnsm(0xf8); |
58 | __ctl_store(cr0, 0, 0); | 58 | __ctl_store(cr0, 0, 0); |
59 | __ctl_clear_bit(0, 28); | 59 | __ctl_clear_bit(0, 28); |
60 | find_memory_chunks(chunk); | 60 | find_memory_chunks(chunk); |
61 | __ctl_load(cr0, 0, 0); | 61 | __ctl_load(cr0, 0, 0); |
62 | __raw_local_irq_ssm(flags); | 62 | arch_local_irq_restore(flags); |
63 | } | 63 | } |
64 | EXPORT_SYMBOL(detect_memory_layout); | 64 | EXPORT_SYMBOL(detect_memory_layout); |
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index ac151399ef34..fab88431a06f 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Heiko Carstens <heiko.carstens@de.ibm.com>, | 8 | * Heiko Carstens <heiko.carstens@de.ibm.com>, |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/kernel_stat.h> | ||
11 | #include <linux/init.h> | 12 | #include <linux/init.h> |
12 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
13 | #include <linux/hardirq.h> | 14 | #include <linux/hardirq.h> |
@@ -95,7 +96,6 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck); | |||
95 | static int notrace s390_revalidate_registers(struct mci *mci) | 96 | static int notrace s390_revalidate_registers(struct mci *mci) |
96 | { | 97 | { |
97 | int kill_task; | 98 | int kill_task; |
98 | u64 tmpclock; | ||
99 | u64 zero; | 99 | u64 zero; |
100 | void *fpt_save_area, *fpt_creg_save_area; | 100 | void *fpt_save_area, *fpt_creg_save_area; |
101 | 101 | ||
@@ -214,11 +214,10 @@ static int notrace s390_revalidate_registers(struct mci *mci) | |||
214 | : "0", "cc"); | 214 | : "0", "cc"); |
215 | #endif | 215 | #endif |
216 | /* Revalidate clock comparator register */ | 216 | /* Revalidate clock comparator register */ |
217 | asm volatile( | 217 | if (S390_lowcore.clock_comparator == -1) |
218 | " stck 0(%1)\n" | 218 | set_clock_comparator(S390_lowcore.mcck_clock); |
219 | " sckc 0(%1)" | 219 | else |
220 | : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory"); | 220 | set_clock_comparator(S390_lowcore.clock_comparator); |
221 | |||
222 | /* Check if old PSW is valid */ | 221 | /* Check if old PSW is valid */ |
223 | if (!mci->wp) | 222 | if (!mci->wp) |
224 | /* | 223 | /* |
@@ -257,7 +256,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs) | |||
257 | nmi_enter(); | 256 | nmi_enter(); |
258 | s390_idle_check(regs, S390_lowcore.mcck_clock, | 257 | s390_idle_check(regs, S390_lowcore.mcck_clock, |
259 | S390_lowcore.mcck_enter_timer); | 258 | S390_lowcore.mcck_enter_timer); |
260 | 259 | kstat_cpu(smp_processor_id()).irqs[NMI_NMI]++; | |
261 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; | 260 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; |
262 | mcck = &__get_cpu_var(cpu_mcck); | 261 | mcck = &__get_cpu_var(cpu_mcck); |
263 | umode = user_mode(regs); | 262 | umode = user_mode(regs); |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index d3a2d1c6438e..541a7509faeb 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -9,38 +9,27 @@ | |||
9 | 9 | ||
10 | #include <linux/compiler.h> | 10 | #include <linux/compiler.h> |
11 | #include <linux/cpu.h> | 11 | #include <linux/cpu.h> |
12 | #include <linux/errno.h> | ||
13 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
14 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
15 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
16 | #include <linux/fs.h> | ||
17 | #include <linux/smp.h> | 15 | #include <linux/smp.h> |
18 | #include <linux/stddef.h> | ||
19 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
20 | #include <linux/unistd.h> | ||
21 | #include <linux/ptrace.h> | ||
22 | #include <linux/vmalloc.h> | ||
23 | #include <linux/user.h> | ||
24 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
25 | #include <linux/delay.h> | ||
26 | #include <linux/reboot.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/notifier.h> | ||
30 | #include <linux/tick.h> | 18 | #include <linux/tick.h> |
31 | #include <linux/elfcore.h> | 19 | #include <linux/personality.h> |
32 | #include <linux/kernel_stat.h> | ||
33 | #include <linux/syscalls.h> | 20 | #include <linux/syscalls.h> |
34 | #include <linux/compat.h> | 21 | #include <linux/compat.h> |
35 | #include <asm/compat.h> | 22 | #include <linux/kprobes.h> |
36 | #include <asm/uaccess.h> | 23 | #include <linux/random.h> |
37 | #include <asm/pgtable.h> | 24 | #include <linux/module.h> |
38 | #include <asm/system.h> | 25 | #include <asm/system.h> |
39 | #include <asm/io.h> | 26 | #include <asm/io.h> |
40 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
41 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
42 | #include <asm/timer.h> | 29 | #include <asm/timer.h> |
43 | #include <asm/nmi.h> | 30 | #include <asm/nmi.h> |
31 | #include <asm/compat.h> | ||
32 | #include <asm/smp.h> | ||
44 | #include "entry.h" | 33 | #include "entry.h" |
45 | 34 | ||
46 | asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); | 35 | asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); |
@@ -75,18 +64,13 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
75 | */ | 64 | */ |
76 | static void default_idle(void) | 65 | static void default_idle(void) |
77 | { | 66 | { |
78 | /* CPU is going idle. */ | 67 | if (cpu_is_offline(smp_processor_id())) |
68 | cpu_die(); | ||
79 | local_irq_disable(); | 69 | local_irq_disable(); |
80 | if (need_resched()) { | 70 | if (need_resched()) { |
81 | local_irq_enable(); | 71 | local_irq_enable(); |
82 | return; | 72 | return; |
83 | } | 73 | } |
84 | #ifdef CONFIG_HOTPLUG_CPU | ||
85 | if (cpu_is_offline(smp_processor_id())) { | ||
86 | preempt_enable_no_resched(); | ||
87 | cpu_die(); | ||
88 | } | ||
89 | #endif | ||
90 | local_mcck_disable(); | 74 | local_mcck_disable(); |
91 | if (test_thread_flag(TIF_MCCK_PENDING)) { | 75 | if (test_thread_flag(TIF_MCCK_PENDING)) { |
92 | local_mcck_enable(); | 76 | local_mcck_enable(); |
@@ -116,15 +100,17 @@ void cpu_idle(void) | |||
116 | } | 100 | } |
117 | } | 101 | } |
118 | 102 | ||
119 | extern void kernel_thread_starter(void); | 103 | extern void __kprobes kernel_thread_starter(void); |
120 | 104 | ||
121 | asm( | 105 | asm( |
122 | ".align 4\n" | 106 | ".section .kprobes.text, \"ax\"\n" |
107 | ".global kernel_thread_starter\n" | ||
123 | "kernel_thread_starter:\n" | 108 | "kernel_thread_starter:\n" |
124 | " la 2,0(10)\n" | 109 | " la 2,0(10)\n" |
125 | " basr 14,9\n" | 110 | " basr 14,9\n" |
126 | " la 2,0\n" | 111 | " la 2,0\n" |
127 | " br 11\n"); | 112 | " br 11\n" |
113 | ".previous\n"); | ||
128 | 114 | ||
129 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | 115 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) |
130 | { | 116 | { |
@@ -214,8 +200,10 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
214 | /* start new process with ar4 pointing to the correct address space */ | 200 | /* start new process with ar4 pointing to the correct address space */ |
215 | p->thread.mm_segment = get_fs(); | 201 | p->thread.mm_segment = get_fs(); |
216 | /* Don't copy debug registers */ | 202 | /* Don't copy debug registers */ |
217 | memset(&p->thread.per_info, 0, sizeof(p->thread.per_info)); | 203 | memset(&p->thread.per_user, 0, sizeof(p->thread.per_user)); |
204 | memset(&p->thread.per_event, 0, sizeof(p->thread.per_event)); | ||
218 | clear_tsk_thread_flag(p, TIF_SINGLE_STEP); | 205 | clear_tsk_thread_flag(p, TIF_SINGLE_STEP); |
206 | clear_tsk_thread_flag(p, TIF_PER_TRAP); | ||
219 | /* Initialize per thread user and system timer values */ | 207 | /* Initialize per thread user and system timer values */ |
220 | ti = task_thread_info(p); | 208 | ti = task_thread_info(p); |
221 | ti->user_timer = 0; | 209 | ti->user_timer = 0; |
@@ -331,3 +319,39 @@ unsigned long get_wchan(struct task_struct *p) | |||
331 | } | 319 | } |
332 | return 0; | 320 | return 0; |
333 | } | 321 | } |
322 | |||
323 | unsigned long arch_align_stack(unsigned long sp) | ||
324 | { | ||
325 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) | ||
326 | sp -= get_random_int() & ~PAGE_MASK; | ||
327 | return sp & ~0xf; | ||
328 | } | ||
329 | |||
330 | static inline unsigned long brk_rnd(void) | ||
331 | { | ||
332 | /* 8MB for 32bit, 1GB for 64bit */ | ||
333 | if (is_32bit_task()) | ||
334 | return (get_random_int() & 0x7ffUL) << PAGE_SHIFT; | ||
335 | else | ||
336 | return (get_random_int() & 0x3ffffUL) << PAGE_SHIFT; | ||
337 | } | ||
338 | |||
339 | unsigned long arch_randomize_brk(struct mm_struct *mm) | ||
340 | { | ||
341 | unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd()); | ||
342 | |||
343 | if (ret < mm->brk) | ||
344 | return mm->brk; | ||
345 | return ret; | ||
346 | } | ||
347 | |||
348 | unsigned long randomize_et_dyn(unsigned long base) | ||
349 | { | ||
350 | unsigned long ret = PAGE_ALIGN(base + brk_rnd()); | ||
351 | |||
352 | if (!(current->flags & PF_RANDOMIZE)) | ||
353 | return base; | ||
354 | if (ret < base) | ||
355 | return base; | ||
356 | return ret; | ||
357 | } | ||
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index ecb2d02b02e4..311e9d712888 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | 16 | #include <linux/cpu.h> | |
17 | #include <asm/elf.h> | 17 | #include <asm/elf.h> |
18 | #include <asm/lowcore.h> | 18 | #include <asm/lowcore.h> |
19 | #include <asm/param.h> | 19 | #include <asm/param.h> |
@@ -35,17 +35,6 @@ void __cpuinit cpu_init(void) | |||
35 | } | 35 | } |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * print_cpu_info - print basic information about a cpu | ||
39 | */ | ||
40 | void __cpuinit print_cpu_info(void) | ||
41 | { | ||
42 | struct cpuid *id = &per_cpu(cpu_id, smp_processor_id()); | ||
43 | |||
44 | pr_info("Processor %d started, address %d, identification %06X\n", | ||
45 | S390_lowcore.cpu_nr, S390_lowcore.cpu_addr, id->ident); | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * show_cpuinfo - Get information on one CPU for use by procfs. | 38 | * show_cpuinfo - Get information on one CPU for use by procfs. |
50 | */ | 39 | */ |
51 | static int show_cpuinfo(struct seq_file *m, void *v) | 40 | static int show_cpuinfo(struct seq_file *m, void *v) |
@@ -57,9 +46,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
57 | unsigned long n = (unsigned long) v - 1; | 46 | unsigned long n = (unsigned long) v - 1; |
58 | int i; | 47 | int i; |
59 | 48 | ||
60 | s390_adjust_jiffies(); | ||
61 | preempt_disable(); | ||
62 | if (!n) { | 49 | if (!n) { |
50 | s390_adjust_jiffies(); | ||
63 | seq_printf(m, "vendor_id : IBM/S390\n" | 51 | seq_printf(m, "vendor_id : IBM/S390\n" |
64 | "# processors : %i\n" | 52 | "# processors : %i\n" |
65 | "bogomips per cpu: %lu.%02lu\n", | 53 | "bogomips per cpu: %lu.%02lu\n", |
@@ -71,7 +59,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
71 | seq_printf(m, "%s ", hwcap_str[i]); | 59 | seq_printf(m, "%s ", hwcap_str[i]); |
72 | seq_puts(m, "\n"); | 60 | seq_puts(m, "\n"); |
73 | } | 61 | } |
74 | 62 | get_online_cpus(); | |
75 | if (cpu_online(n)) { | 63 | if (cpu_online(n)) { |
76 | struct cpuid *id = &per_cpu(cpu_id, n); | 64 | struct cpuid *id = &per_cpu(cpu_id, n); |
77 | seq_printf(m, "processor %li: " | 65 | seq_printf(m, "processor %li: " |
@@ -80,7 +68,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
80 | "machine = %04X\n", | 68 | "machine = %04X\n", |
81 | n, id->version, id->ident, id->machine); | 69 | n, id->version, id->ident, id->machine); |
82 | } | 70 | } |
83 | preempt_enable(); | 71 | put_online_cpus(); |
84 | return 0; | 72 | return 0; |
85 | } | 73 | } |
86 | 74 | ||
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 83339d33c4b1..ef86ad243986 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -1,25 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/ptrace.c | 2 | * Ptrace user space interface. |
3 | * | 3 | * |
4 | * S390 version | 4 | * Copyright IBM Corp. 1999,2010 |
5 | * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation | 5 | * Author(s): Denis Joseph Barrow |
6 | * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), | ||
7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 6 | * Martin Schwidefsky (schwidefsky@de.ibm.com) |
8 | * | ||
9 | * Based on PowerPC version | ||
10 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
11 | * | ||
12 | * Derived from "arch/m68k/kernel/ptrace.c" | ||
13 | * Copyright (C) 1994 by Hamish Macdonald | ||
14 | * Taken from linux/kernel/ptrace.c and modified for M680x0. | ||
15 | * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds | ||
16 | * | ||
17 | * Modified by Cort Dougan (cort@cs.nmt.edu) | ||
18 | * | ||
19 | * | ||
20 | * This file is subject to the terms and conditions of the GNU General | ||
21 | * Public License. See the file README.legal in the main directory of | ||
22 | * this archive for more details. | ||
23 | */ | 7 | */ |
24 | 8 | ||
25 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
@@ -61,76 +45,58 @@ enum s390_regset { | |||
61 | REGSET_GENERAL_EXTENDED, | 45 | REGSET_GENERAL_EXTENDED, |
62 | }; | 46 | }; |
63 | 47 | ||
64 | static void | 48 | void update_per_regs(struct task_struct *task) |
65 | FixPerRegisters(struct task_struct *task) | ||
66 | { | 49 | { |
67 | struct pt_regs *regs; | 50 | static const struct per_regs per_single_step = { |
68 | per_struct *per_info; | 51 | .control = PER_EVENT_IFETCH, |
69 | per_cr_words cr_words; | 52 | .start = 0, |
70 | 53 | .end = PSW_ADDR_INSN, | |
71 | regs = task_pt_regs(task); | 54 | }; |
72 | per_info = (per_struct *) &task->thread.per_info; | 55 | struct pt_regs *regs = task_pt_regs(task); |
73 | per_info->control_regs.bits.em_instruction_fetch = | 56 | struct thread_struct *thread = &task->thread; |
74 | per_info->single_step | per_info->instruction_fetch; | 57 | const struct per_regs *new; |
75 | 58 | struct per_regs old; | |
76 | if (per_info->single_step) { | 59 | |
77 | per_info->control_regs.bits.starting_addr = 0; | 60 | /* TIF_SINGLE_STEP overrides the user specified PER registers. */ |
78 | #ifdef CONFIG_COMPAT | 61 | new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ? |
79 | if (is_compat_task()) | 62 | &per_single_step : &thread->per_user; |
80 | per_info->control_regs.bits.ending_addr = 0x7fffffffUL; | 63 | |
81 | else | 64 | /* Take care of the PER enablement bit in the PSW. */ |
82 | #endif | 65 | if (!(new->control & PER_EVENT_MASK)) { |
83 | per_info->control_regs.bits.ending_addr = PSW_ADDR_INSN; | ||
84 | } else { | ||
85 | per_info->control_regs.bits.starting_addr = | ||
86 | per_info->starting_addr; | ||
87 | per_info->control_regs.bits.ending_addr = | ||
88 | per_info->ending_addr; | ||
89 | } | ||
90 | /* | ||
91 | * if any of the control reg tracing bits are on | ||
92 | * we switch on per in the psw | ||
93 | */ | ||
94 | if (per_info->control_regs.words.cr[0] & PER_EM_MASK) | ||
95 | regs->psw.mask |= PSW_MASK_PER; | ||
96 | else | ||
97 | regs->psw.mask &= ~PSW_MASK_PER; | 66 | regs->psw.mask &= ~PSW_MASK_PER; |
98 | 67 | return; | |
99 | if (per_info->control_regs.bits.em_storage_alteration) | ||
100 | per_info->control_regs.bits.storage_alt_space_ctl = 1; | ||
101 | else | ||
102 | per_info->control_regs.bits.storage_alt_space_ctl = 0; | ||
103 | |||
104 | if (task == current) { | ||
105 | __ctl_store(cr_words, 9, 11); | ||
106 | if (memcmp(&cr_words, &per_info->control_regs.words, | ||
107 | sizeof(cr_words)) != 0) | ||
108 | __ctl_load(per_info->control_regs.words, 9, 11); | ||
109 | } | 68 | } |
69 | regs->psw.mask |= PSW_MASK_PER; | ||
70 | __ctl_store(old, 9, 11); | ||
71 | if (memcmp(new, &old, sizeof(struct per_regs)) != 0) | ||
72 | __ctl_load(*new, 9, 11); | ||
110 | } | 73 | } |
111 | 74 | ||
112 | void user_enable_single_step(struct task_struct *task) | 75 | void user_enable_single_step(struct task_struct *task) |
113 | { | 76 | { |
114 | task->thread.per_info.single_step = 1; | 77 | set_tsk_thread_flag(task, TIF_SINGLE_STEP); |
115 | FixPerRegisters(task); | 78 | if (task == current) |
79 | update_per_regs(task); | ||
116 | } | 80 | } |
117 | 81 | ||
118 | void user_disable_single_step(struct task_struct *task) | 82 | void user_disable_single_step(struct task_struct *task) |
119 | { | 83 | { |
120 | task->thread.per_info.single_step = 0; | 84 | clear_tsk_thread_flag(task, TIF_SINGLE_STEP); |
121 | FixPerRegisters(task); | 85 | if (task == current) |
86 | update_per_regs(task); | ||
122 | } | 87 | } |
123 | 88 | ||
124 | /* | 89 | /* |
125 | * Called by kernel/ptrace.c when detaching.. | 90 | * Called by kernel/ptrace.c when detaching.. |
126 | * | 91 | * |
127 | * Make sure single step bits etc are not set. | 92 | * Clear all debugging related fields. |
128 | */ | 93 | */ |
129 | void | 94 | void ptrace_disable(struct task_struct *task) |
130 | ptrace_disable(struct task_struct *child) | ||
131 | { | 95 | { |
132 | /* make sure the single step bit is not set. */ | 96 | memset(&task->thread.per_user, 0, sizeof(task->thread.per_user)); |
133 | user_disable_single_step(child); | 97 | memset(&task->thread.per_event, 0, sizeof(task->thread.per_event)); |
98 | clear_tsk_thread_flag(task, TIF_SINGLE_STEP); | ||
99 | clear_tsk_thread_flag(task, TIF_PER_TRAP); | ||
134 | } | 100 | } |
135 | 101 | ||
136 | #ifndef CONFIG_64BIT | 102 | #ifndef CONFIG_64BIT |
@@ -139,6 +105,47 @@ ptrace_disable(struct task_struct *child) | |||
139 | # define __ADDR_MASK 7 | 105 | # define __ADDR_MASK 7 |
140 | #endif | 106 | #endif |
141 | 107 | ||
108 | static inline unsigned long __peek_user_per(struct task_struct *child, | ||
109 | addr_t addr) | ||
110 | { | ||
111 | struct per_struct_kernel *dummy = NULL; | ||
112 | |||
113 | if (addr == (addr_t) &dummy->cr9) | ||
114 | /* Control bits of the active per set. */ | ||
115 | return test_thread_flag(TIF_SINGLE_STEP) ? | ||
116 | PER_EVENT_IFETCH : child->thread.per_user.control; | ||
117 | else if (addr == (addr_t) &dummy->cr10) | ||
118 | /* Start address of the active per set. */ | ||
119 | return test_thread_flag(TIF_SINGLE_STEP) ? | ||
120 | 0 : child->thread.per_user.start; | ||
121 | else if (addr == (addr_t) &dummy->cr11) | ||
122 | /* End address of the active per set. */ | ||
123 | return test_thread_flag(TIF_SINGLE_STEP) ? | ||
124 | PSW_ADDR_INSN : child->thread.per_user.end; | ||
125 | else if (addr == (addr_t) &dummy->bits) | ||
126 | /* Single-step bit. */ | ||
127 | return test_thread_flag(TIF_SINGLE_STEP) ? | ||
128 | (1UL << (BITS_PER_LONG - 1)) : 0; | ||
129 | else if (addr == (addr_t) &dummy->starting_addr) | ||
130 | /* Start address of the user specified per set. */ | ||
131 | return child->thread.per_user.start; | ||
132 | else if (addr == (addr_t) &dummy->ending_addr) | ||
133 | /* End address of the user specified per set. */ | ||
134 | return child->thread.per_user.end; | ||
135 | else if (addr == (addr_t) &dummy->perc_atmid) | ||
136 | /* PER code, ATMID and AI of the last PER trap */ | ||
137 | return (unsigned long) | ||
138 | child->thread.per_event.cause << (BITS_PER_LONG - 16); | ||
139 | else if (addr == (addr_t) &dummy->address) | ||
140 | /* Address of the last PER trap */ | ||
141 | return child->thread.per_event.address; | ||
142 | else if (addr == (addr_t) &dummy->access_id) | ||
143 | /* Access id of the last PER trap */ | ||
144 | return (unsigned long) | ||
145 | child->thread.per_event.paid << (BITS_PER_LONG - 8); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
142 | /* | 149 | /* |
143 | * Read the word at offset addr from the user area of a process. The | 150 | * Read the word at offset addr from the user area of a process. The |
144 | * trouble here is that the information is littered over different | 151 | * trouble here is that the information is littered over different |
@@ -204,10 +211,10 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr) | |||
204 | 211 | ||
205 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { | 212 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { |
206 | /* | 213 | /* |
207 | * per_info is found in the thread structure | 214 | * Handle access to the per_info structure. |
208 | */ | 215 | */ |
209 | offset = addr - (addr_t) &dummy->regs.per_info; | 216 | addr -= (addr_t) &dummy->regs.per_info; |
210 | tmp = *(addr_t *)((addr_t) &child->thread.per_info + offset); | 217 | tmp = __peek_user_per(child, addr); |
211 | 218 | ||
212 | } else | 219 | } else |
213 | tmp = 0; | 220 | tmp = 0; |
@@ -237,6 +244,35 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) | |||
237 | return put_user(tmp, (addr_t __user *) data); | 244 | return put_user(tmp, (addr_t __user *) data); |
238 | } | 245 | } |
239 | 246 | ||
247 | static inline void __poke_user_per(struct task_struct *child, | ||
248 | addr_t addr, addr_t data) | ||
249 | { | ||
250 | struct per_struct_kernel *dummy = NULL; | ||
251 | |||
252 | /* | ||
253 | * There are only three fields in the per_info struct that the | ||
254 | * debugger user can write to. | ||
255 | * 1) cr9: the debugger wants to set a new PER event mask | ||
256 | * 2) starting_addr: the debugger wants to set a new starting | ||
257 | * address to use with the PER event mask. | ||
258 | * 3) ending_addr: the debugger wants to set a new ending | ||
259 | * address to use with the PER event mask. | ||
260 | * The user specified PER event mask and the start and end | ||
261 | * addresses are used only if single stepping is not in effect. | ||
262 | * Writes to any other field in per_info are ignored. | ||
263 | */ | ||
264 | if (addr == (addr_t) &dummy->cr9) | ||
265 | /* PER event mask of the user specified per set. */ | ||
266 | child->thread.per_user.control = | ||
267 | data & (PER_EVENT_MASK | PER_CONTROL_MASK); | ||
268 | else if (addr == (addr_t) &dummy->starting_addr) | ||
269 | /* Starting address of the user specified per set. */ | ||
270 | child->thread.per_user.start = data; | ||
271 | else if (addr == (addr_t) &dummy->ending_addr) | ||
272 | /* Ending address of the user specified per set. */ | ||
273 | child->thread.per_user.end = data; | ||
274 | } | ||
275 | |||
240 | /* | 276 | /* |
241 | * Write a word to the user area of a process at location addr. This | 277 | * Write a word to the user area of a process at location addr. This |
242 | * operation does have an additional problem compared to peek_user. | 278 | * operation does have an additional problem compared to peek_user. |
@@ -311,19 +347,17 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) | |||
311 | 347 | ||
312 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { | 348 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { |
313 | /* | 349 | /* |
314 | * per_info is found in the thread structure | 350 | * Handle access to the per_info structure. |
315 | */ | 351 | */ |
316 | offset = addr - (addr_t) &dummy->regs.per_info; | 352 | addr -= (addr_t) &dummy->regs.per_info; |
317 | *(addr_t *)((addr_t) &child->thread.per_info + offset) = data; | 353 | __poke_user_per(child, addr, data); |
318 | 354 | ||
319 | } | 355 | } |
320 | 356 | ||
321 | FixPerRegisters(child); | ||
322 | return 0; | 357 | return 0; |
323 | } | 358 | } |
324 | 359 | ||
325 | static int | 360 | static int poke_user(struct task_struct *child, addr_t addr, addr_t data) |
326 | poke_user(struct task_struct *child, addr_t addr, addr_t data) | ||
327 | { | 361 | { |
328 | addr_t mask; | 362 | addr_t mask; |
329 | 363 | ||
@@ -343,7 +377,8 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) | |||
343 | return __poke_user(child, addr, data); | 377 | return __poke_user(child, addr, data); |
344 | } | 378 | } |
345 | 379 | ||
346 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 380 | long arch_ptrace(struct task_struct *child, long request, |
381 | unsigned long addr, unsigned long data) | ||
347 | { | 382 | { |
348 | ptrace_area parea; | 383 | ptrace_area parea; |
349 | int copied, ret; | 384 | int copied, ret; |
@@ -409,12 +444,53 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
409 | */ | 444 | */ |
410 | 445 | ||
411 | /* | 446 | /* |
447 | * Same as peek_user_per but for a 31 bit program. | ||
448 | */ | ||
449 | static inline __u32 __peek_user_per_compat(struct task_struct *child, | ||
450 | addr_t addr) | ||
451 | { | ||
452 | struct compat_per_struct_kernel *dummy32 = NULL; | ||
453 | |||
454 | if (addr == (addr_t) &dummy32->cr9) | ||
455 | /* Control bits of the active per set. */ | ||
456 | return (__u32) test_thread_flag(TIF_SINGLE_STEP) ? | ||
457 | PER_EVENT_IFETCH : child->thread.per_user.control; | ||
458 | else if (addr == (addr_t) &dummy32->cr10) | ||
459 | /* Start address of the active per set. */ | ||
460 | return (__u32) test_thread_flag(TIF_SINGLE_STEP) ? | ||
461 | 0 : child->thread.per_user.start; | ||
462 | else if (addr == (addr_t) &dummy32->cr11) | ||
463 | /* End address of the active per set. */ | ||
464 | return test_thread_flag(TIF_SINGLE_STEP) ? | ||
465 | PSW32_ADDR_INSN : child->thread.per_user.end; | ||
466 | else if (addr == (addr_t) &dummy32->bits) | ||
467 | /* Single-step bit. */ | ||
468 | return (__u32) test_thread_flag(TIF_SINGLE_STEP) ? | ||
469 | 0x80000000 : 0; | ||
470 | else if (addr == (addr_t) &dummy32->starting_addr) | ||
471 | /* Start address of the user specified per set. */ | ||
472 | return (__u32) child->thread.per_user.start; | ||
473 | else if (addr == (addr_t) &dummy32->ending_addr) | ||
474 | /* End address of the user specified per set. */ | ||
475 | return (__u32) child->thread.per_user.end; | ||
476 | else if (addr == (addr_t) &dummy32->perc_atmid) | ||
477 | /* PER code, ATMID and AI of the last PER trap */ | ||
478 | return (__u32) child->thread.per_event.cause << 16; | ||
479 | else if (addr == (addr_t) &dummy32->address) | ||
480 | /* Address of the last PER trap */ | ||
481 | return (__u32) child->thread.per_event.address; | ||
482 | else if (addr == (addr_t) &dummy32->access_id) | ||
483 | /* Access id of the last PER trap */ | ||
484 | return (__u32) child->thread.per_event.paid << 24; | ||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | /* | ||
412 | * Same as peek_user but for a 31 bit program. | 489 | * Same as peek_user but for a 31 bit program. |
413 | */ | 490 | */ |
414 | static u32 __peek_user_compat(struct task_struct *child, addr_t addr) | 491 | static u32 __peek_user_compat(struct task_struct *child, addr_t addr) |
415 | { | 492 | { |
416 | struct user32 *dummy32 = NULL; | 493 | struct compat_user *dummy32 = NULL; |
417 | per_struct32 *dummy_per32 = NULL; | ||
418 | addr_t offset; | 494 | addr_t offset; |
419 | __u32 tmp; | 495 | __u32 tmp; |
420 | 496 | ||
@@ -464,19 +540,10 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr) | |||
464 | 540 | ||
465 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { | 541 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { |
466 | /* | 542 | /* |
467 | * per_info is found in the thread structure | 543 | * Handle access to the per_info structure. |
468 | */ | 544 | */ |
469 | offset = addr - (addr_t) &dummy32->regs.per_info; | 545 | addr -= (addr_t) &dummy32->regs.per_info; |
470 | /* This is magic. See per_struct and per_struct32. */ | 546 | tmp = __peek_user_per_compat(child, addr); |
471 | if ((offset >= (addr_t) &dummy_per32->control_regs && | ||
472 | offset < (addr_t) (&dummy_per32->control_regs + 1)) || | ||
473 | (offset >= (addr_t) &dummy_per32->starting_addr && | ||
474 | offset <= (addr_t) &dummy_per32->ending_addr) || | ||
475 | offset == (addr_t) &dummy_per32->lowcore.words.address) | ||
476 | offset = offset*2 + 4; | ||
477 | else | ||
478 | offset = offset*2; | ||
479 | tmp = *(__u32 *)((addr_t) &child->thread.per_info + offset); | ||
480 | 547 | ||
481 | } else | 548 | } else |
482 | tmp = 0; | 549 | tmp = 0; |
@@ -497,13 +564,32 @@ static int peek_user_compat(struct task_struct *child, | |||
497 | } | 564 | } |
498 | 565 | ||
499 | /* | 566 | /* |
567 | * Same as poke_user_per but for a 31 bit program. | ||
568 | */ | ||
569 | static inline void __poke_user_per_compat(struct task_struct *child, | ||
570 | addr_t addr, __u32 data) | ||
571 | { | ||
572 | struct compat_per_struct_kernel *dummy32 = NULL; | ||
573 | |||
574 | if (addr == (addr_t) &dummy32->cr9) | ||
575 | /* PER event mask of the user specified per set. */ | ||
576 | child->thread.per_user.control = | ||
577 | data & (PER_EVENT_MASK | PER_CONTROL_MASK); | ||
578 | else if (addr == (addr_t) &dummy32->starting_addr) | ||
579 | /* Starting address of the user specified per set. */ | ||
580 | child->thread.per_user.start = data; | ||
581 | else if (addr == (addr_t) &dummy32->ending_addr) | ||
582 | /* Ending address of the user specified per set. */ | ||
583 | child->thread.per_user.end = data; | ||
584 | } | ||
585 | |||
586 | /* | ||
500 | * Same as poke_user but for a 31 bit program. | 587 | * Same as poke_user but for a 31 bit program. |
501 | */ | 588 | */ |
502 | static int __poke_user_compat(struct task_struct *child, | 589 | static int __poke_user_compat(struct task_struct *child, |
503 | addr_t addr, addr_t data) | 590 | addr_t addr, addr_t data) |
504 | { | 591 | { |
505 | struct user32 *dummy32 = NULL; | 592 | struct compat_user *dummy32 = NULL; |
506 | per_struct32 *dummy_per32 = NULL; | ||
507 | __u32 tmp = (__u32) data; | 593 | __u32 tmp = (__u32) data; |
508 | addr_t offset; | 594 | addr_t offset; |
509 | 595 | ||
@@ -560,37 +646,20 @@ static int __poke_user_compat(struct task_struct *child, | |||
560 | 646 | ||
561 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { | 647 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { |
562 | /* | 648 | /* |
563 | * per_info is found in the thread structure. | 649 | * Handle access to the per_info structure. |
564 | */ | ||
565 | offset = addr - (addr_t) &dummy32->regs.per_info; | ||
566 | /* | ||
567 | * This is magic. See per_struct and per_struct32. | ||
568 | * By incident the offsets in per_struct are exactly | ||
569 | * twice the offsets in per_struct32 for all fields. | ||
570 | * The 8 byte fields need special handling though, | ||
571 | * because the second half (bytes 4-7) is needed and | ||
572 | * not the first half. | ||
573 | */ | 650 | */ |
574 | if ((offset >= (addr_t) &dummy_per32->control_regs && | 651 | addr -= (addr_t) &dummy32->regs.per_info; |
575 | offset < (addr_t) (&dummy_per32->control_regs + 1)) || | 652 | __poke_user_per_compat(child, addr, data); |
576 | (offset >= (addr_t) &dummy_per32->starting_addr && | ||
577 | offset <= (addr_t) &dummy_per32->ending_addr) || | ||
578 | offset == (addr_t) &dummy_per32->lowcore.words.address) | ||
579 | offset = offset*2 + 4; | ||
580 | else | ||
581 | offset = offset*2; | ||
582 | *(__u32 *)((addr_t) &child->thread.per_info + offset) = tmp; | ||
583 | |||
584 | } | 653 | } |
585 | 654 | ||
586 | FixPerRegisters(child); | ||
587 | return 0; | 655 | return 0; |
588 | } | 656 | } |
589 | 657 | ||
590 | static int poke_user_compat(struct task_struct *child, | 658 | static int poke_user_compat(struct task_struct *child, |
591 | addr_t addr, addr_t data) | 659 | addr_t addr, addr_t data) |
592 | { | 660 | { |
593 | if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user32) - 3) | 661 | if (!is_compat_task() || (addr & 3) || |
662 | addr > sizeof(struct compat_user) - 3) | ||
594 | return -EIO; | 663 | return -EIO; |
595 | 664 | ||
596 | return __poke_user_compat(child, addr, data); | 665 | return __poke_user_compat(child, addr, data); |
@@ -601,7 +670,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
601 | { | 670 | { |
602 | unsigned long addr = caddr; | 671 | unsigned long addr = caddr; |
603 | unsigned long data = cdata; | 672 | unsigned long data = cdata; |
604 | ptrace_area_emu31 parea; | 673 | compat_ptrace_area parea; |
605 | int copied, ret; | 674 | int copied, ret; |
606 | 675 | ||
607 | switch (request) { | 676 | switch (request) { |
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S index 5e73dee63baa..9eabbc90795d 100644 --- a/arch/s390/kernel/reipl64.S +++ b/arch/s390/kernel/reipl64.S | |||
@@ -78,7 +78,7 @@ do_reipl_asm: basr %r13,0 | |||
78 | * in the ESA psw. | 78 | * in the ESA psw. |
79 | * Bit 31 of the addresses has to be 0 for the | 79 | * Bit 31 of the addresses has to be 0 for the |
80 | * 31bit lpswe instruction a fact they appear to have | 80 | * 31bit lpswe instruction a fact they appear to have |
81 | * ommited from the pop. | 81 | * omitted from the pop. |
82 | */ | 82 | */ |
83 | .Lnewpsw: .quad 0x0000000080000000 | 83 | .Lnewpsw: .quad 0x0000000080000000 |
84 | .quad .Lpg1 | 84 | .quad .Lpg1 |
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c deleted file mode 100644 index 9ce641b5291f..000000000000 --- a/arch/s390/kernel/s390_ext.c +++ /dev/null | |||
@@ -1,142 +0,0 @@ | |||
1 | /* | ||
2 | * arch/s390/kernel/s390_ext.c | ||
3 | * | ||
4 | * S390 version | ||
5 | * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation | ||
6 | * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com), | ||
7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/ftrace.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/kernel_stat.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <asm/cputime.h> | ||
18 | #include <asm/lowcore.h> | ||
19 | #include <asm/s390_ext.h> | ||
20 | #include <asm/irq_regs.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include "entry.h" | ||
23 | |||
24 | /* | ||
25 | * ext_int_hash[index] is the start of the list for all external interrupts | ||
26 | * that hash to this index. With the current set of external interrupts | ||
27 | * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000 | ||
28 | * iucv and 0x2603 pfault) this is always the first element. | ||
29 | */ | ||
30 | ext_int_info_t *ext_int_hash[256] = { NULL, }; | ||
31 | |||
32 | static inline int ext_hash(__u16 code) | ||
33 | { | ||
34 | return (code + (code >> 9)) & 0xff; | ||
35 | } | ||
36 | |||
37 | int register_external_interrupt(__u16 code, ext_int_handler_t handler) | ||
38 | { | ||
39 | ext_int_info_t *p; | ||
40 | int index; | ||
41 | |||
42 | p = kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC); | ||
43 | if (p == NULL) | ||
44 | return -ENOMEM; | ||
45 | p->code = code; | ||
46 | p->handler = handler; | ||
47 | index = ext_hash(code); | ||
48 | p->next = ext_int_hash[index]; | ||
49 | ext_int_hash[index] = p; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | int register_early_external_interrupt(__u16 code, ext_int_handler_t handler, | ||
54 | ext_int_info_t *p) | ||
55 | { | ||
56 | int index; | ||
57 | |||
58 | if (p == NULL) | ||
59 | return -EINVAL; | ||
60 | p->code = code; | ||
61 | p->handler = handler; | ||
62 | index = ext_hash(code); | ||
63 | p->next = ext_int_hash[index]; | ||
64 | ext_int_hash[index] = p; | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | int unregister_external_interrupt(__u16 code, ext_int_handler_t handler) | ||
69 | { | ||
70 | ext_int_info_t *p, *q; | ||
71 | int index; | ||
72 | |||
73 | index = ext_hash(code); | ||
74 | q = NULL; | ||
75 | p = ext_int_hash[index]; | ||
76 | while (p != NULL) { | ||
77 | if (p->code == code && p->handler == handler) | ||
78 | break; | ||
79 | q = p; | ||
80 | p = p->next; | ||
81 | } | ||
82 | if (p == NULL) | ||
83 | return -ENOENT; | ||
84 | if (q != NULL) | ||
85 | q->next = p->next; | ||
86 | else | ||
87 | ext_int_hash[index] = p->next; | ||
88 | kfree(p); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler, | ||
93 | ext_int_info_t *p) | ||
94 | { | ||
95 | ext_int_info_t *q; | ||
96 | int index; | ||
97 | |||
98 | if (p == NULL || p->code != code || p->handler != handler) | ||
99 | return -EINVAL; | ||
100 | index = ext_hash(code); | ||
101 | q = ext_int_hash[index]; | ||
102 | if (p != q) { | ||
103 | while (q != NULL) { | ||
104 | if (q->next == p) | ||
105 | break; | ||
106 | q = q->next; | ||
107 | } | ||
108 | if (q == NULL) | ||
109 | return -ENOENT; | ||
110 | q->next = p->next; | ||
111 | } else | ||
112 | ext_int_hash[index] = p->next; | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | void __irq_entry do_extint(struct pt_regs *regs, unsigned short code) | ||
117 | { | ||
118 | ext_int_info_t *p; | ||
119 | int index; | ||
120 | struct pt_regs *old_regs; | ||
121 | |||
122 | old_regs = set_irq_regs(regs); | ||
123 | s390_idle_check(regs, S390_lowcore.int_clock, | ||
124 | S390_lowcore.async_enter_timer); | ||
125 | irq_enter(); | ||
126 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) | ||
127 | /* Serve timer interrupts first. */ | ||
128 | clock_comparator_work(); | ||
129 | kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; | ||
130 | if (code != 0x1004) | ||
131 | __get_cpu_var(s390_idle).nohz_delay = 1; | ||
132 | index = ext_hash(code); | ||
133 | for (p = ext_int_hash[index]; p; p = p->next) { | ||
134 | if (likely(p->code == code)) | ||
135 | p->handler(code); | ||
136 | } | ||
137 | irq_exit(); | ||
138 | set_irq_regs(old_regs); | ||
139 | } | ||
140 | |||
141 | EXPORT_SYMBOL(register_external_interrupt); | ||
142 | EXPORT_SYMBOL(unregister_external_interrupt); | ||
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index c8e8e1354e1d..0c35dee10b00 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -102,16 +102,6 @@ EXPORT_SYMBOL(lowcore_ptr); | |||
102 | 102 | ||
103 | #include <asm/setup.h> | 103 | #include <asm/setup.h> |
104 | 104 | ||
105 | static struct resource code_resource = { | ||
106 | .name = "Kernel code", | ||
107 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | ||
108 | }; | ||
109 | |||
110 | static struct resource data_resource = { | ||
111 | .name = "Kernel data", | ||
112 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | ||
113 | }; | ||
114 | |||
115 | /* | 105 | /* |
116 | * condev= and conmode= setup parameter. | 106 | * condev= and conmode= setup parameter. |
117 | */ | 107 | */ |
@@ -315,8 +305,7 @@ static int set_amode_and_uaccess(unsigned long user_amode, | |||
315 | */ | 305 | */ |
316 | static int __init early_parse_switch_amode(char *p) | 306 | static int __init early_parse_switch_amode(char *p) |
317 | { | 307 | { |
318 | if (user_mode != SECONDARY_SPACE_MODE) | 308 | user_mode = PRIMARY_SPACE_MODE; |
319 | user_mode = PRIMARY_SPACE_MODE; | ||
320 | return 0; | 309 | return 0; |
321 | } | 310 | } |
322 | early_param("switch_amode", early_parse_switch_amode); | 311 | early_param("switch_amode", early_parse_switch_amode); |
@@ -325,10 +314,6 @@ static int __init early_parse_user_mode(char *p) | |||
325 | { | 314 | { |
326 | if (p && strcmp(p, "primary") == 0) | 315 | if (p && strcmp(p, "primary") == 0) |
327 | user_mode = PRIMARY_SPACE_MODE; | 316 | user_mode = PRIMARY_SPACE_MODE; |
328 | #ifdef CONFIG_S390_EXEC_PROTECT | ||
329 | else if (p && strcmp(p, "secondary") == 0) | ||
330 | user_mode = SECONDARY_SPACE_MODE; | ||
331 | #endif | ||
332 | else if (!p || strcmp(p, "home") == 0) | 317 | else if (!p || strcmp(p, "home") == 0) |
333 | user_mode = HOME_SPACE_MODE; | 318 | user_mode = HOME_SPACE_MODE; |
334 | else | 319 | else |
@@ -337,31 +322,9 @@ static int __init early_parse_user_mode(char *p) | |||
337 | } | 322 | } |
338 | early_param("user_mode", early_parse_user_mode); | 323 | early_param("user_mode", early_parse_user_mode); |
339 | 324 | ||
340 | #ifdef CONFIG_S390_EXEC_PROTECT | ||
341 | /* | ||
342 | * Enable execute protection? | ||
343 | */ | ||
344 | static int __init early_parse_noexec(char *p) | ||
345 | { | ||
346 | if (!strncmp(p, "off", 3)) | ||
347 | return 0; | ||
348 | user_mode = SECONDARY_SPACE_MODE; | ||
349 | return 0; | ||
350 | } | ||
351 | early_param("noexec", early_parse_noexec); | ||
352 | #endif /* CONFIG_S390_EXEC_PROTECT */ | ||
353 | |||
354 | static void setup_addressing_mode(void) | 325 | static void setup_addressing_mode(void) |
355 | { | 326 | { |
356 | if (user_mode == SECONDARY_SPACE_MODE) { | 327 | if (user_mode == PRIMARY_SPACE_MODE) { |
357 | if (set_amode_and_uaccess(PSW_ASC_SECONDARY, | ||
358 | PSW32_ASC_SECONDARY)) | ||
359 | pr_info("Execute protection active, " | ||
360 | "mvcos available\n"); | ||
361 | else | ||
362 | pr_info("Execute protection active, " | ||
363 | "mvcos not available\n"); | ||
364 | } else if (user_mode == PRIMARY_SPACE_MODE) { | ||
365 | if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY)) | 328 | if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY)) |
366 | pr_info("Address spaces switched, " | 329 | pr_info("Address spaces switched, " |
367 | "mvcos available\n"); | 330 | "mvcos available\n"); |
@@ -409,6 +372,9 @@ setup_lowcore(void) | |||
409 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; | 372 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; |
410 | lc->thread_info = (unsigned long) &init_thread_union; | 373 | lc->thread_info = (unsigned long) &init_thread_union; |
411 | lc->machine_flags = S390_lowcore.machine_flags; | 374 | lc->machine_flags = S390_lowcore.machine_flags; |
375 | lc->stfl_fac_list = S390_lowcore.stfl_fac_list; | ||
376 | memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list, | ||
377 | MAX_FACILITY_BIT/8); | ||
412 | #ifndef CONFIG_64BIT | 378 | #ifndef CONFIG_64BIT |
413 | if (MACHINE_HAS_IEEE) { | 379 | if (MACHINE_HAS_IEEE) { |
414 | lc->extended_save_area_addr = (__u32) | 380 | lc->extended_save_area_addr = (__u32) |
@@ -433,21 +399,43 @@ setup_lowcore(void) | |||
433 | lowcore_ptr[0] = lc; | 399 | lowcore_ptr[0] = lc; |
434 | } | 400 | } |
435 | 401 | ||
436 | static void __init | 402 | static struct resource code_resource = { |
437 | setup_resources(void) | 403 | .name = "Kernel code", |
404 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | ||
405 | }; | ||
406 | |||
407 | static struct resource data_resource = { | ||
408 | .name = "Kernel data", | ||
409 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | ||
410 | }; | ||
411 | |||
412 | static struct resource bss_resource = { | ||
413 | .name = "Kernel bss", | ||
414 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | ||
415 | }; | ||
416 | |||
417 | static struct resource __initdata *standard_resources[] = { | ||
418 | &code_resource, | ||
419 | &data_resource, | ||
420 | &bss_resource, | ||
421 | }; | ||
422 | |||
423 | static void __init setup_resources(void) | ||
438 | { | 424 | { |
439 | struct resource *res, *sub_res; | 425 | struct resource *res, *std_res, *sub_res; |
440 | int i; | 426 | int i, j; |
441 | 427 | ||
442 | code_resource.start = (unsigned long) &_text; | 428 | code_resource.start = (unsigned long) &_text; |
443 | code_resource.end = (unsigned long) &_etext - 1; | 429 | code_resource.end = (unsigned long) &_etext - 1; |
444 | data_resource.start = (unsigned long) &_etext; | 430 | data_resource.start = (unsigned long) &_etext; |
445 | data_resource.end = (unsigned long) &_edata - 1; | 431 | data_resource.end = (unsigned long) &_edata - 1; |
432 | bss_resource.start = (unsigned long) &__bss_start; | ||
433 | bss_resource.end = (unsigned long) &__bss_stop - 1; | ||
446 | 434 | ||
447 | for (i = 0; i < MEMORY_CHUNKS; i++) { | 435 | for (i = 0; i < MEMORY_CHUNKS; i++) { |
448 | if (!memory_chunk[i].size) | 436 | if (!memory_chunk[i].size) |
449 | continue; | 437 | continue; |
450 | res = alloc_bootmem_low(sizeof(struct resource)); | 438 | res = alloc_bootmem_low(sizeof(*res)); |
451 | res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; | 439 | res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; |
452 | switch (memory_chunk[i].type) { | 440 | switch (memory_chunk[i].type) { |
453 | case CHUNK_READ_WRITE: | 441 | case CHUNK_READ_WRITE: |
@@ -461,40 +449,24 @@ setup_resources(void) | |||
461 | res->name = "reserved"; | 449 | res->name = "reserved"; |
462 | } | 450 | } |
463 | res->start = memory_chunk[i].addr; | 451 | res->start = memory_chunk[i].addr; |
464 | res->end = memory_chunk[i].addr + memory_chunk[i].size - 1; | 452 | res->end = res->start + memory_chunk[i].size - 1; |
465 | request_resource(&iomem_resource, res); | 453 | request_resource(&iomem_resource, res); |
466 | 454 | ||
467 | if (code_resource.start >= res->start && | 455 | for (j = 0; j < ARRAY_SIZE(standard_resources); j++) { |
468 | code_resource.start <= res->end && | 456 | std_res = standard_resources[j]; |
469 | code_resource.end > res->end) { | 457 | if (std_res->start < res->start || |
470 | sub_res = alloc_bootmem_low(sizeof(struct resource)); | 458 | std_res->start > res->end) |
471 | memcpy(sub_res, &code_resource, | 459 | continue; |
472 | sizeof(struct resource)); | 460 | if (std_res->end > res->end) { |
473 | sub_res->end = res->end; | 461 | sub_res = alloc_bootmem_low(sizeof(*sub_res)); |
474 | code_resource.start = res->end + 1; | 462 | *sub_res = *std_res; |
475 | request_resource(res, sub_res); | 463 | sub_res->end = res->end; |
476 | } | 464 | std_res->start = res->end + 1; |
477 | 465 | request_resource(res, sub_res); | |
478 | if (code_resource.start >= res->start && | 466 | } else { |
479 | code_resource.start <= res->end && | 467 | request_resource(res, std_res); |
480 | code_resource.end <= res->end) | 468 | } |
481 | request_resource(res, &code_resource); | ||
482 | |||
483 | if (data_resource.start >= res->start && | ||
484 | data_resource.start <= res->end && | ||
485 | data_resource.end > res->end) { | ||
486 | sub_res = alloc_bootmem_low(sizeof(struct resource)); | ||
487 | memcpy(sub_res, &data_resource, | ||
488 | sizeof(struct resource)); | ||
489 | sub_res->end = res->end; | ||
490 | data_resource.start = res->end + 1; | ||
491 | request_resource(res, sub_res); | ||
492 | } | 469 | } |
493 | |||
494 | if (data_resource.start >= res->start && | ||
495 | data_resource.start <= res->end && | ||
496 | data_resource.end <= res->end) | ||
497 | request_resource(res, &data_resource); | ||
498 | } | 470 | } |
499 | } | 471 | } |
500 | 472 | ||
@@ -627,7 +599,8 @@ setup_memory(void) | |||
627 | add_active_range(0, start_chunk, end_chunk); | 599 | add_active_range(0, start_chunk, end_chunk); |
628 | pfn = max(start_chunk, start_pfn); | 600 | pfn = max(start_chunk, start_pfn); |
629 | for (; pfn < end_chunk; pfn++) | 601 | for (; pfn < end_chunk; pfn++) |
630 | page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY); | 602 | page_set_storage_key(PFN_PHYS(pfn), |
603 | PAGE_DEFAULT_KEY, 0); | ||
631 | } | 604 | } |
632 | 605 | ||
633 | psw_set_key(PAGE_DEFAULT_KEY); | 606 | psw_set_key(PAGE_DEFAULT_KEY); |
@@ -674,12 +647,9 @@ setup_memory(void) | |||
674 | static void __init setup_hwcaps(void) | 647 | static void __init setup_hwcaps(void) |
675 | { | 648 | { |
676 | static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; | 649 | static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; |
677 | unsigned long long facility_list_extended; | ||
678 | unsigned int facility_list; | ||
679 | struct cpuid cpu_id; | 650 | struct cpuid cpu_id; |
680 | int i; | 651 | int i; |
681 | 652 | ||
682 | facility_list = stfl(); | ||
683 | /* | 653 | /* |
684 | * The store facility list bits numbers as found in the principles | 654 | * The store facility list bits numbers as found in the principles |
685 | * of operation are numbered with bit 1UL<<31 as number 0 to | 655 | * of operation are numbered with bit 1UL<<31 as number 0 to |
@@ -699,11 +669,10 @@ static void __init setup_hwcaps(void) | |||
699 | * HWCAP_S390_ETF3EH bit 8 (22 && 30). | 669 | * HWCAP_S390_ETF3EH bit 8 (22 && 30). |
700 | */ | 670 | */ |
701 | for (i = 0; i < 6; i++) | 671 | for (i = 0; i < 6; i++) |
702 | if (facility_list & (1UL << (31 - stfl_bits[i]))) | 672 | if (test_facility(stfl_bits[i])) |
703 | elf_hwcap |= 1UL << i; | 673 | elf_hwcap |= 1UL << i; |
704 | 674 | ||
705 | if ((facility_list & (1UL << (31 - 22))) | 675 | if (test_facility(22) && test_facility(30)) |
706 | && (facility_list & (1UL << (31 - 30)))) | ||
707 | elf_hwcap |= HWCAP_S390_ETF3EH; | 676 | elf_hwcap |= HWCAP_S390_ETF3EH; |
708 | 677 | ||
709 | /* | 678 | /* |
@@ -712,19 +681,15 @@ static void __init setup_hwcaps(void) | |||
712 | * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information | 681 | * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information |
713 | * as stored by stfl, bits 32-xxx contain additional facilities. | 682 | * as stored by stfl, bits 32-xxx contain additional facilities. |
714 | * How many facility words are stored depends on the number of | 683 | * How many facility words are stored depends on the number of |
715 | * doublewords passed to the instruction. The additional facilites | 684 | * doublewords passed to the instruction. The additional facilities |
716 | * are: | 685 | * are: |
717 | * Bit 42: decimal floating point facility is installed | 686 | * Bit 42: decimal floating point facility is installed |
718 | * Bit 44: perform floating point operation facility is installed | 687 | * Bit 44: perform floating point operation facility is installed |
719 | * translated to: | 688 | * translated to: |
720 | * HWCAP_S390_DFP bit 6 (42 && 44). | 689 | * HWCAP_S390_DFP bit 6 (42 && 44). |
721 | */ | 690 | */ |
722 | if ((elf_hwcap & (1UL << 2)) && | 691 | if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44)) |
723 | __stfle(&facility_list_extended, 1) > 0) { | 692 | elf_hwcap |= HWCAP_S390_DFP; |
724 | if ((facility_list_extended & (1ULL << (63 - 42))) | ||
725 | && (facility_list_extended & (1ULL << (63 - 44)))) | ||
726 | elf_hwcap |= HWCAP_S390_DFP; | ||
727 | } | ||
728 | 693 | ||
729 | /* | 694 | /* |
730 | * Huge page support HWCAP_S390_HPAGE is bit 7. | 695 | * Huge page support HWCAP_S390_HPAGE is bit 7. |
@@ -765,6 +730,9 @@ static void __init setup_hwcaps(void) | |||
765 | case 0x2098: | 730 | case 0x2098: |
766 | strcpy(elf_platform, "z10"); | 731 | strcpy(elf_platform, "z10"); |
767 | break; | 732 | break; |
733 | case 0x2817: | ||
734 | strcpy(elf_platform, "z196"); | ||
735 | break; | ||
768 | } | 736 | } |
769 | } | 737 | } |
770 | 738 | ||
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index ee7ac8b11782..abbb3c3c7aab 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c | |||
@@ -505,7 +505,7 @@ void do_signal(struct pt_regs *regs) | |||
505 | * Let tracing know that we've done the handler setup. | 505 | * Let tracing know that we've done the handler setup. |
506 | */ | 506 | */ |
507 | tracehook_signal_handler(signr, &info, &ka, regs, | 507 | tracehook_signal_handler(signr, &info, &ka, regs, |
508 | current->thread.per_info.single_step); | 508 | test_thread_flag(TIF_SINGLE_STEP)); |
509 | } | 509 | } |
510 | return; | 510 | return; |
511 | } | 511 | } |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 8127ebd59c4d..1d55c95f617c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #define KMSG_COMPONENT "cpu" | 23 | #define KMSG_COMPONENT "cpu" |
24 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 24 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
25 | 25 | ||
26 | #include <linux/workqueue.h> | ||
26 | #include <linux/module.h> | 27 | #include <linux/module.h> |
27 | #include <linux/init.h> | 28 | #include <linux/init.h> |
28 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
@@ -43,7 +44,6 @@ | |||
43 | #include <asm/sigp.h> | 44 | #include <asm/sigp.h> |
44 | #include <asm/pgalloc.h> | 45 | #include <asm/pgalloc.h> |
45 | #include <asm/irq.h> | 46 | #include <asm/irq.h> |
46 | #include <asm/s390_ext.h> | ||
47 | #include <asm/cpcmd.h> | 47 | #include <asm/cpcmd.h> |
48 | #include <asm/tlbflush.h> | 48 | #include <asm/tlbflush.h> |
49 | #include <asm/timer.h> | 49 | #include <asm/timer.h> |
@@ -156,18 +156,20 @@ void smp_send_stop(void) | |||
156 | * cpus are handled. | 156 | * cpus are handled. |
157 | */ | 157 | */ |
158 | 158 | ||
159 | static void do_ext_call_interrupt(__u16 code) | 159 | static void do_ext_call_interrupt(unsigned int ext_int_code, |
160 | unsigned int param32, unsigned long param64) | ||
160 | { | 161 | { |
161 | unsigned long bits; | 162 | unsigned long bits; |
162 | 163 | ||
164 | kstat_cpu(smp_processor_id()).irqs[EXTINT_IPI]++; | ||
163 | /* | 165 | /* |
164 | * handle bit signal external calls | 166 | * handle bit signal external calls |
165 | * | ||
166 | * For the ec_schedule signal we have to do nothing. All the work | ||
167 | * is done automatically when we return from the interrupt. | ||
168 | */ | 167 | */ |
169 | bits = xchg(&S390_lowcore.ext_call_fast, 0); | 168 | bits = xchg(&S390_lowcore.ext_call_fast, 0); |
170 | 169 | ||
170 | if (test_bit(ec_schedule, &bits)) | ||
171 | scheduler_ipi(); | ||
172 | |||
171 | if (test_bit(ec_call_function, &bits)) | 173 | if (test_bit(ec_call_function, &bits)) |
172 | generic_smp_call_function_interrupt(); | 174 | generic_smp_call_function_interrupt(); |
173 | 175 | ||
@@ -260,7 +262,7 @@ void smp_ctl_set_bit(int cr, int bit) | |||
260 | 262 | ||
261 | memset(&parms.orvals, 0, sizeof(parms.orvals)); | 263 | memset(&parms.orvals, 0, sizeof(parms.orvals)); |
262 | memset(&parms.andvals, 0xff, sizeof(parms.andvals)); | 264 | memset(&parms.andvals, 0xff, sizeof(parms.andvals)); |
263 | parms.orvals[cr] = 1 << bit; | 265 | parms.orvals[cr] = 1UL << bit; |
264 | on_each_cpu(smp_ctl_bit_callback, &parms, 1); | 266 | on_each_cpu(smp_ctl_bit_callback, &parms, 1); |
265 | } | 267 | } |
266 | EXPORT_SYMBOL(smp_ctl_set_bit); | 268 | EXPORT_SYMBOL(smp_ctl_set_bit); |
@@ -274,7 +276,7 @@ void smp_ctl_clear_bit(int cr, int bit) | |||
274 | 276 | ||
275 | memset(&parms.orvals, 0, sizeof(parms.orvals)); | 277 | memset(&parms.orvals, 0, sizeof(parms.orvals)); |
276 | memset(&parms.andvals, 0xff, sizeof(parms.andvals)); | 278 | memset(&parms.andvals, 0xff, sizeof(parms.andvals)); |
277 | parms.andvals[cr] = ~(1L << bit); | 279 | parms.andvals[cr] = ~(1UL << bit); |
278 | on_each_cpu(smp_ctl_bit_callback, &parms, 1); | 280 | on_each_cpu(smp_ctl_bit_callback, &parms, 1); |
279 | } | 281 | } |
280 | EXPORT_SYMBOL(smp_ctl_clear_bit); | 282 | EXPORT_SYMBOL(smp_ctl_clear_bit); |
@@ -332,7 +334,7 @@ static int smp_rescan_cpus_sigp(cpumask_t avail) | |||
332 | smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN; | 334 | smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN; |
333 | if (!cpu_stopped(logical_cpu)) | 335 | if (!cpu_stopped(logical_cpu)) |
334 | continue; | 336 | continue; |
335 | cpu_set(logical_cpu, cpu_present_map); | 337 | set_cpu_present(logical_cpu, true); |
336 | smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; | 338 | smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; |
337 | logical_cpu = cpumask_next(logical_cpu, &avail); | 339 | logical_cpu = cpumask_next(logical_cpu, &avail); |
338 | if (logical_cpu >= nr_cpu_ids) | 340 | if (logical_cpu >= nr_cpu_ids) |
@@ -364,7 +366,7 @@ static int smp_rescan_cpus_sclp(cpumask_t avail) | |||
364 | continue; | 366 | continue; |
365 | __cpu_logical_map[logical_cpu] = cpu_id; | 367 | __cpu_logical_map[logical_cpu] = cpu_id; |
366 | smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN; | 368 | smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN; |
367 | cpu_set(logical_cpu, cpu_present_map); | 369 | set_cpu_present(logical_cpu, true); |
368 | if (cpu >= info->configured) | 370 | if (cpu >= info->configured) |
369 | smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY; | 371 | smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY; |
370 | else | 372 | else |
@@ -382,7 +384,7 @@ static int __smp_rescan_cpus(void) | |||
382 | { | 384 | { |
383 | cpumask_t avail; | 385 | cpumask_t avail; |
384 | 386 | ||
385 | cpus_xor(avail, cpu_possible_map, cpu_present_map); | 387 | cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask); |
386 | if (smp_use_sigp_detection) | 388 | if (smp_use_sigp_detection) |
387 | return smp_rescan_cpus_sigp(avail); | 389 | return smp_rescan_cpus_sigp(avail); |
388 | else | 390 | else |
@@ -464,29 +466,29 @@ int __cpuinit start_secondary(void *cpuvoid) | |||
464 | notify_cpu_starting(smp_processor_id()); | 466 | notify_cpu_starting(smp_processor_id()); |
465 | /* Mark this cpu as online */ | 467 | /* Mark this cpu as online */ |
466 | ipi_call_lock(); | 468 | ipi_call_lock(); |
467 | cpu_set(smp_processor_id(), cpu_online_map); | 469 | set_cpu_online(smp_processor_id(), true); |
468 | ipi_call_unlock(); | 470 | ipi_call_unlock(); |
469 | /* Switch on interrupts */ | 471 | /* Switch on interrupts */ |
470 | local_irq_enable(); | 472 | local_irq_enable(); |
471 | /* Print info about this processor */ | ||
472 | print_cpu_info(); | ||
473 | /* cpu_idle will call schedule for us */ | 473 | /* cpu_idle will call schedule for us */ |
474 | cpu_idle(); | 474 | cpu_idle(); |
475 | return 0; | 475 | return 0; |
476 | } | 476 | } |
477 | 477 | ||
478 | static void __init smp_create_idle(unsigned int cpu) | 478 | struct create_idle { |
479 | struct work_struct work; | ||
480 | struct task_struct *idle; | ||
481 | struct completion done; | ||
482 | int cpu; | ||
483 | }; | ||
484 | |||
485 | static void __cpuinit smp_fork_idle(struct work_struct *work) | ||
479 | { | 486 | { |
480 | struct task_struct *p; | 487 | struct create_idle *c_idle; |
481 | 488 | ||
482 | /* | 489 | c_idle = container_of(work, struct create_idle, work); |
483 | * don't care about the psw and regs settings since we'll never | 490 | c_idle->idle = fork_idle(c_idle->cpu); |
484 | * reschedule the forked task. | 491 | complete(&c_idle->done); |
485 | */ | ||
486 | p = fork_idle(cpu); | ||
487 | if (IS_ERR(p)) | ||
488 | panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); | ||
489 | current_set[cpu] = p; | ||
490 | } | 492 | } |
491 | 493 | ||
492 | static int __cpuinit smp_alloc_lowcore(int cpu) | 494 | static int __cpuinit smp_alloc_lowcore(int cpu) |
@@ -550,6 +552,7 @@ static void smp_free_lowcore(int cpu) | |||
550 | int __cpuinit __cpu_up(unsigned int cpu) | 552 | int __cpuinit __cpu_up(unsigned int cpu) |
551 | { | 553 | { |
552 | struct _lowcore *cpu_lowcore; | 554 | struct _lowcore *cpu_lowcore; |
555 | struct create_idle c_idle; | ||
553 | struct task_struct *idle; | 556 | struct task_struct *idle; |
554 | struct stack_frame *sf; | 557 | struct stack_frame *sf; |
555 | u32 lowcore; | 558 | u32 lowcore; |
@@ -557,6 +560,19 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
557 | 560 | ||
558 | if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) | 561 | if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) |
559 | return -EIO; | 562 | return -EIO; |
563 | idle = current_set[cpu]; | ||
564 | if (!idle) { | ||
565 | c_idle.done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done); | ||
566 | INIT_WORK_ONSTACK(&c_idle.work, smp_fork_idle); | ||
567 | c_idle.cpu = cpu; | ||
568 | schedule_work(&c_idle.work); | ||
569 | wait_for_completion(&c_idle.done); | ||
570 | if (IS_ERR(c_idle.idle)) | ||
571 | return PTR_ERR(c_idle.idle); | ||
572 | idle = c_idle.idle; | ||
573 | current_set[cpu] = c_idle.idle; | ||
574 | } | ||
575 | init_idle(idle, cpu); | ||
560 | if (smp_alloc_lowcore(cpu)) | 576 | if (smp_alloc_lowcore(cpu)) |
561 | return -ENOMEM; | 577 | return -ENOMEM; |
562 | do { | 578 | do { |
@@ -571,7 +587,6 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
571 | while (sigp_p(lowcore, cpu, sigp_set_prefix) == sigp_busy) | 587 | while (sigp_p(lowcore, cpu, sigp_set_prefix) == sigp_busy) |
572 | udelay(10); | 588 | udelay(10); |
573 | 589 | ||
574 | idle = current_set[cpu]; | ||
575 | cpu_lowcore = lowcore_ptr[cpu]; | 590 | cpu_lowcore = lowcore_ptr[cpu]; |
576 | cpu_lowcore->kernel_stack = (unsigned long) | 591 | cpu_lowcore->kernel_stack = (unsigned long) |
577 | task_stack_page(idle) + THREAD_SIZE; | 592 | task_stack_page(idle) + THREAD_SIZE; |
@@ -593,6 +608,8 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
593 | cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; | 608 | cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; |
594 | cpu_lowcore->machine_flags = S390_lowcore.machine_flags; | 609 | cpu_lowcore->machine_flags = S390_lowcore.machine_flags; |
595 | cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func; | 610 | cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func; |
611 | memcpy(cpu_lowcore->stfle_fac_list, S390_lowcore.stfle_fac_list, | ||
612 | MAX_FACILITY_BIT/8); | ||
596 | eieio(); | 613 | eieio(); |
597 | 614 | ||
598 | while (sigp(cpu, sigp_restart) == sigp_busy) | 615 | while (sigp(cpu, sigp_restart) == sigp_busy) |
@@ -626,7 +643,7 @@ int __cpu_disable(void) | |||
626 | struct ec_creg_mask_parms cr_parms; | 643 | struct ec_creg_mask_parms cr_parms; |
627 | int cpu = smp_processor_id(); | 644 | int cpu = smp_processor_id(); |
628 | 645 | ||
629 | cpu_clear(cpu, cpu_online_map); | 646 | set_cpu_online(cpu, false); |
630 | 647 | ||
631 | /* Disable pfault pseudo page faults on this cpu. */ | 648 | /* Disable pfault pseudo page faults on this cpu. */ |
632 | pfault_fini(); | 649 | pfault_fini(); |
@@ -636,8 +653,8 @@ int __cpu_disable(void) | |||
636 | 653 | ||
637 | /* disable all external interrupts */ | 654 | /* disable all external interrupts */ |
638 | cr_parms.orvals[0] = 0; | 655 | cr_parms.orvals[0] = 0; |
639 | cr_parms.andvals[0] = ~(1 << 15 | 1 << 14 | 1 << 13 | 1 << 12 | | 656 | cr_parms.andvals[0] = ~(1 << 15 | 1 << 14 | 1 << 13 | 1 << 11 | |
640 | 1 << 11 | 1 << 10 | 1 << 6 | 1 << 4); | 657 | 1 << 10 | 1 << 9 | 1 << 6 | 1 << 4); |
641 | /* disable all I/O interrupts */ | 658 | /* disable all I/O interrupts */ |
642 | cr_parms.orvals[6] = 0; | 659 | cr_parms.orvals[6] = 0; |
643 | cr_parms.andvals[6] = ~(1 << 31 | 1 << 30 | 1 << 29 | 1 << 28 | | 660 | cr_parms.andvals[6] = ~(1 << 31 | 1 << 30 | 1 << 29 | 1 << 28 | |
@@ -661,10 +678,9 @@ void __cpu_die(unsigned int cpu) | |||
661 | udelay(10); | 678 | udelay(10); |
662 | smp_free_lowcore(cpu); | 679 | smp_free_lowcore(cpu); |
663 | atomic_dec(&init_mm.context.attach_count); | 680 | atomic_dec(&init_mm.context.attach_count); |
664 | pr_info("Processor %d stopped\n", cpu); | ||
665 | } | 681 | } |
666 | 682 | ||
667 | void cpu_die(void) | 683 | void __noreturn cpu_die(void) |
668 | { | 684 | { |
669 | idle_task_exit(); | 685 | idle_task_exit(); |
670 | while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) | 686 | while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) |
@@ -681,14 +697,12 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
681 | #endif | 697 | #endif |
682 | unsigned long async_stack, panic_stack; | 698 | unsigned long async_stack, panic_stack; |
683 | struct _lowcore *lowcore; | 699 | struct _lowcore *lowcore; |
684 | unsigned int cpu; | ||
685 | 700 | ||
686 | smp_detect_cpus(); | 701 | smp_detect_cpus(); |
687 | 702 | ||
688 | /* request the 0x1201 emergency signal external interrupt */ | 703 | /* request the 0x1201 emergency signal external interrupt */ |
689 | if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) | 704 | if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) |
690 | panic("Couldn't request external interrupt 0x1201"); | 705 | panic("Couldn't request external interrupt 0x1201"); |
691 | print_cpu_info(); | ||
692 | 706 | ||
693 | /* Reallocate current lowcore, but keep its contents. */ | 707 | /* Reallocate current lowcore, but keep its contents. */ |
694 | lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); | 708 | lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); |
@@ -716,9 +730,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
716 | if (vdso_alloc_per_cpu(smp_processor_id(), &S390_lowcore)) | 730 | if (vdso_alloc_per_cpu(smp_processor_id(), &S390_lowcore)) |
717 | BUG(); | 731 | BUG(); |
718 | #endif | 732 | #endif |
719 | for_each_possible_cpu(cpu) | ||
720 | if (cpu != smp_processor_id()) | ||
721 | smp_create_idle(cpu); | ||
722 | } | 733 | } |
723 | 734 | ||
724 | void __init smp_prepare_boot_cpu(void) | 735 | void __init smp_prepare_boot_cpu(void) |
@@ -726,8 +737,8 @@ void __init smp_prepare_boot_cpu(void) | |||
726 | BUG_ON(smp_processor_id() != 0); | 737 | BUG_ON(smp_processor_id() != 0); |
727 | 738 | ||
728 | current_thread_info()->cpu = 0; | 739 | current_thread_info()->cpu = 0; |
729 | cpu_set(0, cpu_present_map); | 740 | set_cpu_present(0, true); |
730 | cpu_set(0, cpu_online_map); | 741 | set_cpu_online(0, true); |
731 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; | 742 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; |
732 | current_set[0] = current; | 743 | current_set[0] = current; |
733 | smp_cpu_state[0] = CPU_STATE_CONFIGURED; | 744 | smp_cpu_state[0] = CPU_STATE_CONFIGURED; |
@@ -1004,21 +1015,21 @@ int __ref smp_rescan_cpus(void) | |||
1004 | 1015 | ||
1005 | get_online_cpus(); | 1016 | get_online_cpus(); |
1006 | mutex_lock(&smp_cpu_state_mutex); | 1017 | mutex_lock(&smp_cpu_state_mutex); |
1007 | newcpus = cpu_present_map; | 1018 | cpumask_copy(&newcpus, cpu_present_mask); |
1008 | rc = __smp_rescan_cpus(); | 1019 | rc = __smp_rescan_cpus(); |
1009 | if (rc) | 1020 | if (rc) |
1010 | goto out; | 1021 | goto out; |
1011 | cpus_andnot(newcpus, cpu_present_map, newcpus); | 1022 | cpumask_andnot(&newcpus, cpu_present_mask, &newcpus); |
1012 | for_each_cpu_mask(cpu, newcpus) { | 1023 | for_each_cpu(cpu, &newcpus) { |
1013 | rc = smp_add_present_cpu(cpu); | 1024 | rc = smp_add_present_cpu(cpu); |
1014 | if (rc) | 1025 | if (rc) |
1015 | cpu_clear(cpu, cpu_present_map); | 1026 | set_cpu_present(cpu, false); |
1016 | } | 1027 | } |
1017 | rc = 0; | 1028 | rc = 0; |
1018 | out: | 1029 | out: |
1019 | mutex_unlock(&smp_cpu_state_mutex); | 1030 | mutex_unlock(&smp_cpu_state_mutex); |
1020 | put_online_cpus(); | 1031 | put_online_cpus(); |
1021 | if (!cpus_empty(newcpus)) | 1032 | if (!cpumask_empty(&newcpus)) |
1022 | topology_schedule_update(); | 1033 | topology_schedule_update(); |
1023 | return rc; | 1034 | return rc; |
1024 | } | 1035 | } |
diff --git a/arch/s390/kernel/switch_cpu.S b/arch/s390/kernel/switch_cpu.S index 469f11b574fa..20530dd2eab1 100644 --- a/arch/s390/kernel/switch_cpu.S +++ b/arch/s390/kernel/switch_cpu.S | |||
@@ -46,7 +46,9 @@ smp_restart_cpu: | |||
46 | ltr %r4,%r4 /* New stack ? */ | 46 | ltr %r4,%r4 /* New stack ? */ |
47 | jz 1f | 47 | jz 1f |
48 | lr %r15,%r4 | 48 | lr %r15,%r4 |
49 | 1: basr %r14,%r2 | 49 | 1: lr %r14,%r2 /* r14: Function to call */ |
50 | lr %r2,%r3 /* r2 : Parameter for function*/ | ||
51 | basr %r14,%r14 /* Call function */ | ||
50 | 52 | ||
51 | .gprregs_addr: | 53 | .gprregs_addr: |
52 | .long .gprregs | 54 | .long .gprregs |
diff --git a/arch/s390/kernel/switch_cpu64.S b/arch/s390/kernel/switch_cpu64.S index d94aacc898cb..5be3f43898f9 100644 --- a/arch/s390/kernel/switch_cpu64.S +++ b/arch/s390/kernel/switch_cpu64.S | |||
@@ -42,7 +42,9 @@ smp_restart_cpu: | |||
42 | ltgr %r4,%r4 /* New stack ? */ | 42 | ltgr %r4,%r4 /* New stack ? */ |
43 | jz 1f | 43 | jz 1f |
44 | lgr %r15,%r4 | 44 | lgr %r15,%r4 |
45 | 1: basr %r14,%r2 | 45 | 1: lgr %r14,%r2 /* r14: Function to call */ |
46 | lgr %r2,%r3 /* r2 : Parameter for function*/ | ||
47 | basr %r14,%r14 /* Call function */ | ||
46 | 48 | ||
47 | .section .data,"aw",@progbits | 49 | .section .data,"aw",@progbits |
48 | .gprregs: | 50 | .gprregs: |
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index a8fee1b14395..6ee39ef8fe4a 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
@@ -343,3 +343,8 @@ SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper) | |||
343 | SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper) | 343 | SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper) |
344 | SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper) | 344 | SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper) |
345 | SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper) | 345 | SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper) |
346 | SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */ | ||
347 | SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at_wrapper) | ||
348 | SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper) | ||
349 | SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper) | ||
350 | SYSCALL(sys_setns,sys_setns,sys_setns_wrapper) | ||
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index a0ffc7717ed6..5c9e439bf3f6 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <asm/ebcdic.h> | 15 | #include <asm/ebcdic.h> |
16 | #include <asm/sysinfo.h> | 16 | #include <asm/sysinfo.h> |
17 | #include <asm/cpcmd.h> | 17 | #include <asm/cpcmd.h> |
18 | #include <asm/topology.h> | ||
18 | 19 | ||
19 | /* Sigh, math-emu. Don't ask. */ | 20 | /* Sigh, math-emu. Don't ask. */ |
20 | #include <asm/sfp-util.h> | 21 | #include <asm/sfp-util.h> |
@@ -74,6 +75,44 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) | |||
74 | "Model Temp. Capacity: %-16.16s %08u\n", | 75 | "Model Temp. Capacity: %-16.16s %08u\n", |
75 | info->model_temp_cap, | 76 | info->model_temp_cap, |
76 | *(u32 *) info->model_temp_cap_rating); | 77 | *(u32 *) info->model_temp_cap_rating); |
78 | if (info->cai) { | ||
79 | len += sprintf(page + len, | ||
80 | "Capacity Adj. Ind.: %d\n", | ||
81 | info->cai); | ||
82 | len += sprintf(page + len, "Capacity Ch. Reason: %d\n", | ||
83 | info->ccr); | ||
84 | } | ||
85 | return len; | ||
86 | } | ||
87 | |||
88 | static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len) | ||
89 | { | ||
90 | static int max_mnest; | ||
91 | int i, rc; | ||
92 | |||
93 | len += sprintf(page + len, "\n"); | ||
94 | if (!MACHINE_HAS_TOPOLOGY) | ||
95 | return len; | ||
96 | if (max_mnest) { | ||
97 | stsi(info, 15, 1, max_mnest); | ||
98 | } else { | ||
99 | for (max_mnest = 6; max_mnest > 1; max_mnest--) { | ||
100 | rc = stsi(info, 15, 1, max_mnest); | ||
101 | if (rc != -ENOSYS) | ||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | len += sprintf(page + len, "CPU Topology HW: "); | ||
106 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | ||
107 | len += sprintf(page + len, " %d", info->mag[i]); | ||
108 | len += sprintf(page + len, "\n"); | ||
109 | #ifdef CONFIG_SCHED_MC | ||
110 | store_topology(info); | ||
111 | len += sprintf(page + len, "CPU Topology SW: "); | ||
112 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | ||
113 | len += sprintf(page + len, " %d", info->mag[i]); | ||
114 | len += sprintf(page + len, "\n"); | ||
115 | #endif | ||
77 | return len; | 116 | return len; |
78 | } | 117 | } |
79 | 118 | ||
@@ -87,7 +126,6 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) | |||
87 | ext = (struct sysinfo_1_2_2_extension *) | 126 | ext = (struct sysinfo_1_2_2_extension *) |
88 | ((unsigned long) info + info->acc_offset); | 127 | ((unsigned long) info + info->acc_offset); |
89 | 128 | ||
90 | len += sprintf(page + len, "\n"); | ||
91 | len += sprintf(page + len, "CPUs Total: %d\n", | 129 | len += sprintf(page + len, "CPUs Total: %d\n", |
92 | info->cpus_total); | 130 | info->cpus_total); |
93 | len += sprintf(page + len, "CPUs Configured: %d\n", | 131 | len += sprintf(page + len, "CPUs Configured: %d\n", |
@@ -217,6 +255,9 @@ static int proc_read_sysinfo(char *page, char **start, | |||
217 | len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len); | 255 | len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len); |
218 | 256 | ||
219 | if (level >= 1) | 257 | if (level >= 1) |
258 | len = stsi_15_1_x((struct sysinfo_15_1_x *) info, page, len); | ||
259 | |||
260 | if (level >= 1) | ||
220 | len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len); | 261 | len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len); |
221 | 262 | ||
222 | if (level >= 2) | 263 | if (level >= 2) |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 2896cac9c14a..dff933065ab6 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #define KMSG_COMPONENT "time" | 15 | #define KMSG_COMPONENT "time" |
16 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 16 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
17 | 17 | ||
18 | #include <linux/kernel_stat.h> | ||
18 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
@@ -37,9 +38,9 @@ | |||
37 | #include <linux/clocksource.h> | 38 | #include <linux/clocksource.h> |
38 | #include <linux/clockchips.h> | 39 | #include <linux/clockchips.h> |
39 | #include <linux/gfp.h> | 40 | #include <linux/gfp.h> |
41 | #include <linux/kprobes.h> | ||
40 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
41 | #include <asm/delay.h> | 43 | #include <asm/delay.h> |
42 | #include <asm/s390_ext.h> | ||
43 | #include <asm/div64.h> | 44 | #include <asm/div64.h> |
44 | #include <asm/vdso.h> | 45 | #include <asm/vdso.h> |
45 | #include <asm/irq.h> | 46 | #include <asm/irq.h> |
@@ -60,7 +61,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators); | |||
60 | /* | 61 | /* |
61 | * Scheduler clock - returns current time in nanosec units. | 62 | * Scheduler clock - returns current time in nanosec units. |
62 | */ | 63 | */ |
63 | unsigned long long notrace sched_clock(void) | 64 | unsigned long long notrace __kprobes sched_clock(void) |
64 | { | 65 | { |
65 | return (get_clock_monotonic() * 125) >> 9; | 66 | return (get_clock_monotonic() * 125) >> 9; |
66 | } | 67 | } |
@@ -155,8 +156,11 @@ void init_cpu_timer(void) | |||
155 | __ctl_set_bit(0, 4); | 156 | __ctl_set_bit(0, 4); |
156 | } | 157 | } |
157 | 158 | ||
158 | static void clock_comparator_interrupt(__u16 code) | 159 | static void clock_comparator_interrupt(unsigned int ext_int_code, |
160 | unsigned int param32, | ||
161 | unsigned long param64) | ||
159 | { | 162 | { |
163 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CLK]++; | ||
160 | if (S390_lowcore.clock_comparator == -1ULL) | 164 | if (S390_lowcore.clock_comparator == -1ULL) |
161 | set_clock_comparator(S390_lowcore.clock_comparator); | 165 | set_clock_comparator(S390_lowcore.clock_comparator); |
162 | } | 166 | } |
@@ -164,14 +168,14 @@ static void clock_comparator_interrupt(__u16 code) | |||
164 | static void etr_timing_alert(struct etr_irq_parm *); | 168 | static void etr_timing_alert(struct etr_irq_parm *); |
165 | static void stp_timing_alert(struct stp_irq_parm *); | 169 | static void stp_timing_alert(struct stp_irq_parm *); |
166 | 170 | ||
167 | static void timing_alert_interrupt(__u16 code) | 171 | static void timing_alert_interrupt(unsigned int ext_int_code, |
172 | unsigned int param32, unsigned long param64) | ||
168 | { | 173 | { |
169 | if (S390_lowcore.ext_params & 0x00c40000) | 174 | kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++; |
170 | etr_timing_alert((struct etr_irq_parm *) | 175 | if (param32 & 0x00c40000) |
171 | &S390_lowcore.ext_params); | 176 | etr_timing_alert((struct etr_irq_parm *) ¶m32); |
172 | if (S390_lowcore.ext_params & 0x00038000) | 177 | if (param32 & 0x00038000) |
173 | stp_timing_alert((struct stp_irq_parm *) | 178 | stp_timing_alert((struct stp_irq_parm *) ¶m32); |
174 | &S390_lowcore.ext_params); | ||
175 | } | 179 | } |
176 | 180 | ||
177 | static void etr_reset(void); | 181 | static void etr_reset(void); |
@@ -719,7 +723,7 @@ static void clock_sync_cpu(struct clock_sync_data *sync) | |||
719 | } | 723 | } |
720 | 724 | ||
721 | /* | 725 | /* |
722 | * Sync the TOD clock using the port refered to by aibp. This port | 726 | * Sync the TOD clock using the port referred to by aibp. This port |
723 | * has to be enabled and the other port has to be disabled. The | 727 | * has to be enabled and the other port has to be disabled. The |
724 | * last eacr update has to be more than 1.6 seconds in the past. | 728 | * last eacr update has to be more than 1.6 seconds in the past. |
725 | */ | 729 | */ |
@@ -805,7 +809,7 @@ static int etr_sync_clock_stop(struct etr_aib *aib, int port) | |||
805 | etr_sync.etr_port = port; | 809 | etr_sync.etr_port = port; |
806 | get_online_cpus(); | 810 | get_online_cpus(); |
807 | atomic_set(&etr_sync.cpus, num_online_cpus() - 1); | 811 | atomic_set(&etr_sync.cpus, num_online_cpus() - 1); |
808 | rc = stop_machine(etr_sync_clock, &etr_sync, &cpu_online_map); | 812 | rc = stop_machine(etr_sync_clock, &etr_sync, cpu_online_mask); |
809 | put_online_cpus(); | 813 | put_online_cpus(); |
810 | return rc; | 814 | return rc; |
811 | } | 815 | } |
@@ -1007,7 +1011,7 @@ static void etr_work_fn(struct work_struct *work) | |||
1007 | eacr = etr_handle_update(&aib, eacr); | 1011 | eacr = etr_handle_update(&aib, eacr); |
1008 | 1012 | ||
1009 | /* | 1013 | /* |
1010 | * Select ports to enable. The prefered synchronization mode is PPS. | 1014 | * Select ports to enable. The preferred synchronization mode is PPS. |
1011 | * If a port can be enabled depends on a number of things: | 1015 | * If a port can be enabled depends on a number of things: |
1012 | * 1) The port needs to be online and uptodate. A port is not | 1016 | * 1) The port needs to be online and uptodate. A port is not |
1013 | * disabled just because it is not uptodate, but it is only | 1017 | * disabled just because it is not uptodate, but it is only |
@@ -1086,7 +1090,7 @@ static void etr_work_fn(struct work_struct *work) | |||
1086 | /* | 1090 | /* |
1087 | * Update eacr and try to synchronize the clock. If the update | 1091 | * Update eacr and try to synchronize the clock. If the update |
1088 | * of eacr caused a stepping port switch (or if we have to | 1092 | * of eacr caused a stepping port switch (or if we have to |
1089 | * assume that a stepping port switch has occured) or the | 1093 | * assume that a stepping port switch has occurred) or the |
1090 | * clock syncing failed, reset the sync check control bit | 1094 | * clock syncing failed, reset the sync check control bit |
1091 | * and set up a timer to try again after 0.5 seconds | 1095 | * and set up a timer to try again after 0.5 seconds |
1092 | */ | 1096 | */ |
@@ -1574,7 +1578,7 @@ static void stp_work_fn(struct work_struct *work) | |||
1574 | memset(&stp_sync, 0, sizeof(stp_sync)); | 1578 | memset(&stp_sync, 0, sizeof(stp_sync)); |
1575 | get_online_cpus(); | 1579 | get_online_cpus(); |
1576 | atomic_set(&stp_sync.cpus, num_online_cpus() - 1); | 1580 | atomic_set(&stp_sync.cpus, num_online_cpus() - 1); |
1577 | stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map); | 1581 | stop_machine(stp_sync_clock, &stp_sync, cpu_online_mask); |
1578 | put_online_cpus(); | 1582 | put_online_cpus(); |
1579 | 1583 | ||
1580 | if (!check_sync_clock()) | 1584 | if (!check_sync_clock()) |
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index bcef00766a64..0cd340b72632 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
@@ -17,159 +17,140 @@ | |||
17 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
18 | #include <linux/cpuset.h> | 18 | #include <linux/cpuset.h> |
19 | #include <asm/delay.h> | 19 | #include <asm/delay.h> |
20 | #include <asm/s390_ext.h> | ||
21 | #include <asm/sysinfo.h> | ||
22 | |||
23 | #define CPU_BITS 64 | ||
24 | #define NR_MAG 6 | ||
25 | 20 | ||
26 | #define PTF_HORIZONTAL (0UL) | 21 | #define PTF_HORIZONTAL (0UL) |
27 | #define PTF_VERTICAL (1UL) | 22 | #define PTF_VERTICAL (1UL) |
28 | #define PTF_CHECK (2UL) | 23 | #define PTF_CHECK (2UL) |
29 | 24 | ||
30 | struct tl_cpu { | 25 | struct mask_info { |
31 | unsigned char reserved0[4]; | 26 | struct mask_info *next; |
32 | unsigned char :6; | ||
33 | unsigned char pp:2; | ||
34 | unsigned char reserved1; | ||
35 | unsigned short origin; | ||
36 | unsigned long mask[CPU_BITS / BITS_PER_LONG]; | ||
37 | }; | ||
38 | |||
39 | struct tl_container { | ||
40 | unsigned char reserved[7]; | ||
41 | unsigned char id; | ||
42 | }; | ||
43 | |||
44 | union tl_entry { | ||
45 | unsigned char nl; | ||
46 | struct tl_cpu cpu; | ||
47 | struct tl_container container; | ||
48 | }; | ||
49 | |||
50 | struct tl_info { | ||
51 | unsigned char reserved0[2]; | ||
52 | unsigned short length; | ||
53 | unsigned char mag[NR_MAG]; | ||
54 | unsigned char reserved1; | ||
55 | unsigned char mnest; | ||
56 | unsigned char reserved2[4]; | ||
57 | union tl_entry tle[0]; | ||
58 | }; | ||
59 | |||
60 | struct core_info { | ||
61 | struct core_info *next; | ||
62 | unsigned char id; | 27 | unsigned char id; |
63 | cpumask_t mask; | 28 | cpumask_t mask; |
64 | }; | 29 | }; |
65 | 30 | ||
66 | static int topology_enabled; | 31 | static int topology_enabled = 1; |
67 | static void topology_work_fn(struct work_struct *work); | 32 | static void topology_work_fn(struct work_struct *work); |
68 | static struct tl_info *tl_info; | 33 | static struct sysinfo_15_1_x *tl_info; |
69 | static struct core_info core_info; | ||
70 | static int machine_has_topology; | ||
71 | static struct timer_list topology_timer; | 34 | static struct timer_list topology_timer; |
72 | static void set_topology_timer(void); | 35 | static void set_topology_timer(void); |
73 | static DECLARE_WORK(topology_work, topology_work_fn); | 36 | static DECLARE_WORK(topology_work, topology_work_fn); |
74 | /* topology_lock protects the core linked list */ | 37 | /* topology_lock protects the core linked list */ |
75 | static DEFINE_SPINLOCK(topology_lock); | 38 | static DEFINE_SPINLOCK(topology_lock); |
76 | 39 | ||
40 | static struct mask_info core_info; | ||
77 | cpumask_t cpu_core_map[NR_CPUS]; | 41 | cpumask_t cpu_core_map[NR_CPUS]; |
78 | unsigned char cpu_core_id[NR_CPUS]; | 42 | unsigned char cpu_core_id[NR_CPUS]; |
79 | 43 | ||
80 | static cpumask_t cpu_coregroup_map(unsigned int cpu) | 44 | #ifdef CONFIG_SCHED_BOOK |
45 | static struct mask_info book_info; | ||
46 | cpumask_t cpu_book_map[NR_CPUS]; | ||
47 | unsigned char cpu_book_id[NR_CPUS]; | ||
48 | #endif | ||
49 | |||
50 | static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) | ||
81 | { | 51 | { |
82 | struct core_info *core = &core_info; | ||
83 | unsigned long flags; | ||
84 | cpumask_t mask; | 52 | cpumask_t mask; |
85 | 53 | ||
86 | cpus_clear(mask); | 54 | cpumask_clear(&mask); |
87 | if (!topology_enabled || !machine_has_topology) | 55 | if (!topology_enabled || !MACHINE_HAS_TOPOLOGY) { |
88 | return cpu_possible_map; | 56 | cpumask_copy(&mask, cpumask_of(cpu)); |
89 | spin_lock_irqsave(&topology_lock, flags); | 57 | return mask; |
90 | while (core) { | 58 | } |
91 | if (cpu_isset(cpu, core->mask)) { | 59 | while (info) { |
92 | mask = core->mask; | 60 | if (cpumask_test_cpu(cpu, &info->mask)) { |
61 | mask = info->mask; | ||
93 | break; | 62 | break; |
94 | } | 63 | } |
95 | core = core->next; | 64 | info = info->next; |
96 | } | 65 | } |
97 | spin_unlock_irqrestore(&topology_lock, flags); | 66 | if (cpumask_empty(&mask)) |
98 | if (cpus_empty(mask)) | 67 | cpumask_copy(&mask, cpumask_of(cpu)); |
99 | mask = cpumask_of_cpu(cpu); | ||
100 | return mask; | 68 | return mask; |
101 | } | 69 | } |
102 | 70 | ||
103 | const struct cpumask *cpu_coregroup_mask(unsigned int cpu) | 71 | static void add_cpus_to_mask(struct topology_cpu *tl_cpu, |
104 | { | 72 | struct mask_info *book, struct mask_info *core) |
105 | return &cpu_core_map[cpu]; | ||
106 | } | ||
107 | |||
108 | static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core) | ||
109 | { | 73 | { |
110 | unsigned int cpu; | 74 | unsigned int cpu; |
111 | 75 | ||
112 | for (cpu = find_first_bit(&tl_cpu->mask[0], CPU_BITS); | 76 | for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS); |
113 | cpu < CPU_BITS; | 77 | cpu < TOPOLOGY_CPU_BITS; |
114 | cpu = find_next_bit(&tl_cpu->mask[0], CPU_BITS, cpu + 1)) | 78 | cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1)) |
115 | { | 79 | { |
116 | unsigned int rcpu, lcpu; | 80 | unsigned int rcpu, lcpu; |
117 | 81 | ||
118 | rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin; | 82 | rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin; |
119 | for_each_present_cpu(lcpu) { | 83 | for_each_present_cpu(lcpu) { |
120 | if (cpu_logical_map(lcpu) == rcpu) { | 84 | if (cpu_logical_map(lcpu) != rcpu) |
121 | cpu_set(lcpu, core->mask); | 85 | continue; |
122 | cpu_core_id[lcpu] = core->id; | 86 | #ifdef CONFIG_SCHED_BOOK |
123 | smp_cpu_polarization[lcpu] = tl_cpu->pp; | 87 | cpumask_set_cpu(lcpu, &book->mask); |
124 | } | 88 | cpu_book_id[lcpu] = book->id; |
89 | #endif | ||
90 | cpumask_set_cpu(lcpu, &core->mask); | ||
91 | cpu_core_id[lcpu] = core->id; | ||
92 | smp_cpu_polarization[lcpu] = tl_cpu->pp; | ||
125 | } | 93 | } |
126 | } | 94 | } |
127 | } | 95 | } |
128 | 96 | ||
129 | static void clear_cores(void) | 97 | static void clear_masks(void) |
130 | { | 98 | { |
131 | struct core_info *core = &core_info; | 99 | struct mask_info *info; |
132 | 100 | ||
133 | while (core) { | 101 | info = &core_info; |
134 | cpus_clear(core->mask); | 102 | while (info) { |
135 | core = core->next; | 103 | cpumask_clear(&info->mask); |
104 | info = info->next; | ||
136 | } | 105 | } |
106 | #ifdef CONFIG_SCHED_BOOK | ||
107 | info = &book_info; | ||
108 | while (info) { | ||
109 | cpumask_clear(&info->mask); | ||
110 | info = info->next; | ||
111 | } | ||
112 | #endif | ||
137 | } | 113 | } |
138 | 114 | ||
139 | static union tl_entry *next_tle(union tl_entry *tle) | 115 | static union topology_entry *next_tle(union topology_entry *tle) |
140 | { | 116 | { |
141 | if (tle->nl) | 117 | if (!tle->nl) |
142 | return (union tl_entry *)((struct tl_container *)tle + 1); | 118 | return (union topology_entry *)((struct topology_cpu *)tle + 1); |
143 | else | 119 | return (union topology_entry *)((struct topology_container *)tle + 1); |
144 | return (union tl_entry *)((struct tl_cpu *)tle + 1); | ||
145 | } | 120 | } |
146 | 121 | ||
147 | static void tl_to_cores(struct tl_info *info) | 122 | static void tl_to_cores(struct sysinfo_15_1_x *info) |
148 | { | 123 | { |
149 | union tl_entry *tle, *end; | 124 | #ifdef CONFIG_SCHED_BOOK |
150 | struct core_info *core = &core_info; | 125 | struct mask_info *book = &book_info; |
126 | #else | ||
127 | struct mask_info *book = NULL; | ||
128 | #endif | ||
129 | struct mask_info *core = &core_info; | ||
130 | union topology_entry *tle, *end; | ||
131 | |||
151 | 132 | ||
152 | spin_lock_irq(&topology_lock); | 133 | spin_lock_irq(&topology_lock); |
153 | clear_cores(); | 134 | clear_masks(); |
154 | tle = info->tle; | 135 | tle = info->tle; |
155 | end = (union tl_entry *)((unsigned long)info + info->length); | 136 | end = (union topology_entry *)((unsigned long)info + info->length); |
156 | while (tle < end) { | 137 | while (tle < end) { |
157 | switch (tle->nl) { | 138 | switch (tle->nl) { |
158 | case 5: | 139 | #ifdef CONFIG_SCHED_BOOK |
159 | case 4: | ||
160 | case 3: | ||
161 | case 2: | 140 | case 2: |
141 | book = book->next; | ||
142 | book->id = tle->container.id; | ||
162 | break; | 143 | break; |
144 | #endif | ||
163 | case 1: | 145 | case 1: |
164 | core = core->next; | 146 | core = core->next; |
165 | core->id = tle->container.id; | 147 | core->id = tle->container.id; |
166 | break; | 148 | break; |
167 | case 0: | 149 | case 0: |
168 | add_cpus_to_core(&tle->cpu, core); | 150 | add_cpus_to_mask(&tle->cpu, book, core); |
169 | break; | 151 | break; |
170 | default: | 152 | default: |
171 | clear_cores(); | 153 | clear_masks(); |
172 | machine_has_topology = 0; | ||
173 | goto out; | 154 | goto out; |
174 | } | 155 | } |
175 | tle = next_tle(tle); | 156 | tle = next_tle(tle); |
@@ -206,7 +187,7 @@ int topology_set_cpu_management(int fc) | |||
206 | int cpu; | 187 | int cpu; |
207 | int rc; | 188 | int rc; |
208 | 189 | ||
209 | if (!machine_has_topology) | 190 | if (!MACHINE_HAS_TOPOLOGY) |
210 | return -EOPNOTSUPP; | 191 | return -EOPNOTSUPP; |
211 | if (fc) | 192 | if (fc) |
212 | rc = ptf(PTF_VERTICAL); | 193 | rc = ptf(PTF_VERTICAL); |
@@ -221,24 +202,43 @@ int topology_set_cpu_management(int fc) | |||
221 | 202 | ||
222 | static void update_cpu_core_map(void) | 203 | static void update_cpu_core_map(void) |
223 | { | 204 | { |
205 | unsigned long flags; | ||
224 | int cpu; | 206 | int cpu; |
225 | 207 | ||
226 | for_each_possible_cpu(cpu) | 208 | spin_lock_irqsave(&topology_lock, flags); |
227 | cpu_core_map[cpu] = cpu_coregroup_map(cpu); | 209 | for_each_possible_cpu(cpu) { |
210 | cpu_core_map[cpu] = cpu_group_map(&core_info, cpu); | ||
211 | #ifdef CONFIG_SCHED_BOOK | ||
212 | cpu_book_map[cpu] = cpu_group_map(&book_info, cpu); | ||
213 | #endif | ||
214 | } | ||
215 | spin_unlock_irqrestore(&topology_lock, flags); | ||
216 | } | ||
217 | |||
218 | void store_topology(struct sysinfo_15_1_x *info) | ||
219 | { | ||
220 | #ifdef CONFIG_SCHED_BOOK | ||
221 | int rc; | ||
222 | |||
223 | rc = stsi(info, 15, 1, 3); | ||
224 | if (rc != -ENOSYS) | ||
225 | return; | ||
226 | #endif | ||
227 | stsi(info, 15, 1, 2); | ||
228 | } | 228 | } |
229 | 229 | ||
230 | int arch_update_cpu_topology(void) | 230 | int arch_update_cpu_topology(void) |
231 | { | 231 | { |
232 | struct tl_info *info = tl_info; | 232 | struct sysinfo_15_1_x *info = tl_info; |
233 | struct sys_device *sysdev; | 233 | struct sys_device *sysdev; |
234 | int cpu; | 234 | int cpu; |
235 | 235 | ||
236 | if (!machine_has_topology) { | 236 | if (!MACHINE_HAS_TOPOLOGY) { |
237 | update_cpu_core_map(); | 237 | update_cpu_core_map(); |
238 | topology_update_polarization_simple(); | 238 | topology_update_polarization_simple(); |
239 | return 0; | 239 | return 0; |
240 | } | 240 | } |
241 | stsi(info, 15, 1, 2); | 241 | store_topology(info); |
242 | tl_to_cores(info); | 242 | tl_to_cores(info); |
243 | update_cpu_core_map(); | 243 | update_cpu_core_map(); |
244 | for_each_online_cpu(cpu) { | 244 | for_each_online_cpu(cpu) { |
@@ -275,9 +275,9 @@ static void set_topology_timer(void) | |||
275 | 275 | ||
276 | static int __init early_parse_topology(char *p) | 276 | static int __init early_parse_topology(char *p) |
277 | { | 277 | { |
278 | if (strncmp(p, "on", 2)) | 278 | if (strncmp(p, "off", 3)) |
279 | return 0; | 279 | return 0; |
280 | topology_enabled = 1; | 280 | topology_enabled = 0; |
281 | return 0; | 281 | return 0; |
282 | } | 282 | } |
283 | early_param("topology", early_parse_topology); | 283 | early_param("topology", early_parse_topology); |
@@ -287,7 +287,7 @@ static int __init init_topology_update(void) | |||
287 | int rc; | 287 | int rc; |
288 | 288 | ||
289 | rc = 0; | 289 | rc = 0; |
290 | if (!machine_has_topology) { | 290 | if (!MACHINE_HAS_TOPOLOGY) { |
291 | topology_update_polarization_simple(); | 291 | topology_update_polarization_simple(); |
292 | goto out; | 292 | goto out; |
293 | } | 293 | } |
@@ -299,41 +299,37 @@ out: | |||
299 | } | 299 | } |
300 | __initcall(init_topology_update); | 300 | __initcall(init_topology_update); |
301 | 301 | ||
302 | static void alloc_masks(struct sysinfo_15_1_x *info, struct mask_info *mask, | ||
303 | int offset) | ||
304 | { | ||
305 | int i, nr_masks; | ||
306 | |||
307 | nr_masks = info->mag[TOPOLOGY_NR_MAG - offset]; | ||
308 | for (i = 0; i < info->mnest - offset; i++) | ||
309 | nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i]; | ||
310 | nr_masks = max(nr_masks, 1); | ||
311 | for (i = 0; i < nr_masks; i++) { | ||
312 | mask->next = alloc_bootmem(sizeof(struct mask_info)); | ||
313 | mask = mask->next; | ||
314 | } | ||
315 | } | ||
316 | |||
302 | void __init s390_init_cpu_topology(void) | 317 | void __init s390_init_cpu_topology(void) |
303 | { | 318 | { |
304 | unsigned long long facility_bits; | 319 | struct sysinfo_15_1_x *info; |
305 | struct tl_info *info; | ||
306 | struct core_info *core; | ||
307 | int nr_cores; | ||
308 | int i; | 320 | int i; |
309 | 321 | ||
310 | if (stfle(&facility_bits, 1) <= 0) | 322 | if (!MACHINE_HAS_TOPOLOGY) |
311 | return; | ||
312 | if (!(facility_bits & (1ULL << 52)) || !(facility_bits & (1ULL << 61))) | ||
313 | return; | 323 | return; |
314 | machine_has_topology = 1; | ||
315 | |||
316 | tl_info = alloc_bootmem_pages(PAGE_SIZE); | 324 | tl_info = alloc_bootmem_pages(PAGE_SIZE); |
317 | info = tl_info; | 325 | info = tl_info; |
318 | stsi(info, 15, 1, 2); | 326 | store_topology(info); |
319 | |||
320 | nr_cores = info->mag[NR_MAG - 2]; | ||
321 | for (i = 0; i < info->mnest - 2; i++) | ||
322 | nr_cores *= info->mag[NR_MAG - 3 - i]; | ||
323 | |||
324 | pr_info("The CPU configuration topology of the machine is:"); | 327 | pr_info("The CPU configuration topology of the machine is:"); |
325 | for (i = 0; i < NR_MAG; i++) | 328 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) |
326 | printk(" %d", info->mag[i]); | 329 | printk(" %d", info->mag[i]); |
327 | printk(" / %d\n", info->mnest); | 330 | printk(" / %d\n", info->mnest); |
328 | 331 | alloc_masks(info, &core_info, 2); | |
329 | core = &core_info; | 332 | #ifdef CONFIG_SCHED_BOOK |
330 | for (i = 0; i < nr_cores; i++) { | 333 | alloc_masks(info, &book_info, 3); |
331 | core->next = alloc_bootmem(sizeof(struct core_info)); | 334 | #endif |
332 | core = core->next; | ||
333 | if (!core) | ||
334 | goto error; | ||
335 | } | ||
336 | return; | ||
337 | error: | ||
338 | machine_has_topology = 0; | ||
339 | } | 335 | } |
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 5d8f0f3d0250..a65d2e82f61d 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <asm/atomic.h> | 39 | #include <asm/atomic.h> |
40 | #include <asm/mathemu.h> | 40 | #include <asm/mathemu.h> |
41 | #include <asm/cpcmd.h> | 41 | #include <asm/cpcmd.h> |
42 | #include <asm/s390_ext.h> | ||
43 | #include <asm/lowcore.h> | 42 | #include <asm/lowcore.h> |
44 | #include <asm/debug.h> | 43 | #include <asm/debug.h> |
45 | #include "entry.h" | 44 | #include "entry.h" |
@@ -237,43 +236,6 @@ void show_regs(struct pt_regs *regs) | |||
237 | show_last_breaking_event(regs); | 236 | show_last_breaking_event(regs); |
238 | } | 237 | } |
239 | 238 | ||
240 | /* This is called from fs/proc/array.c */ | ||
241 | void task_show_regs(struct seq_file *m, struct task_struct *task) | ||
242 | { | ||
243 | struct pt_regs *regs; | ||
244 | |||
245 | regs = task_pt_regs(task); | ||
246 | seq_printf(m, "task: %p, ksp: %p\n", | ||
247 | task, (void *)task->thread.ksp); | ||
248 | seq_printf(m, "User PSW : %p %p\n", | ||
249 | (void *) regs->psw.mask, (void *)regs->psw.addr); | ||
250 | |||
251 | seq_printf(m, "User GPRS: " FOURLONG, | ||
252 | regs->gprs[0], regs->gprs[1], | ||
253 | regs->gprs[2], regs->gprs[3]); | ||
254 | seq_printf(m, " " FOURLONG, | ||
255 | regs->gprs[4], regs->gprs[5], | ||
256 | regs->gprs[6], regs->gprs[7]); | ||
257 | seq_printf(m, " " FOURLONG, | ||
258 | regs->gprs[8], regs->gprs[9], | ||
259 | regs->gprs[10], regs->gprs[11]); | ||
260 | seq_printf(m, " " FOURLONG, | ||
261 | regs->gprs[12], regs->gprs[13], | ||
262 | regs->gprs[14], regs->gprs[15]); | ||
263 | seq_printf(m, "User ACRS: %08x %08x %08x %08x\n", | ||
264 | task->thread.acrs[0], task->thread.acrs[1], | ||
265 | task->thread.acrs[2], task->thread.acrs[3]); | ||
266 | seq_printf(m, " %08x %08x %08x %08x\n", | ||
267 | task->thread.acrs[4], task->thread.acrs[5], | ||
268 | task->thread.acrs[6], task->thread.acrs[7]); | ||
269 | seq_printf(m, " %08x %08x %08x %08x\n", | ||
270 | task->thread.acrs[8], task->thread.acrs[9], | ||
271 | task->thread.acrs[10], task->thread.acrs[11]); | ||
272 | seq_printf(m, " %08x %08x %08x %08x\n", | ||
273 | task->thread.acrs[12], task->thread.acrs[13], | ||
274 | task->thread.acrs[14], task->thread.acrs[15]); | ||
275 | } | ||
276 | |||
277 | static DEFINE_SPINLOCK(die_lock); | 239 | static DEFINE_SPINLOCK(die_lock); |
278 | 240 | ||
279 | void die(const char * str, struct pt_regs * regs, long err) | 241 | void die(const char * str, struct pt_regs * regs, long err) |
@@ -329,27 +291,19 @@ int is_valid_bugaddr(unsigned long addr) | |||
329 | return 1; | 291 | return 1; |
330 | } | 292 | } |
331 | 293 | ||
332 | static void __kprobes inline do_trap(long interruption_code, int signr, | 294 | static inline void __kprobes do_trap(long pgm_int_code, int signr, char *str, |
333 | char *str, struct pt_regs *regs, | 295 | struct pt_regs *regs, siginfo_t *info) |
334 | siginfo_t *info) | ||
335 | { | 296 | { |
336 | /* | 297 | if (notify_die(DIE_TRAP, str, regs, pgm_int_code, |
337 | * We got all needed information from the lowcore and can | 298 | pgm_int_code, signr) == NOTIFY_STOP) |
338 | * now safely switch on interrupts. | ||
339 | */ | ||
340 | if (regs->psw.mask & PSW_MASK_PSTATE) | ||
341 | local_irq_enable(); | ||
342 | |||
343 | if (notify_die(DIE_TRAP, str, regs, interruption_code, | ||
344 | interruption_code, signr) == NOTIFY_STOP) | ||
345 | return; | 299 | return; |
346 | 300 | ||
347 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 301 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
348 | struct task_struct *tsk = current; | 302 | struct task_struct *tsk = current; |
349 | 303 | ||
350 | tsk->thread.trap_no = interruption_code & 0xffff; | 304 | tsk->thread.trap_no = pgm_int_code & 0xffff; |
351 | force_sig_info(signr, info, tsk); | 305 | force_sig_info(signr, info, tsk); |
352 | report_user_fault(regs, interruption_code, signr); | 306 | report_user_fault(regs, pgm_int_code, signr); |
353 | } else { | 307 | } else { |
354 | const struct exception_table_entry *fixup; | 308 | const struct exception_table_entry *fixup; |
355 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); | 309 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
@@ -361,77 +315,77 @@ static void __kprobes inline do_trap(long interruption_code, int signr, | |||
361 | btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs); | 315 | btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs); |
362 | if (btt == BUG_TRAP_TYPE_WARN) | 316 | if (btt == BUG_TRAP_TYPE_WARN) |
363 | return; | 317 | return; |
364 | die(str, regs, interruption_code); | 318 | die(str, regs, pgm_int_code); |
365 | } | 319 | } |
366 | } | 320 | } |
367 | } | 321 | } |
368 | 322 | ||
369 | static inline void __user *get_check_address(struct pt_regs *regs) | 323 | static inline void __user *get_psw_address(struct pt_regs *regs, |
324 | long pgm_int_code) | ||
370 | { | 325 | { |
371 | return (void __user *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN); | 326 | return (void __user *) |
327 | ((regs->psw.addr - (pgm_int_code >> 16)) & PSW_ADDR_INSN); | ||
372 | } | 328 | } |
373 | 329 | ||
374 | void __kprobes do_single_step(struct pt_regs *regs) | 330 | void __kprobes do_per_trap(struct pt_regs *regs) |
375 | { | 331 | { |
376 | if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, | 332 | if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) |
377 | SIGTRAP) == NOTIFY_STOP){ | ||
378 | return; | 333 | return; |
379 | } | ||
380 | if (tracehook_consider_fatal_signal(current, SIGTRAP)) | 334 | if (tracehook_consider_fatal_signal(current, SIGTRAP)) |
381 | force_sig(SIGTRAP, current); | 335 | force_sig(SIGTRAP, current); |
382 | } | 336 | } |
383 | 337 | ||
384 | static void default_trap_handler(struct pt_regs * regs, long interruption_code) | 338 | static void default_trap_handler(struct pt_regs *regs, long pgm_int_code, |
339 | unsigned long trans_exc_code) | ||
385 | { | 340 | { |
386 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 341 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
387 | local_irq_enable(); | 342 | report_user_fault(regs, pgm_int_code, SIGSEGV); |
388 | report_user_fault(regs, interruption_code, SIGSEGV); | ||
389 | do_exit(SIGSEGV); | 343 | do_exit(SIGSEGV); |
390 | } else | 344 | } else |
391 | die("Unknown program exception", regs, interruption_code); | 345 | die("Unknown program exception", regs, pgm_int_code); |
392 | } | 346 | } |
393 | 347 | ||
394 | #define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \ | 348 | #define DO_ERROR_INFO(name, signr, sicode, str) \ |
395 | static void name(struct pt_regs * regs, long interruption_code) \ | 349 | static void name(struct pt_regs *regs, long pgm_int_code, \ |
350 | unsigned long trans_exc_code) \ | ||
396 | { \ | 351 | { \ |
397 | siginfo_t info; \ | 352 | siginfo_t info; \ |
398 | info.si_signo = signr; \ | 353 | info.si_signo = signr; \ |
399 | info.si_errno = 0; \ | 354 | info.si_errno = 0; \ |
400 | info.si_code = sicode; \ | 355 | info.si_code = sicode; \ |
401 | info.si_addr = siaddr; \ | 356 | info.si_addr = get_psw_address(regs, pgm_int_code); \ |
402 | do_trap(interruption_code, signr, str, regs, &info); \ | 357 | do_trap(pgm_int_code, signr, str, regs, &info); \ |
403 | } | 358 | } |
404 | 359 | ||
405 | DO_ERROR_INFO(SIGILL, "addressing exception", addressing_exception, | 360 | DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR, |
406 | ILL_ILLADR, get_check_address(regs)) | 361 | "addressing exception") |
407 | DO_ERROR_INFO(SIGILL, "execute exception", execute_exception, | 362 | DO_ERROR_INFO(execute_exception, SIGILL, ILL_ILLOPN, |
408 | ILL_ILLOPN, get_check_address(regs)) | 363 | "execute exception") |
409 | DO_ERROR_INFO(SIGFPE, "fixpoint divide exception", divide_exception, | 364 | DO_ERROR_INFO(divide_exception, SIGFPE, FPE_INTDIV, |
410 | FPE_INTDIV, get_check_address(regs)) | 365 | "fixpoint divide exception") |
411 | DO_ERROR_INFO(SIGFPE, "fixpoint overflow exception", overflow_exception, | 366 | DO_ERROR_INFO(overflow_exception, SIGFPE, FPE_INTOVF, |
412 | FPE_INTOVF, get_check_address(regs)) | 367 | "fixpoint overflow exception") |
413 | DO_ERROR_INFO(SIGFPE, "HFP overflow exception", hfp_overflow_exception, | 368 | DO_ERROR_INFO(hfp_overflow_exception, SIGFPE, FPE_FLTOVF, |
414 | FPE_FLTOVF, get_check_address(regs)) | 369 | "HFP overflow exception") |
415 | DO_ERROR_INFO(SIGFPE, "HFP underflow exception", hfp_underflow_exception, | 370 | DO_ERROR_INFO(hfp_underflow_exception, SIGFPE, FPE_FLTUND, |
416 | FPE_FLTUND, get_check_address(regs)) | 371 | "HFP underflow exception") |
417 | DO_ERROR_INFO(SIGFPE, "HFP significance exception", hfp_significance_exception, | 372 | DO_ERROR_INFO(hfp_significance_exception, SIGFPE, FPE_FLTRES, |
418 | FPE_FLTRES, get_check_address(regs)) | 373 | "HFP significance exception") |
419 | DO_ERROR_INFO(SIGFPE, "HFP divide exception", hfp_divide_exception, | 374 | DO_ERROR_INFO(hfp_divide_exception, SIGFPE, FPE_FLTDIV, |
420 | FPE_FLTDIV, get_check_address(regs)) | 375 | "HFP divide exception") |
421 | DO_ERROR_INFO(SIGFPE, "HFP square root exception", hfp_sqrt_exception, | 376 | DO_ERROR_INFO(hfp_sqrt_exception, SIGFPE, FPE_FLTINV, |
422 | FPE_FLTINV, get_check_address(regs)) | 377 | "HFP square root exception") |
423 | DO_ERROR_INFO(SIGILL, "operand exception", operand_exception, | 378 | DO_ERROR_INFO(operand_exception, SIGILL, ILL_ILLOPN, |
424 | ILL_ILLOPN, get_check_address(regs)) | 379 | "operand exception") |
425 | DO_ERROR_INFO(SIGILL, "privileged operation", privileged_op, | 380 | DO_ERROR_INFO(privileged_op, SIGILL, ILL_PRVOPC, |
426 | ILL_PRVOPC, get_check_address(regs)) | 381 | "privileged operation") |
427 | DO_ERROR_INFO(SIGILL, "special operation exception", special_op_exception, | 382 | DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN, |
428 | ILL_ILLOPN, get_check_address(regs)) | 383 | "special operation exception") |
429 | DO_ERROR_INFO(SIGILL, "translation exception", translation_exception, | 384 | DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, |
430 | ILL_ILLOPN, get_check_address(regs)) | 385 | "translation exception") |
431 | 386 | ||
432 | static inline void | 387 | static inline void do_fp_trap(struct pt_regs *regs, void __user *location, |
433 | do_fp_trap(struct pt_regs *regs, void __user *location, | 388 | int fpc, long pgm_int_code) |
434 | int fpc, long interruption_code) | ||
435 | { | 389 | { |
436 | siginfo_t si; | 390 | siginfo_t si; |
437 | 391 | ||
@@ -453,26 +407,19 @@ do_fp_trap(struct pt_regs *regs, void __user *location, | |||
453 | else if (fpc & 0x0800) /* inexact */ | 407 | else if (fpc & 0x0800) /* inexact */ |
454 | si.si_code = FPE_FLTRES; | 408 | si.si_code = FPE_FLTRES; |
455 | } | 409 | } |
456 | current->thread.ieee_instruction_pointer = (addr_t) location; | 410 | do_trap(pgm_int_code, SIGFPE, |
457 | do_trap(interruption_code, SIGFPE, | ||
458 | "floating point exception", regs, &si); | 411 | "floating point exception", regs, &si); |
459 | } | 412 | } |
460 | 413 | ||
461 | static void illegal_op(struct pt_regs * regs, long interruption_code) | 414 | static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, |
415 | unsigned long trans_exc_code) | ||
462 | { | 416 | { |
463 | siginfo_t info; | 417 | siginfo_t info; |
464 | __u8 opcode[6]; | 418 | __u8 opcode[6]; |
465 | __u16 __user *location; | 419 | __u16 __user *location; |
466 | int signal = 0; | 420 | int signal = 0; |
467 | 421 | ||
468 | location = get_check_address(regs); | 422 | location = get_psw_address(regs, pgm_int_code); |
469 | |||
470 | /* | ||
471 | * We got all needed information from the lowcore and can | ||
472 | * now safely switch on interrupts. | ||
473 | */ | ||
474 | if (regs->psw.mask & PSW_MASK_PSTATE) | ||
475 | local_irq_enable(); | ||
476 | 423 | ||
477 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 424 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
478 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) | 425 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) |
@@ -512,7 +459,7 @@ static void illegal_op(struct pt_regs * regs, long interruption_code) | |||
512 | * If we get an illegal op in kernel mode, send it through the | 459 | * If we get an illegal op in kernel mode, send it through the |
513 | * kprobes notifier. If kprobes doesn't pick it up, SIGILL | 460 | * kprobes notifier. If kprobes doesn't pick it up, SIGILL |
514 | */ | 461 | */ |
515 | if (notify_die(DIE_BPT, "bpt", regs, interruption_code, | 462 | if (notify_die(DIE_BPT, "bpt", regs, pgm_int_code, |
516 | 3, SIGTRAP) != NOTIFY_STOP) | 463 | 3, SIGTRAP) != NOTIFY_STOP) |
517 | signal = SIGILL; | 464 | signal = SIGILL; |
518 | } | 465 | } |
@@ -520,13 +467,13 @@ static void illegal_op(struct pt_regs * regs, long interruption_code) | |||
520 | #ifdef CONFIG_MATHEMU | 467 | #ifdef CONFIG_MATHEMU |
521 | if (signal == SIGFPE) | 468 | if (signal == SIGFPE) |
522 | do_fp_trap(regs, location, | 469 | do_fp_trap(regs, location, |
523 | current->thread.fp_regs.fpc, interruption_code); | 470 | current->thread.fp_regs.fpc, pgm_int_code); |
524 | else if (signal == SIGSEGV) { | 471 | else if (signal == SIGSEGV) { |
525 | info.si_signo = signal; | 472 | info.si_signo = signal; |
526 | info.si_errno = 0; | 473 | info.si_errno = 0; |
527 | info.si_code = SEGV_MAPERR; | 474 | info.si_code = SEGV_MAPERR; |
528 | info.si_addr = (void __user *) location; | 475 | info.si_addr = (void __user *) location; |
529 | do_trap(interruption_code, signal, | 476 | do_trap(pgm_int_code, signal, |
530 | "user address fault", regs, &info); | 477 | "user address fault", regs, &info); |
531 | } else | 478 | } else |
532 | #endif | 479 | #endif |
@@ -535,28 +482,22 @@ static void illegal_op(struct pt_regs * regs, long interruption_code) | |||
535 | info.si_errno = 0; | 482 | info.si_errno = 0; |
536 | info.si_code = ILL_ILLOPC; | 483 | info.si_code = ILL_ILLOPC; |
537 | info.si_addr = (void __user *) location; | 484 | info.si_addr = (void __user *) location; |
538 | do_trap(interruption_code, signal, | 485 | do_trap(pgm_int_code, signal, |
539 | "illegal operation", regs, &info); | 486 | "illegal operation", regs, &info); |
540 | } | 487 | } |
541 | } | 488 | } |
542 | 489 | ||
543 | 490 | ||
544 | #ifdef CONFIG_MATHEMU | 491 | #ifdef CONFIG_MATHEMU |
545 | asmlinkage void | 492 | asmlinkage void specification_exception(struct pt_regs *regs, |
546 | specification_exception(struct pt_regs * regs, long interruption_code) | 493 | long pgm_int_code, |
494 | unsigned long trans_exc_code) | ||
547 | { | 495 | { |
548 | __u8 opcode[6]; | 496 | __u8 opcode[6]; |
549 | __u16 __user *location = NULL; | 497 | __u16 __user *location = NULL; |
550 | int signal = 0; | 498 | int signal = 0; |
551 | 499 | ||
552 | location = (__u16 __user *) get_check_address(regs); | 500 | location = (__u16 __user *) get_psw_address(regs, pgm_int_code); |
553 | |||
554 | /* | ||
555 | * We got all needed information from the lowcore and can | ||
556 | * now safely switch on interrupts. | ||
557 | */ | ||
558 | if (regs->psw.mask & PSW_MASK_PSTATE) | ||
559 | local_irq_enable(); | ||
560 | 501 | ||
561 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 502 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
562 | get_user(*((__u16 *) opcode), location); | 503 | get_user(*((__u16 *) opcode), location); |
@@ -592,35 +533,29 @@ specification_exception(struct pt_regs * regs, long interruption_code) | |||
592 | 533 | ||
593 | if (signal == SIGFPE) | 534 | if (signal == SIGFPE) |
594 | do_fp_trap(regs, location, | 535 | do_fp_trap(regs, location, |
595 | current->thread.fp_regs.fpc, interruption_code); | 536 | current->thread.fp_regs.fpc, pgm_int_code); |
596 | else if (signal) { | 537 | else if (signal) { |
597 | siginfo_t info; | 538 | siginfo_t info; |
598 | info.si_signo = signal; | 539 | info.si_signo = signal; |
599 | info.si_errno = 0; | 540 | info.si_errno = 0; |
600 | info.si_code = ILL_ILLOPN; | 541 | info.si_code = ILL_ILLOPN; |
601 | info.si_addr = location; | 542 | info.si_addr = location; |
602 | do_trap(interruption_code, signal, | 543 | do_trap(pgm_int_code, signal, |
603 | "specification exception", regs, &info); | 544 | "specification exception", regs, &info); |
604 | } | 545 | } |
605 | } | 546 | } |
606 | #else | 547 | #else |
607 | DO_ERROR_INFO(SIGILL, "specification exception", specification_exception, | 548 | DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN, |
608 | ILL_ILLOPN, get_check_address(regs)); | 549 | "specification exception"); |
609 | #endif | 550 | #endif |
610 | 551 | ||
611 | static void data_exception(struct pt_regs * regs, long interruption_code) | 552 | static void data_exception(struct pt_regs *regs, long pgm_int_code, |
553 | unsigned long trans_exc_code) | ||
612 | { | 554 | { |
613 | __u16 __user *location; | 555 | __u16 __user *location; |
614 | int signal = 0; | 556 | int signal = 0; |
615 | 557 | ||
616 | location = get_check_address(regs); | 558 | location = get_psw_address(regs, pgm_int_code); |
617 | |||
618 | /* | ||
619 | * We got all needed information from the lowcore and can | ||
620 | * now safely switch on interrupts. | ||
621 | */ | ||
622 | if (regs->psw.mask & PSW_MASK_PSTATE) | ||
623 | local_irq_enable(); | ||
624 | 559 | ||
625 | if (MACHINE_HAS_IEEE) | 560 | if (MACHINE_HAS_IEEE) |
626 | asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); | 561 | asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); |
@@ -686,19 +621,19 @@ static void data_exception(struct pt_regs * regs, long interruption_code) | |||
686 | signal = SIGILL; | 621 | signal = SIGILL; |
687 | if (signal == SIGFPE) | 622 | if (signal == SIGFPE) |
688 | do_fp_trap(regs, location, | 623 | do_fp_trap(regs, location, |
689 | current->thread.fp_regs.fpc, interruption_code); | 624 | current->thread.fp_regs.fpc, pgm_int_code); |
690 | else if (signal) { | 625 | else if (signal) { |
691 | siginfo_t info; | 626 | siginfo_t info; |
692 | info.si_signo = signal; | 627 | info.si_signo = signal; |
693 | info.si_errno = 0; | 628 | info.si_errno = 0; |
694 | info.si_code = ILL_ILLOPN; | 629 | info.si_code = ILL_ILLOPN; |
695 | info.si_addr = location; | 630 | info.si_addr = location; |
696 | do_trap(interruption_code, signal, | 631 | do_trap(pgm_int_code, signal, "data exception", regs, &info); |
697 | "data exception", regs, &info); | ||
698 | } | 632 | } |
699 | } | 633 | } |
700 | 634 | ||
701 | static void space_switch_exception(struct pt_regs * regs, long int_code) | 635 | static void space_switch_exception(struct pt_regs *regs, long pgm_int_code, |
636 | unsigned long trans_exc_code) | ||
702 | { | 637 | { |
703 | siginfo_t info; | 638 | siginfo_t info; |
704 | 639 | ||
@@ -709,11 +644,11 @@ static void space_switch_exception(struct pt_regs * regs, long int_code) | |||
709 | info.si_signo = SIGILL; | 644 | info.si_signo = SIGILL; |
710 | info.si_errno = 0; | 645 | info.si_errno = 0; |
711 | info.si_code = ILL_PRVOPC; | 646 | info.si_code = ILL_PRVOPC; |
712 | info.si_addr = get_check_address(regs); | 647 | info.si_addr = get_psw_address(regs, pgm_int_code); |
713 | do_trap(int_code, SIGILL, "space switch event", regs, &info); | 648 | do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info); |
714 | } | 649 | } |
715 | 650 | ||
716 | asmlinkage void kernel_stack_overflow(struct pt_regs * regs) | 651 | asmlinkage void __kprobes kernel_stack_overflow(struct pt_regs * regs) |
717 | { | 652 | { |
718 | bust_spinlocks(1); | 653 | bust_spinlocks(1); |
719 | printk("Kernel stack overflow.\n"); | 654 | printk("Kernel stack overflow.\n"); |
@@ -758,5 +693,6 @@ void __init trap_init(void) | |||
758 | pgm_check_table[0x15] = &operand_exception; | 693 | pgm_check_table[0x15] = &operand_exception; |
759 | pgm_check_table[0x1C] = &space_switch_exception; | 694 | pgm_check_table[0x1C] = &space_switch_exception; |
760 | pgm_check_table[0x1D] = &hfp_sqrt_exception; | 695 | pgm_check_table[0x1D] = &hfp_sqrt_exception; |
761 | pfault_irq_init(); | 696 | /* Enable machine checks early. */ |
697 | local_mcck_enable(); | ||
762 | } | 698 | } |
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 6b83870507d5..d73630b4fe1d 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c | |||
@@ -84,11 +84,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data; | |||
84 | */ | 84 | */ |
85 | static void vdso_init_data(struct vdso_data *vd) | 85 | static void vdso_init_data(struct vdso_data *vd) |
86 | { | 86 | { |
87 | unsigned int facility_list; | 87 | vd->ectg_available = user_mode != HOME_SPACE_MODE && test_facility(31); |
88 | |||
89 | facility_list = stfl(); | ||
90 | vd->ectg_available = | ||
91 | user_mode != HOME_SPACE_MODE && (facility_list & 1); | ||
92 | } | 88 | } |
93 | 89 | ||
94 | #ifdef CONFIG_64BIT | 90 | #ifdef CONFIG_64BIT |
@@ -207,7 +203,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
207 | if (!uses_interp) | 203 | if (!uses_interp) |
208 | return 0; | 204 | return 0; |
209 | 205 | ||
210 | vdso_base = mm->mmap_base; | ||
211 | #ifdef CONFIG_64BIT | 206 | #ifdef CONFIG_64BIT |
212 | vdso_pagelist = vdso64_pagelist; | 207 | vdso_pagelist = vdso64_pagelist; |
213 | vdso_pages = vdso64_pages; | 208 | vdso_pages = vdso64_pages; |
@@ -237,8 +232,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
237 | * fail and end up putting it elsewhere. | 232 | * fail and end up putting it elsewhere. |
238 | */ | 233 | */ |
239 | down_write(&mm->mmap_sem); | 234 | down_write(&mm->mmap_sem); |
240 | vdso_base = get_unmapped_area(NULL, vdso_base, | 235 | vdso_base = get_unmapped_area(NULL, 0, vdso_pages << PAGE_SHIFT, 0, 0); |
241 | vdso_pages << PAGE_SHIFT, 0, 0); | ||
242 | if (IS_ERR_VALUE(vdso_base)) { | 236 | if (IS_ERR_VALUE(vdso_base)) { |
243 | rc = vdso_base; | 237 | rc = vdso_base; |
244 | goto out_up; | 238 | goto out_up; |
@@ -343,17 +337,17 @@ static int __init vdso_init(void) | |||
343 | } | 337 | } |
344 | arch_initcall(vdso_init); | 338 | arch_initcall(vdso_init); |
345 | 339 | ||
346 | int in_gate_area_no_task(unsigned long addr) | 340 | int in_gate_area_no_mm(unsigned long addr) |
347 | { | 341 | { |
348 | return 0; | 342 | return 0; |
349 | } | 343 | } |
350 | 344 | ||
351 | int in_gate_area(struct task_struct *task, unsigned long addr) | 345 | int in_gate_area(struct mm_struct *mm, unsigned long addr) |
352 | { | 346 | { |
353 | return 0; | 347 | return 0; |
354 | } | 348 | } |
355 | 349 | ||
356 | struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | 350 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) |
357 | { | 351 | { |
358 | return NULL; | 352 | return NULL; |
359 | } | 353 | } |
diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile index d13e8755a8cc..8ad2b34ad151 100644 --- a/arch/s390/kernel/vdso32/Makefile +++ b/arch/s390/kernel/vdso32/Makefile | |||
@@ -22,6 +22,9 @@ obj-y += vdso32_wrapper.o | |||
22 | extra-y += vdso32.lds | 22 | extra-y += vdso32.lds |
23 | CPPFLAGS_vdso32.lds += -P -C -U$(ARCH) | 23 | CPPFLAGS_vdso32.lds += -P -C -U$(ARCH) |
24 | 24 | ||
25 | # Disable gcov profiling for VDSO code | ||
26 | GCOV_PROFILE := n | ||
27 | |||
25 | # Force dependency (incbin is bad) | 28 | # Force dependency (incbin is bad) |
26 | $(obj)/vdso32_wrapper.o : $(obj)/vdso32.so | 29 | $(obj)/vdso32_wrapper.o : $(obj)/vdso32.so |
27 | 30 | ||
diff --git a/arch/s390/kernel/vdso32/clock_getres.S b/arch/s390/kernel/vdso32/clock_getres.S index 9532c4e6a9d2..36aaa25d05da 100644 --- a/arch/s390/kernel/vdso32/clock_getres.S +++ b/arch/s390/kernel/vdso32/clock_getres.S | |||
@@ -19,9 +19,9 @@ | |||
19 | .type __kernel_clock_getres,@function | 19 | .type __kernel_clock_getres,@function |
20 | __kernel_clock_getres: | 20 | __kernel_clock_getres: |
21 | .cfi_startproc | 21 | .cfi_startproc |
22 | chi %r2,CLOCK_REALTIME | 22 | chi %r2,__CLOCK_REALTIME |
23 | je 0f | 23 | je 0f |
24 | chi %r2,CLOCK_MONOTONIC | 24 | chi %r2,__CLOCK_MONOTONIC |
25 | jne 3f | 25 | jne 3f |
26 | 0: ltr %r3,%r3 | 26 | 0: ltr %r3,%r3 |
27 | jz 2f /* res == NULL */ | 27 | jz 2f /* res == NULL */ |
@@ -34,6 +34,6 @@ __kernel_clock_getres: | |||
34 | 3: lhi %r1,__NR_clock_getres /* fallback to svc */ | 34 | 3: lhi %r1,__NR_clock_getres /* fallback to svc */ |
35 | svc 0 | 35 | svc 0 |
36 | br %r14 | 36 | br %r14 |
37 | 4: .long CLOCK_REALTIME_RES | 37 | 4: .long __CLOCK_REALTIME_RES |
38 | .cfi_endproc | 38 | .cfi_endproc |
39 | .size __kernel_clock_getres,.-__kernel_clock_getres | 39 | .size __kernel_clock_getres,.-__kernel_clock_getres |
diff --git a/arch/s390/kernel/vdso32/clock_gettime.S b/arch/s390/kernel/vdso32/clock_gettime.S index 969643954273..b2224e0b974c 100644 --- a/arch/s390/kernel/vdso32/clock_gettime.S +++ b/arch/s390/kernel/vdso32/clock_gettime.S | |||
@@ -21,9 +21,9 @@ __kernel_clock_gettime: | |||
21 | .cfi_startproc | 21 | .cfi_startproc |
22 | basr %r5,0 | 22 | basr %r5,0 |
23 | 0: al %r5,21f-0b(%r5) /* get &_vdso_data */ | 23 | 0: al %r5,21f-0b(%r5) /* get &_vdso_data */ |
24 | chi %r2,CLOCK_REALTIME | 24 | chi %r2,__CLOCK_REALTIME |
25 | je 10f | 25 | je 10f |
26 | chi %r2,CLOCK_MONOTONIC | 26 | chi %r2,__CLOCK_MONOTONIC |
27 | jne 19f | 27 | jne 19f |
28 | 28 | ||
29 | /* CLOCK_MONOTONIC */ | 29 | /* CLOCK_MONOTONIC */ |
diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile index 449352dda9cd..2a8ddfd12a5b 100644 --- a/arch/s390/kernel/vdso64/Makefile +++ b/arch/s390/kernel/vdso64/Makefile | |||
@@ -22,6 +22,9 @@ obj-y += vdso64_wrapper.o | |||
22 | extra-y += vdso64.lds | 22 | extra-y += vdso64.lds |
23 | CPPFLAGS_vdso64.lds += -P -C -U$(ARCH) | 23 | CPPFLAGS_vdso64.lds += -P -C -U$(ARCH) |
24 | 24 | ||
25 | # Disable gcov profiling for VDSO code | ||
26 | GCOV_PROFILE := n | ||
27 | |||
25 | # Force dependency (incbin is bad) | 28 | # Force dependency (incbin is bad) |
26 | $(obj)/vdso64_wrapper.o : $(obj)/vdso64.so | 29 | $(obj)/vdso64_wrapper.o : $(obj)/vdso64.so |
27 | 30 | ||
diff --git a/arch/s390/kernel/vdso64/clock_getres.S b/arch/s390/kernel/vdso64/clock_getres.S index 9ce8caafdb4e..176e1f75f9aa 100644 --- a/arch/s390/kernel/vdso64/clock_getres.S +++ b/arch/s390/kernel/vdso64/clock_getres.S | |||
@@ -19,9 +19,9 @@ | |||
19 | .type __kernel_clock_getres,@function | 19 | .type __kernel_clock_getres,@function |
20 | __kernel_clock_getres: | 20 | __kernel_clock_getres: |
21 | .cfi_startproc | 21 | .cfi_startproc |
22 | cghi %r2,CLOCK_REALTIME | 22 | cghi %r2,__CLOCK_REALTIME |
23 | je 0f | 23 | je 0f |
24 | cghi %r2,CLOCK_MONOTONIC | 24 | cghi %r2,__CLOCK_MONOTONIC |
25 | je 0f | 25 | je 0f |
26 | cghi %r2,-2 /* CLOCK_THREAD_CPUTIME_ID for this thread */ | 26 | cghi %r2,-2 /* CLOCK_THREAD_CPUTIME_ID for this thread */ |
27 | jne 2f | 27 | jne 2f |
@@ -39,6 +39,6 @@ __kernel_clock_getres: | |||
39 | 2: lghi %r1,__NR_clock_getres /* fallback to svc */ | 39 | 2: lghi %r1,__NR_clock_getres /* fallback to svc */ |
40 | svc 0 | 40 | svc 0 |
41 | br %r14 | 41 | br %r14 |
42 | 3: .quad CLOCK_REALTIME_RES | 42 | 3: .quad __CLOCK_REALTIME_RES |
43 | .cfi_endproc | 43 | .cfi_endproc |
44 | .size __kernel_clock_getres,.-__kernel_clock_getres | 44 | .size __kernel_clock_getres,.-__kernel_clock_getres |
diff --git a/arch/s390/kernel/vdso64/clock_gettime.S b/arch/s390/kernel/vdso64/clock_gettime.S index f40467884a03..d46c95ed5f19 100644 --- a/arch/s390/kernel/vdso64/clock_gettime.S +++ b/arch/s390/kernel/vdso64/clock_gettime.S | |||
@@ -20,11 +20,11 @@ | |||
20 | __kernel_clock_gettime: | 20 | __kernel_clock_gettime: |
21 | .cfi_startproc | 21 | .cfi_startproc |
22 | larl %r5,_vdso_data | 22 | larl %r5,_vdso_data |
23 | cghi %r2,CLOCK_REALTIME | 23 | cghi %r2,__CLOCK_REALTIME |
24 | je 4f | 24 | je 4f |
25 | cghi %r2,-2 /* CLOCK_THREAD_CPUTIME_ID for this thread */ | 25 | cghi %r2,-2 /* CLOCK_THREAD_CPUTIME_ID for this thread */ |
26 | je 9f | 26 | je 9f |
27 | cghi %r2,CLOCK_MONOTONIC | 27 | cghi %r2,__CLOCK_MONOTONIC |
28 | jne 12f | 28 | jne 12f |
29 | 29 | ||
30 | /* CLOCK_MONOTONIC */ | 30 | /* CLOCK_MONOTONIC */ |
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index a68ac10213b2..56fe6bc81fee 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S | |||
@@ -77,7 +77,7 @@ SECTIONS | |||
77 | . = ALIGN(PAGE_SIZE); | 77 | . = ALIGN(PAGE_SIZE); |
78 | INIT_DATA_SECTION(0x100) | 78 | INIT_DATA_SECTION(0x100) |
79 | 79 | ||
80 | PERCPU(PAGE_SIZE) | 80 | PERCPU_SECTION(0x100) |
81 | . = ALIGN(PAGE_SIZE); | 81 | . = ALIGN(PAGE_SIZE); |
82 | __init_end = .; /* freed after init ends here */ | 82 | __init_end = .; /* freed after init ends here */ |
83 | 83 | ||
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 3479f1b0d4e0..2d6228f60cd6 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -19,11 +19,13 @@ | |||
19 | #include <linux/kernel_stat.h> | 19 | #include <linux/kernel_stat.h> |
20 | #include <linux/rcupdate.h> | 20 | #include <linux/rcupdate.h> |
21 | #include <linux/posix-timers.h> | 21 | #include <linux/posix-timers.h> |
22 | #include <linux/cpu.h> | ||
23 | #include <linux/kprobes.h> | ||
22 | 24 | ||
23 | #include <asm/s390_ext.h> | ||
24 | #include <asm/timer.h> | 25 | #include <asm/timer.h> |
25 | #include <asm/irq_regs.h> | 26 | #include <asm/irq_regs.h> |
26 | #include <asm/cputime.h> | 27 | #include <asm/cputime.h> |
28 | #include <asm/irq.h> | ||
27 | 29 | ||
28 | static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); | 30 | static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); |
29 | 31 | ||
@@ -42,7 +44,7 @@ static inline void set_vtimer(__u64 expires) | |||
42 | __u64 timer; | 44 | __u64 timer; |
43 | 45 | ||
44 | asm volatile (" STPT %0\n" /* Store current cpu timer value */ | 46 | asm volatile (" STPT %0\n" /* Store current cpu timer value */ |
45 | " SPT %1" /* Set new value immediatly afterwards */ | 47 | " SPT %1" /* Set new value immediately afterwards */ |
46 | : "=m" (timer) : "m" (expires) ); | 48 | : "=m" (timer) : "m" (expires) ); |
47 | S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer; | 49 | S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer; |
48 | S390_lowcore.last_update_timer = expires; | 50 | S390_lowcore.last_update_timer = expires; |
@@ -121,7 +123,7 @@ void account_system_vtime(struct task_struct *tsk) | |||
121 | } | 123 | } |
122 | EXPORT_SYMBOL_GPL(account_system_vtime); | 124 | EXPORT_SYMBOL_GPL(account_system_vtime); |
123 | 125 | ||
124 | void vtime_start_cpu(__u64 int_clock, __u64 enter_timer) | 126 | void __kprobes vtime_start_cpu(__u64 int_clock, __u64 enter_timer) |
125 | { | 127 | { |
126 | struct s390_idle_data *idle = &__get_cpu_var(s390_idle); | 128 | struct s390_idle_data *idle = &__get_cpu_var(s390_idle); |
127 | struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer); | 129 | struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer); |
@@ -161,7 +163,7 @@ void vtime_start_cpu(__u64 int_clock, __u64 enter_timer) | |||
161 | idle->sequence++; | 163 | idle->sequence++; |
162 | } | 164 | } |
163 | 165 | ||
164 | void vtime_stop_cpu(void) | 166 | void __kprobes vtime_stop_cpu(void) |
165 | { | 167 | { |
166 | struct s390_idle_data *idle = &__get_cpu_var(s390_idle); | 168 | struct s390_idle_data *idle = &__get_cpu_var(s390_idle); |
167 | struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer); | 169 | struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer); |
@@ -314,13 +316,15 @@ static void do_callbacks(struct list_head *cb_list) | |||
314 | /* | 316 | /* |
315 | * Handler for the virtual CPU timer. | 317 | * Handler for the virtual CPU timer. |
316 | */ | 318 | */ |
317 | static void do_cpu_timer_interrupt(__u16 error_code) | 319 | static void do_cpu_timer_interrupt(unsigned int ext_int_code, |
320 | unsigned int param32, unsigned long param64) | ||
318 | { | 321 | { |
319 | struct vtimer_queue *vq; | 322 | struct vtimer_queue *vq; |
320 | struct vtimer_list *event, *tmp; | 323 | struct vtimer_list *event, *tmp; |
321 | struct list_head cb_list; /* the callback queue */ | 324 | struct list_head cb_list; /* the callback queue */ |
322 | __u64 elapsed, next; | 325 | __u64 elapsed, next; |
323 | 326 | ||
327 | kstat_cpu(smp_processor_id()).irqs[EXTINT_TMR]++; | ||
324 | INIT_LIST_HEAD(&cb_list); | 328 | INIT_LIST_HEAD(&cb_list); |
325 | vq = &__get_cpu_var(virt_cpu_timer); | 329 | vq = &__get_cpu_var(virt_cpu_timer); |
326 | 330 | ||
@@ -565,6 +569,23 @@ void init_cpu_vtimer(void) | |||
565 | __ctl_set_bit(0,10); | 569 | __ctl_set_bit(0,10); |
566 | } | 570 | } |
567 | 571 | ||
572 | static int __cpuinit s390_nohz_notify(struct notifier_block *self, | ||
573 | unsigned long action, void *hcpu) | ||
574 | { | ||
575 | struct s390_idle_data *idle; | ||
576 | long cpu = (long) hcpu; | ||
577 | |||
578 | idle = &per_cpu(s390_idle, cpu); | ||
579 | switch (action) { | ||
580 | case CPU_DYING: | ||
581 | case CPU_DYING_FROZEN: | ||
582 | idle->nohz_delay = 0; | ||
583 | default: | ||
584 | break; | ||
585 | } | ||
586 | return NOTIFY_OK; | ||
587 | } | ||
588 | |||
568 | void __init vtime_init(void) | 589 | void __init vtime_init(void) |
569 | { | 590 | { |
570 | /* request the cpu timer external interrupt */ | 591 | /* request the cpu timer external interrupt */ |
@@ -573,5 +594,6 @@ void __init vtime_init(void) | |||
573 | 594 | ||
574 | /* Enable cpu timer interrupts on the boot cpu. */ | 595 | /* Enable cpu timer interrupts on the boot cpu. */ |
575 | init_cpu_vtimer(); | 596 | init_cpu_vtimer(); |
597 | cpu_notifier(s390_nohz_notify, 0); | ||
576 | } | 598 | } |
577 | 599 | ||
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index a7251580891c..f66a1bdbb61d 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig | |||
@@ -4,8 +4,8 @@ | |||
4 | source "virt/kvm/Kconfig" | 4 | source "virt/kvm/Kconfig" |
5 | 5 | ||
6 | menuconfig VIRTUALIZATION | 6 | menuconfig VIRTUALIZATION |
7 | bool "Virtualization" | 7 | def_bool y |
8 | default y | 8 | prompt "Virtualization" |
9 | ---help--- | 9 | ---help--- |
10 | Say Y here to get to see options for using your Linux host to run other | 10 | Say Y here to get to see options for using your Linux host to run other |
11 | operating systems inside virtual machines (guests). | 11 | operating systems inside virtual machines (guests). |
@@ -16,7 +16,8 @@ menuconfig VIRTUALIZATION | |||
16 | if VIRTUALIZATION | 16 | if VIRTUALIZATION |
17 | 17 | ||
18 | config KVM | 18 | config KVM |
19 | tristate "Kernel-based Virtual Machine (KVM) support" | 19 | def_tristate y |
20 | prompt "Kernel-based Virtual Machine (KVM) support" | ||
20 | depends on HAVE_KVM && EXPERIMENTAL | 21 | depends on HAVE_KVM && EXPERIMENTAL |
21 | select PREEMPT_NOTIFIERS | 22 | select PREEMPT_NOTIFIERS |
22 | select ANON_INODES | 23 | select ANON_INODES |
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile index e5221ec0b8e3..860d26514c08 100644 --- a/arch/s390/kvm/Makefile +++ b/arch/s390/kvm/Makefile | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o) | 9 | common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o) |
10 | 10 | ||
11 | EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm | 11 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm |
12 | 12 | ||
13 | kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o | 13 | kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o |
14 | obj-$(CONFIG_KVM) += kvm.o | 14 | obj-$(CONFIG_KVM) += kvm.o |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 4fe68650535c..67345ae7ce8d 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -164,24 +164,18 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
164 | return r; | 164 | return r; |
165 | } | 165 | } |
166 | 166 | ||
167 | struct kvm *kvm_arch_create_vm(void) | 167 | int kvm_arch_init_vm(struct kvm *kvm) |
168 | { | 168 | { |
169 | struct kvm *kvm; | ||
170 | int rc; | 169 | int rc; |
171 | char debug_name[16]; | 170 | char debug_name[16]; |
172 | 171 | ||
173 | rc = s390_enable_sie(); | 172 | rc = s390_enable_sie(); |
174 | if (rc) | 173 | if (rc) |
175 | goto out_nokvm; | 174 | goto out_err; |
176 | |||
177 | rc = -ENOMEM; | ||
178 | kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL); | ||
179 | if (!kvm) | ||
180 | goto out_nokvm; | ||
181 | 175 | ||
182 | kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL); | 176 | kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL); |
183 | if (!kvm->arch.sca) | 177 | if (!kvm->arch.sca) |
184 | goto out_nosca; | 178 | goto out_err; |
185 | 179 | ||
186 | sprintf(debug_name, "kvm-%u", current->pid); | 180 | sprintf(debug_name, "kvm-%u", current->pid); |
187 | 181 | ||
@@ -195,13 +189,11 @@ struct kvm *kvm_arch_create_vm(void) | |||
195 | debug_register_view(kvm->arch.dbf, &debug_sprintf_view); | 189 | debug_register_view(kvm->arch.dbf, &debug_sprintf_view); |
196 | VM_EVENT(kvm, 3, "%s", "vm created"); | 190 | VM_EVENT(kvm, 3, "%s", "vm created"); |
197 | 191 | ||
198 | return kvm; | 192 | return 0; |
199 | out_nodbf: | 193 | out_nodbf: |
200 | free_page((unsigned long)(kvm->arch.sca)); | 194 | free_page((unsigned long)(kvm->arch.sca)); |
201 | out_nosca: | 195 | out_err: |
202 | kfree(kvm); | 196 | return rc; |
203 | out_nokvm: | ||
204 | return ERR_PTR(rc); | ||
205 | } | 197 | } |
206 | 198 | ||
207 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) | 199 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) |
@@ -240,11 +232,8 @@ void kvm_arch_sync_events(struct kvm *kvm) | |||
240 | void kvm_arch_destroy_vm(struct kvm *kvm) | 232 | void kvm_arch_destroy_vm(struct kvm *kvm) |
241 | { | 233 | { |
242 | kvm_free_vcpus(kvm); | 234 | kvm_free_vcpus(kvm); |
243 | kvm_free_physmem(kvm); | ||
244 | free_page((unsigned long)(kvm->arch.sca)); | 235 | free_page((unsigned long)(kvm->arch.sca)); |
245 | debug_unregister(kvm->arch.dbf); | 236 | debug_unregister(kvm->arch.dbf); |
246 | cleanup_srcu_struct(&kvm->srcu); | ||
247 | kfree(kvm); | ||
248 | } | 237 | } |
249 | 238 | ||
250 | /* Section: vcpu related */ | 239 | /* Section: vcpu related */ |
@@ -732,7 +721,7 @@ static int __init kvm_s390_init(void) | |||
732 | 721 | ||
733 | /* | 722 | /* |
734 | * guests can ask for up to 255+1 double words, we need a full page | 723 | * guests can ask for up to 255+1 double words, we need a full page |
735 | * to hold the maximum amount of facilites. On the other hand, we | 724 | * to hold the maximum amount of facilities. On the other hand, we |
736 | * only set facilities that are known to work in KVM. | 725 | * only set facilities that are known to work in KVM. |
737 | */ | 726 | */ |
738 | facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA); | 727 | facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA); |
@@ -740,8 +729,9 @@ static int __init kvm_s390_init(void) | |||
740 | kvm_exit(); | 729 | kvm_exit(); |
741 | return -ENOMEM; | 730 | return -ENOMEM; |
742 | } | 731 | } |
743 | stfle(facilities, 1); | 732 | memcpy(facilities, S390_lowcore.stfle_fac_list, 16); |
744 | facilities[0] &= 0xff00fff3f0700000ULL; | 733 | facilities[0] &= 0xff00fff3f47c0000ULL; |
734 | facilities[1] &= 0x201c000000000000ULL; | ||
745 | return 0; | 735 | return 0; |
746 | } | 736 | } |
747 | 737 | ||
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 44205507717c..73c47bd95db3 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -154,12 +154,12 @@ static int handle_chsc(struct kvm_vcpu *vcpu) | |||
154 | 154 | ||
155 | static int handle_stfl(struct kvm_vcpu *vcpu) | 155 | static int handle_stfl(struct kvm_vcpu *vcpu) |
156 | { | 156 | { |
157 | unsigned int facility_list = stfl(); | 157 | unsigned int facility_list; |
158 | int rc; | 158 | int rc; |
159 | 159 | ||
160 | vcpu->stat.instruction_stfl++; | 160 | vcpu->stat.instruction_stfl++; |
161 | /* only pass the facility bits, which we can handle */ | 161 | /* only pass the facility bits, which we can handle */ |
162 | facility_list &= 0xff00fff3; | 162 | facility_list = S390_lowcore.stfl_fac_list & 0xff00fff3; |
163 | 163 | ||
164 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), | 164 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), |
165 | &facility_list, sizeof(facility_list)); | 165 | &facility_list, sizeof(facility_list)); |
@@ -311,7 +311,7 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) | |||
311 | 311 | ||
312 | /* | 312 | /* |
313 | * a lot of B2 instructions are priviledged. We first check for | 313 | * a lot of B2 instructions are priviledged. We first check for |
314 | * the priviledges ones, that we can handle in the kernel. If the | 314 | * the privileged ones, that we can handle in the kernel. If the |
315 | * kernel can handle this instruction, we check for the problem | 315 | * kernel can handle this instruction, we check for the problem |
316 | * state bit and (a) handle the instruction or (b) send a code 2 | 316 | * state bit and (a) handle the instruction or (b) send a code 2 |
317 | * program check. | 317 | * program check. |
diff --git a/arch/s390/kvm/sie64a.S b/arch/s390/kvm/sie64a.S index 7e9d30d567b0..5faa1b1b23fa 100644 --- a/arch/s390/kvm/sie64a.S +++ b/arch/s390/kvm/sie64a.S | |||
@@ -48,10 +48,10 @@ sie_irq_handler: | |||
48 | tm __TI_flags+7(%r2),_TIF_EXIT_SIE | 48 | tm __TI_flags+7(%r2),_TIF_EXIT_SIE |
49 | jz 0f | 49 | jz 0f |
50 | larl %r2,sie_exit # work pending, leave sie | 50 | larl %r2,sie_exit # work pending, leave sie |
51 | stg %r2,__LC_RETURN_PSW+8 | 51 | stg %r2,SPI_PSW+8(0,%r15) |
52 | br %r14 | 52 | br %r14 |
53 | 0: larl %r2,sie_reenter # re-enter with guest id | 53 | 0: larl %r2,sie_reenter # re-enter with guest id |
54 | stg %r2,__LC_RETURN_PSW+8 | 54 | stg %r2,SPI_PSW+8(0,%r15) |
55 | 1: br %r14 | 55 | 1: br %r14 |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -93,4 +93,6 @@ sie_err: | |||
93 | 93 | ||
94 | .section __ex_table,"a" | 94 | .section __ex_table,"a" |
95 | .quad sie_inst,sie_err | 95 | .quad sie_inst,sie_err |
96 | .quad sie_exit,sie_err | ||
97 | .quad sie_reenter,sie_err | ||
96 | .previous | 98 | .previous |
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 752b362bf651..a65229d91c92 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/irqflags.h> | 13 | #include <linux/irqflags.h> |
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <asm/div64.h> | ||
15 | 16 | ||
16 | void __delay(unsigned long loops) | 17 | void __delay(unsigned long loops) |
17 | { | 18 | { |
@@ -29,21 +30,24 @@ static void __udelay_disabled(unsigned long long usecs) | |||
29 | { | 30 | { |
30 | unsigned long mask, cr0, cr0_saved; | 31 | unsigned long mask, cr0, cr0_saved; |
31 | u64 clock_saved; | 32 | u64 clock_saved; |
33 | u64 end; | ||
32 | 34 | ||
35 | mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; | ||
36 | end = get_clock() + (usecs << 12); | ||
33 | clock_saved = local_tick_disable(); | 37 | clock_saved = local_tick_disable(); |
34 | set_clock_comparator(get_clock() + (usecs << 12)); | ||
35 | __ctl_store(cr0_saved, 0, 0); | 38 | __ctl_store(cr0_saved, 0, 0); |
36 | cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; | 39 | cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; |
37 | __ctl_load(cr0 , 0, 0); | 40 | __ctl_load(cr0 , 0, 0); |
38 | mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; | ||
39 | lockdep_off(); | 41 | lockdep_off(); |
40 | trace_hardirqs_on(); | 42 | do { |
41 | __load_psw_mask(mask); | 43 | set_clock_comparator(end); |
42 | local_irq_disable(); | 44 | trace_hardirqs_on(); |
45 | __load_psw_mask(mask); | ||
46 | local_irq_disable(); | ||
47 | } while (get_clock() < end); | ||
43 | lockdep_on(); | 48 | lockdep_on(); |
44 | __ctl_load(cr0_saved, 0, 0); | 49 | __ctl_load(cr0_saved, 0, 0); |
45 | local_tick_enable(clock_saved); | 50 | local_tick_enable(clock_saved); |
46 | set_clock_comparator(S390_lowcore.clock_comparator); | ||
47 | } | 51 | } |
48 | 52 | ||
49 | static void __udelay_enabled(unsigned long long usecs) | 53 | static void __udelay_enabled(unsigned long long usecs) |
@@ -66,7 +70,6 @@ static void __udelay_enabled(unsigned long long usecs) | |||
66 | if (clock_saved) | 70 | if (clock_saved) |
67 | local_tick_enable(clock_saved); | 71 | local_tick_enable(clock_saved); |
68 | } while (get_clock() < end); | 72 | } while (get_clock() < end); |
69 | set_clock_comparator(S390_lowcore.clock_comparator); | ||
70 | } | 73 | } |
71 | 74 | ||
72 | /* | 75 | /* |
@@ -114,3 +117,17 @@ void udelay_simple(unsigned long long usecs) | |||
114 | while (get_clock() < end) | 117 | while (get_clock() < end) |
115 | cpu_relax(); | 118 | cpu_relax(); |
116 | } | 119 | } |
120 | |||
121 | void __ndelay(unsigned long long nsecs) | ||
122 | { | ||
123 | u64 end; | ||
124 | |||
125 | nsecs <<= 9; | ||
126 | do_div(nsecs, 125); | ||
127 | end = get_clock() + nsecs; | ||
128 | if (nsecs & ~0xfffUL) | ||
129 | __udelay(nsecs >> 12); | ||
130 | while (get_clock() < end) | ||
131 | barrier(); | ||
132 | } | ||
133 | EXPORT_SYMBOL(__ndelay); | ||
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h index 126011df14f1..1d2536cb630b 100644 --- a/arch/s390/lib/uaccess.h +++ b/arch/s390/lib/uaccess.h | |||
@@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *); | |||
12 | extern size_t copy_to_user_std(size_t, void __user *, const void *); | 12 | extern size_t copy_to_user_std(size_t, void __user *, const void *); |
13 | extern size_t strnlen_user_std(size_t, const char __user *); | 13 | extern size_t strnlen_user_std(size_t, const char __user *); |
14 | extern size_t strncpy_from_user_std(size_t, const char __user *, char *); | 14 | extern size_t strncpy_from_user_std(size_t, const char __user *, char *); |
15 | extern int futex_atomic_cmpxchg_std(int __user *, int, int); | 15 | extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32); |
16 | extern int futex_atomic_op_std(int, int __user *, int, int *); | 16 | extern int futex_atomic_op_std(int, u32 __user *, int, int *); |
17 | 17 | ||
18 | extern size_t copy_from_user_pt(size_t, const void __user *, void *); | 18 | extern size_t copy_from_user_pt(size_t, const void __user *, void *); |
19 | extern size_t copy_to_user_pt(size_t, void __user *, const void *); | 19 | extern size_t copy_to_user_pt(size_t, void __user *, const void *); |
20 | extern int futex_atomic_op_pt(int, int __user *, int, int *); | 20 | extern int futex_atomic_op_pt(int, u32 __user *, int, int *); |
21 | extern int futex_atomic_cmpxchg_pt(int __user *, int, int); | 21 | extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32); |
22 | 22 | ||
23 | #endif /* __ARCH_S390_LIB_UACCESS_H */ | 23 | #endif /* __ARCH_S390_LIB_UACCESS_H */ |
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index 404f2de296dc..74833831417f 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c | |||
@@ -302,7 +302,7 @@ fault: | |||
302 | : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ | 302 | : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ |
303 | "m" (*uaddr) : "cc" ); | 303 | "m" (*uaddr) : "cc" ); |
304 | 304 | ||
305 | static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old) | 305 | static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) |
306 | { | 306 | { |
307 | int oldval = 0, newval, ret; | 307 | int oldval = 0, newval, ret; |
308 | 308 | ||
@@ -335,7 +335,7 @@ static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old) | |||
335 | return ret; | 335 | return ret; |
336 | } | 336 | } |
337 | 337 | ||
338 | int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old) | 338 | int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) |
339 | { | 339 | { |
340 | int ret; | 340 | int ret; |
341 | 341 | ||
@@ -354,26 +354,29 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old) | |||
354 | return ret; | 354 | return ret; |
355 | } | 355 | } |
356 | 356 | ||
357 | static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval) | 357 | static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, |
358 | u32 oldval, u32 newval) | ||
358 | { | 359 | { |
359 | int ret; | 360 | int ret; |
360 | 361 | ||
361 | asm volatile("0: cs %1,%4,0(%5)\n" | 362 | asm volatile("0: cs %1,%4,0(%5)\n" |
362 | "1: lr %0,%1\n" | 363 | "1: la %0,0\n" |
363 | "2:\n" | 364 | "2:\n" |
364 | EX_TABLE(0b,2b) EX_TABLE(1b,2b) | 365 | EX_TABLE(0b,2b) EX_TABLE(1b,2b) |
365 | : "=d" (ret), "+d" (oldval), "=m" (*uaddr) | 366 | : "=d" (ret), "+d" (oldval), "=m" (*uaddr) |
366 | : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) | 367 | : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) |
367 | : "cc", "memory" ); | 368 | : "cc", "memory" ); |
369 | *uval = oldval; | ||
368 | return ret; | 370 | return ret; |
369 | } | 371 | } |
370 | 372 | ||
371 | int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval) | 373 | int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, |
374 | u32 oldval, u32 newval) | ||
372 | { | 375 | { |
373 | int ret; | 376 | int ret; |
374 | 377 | ||
375 | if (segment_eq(get_fs(), KERNEL_DS)) | 378 | if (segment_eq(get_fs(), KERNEL_DS)) |
376 | return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval); | 379 | return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); |
377 | spin_lock(¤t->mm->page_table_lock); | 380 | spin_lock(¤t->mm->page_table_lock); |
378 | uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr); | 381 | uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr); |
379 | if (!uaddr) { | 382 | if (!uaddr) { |
@@ -382,7 +385,7 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval) | |||
382 | } | 385 | } |
383 | get_page(virt_to_page(uaddr)); | 386 | get_page(virt_to_page(uaddr)); |
384 | spin_unlock(¤t->mm->page_table_lock); | 387 | spin_unlock(¤t->mm->page_table_lock); |
385 | ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval); | 388 | ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); |
386 | put_page(virt_to_page(uaddr)); | 389 | put_page(virt_to_page(uaddr)); |
387 | return ret; | 390 | return ret; |
388 | } | 391 | } |
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c index 07deaeee14c8..bb1a7eed42ce 100644 --- a/arch/s390/lib/uaccess_std.c +++ b/arch/s390/lib/uaccess_std.c | |||
@@ -125,9 +125,9 @@ static size_t copy_in_user_std(size_t size, void __user *to, | |||
125 | unsigned long tmp1; | 125 | unsigned long tmp1; |
126 | 126 | ||
127 | asm volatile( | 127 | asm volatile( |
128 | " sacf 256\n" | ||
128 | " "AHI" %0,-1\n" | 129 | " "AHI" %0,-1\n" |
129 | " jo 5f\n" | 130 | " jo 5f\n" |
130 | " sacf 256\n" | ||
131 | " bras %3,3f\n" | 131 | " bras %3,3f\n" |
132 | "0:"AHI" %0,257\n" | 132 | "0:"AHI" %0,257\n" |
133 | "1: mvc 0(1,%1),0(%2)\n" | 133 | "1: mvc 0(1,%1),0(%2)\n" |
@@ -142,9 +142,8 @@ static size_t copy_in_user_std(size_t size, void __user *to, | |||
142 | "3:"AHI" %0,-256\n" | 142 | "3:"AHI" %0,-256\n" |
143 | " jnm 2b\n" | 143 | " jnm 2b\n" |
144 | "4: ex %0,1b-0b(%3)\n" | 144 | "4: ex %0,1b-0b(%3)\n" |
145 | " sacf 0\n" | ||
146 | "5: "SLR" %0,%0\n" | 145 | "5: "SLR" %0,%0\n" |
147 | "6:\n" | 146 | "6: sacf 0\n" |
148 | EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b) | 147 | EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b) |
149 | : "+a" (size), "+a" (to), "+a" (from), "=a" (tmp1) | 148 | : "+a" (size), "+a" (to), "+a" (from), "=a" (tmp1) |
150 | : : "cc", "memory"); | 149 | : : "cc", "memory"); |
@@ -156,9 +155,9 @@ static size_t clear_user_std(size_t size, void __user *to) | |||
156 | unsigned long tmp1, tmp2; | 155 | unsigned long tmp1, tmp2; |
157 | 156 | ||
158 | asm volatile( | 157 | asm volatile( |
158 | " sacf 256\n" | ||
159 | " "AHI" %0,-1\n" | 159 | " "AHI" %0,-1\n" |
160 | " jo 5f\n" | 160 | " jo 5f\n" |
161 | " sacf 256\n" | ||
162 | " bras %3,3f\n" | 161 | " bras %3,3f\n" |
163 | " xc 0(1,%1),0(%1)\n" | 162 | " xc 0(1,%1),0(%1)\n" |
164 | "0:"AHI" %0,257\n" | 163 | "0:"AHI" %0,257\n" |
@@ -178,9 +177,8 @@ static size_t clear_user_std(size_t size, void __user *to) | |||
178 | "3:"AHI" %0,-256\n" | 177 | "3:"AHI" %0,-256\n" |
179 | " jnm 2b\n" | 178 | " jnm 2b\n" |
180 | "4: ex %0,0(%3)\n" | 179 | "4: ex %0,0(%3)\n" |
181 | " sacf 0\n" | ||
182 | "5: "SLR" %0,%0\n" | 180 | "5: "SLR" %0,%0\n" |
183 | "6:\n" | 181 | "6: sacf 0\n" |
184 | EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b) | 182 | EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b) |
185 | : "+a" (size), "+a" (to), "=a" (tmp1), "=a" (tmp2) | 183 | : "+a" (size), "+a" (to), "=a" (tmp1), "=a" (tmp2) |
186 | : : "cc", "memory"); | 184 | : : "cc", "memory"); |
@@ -257,7 +255,7 @@ size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst) | |||
257 | : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ | 255 | : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ |
258 | "m" (*uaddr) : "cc"); | 256 | "m" (*uaddr) : "cc"); |
259 | 257 | ||
260 | int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old) | 258 | int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old) |
261 | { | 259 | { |
262 | int oldval = 0, newval, ret; | 260 | int oldval = 0, newval, ret; |
263 | 261 | ||
@@ -289,19 +287,21 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old) | |||
289 | return ret; | 287 | return ret; |
290 | } | 288 | } |
291 | 289 | ||
292 | int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval) | 290 | int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr, |
291 | u32 oldval, u32 newval) | ||
293 | { | 292 | { |
294 | int ret; | 293 | int ret; |
295 | 294 | ||
296 | asm volatile( | 295 | asm volatile( |
297 | " sacf 256\n" | 296 | " sacf 256\n" |
298 | "0: cs %1,%4,0(%5)\n" | 297 | "0: cs %1,%4,0(%5)\n" |
299 | "1: lr %0,%1\n" | 298 | "1: la %0,0\n" |
300 | "2: sacf 0\n" | 299 | "2: sacf 0\n" |
301 | EX_TABLE(0b,2b) EX_TABLE(1b,2b) | 300 | EX_TABLE(0b,2b) EX_TABLE(1b,2b) |
302 | : "=d" (ret), "+d" (oldval), "=m" (*uaddr) | 301 | : "=d" (ret), "+d" (oldval), "=m" (*uaddr) |
303 | : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) | 302 | : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) |
304 | : "cc", "memory" ); | 303 | : "cc", "memory" ); |
304 | *uval = oldval; | ||
305 | return ret; | 305 | return ret; |
306 | } | 306 | } |
307 | 307 | ||
diff --git a/arch/s390/math-emu/Makefile b/arch/s390/math-emu/Makefile index c84890341052..51d399549f60 100644 --- a/arch/s390/math-emu/Makefile +++ b/arch/s390/math-emu/Makefile | |||
@@ -4,4 +4,4 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_MATHEMU) := math.o | 5 | obj-$(CONFIG_MATHEMU) := math.o |
6 | 6 | ||
7 | EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w | 7 | ccflags-y := -I$(src) -Iinclude/math-emu -w |
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile index eec054484419..d98fe9004a52 100644 --- a/arch/s390/mm/Makefile +++ b/arch/s390/mm/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \ | 5 | obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \ |
6 | page-states.o | 6 | page-states.o gup.o |
7 | obj-$(CONFIG_CMM) += cmm.o | 7 | obj-$(CONFIG_CMM) += cmm.o |
8 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 8 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
9 | obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o | ||
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index a9550dca3e4b..1f1dba9dcf58 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c | |||
@@ -23,7 +23,10 @@ | |||
23 | #include <asm/pgalloc.h> | 23 | #include <asm/pgalloc.h> |
24 | #include <asm/diag.h> | 24 | #include <asm/diag.h> |
25 | 25 | ||
26 | static char *sender = "VMRMSVM"; | 26 | #ifdef CONFIG_CMM_IUCV |
27 | static char *cmm_default_sender = "VMRMSVM"; | ||
28 | #endif | ||
29 | static char *sender; | ||
27 | module_param(sender, charp, 0400); | 30 | module_param(sender, charp, 0400); |
28 | MODULE_PARM_DESC(sender, | 31 | MODULE_PARM_DESC(sender, |
29 | "Guest name that may send SMSG messages (default VMRMSVM)"); | 32 | "Guest name that may send SMSG messages (default VMRMSVM)"); |
@@ -88,7 +91,7 @@ static long cmm_alloc_pages(long nr, long *counter, | |||
88 | } else | 91 | } else |
89 | free_page((unsigned long) npa); | 92 | free_page((unsigned long) npa); |
90 | } | 93 | } |
91 | diag10(addr); | 94 | diag10_range(addr >> PAGE_SHIFT, 1); |
92 | pa->pages[pa->index++] = addr; | 95 | pa->pages[pa->index++] = addr; |
93 | (*counter)++; | 96 | (*counter)++; |
94 | spin_unlock(&cmm_lock); | 97 | spin_unlock(&cmm_lock); |
@@ -440,6 +443,8 @@ static int __init cmm_init(void) | |||
440 | int len = strlen(sender); | 443 | int len = strlen(sender); |
441 | while (len--) | 444 | while (len--) |
442 | sender[len] = toupper(sender[len]); | 445 | sender[len] = toupper(sender[len]); |
446 | } else { | ||
447 | sender = cmm_default_sender; | ||
443 | } | 448 | } |
444 | 449 | ||
445 | rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); | 450 | rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); |
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 3cc95dd0a3a6..075ddada4911 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c | |||
@@ -412,6 +412,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long | |||
412 | struct dcss_segment *seg; | 412 | struct dcss_segment *seg; |
413 | int rc, diag_cc; | 413 | int rc, diag_cc; |
414 | 414 | ||
415 | start_addr = end_addr = 0; | ||
415 | seg = kmalloc(sizeof(*seg), GFP_KERNEL | GFP_DMA); | 416 | seg = kmalloc(sizeof(*seg), GFP_KERNEL | GFP_DMA); |
416 | if (seg == NULL) { | 417 | if (seg == NULL) { |
417 | rc = -ENOMEM; | 418 | rc = -ENOMEM; |
@@ -573,6 +574,7 @@ segment_modify_shared (char *name, int do_nonshared) | |||
573 | unsigned long start_addr, end_addr, dummy; | 574 | unsigned long start_addr, end_addr, dummy; |
574 | int rc, diag_cc; | 575 | int rc, diag_cc; |
575 | 576 | ||
577 | start_addr = end_addr = 0; | ||
576 | mutex_lock(&dcss_lock); | 578 | mutex_lock(&dcss_lock); |
577 | seg = segment_by_name (name); | 579 | seg = segment_by_name (name); |
578 | if (seg == NULL) { | 580 | if (seg == NULL) { |
@@ -681,8 +683,6 @@ void | |||
681 | segment_save(char *name) | 683 | segment_save(char *name) |
682 | { | 684 | { |
683 | struct dcss_segment *seg; | 685 | struct dcss_segment *seg; |
684 | int startpfn = 0; | ||
685 | int endpfn = 0; | ||
686 | char cmd1[160]; | 686 | char cmd1[160]; |
687 | char cmd2[80]; | 687 | char cmd2[80]; |
688 | int i, response; | 688 | int i, response; |
@@ -698,8 +698,6 @@ segment_save(char *name) | |||
698 | goto out; | 698 | goto out; |
699 | } | 699 | } |
700 | 700 | ||
701 | startpfn = seg->start_addr >> PAGE_SHIFT; | ||
702 | endpfn = (seg->end) >> PAGE_SHIFT; | ||
703 | sprintf(cmd1, "DEFSEG %s", name); | 701 | sprintf(cmd1, "DEFSEG %s", name); |
704 | for (i=0; i<seg->segcnt; i++) { | 702 | for (i=0; i<seg->segcnt; i++) { |
705 | sprintf(cmd1+strlen(cmd1), " %lX-%lX %s", | 703 | sprintf(cmd1+strlen(cmd1), " %lX-%lX %s", |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 2505b2ea0ef1..fe103e891e7a 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * Copyright (C) 1995 Linus Torvalds | 10 | * Copyright (C) 1995 Linus Torvalds |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/kernel_stat.h> | ||
13 | #include <linux/perf_event.h> | 14 | #include <linux/perf_event.h> |
14 | #include <linux/signal.h> | 15 | #include <linux/signal.h> |
15 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
@@ -33,7 +34,7 @@ | |||
33 | #include <asm/asm-offsets.h> | 34 | #include <asm/asm-offsets.h> |
34 | #include <asm/system.h> | 35 | #include <asm/system.h> |
35 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
36 | #include <asm/s390_ext.h> | 37 | #include <asm/irq.h> |
37 | #include <asm/mmu_context.h> | 38 | #include <asm/mmu_context.h> |
38 | #include <asm/compat.h> | 39 | #include <asm/compat.h> |
39 | #include "../kernel/entry.h" | 40 | #include "../kernel/entry.h" |
@@ -52,6 +53,14 @@ | |||
52 | #define VM_FAULT_BADMAP 0x020000 | 53 | #define VM_FAULT_BADMAP 0x020000 |
53 | #define VM_FAULT_BADACCESS 0x040000 | 54 | #define VM_FAULT_BADACCESS 0x040000 |
54 | 55 | ||
56 | static unsigned long store_indication; | ||
57 | |||
58 | void fault_init(void) | ||
59 | { | ||
60 | if (test_facility(2) && test_facility(75)) | ||
61 | store_indication = 0xc00; | ||
62 | } | ||
63 | |||
55 | static inline int notify_page_fault(struct pt_regs *regs) | 64 | static inline int notify_page_fault(struct pt_regs *regs) |
56 | { | 65 | { |
57 | int ret = 0; | 66 | int ret = 0; |
@@ -199,42 +208,22 @@ static noinline void do_sigbus(struct pt_regs *regs, long int_code, | |||
199 | unsigned long trans_exc_code) | 208 | unsigned long trans_exc_code) |
200 | { | 209 | { |
201 | struct task_struct *tsk = current; | 210 | struct task_struct *tsk = current; |
211 | unsigned long address; | ||
212 | struct siginfo si; | ||
202 | 213 | ||
203 | /* | 214 | /* |
204 | * Send a sigbus, regardless of whether we were in kernel | 215 | * Send a sigbus, regardless of whether we were in kernel |
205 | * or user mode. | 216 | * or user mode. |
206 | */ | 217 | */ |
207 | tsk->thread.prot_addr = trans_exc_code & __FAIL_ADDR_MASK; | 218 | address = trans_exc_code & __FAIL_ADDR_MASK; |
219 | tsk->thread.prot_addr = address; | ||
208 | tsk->thread.trap_no = int_code; | 220 | tsk->thread.trap_no = int_code; |
209 | force_sig(SIGBUS, tsk); | 221 | si.si_signo = SIGBUS; |
210 | } | 222 | si.si_errno = 0; |
211 | 223 | si.si_code = BUS_ADRERR; | |
212 | #ifdef CONFIG_S390_EXEC_PROTECT | 224 | si.si_addr = (void __user *) address; |
213 | static noinline int signal_return(struct pt_regs *regs, long int_code, | 225 | force_sig_info(SIGBUS, &si, tsk); |
214 | unsigned long trans_exc_code) | ||
215 | { | ||
216 | u16 instruction; | ||
217 | int rc; | ||
218 | |||
219 | rc = __get_user(instruction, (u16 __user *) regs->psw.addr); | ||
220 | |||
221 | if (!rc && instruction == 0x0a77) { | ||
222 | clear_tsk_thread_flag(current, TIF_SINGLE_STEP); | ||
223 | if (is_compat_task()) | ||
224 | sys32_sigreturn(); | ||
225 | else | ||
226 | sys_sigreturn(); | ||
227 | } else if (!rc && instruction == 0x0aad) { | ||
228 | clear_tsk_thread_flag(current, TIF_SINGLE_STEP); | ||
229 | if (is_compat_task()) | ||
230 | sys32_rt_sigreturn(); | ||
231 | else | ||
232 | sys_rt_sigreturn(); | ||
233 | } else | ||
234 | do_sigsegv(regs, int_code, SEGV_MAPERR, trans_exc_code); | ||
235 | return 0; | ||
236 | } | 226 | } |
237 | #endif /* CONFIG_S390_EXEC_PROTECT */ | ||
238 | 227 | ||
239 | static noinline void do_fault_error(struct pt_regs *regs, long int_code, | 228 | static noinline void do_fault_error(struct pt_regs *regs, long int_code, |
240 | unsigned long trans_exc_code, int fault) | 229 | unsigned long trans_exc_code, int fault) |
@@ -243,13 +232,6 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code, | |||
243 | 232 | ||
244 | switch (fault) { | 233 | switch (fault) { |
245 | case VM_FAULT_BADACCESS: | 234 | case VM_FAULT_BADACCESS: |
246 | #ifdef CONFIG_S390_EXEC_PROTECT | ||
247 | if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY && | ||
248 | (trans_exc_code & 3) == 0) { | ||
249 | signal_return(regs, int_code, trans_exc_code); | ||
250 | break; | ||
251 | } | ||
252 | #endif /* CONFIG_S390_EXEC_PROTECT */ | ||
253 | case VM_FAULT_BADMAP: | 235 | case VM_FAULT_BADMAP: |
254 | /* Bad memory access. Check if it is kernel or user space. */ | 236 | /* Bad memory access. Check if it is kernel or user space. */ |
255 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 237 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
@@ -263,13 +245,17 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code, | |||
263 | do_no_context(regs, int_code, trans_exc_code); | 245 | do_no_context(regs, int_code, trans_exc_code); |
264 | break; | 246 | break; |
265 | default: /* fault & VM_FAULT_ERROR */ | 247 | default: /* fault & VM_FAULT_ERROR */ |
266 | if (fault & VM_FAULT_OOM) | 248 | if (fault & VM_FAULT_OOM) { |
267 | pagefault_out_of_memory(); | 249 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) |
268 | else if (fault & VM_FAULT_SIGBUS) { | 250 | do_no_context(regs, int_code, trans_exc_code); |
269 | do_sigbus(regs, int_code, trans_exc_code); | 251 | else |
252 | pagefault_out_of_memory(); | ||
253 | } else if (fault & VM_FAULT_SIGBUS) { | ||
270 | /* Kernel mode? Handle exceptions or die */ | 254 | /* Kernel mode? Handle exceptions or die */ |
271 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) | 255 | if (!(regs->psw.mask & PSW_MASK_PSTATE)) |
272 | do_no_context(regs, int_code, trans_exc_code); | 256 | do_no_context(regs, int_code, trans_exc_code); |
257 | else | ||
258 | do_sigbus(regs, int_code, trans_exc_code); | ||
273 | } else | 259 | } else |
274 | BUG(); | 260 | BUG(); |
275 | break; | 261 | break; |
@@ -294,6 +280,7 @@ static inline int do_exception(struct pt_regs *regs, int access, | |||
294 | struct mm_struct *mm; | 280 | struct mm_struct *mm; |
295 | struct vm_area_struct *vma; | 281 | struct vm_area_struct *vma; |
296 | unsigned long address; | 282 | unsigned long address; |
283 | unsigned int flags; | ||
297 | int fault; | 284 | int fault; |
298 | 285 | ||
299 | if (notify_page_fault(regs)) | 286 | if (notify_page_fault(regs)) |
@@ -312,13 +299,11 @@ static inline int do_exception(struct pt_regs *regs, int access, | |||
312 | goto out; | 299 | goto out; |
313 | 300 | ||
314 | address = trans_exc_code & __FAIL_ADDR_MASK; | 301 | address = trans_exc_code & __FAIL_ADDR_MASK; |
315 | /* | ||
316 | * When we get here, the fault happened in the current | ||
317 | * task's user address space, so we can switch on the | ||
318 | * interrupts again and then search the VMAs | ||
319 | */ | ||
320 | local_irq_enable(); | ||
321 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); | 302 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); |
303 | flags = FAULT_FLAG_ALLOW_RETRY; | ||
304 | if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400) | ||
305 | flags |= FAULT_FLAG_WRITE; | ||
306 | retry: | ||
322 | down_read(&mm->mmap_sem); | 307 | down_read(&mm->mmap_sem); |
323 | 308 | ||
324 | fault = VM_FAULT_BADMAP; | 309 | fault = VM_FAULT_BADMAP; |
@@ -348,25 +333,37 @@ static inline int do_exception(struct pt_regs *regs, int access, | |||
348 | * make sure we exit gracefully rather than endlessly redo | 333 | * make sure we exit gracefully rather than endlessly redo |
349 | * the fault. | 334 | * the fault. |
350 | */ | 335 | */ |
351 | fault = handle_mm_fault(mm, vma, address, | 336 | fault = handle_mm_fault(mm, vma, address, flags); |
352 | (access == VM_WRITE) ? FAULT_FLAG_WRITE : 0); | ||
353 | if (unlikely(fault & VM_FAULT_ERROR)) | 337 | if (unlikely(fault & VM_FAULT_ERROR)) |
354 | goto out_up; | 338 | goto out_up; |
355 | 339 | ||
356 | if (fault & VM_FAULT_MAJOR) { | 340 | /* |
357 | tsk->maj_flt++; | 341 | * Major/minor page fault accounting is only done on the |
358 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, | 342 | * initial attempt. If we go through a retry, it is extremely |
359 | regs, address); | 343 | * likely that the page will be found in page cache at that point. |
360 | } else { | 344 | */ |
361 | tsk->min_flt++; | 345 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
362 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, | 346 | if (fault & VM_FAULT_MAJOR) { |
363 | regs, address); | 347 | tsk->maj_flt++; |
348 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, | ||
349 | regs, address); | ||
350 | } else { | ||
351 | tsk->min_flt++; | ||
352 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, | ||
353 | regs, address); | ||
354 | } | ||
355 | if (fault & VM_FAULT_RETRY) { | ||
356 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | ||
357 | * of starvation. */ | ||
358 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
359 | goto retry; | ||
360 | } | ||
364 | } | 361 | } |
365 | /* | 362 | /* |
366 | * The instruction that caused the program check will | 363 | * The instruction that caused the program check will |
367 | * be repeated. Don't signal single step via SIGTRAP. | 364 | * be repeated. Don't signal single step via SIGTRAP. |
368 | */ | 365 | */ |
369 | clear_tsk_thread_flag(tsk, TIF_SINGLE_STEP); | 366 | clear_tsk_thread_flag(tsk, TIF_PER_TRAP); |
370 | fault = 0; | 367 | fault = 0; |
371 | out_up: | 368 | out_up: |
372 | up_read(&mm->mmap_sem); | 369 | up_read(&mm->mmap_sem); |
@@ -374,20 +371,20 @@ out: | |||
374 | return fault; | 371 | return fault; |
375 | } | 372 | } |
376 | 373 | ||
377 | void __kprobes do_protection_exception(struct pt_regs *regs, long int_code) | 374 | void __kprobes do_protection_exception(struct pt_regs *regs, long pgm_int_code, |
375 | unsigned long trans_exc_code) | ||
378 | { | 376 | { |
379 | unsigned long trans_exc_code = S390_lowcore.trans_exc_code; | ||
380 | int fault; | 377 | int fault; |
381 | 378 | ||
382 | /* Protection exception is supressing, decrement psw address. */ | 379 | /* Protection exception is suppressing, decrement psw address. */ |
383 | regs->psw.addr -= (int_code >> 16); | 380 | regs->psw.addr -= (pgm_int_code >> 16); |
384 | /* | 381 | /* |
385 | * Check for low-address protection. This needs to be treated | 382 | * Check for low-address protection. This needs to be treated |
386 | * as a special case because the translation exception code | 383 | * as a special case because the translation exception code |
387 | * field is not guaranteed to contain valid data in this case. | 384 | * field is not guaranteed to contain valid data in this case. |
388 | */ | 385 | */ |
389 | if (unlikely(!(trans_exc_code & 4))) { | 386 | if (unlikely(!(trans_exc_code & 4))) { |
390 | do_low_address(regs, int_code, trans_exc_code); | 387 | do_low_address(regs, pgm_int_code, trans_exc_code); |
391 | return; | 388 | return; |
392 | } | 389 | } |
393 | fault = do_exception(regs, VM_WRITE, trans_exc_code); | 390 | fault = do_exception(regs, VM_WRITE, trans_exc_code); |
@@ -395,34 +392,27 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long int_code) | |||
395 | do_fault_error(regs, 4, trans_exc_code, fault); | 392 | do_fault_error(regs, 4, trans_exc_code, fault); |
396 | } | 393 | } |
397 | 394 | ||
398 | void __kprobes do_dat_exception(struct pt_regs *regs, long int_code) | 395 | void __kprobes do_dat_exception(struct pt_regs *regs, long pgm_int_code, |
396 | unsigned long trans_exc_code) | ||
399 | { | 397 | { |
400 | unsigned long trans_exc_code = S390_lowcore.trans_exc_code; | ||
401 | int access, fault; | 398 | int access, fault; |
402 | 399 | ||
403 | access = VM_READ | VM_EXEC | VM_WRITE; | 400 | access = VM_READ | VM_EXEC | VM_WRITE; |
404 | #ifdef CONFIG_S390_EXEC_PROTECT | ||
405 | if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY && | ||
406 | (trans_exc_code & 3) == 0) | ||
407 | access = VM_EXEC; | ||
408 | #endif | ||
409 | fault = do_exception(regs, access, trans_exc_code); | 401 | fault = do_exception(regs, access, trans_exc_code); |
410 | if (unlikely(fault)) | 402 | if (unlikely(fault)) |
411 | do_fault_error(regs, int_code & 255, trans_exc_code, fault); | 403 | do_fault_error(regs, pgm_int_code & 255, trans_exc_code, fault); |
412 | } | 404 | } |
413 | 405 | ||
414 | #ifdef CONFIG_64BIT | 406 | #ifdef CONFIG_64BIT |
415 | void __kprobes do_asce_exception(struct pt_regs *regs, long int_code) | 407 | void __kprobes do_asce_exception(struct pt_regs *regs, long pgm_int_code, |
408 | unsigned long trans_exc_code) | ||
416 | { | 409 | { |
417 | unsigned long trans_exc_code = S390_lowcore.trans_exc_code; | ||
418 | struct mm_struct *mm = current->mm; | 410 | struct mm_struct *mm = current->mm; |
419 | struct vm_area_struct *vma; | 411 | struct vm_area_struct *vma; |
420 | 412 | ||
421 | if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm)) | 413 | if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm)) |
422 | goto no_context; | 414 | goto no_context; |
423 | 415 | ||
424 | local_irq_enable(); | ||
425 | |||
426 | down_read(&mm->mmap_sem); | 416 | down_read(&mm->mmap_sem); |
427 | vma = find_vma(mm, trans_exc_code & __FAIL_ADDR_MASK); | 417 | vma = find_vma(mm, trans_exc_code & __FAIL_ADDR_MASK); |
428 | up_read(&mm->mmap_sem); | 418 | up_read(&mm->mmap_sem); |
@@ -434,16 +424,16 @@ void __kprobes do_asce_exception(struct pt_regs *regs, long int_code) | |||
434 | 424 | ||
435 | /* User mode accesses just cause a SIGSEGV */ | 425 | /* User mode accesses just cause a SIGSEGV */ |
436 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 426 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
437 | do_sigsegv(regs, int_code, SEGV_MAPERR, trans_exc_code); | 427 | do_sigsegv(regs, pgm_int_code, SEGV_MAPERR, trans_exc_code); |
438 | return; | 428 | return; |
439 | } | 429 | } |
440 | 430 | ||
441 | no_context: | 431 | no_context: |
442 | do_no_context(regs, int_code, trans_exc_code); | 432 | do_no_context(regs, pgm_int_code, trans_exc_code); |
443 | } | 433 | } |
444 | #endif | 434 | #endif |
445 | 435 | ||
446 | int __handle_fault(unsigned long uaddr, unsigned long int_code, int write_user) | 436 | int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) |
447 | { | 437 | { |
448 | struct pt_regs regs; | 438 | struct pt_regs regs; |
449 | int access, fault; | 439 | int access, fault; |
@@ -454,14 +444,13 @@ int __handle_fault(unsigned long uaddr, unsigned long int_code, int write_user) | |||
454 | regs.psw.addr = (unsigned long) __builtin_return_address(0); | 444 | regs.psw.addr = (unsigned long) __builtin_return_address(0); |
455 | regs.psw.addr |= PSW_ADDR_AMODE; | 445 | regs.psw.addr |= PSW_ADDR_AMODE; |
456 | uaddr &= PAGE_MASK; | 446 | uaddr &= PAGE_MASK; |
457 | access = write_user ? VM_WRITE : VM_READ; | 447 | access = write ? VM_WRITE : VM_READ; |
458 | fault = do_exception(®s, access, uaddr | 2); | 448 | fault = do_exception(®s, access, uaddr | 2); |
459 | if (unlikely(fault)) { | 449 | if (unlikely(fault)) { |
460 | if (fault & VM_FAULT_OOM) { | 450 | if (fault & VM_FAULT_OOM) |
461 | pagefault_out_of_memory(); | 451 | return -EFAULT; |
462 | fault = 0; | 452 | else if (fault & VM_FAULT_SIGBUS) |
463 | } else if (fault & VM_FAULT_SIGBUS) | 453 | do_sigbus(®s, pgm_int_code, uaddr); |
464 | do_sigbus(®s, int_code, uaddr); | ||
465 | } | 454 | } |
466 | return fault ? -EFAULT : 0; | 455 | return fault ? -EFAULT : 0; |
467 | } | 456 | } |
@@ -470,8 +459,7 @@ int __handle_fault(unsigned long uaddr, unsigned long int_code, int write_user) | |||
470 | /* | 459 | /* |
471 | * 'pfault' pseudo page faults routines. | 460 | * 'pfault' pseudo page faults routines. |
472 | */ | 461 | */ |
473 | static ext_int_info_t ext_int_pfault; | 462 | static int pfault_disable; |
474 | static int pfault_disable = 0; | ||
475 | 463 | ||
476 | static int __init nopfault(char *str) | 464 | static int __init nopfault(char *str) |
477 | { | 465 | { |
@@ -481,22 +469,28 @@ static int __init nopfault(char *str) | |||
481 | 469 | ||
482 | __setup("nopfault", nopfault); | 470 | __setup("nopfault", nopfault); |
483 | 471 | ||
484 | typedef struct { | 472 | struct pfault_refbk { |
485 | __u16 refdiagc; | 473 | u16 refdiagc; |
486 | __u16 reffcode; | 474 | u16 reffcode; |
487 | __u16 refdwlen; | 475 | u16 refdwlen; |
488 | __u16 refversn; | 476 | u16 refversn; |
489 | __u64 refgaddr; | 477 | u64 refgaddr; |
490 | __u64 refselmk; | 478 | u64 refselmk; |
491 | __u64 refcmpmk; | 479 | u64 refcmpmk; |
492 | __u64 reserved; | 480 | u64 reserved; |
493 | } __attribute__ ((packed, aligned(8))) pfault_refbk_t; | 481 | } __attribute__ ((packed, aligned(8))); |
494 | 482 | ||
495 | int pfault_init(void) | 483 | int pfault_init(void) |
496 | { | 484 | { |
497 | pfault_refbk_t refbk = | 485 | struct pfault_refbk refbk = { |
498 | { 0x258, 0, 5, 2, __LC_CURRENT, 1ULL << 48, 1ULL << 48, | 486 | .refdiagc = 0x258, |
499 | __PF_RES_FIELD }; | 487 | .reffcode = 0, |
488 | .refdwlen = 5, | ||
489 | .refversn = 2, | ||
490 | .refgaddr = __LC_CURRENT_PID, | ||
491 | .refselmk = 1ULL << 48, | ||
492 | .refcmpmk = 1ULL << 48, | ||
493 | .reserved = __PF_RES_FIELD }; | ||
500 | int rc; | 494 | int rc; |
501 | 495 | ||
502 | if (!MACHINE_IS_VM || pfault_disable) | 496 | if (!MACHINE_IS_VM || pfault_disable) |
@@ -508,18 +502,20 @@ int pfault_init(void) | |||
508 | "2:\n" | 502 | "2:\n" |
509 | EX_TABLE(0b,1b) | 503 | EX_TABLE(0b,1b) |
510 | : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc"); | 504 | : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc"); |
511 | __ctl_set_bit(0, 9); | ||
512 | return rc; | 505 | return rc; |
513 | } | 506 | } |
514 | 507 | ||
515 | void pfault_fini(void) | 508 | void pfault_fini(void) |
516 | { | 509 | { |
517 | pfault_refbk_t refbk = | 510 | struct pfault_refbk refbk = { |
518 | { 0x258, 1, 5, 2, 0ULL, 0ULL, 0ULL, 0ULL }; | 511 | .refdiagc = 0x258, |
512 | .reffcode = 1, | ||
513 | .refdwlen = 5, | ||
514 | .refversn = 2, | ||
515 | }; | ||
519 | 516 | ||
520 | if (!MACHINE_IS_VM || pfault_disable) | 517 | if (!MACHINE_IS_VM || pfault_disable) |
521 | return; | 518 | return; |
522 | __ctl_clear_bit(0,9); | ||
523 | asm volatile( | 519 | asm volatile( |
524 | " diag %0,0,0x258\n" | 520 | " diag %0,0,0x258\n" |
525 | "0:\n" | 521 | "0:\n" |
@@ -527,10 +523,15 @@ void pfault_fini(void) | |||
527 | : : "a" (&refbk), "m" (refbk) : "cc"); | 523 | : : "a" (&refbk), "m" (refbk) : "cc"); |
528 | } | 524 | } |
529 | 525 | ||
530 | static void pfault_interrupt(__u16 int_code) | 526 | static DEFINE_SPINLOCK(pfault_lock); |
527 | static LIST_HEAD(pfault_list); | ||
528 | |||
529 | static void pfault_interrupt(unsigned int ext_int_code, | ||
530 | unsigned int param32, unsigned long param64) | ||
531 | { | 531 | { |
532 | struct task_struct *tsk; | 532 | struct task_struct *tsk; |
533 | __u16 subcode; | 533 | __u16 subcode; |
534 | pid_t pid; | ||
534 | 535 | ||
535 | /* | 536 | /* |
536 | * Get the external interruption subcode & pfault | 537 | * Get the external interruption subcode & pfault |
@@ -538,63 +539,107 @@ static void pfault_interrupt(__u16 int_code) | |||
538 | * in the 'cpu address' field associated with the | 539 | * in the 'cpu address' field associated with the |
539 | * external interrupt. | 540 | * external interrupt. |
540 | */ | 541 | */ |
541 | subcode = S390_lowcore.cpu_addr; | 542 | subcode = ext_int_code >> 16; |
542 | if ((subcode & 0xff00) != __SUBCODE_MASK) | 543 | if ((subcode & 0xff00) != __SUBCODE_MASK) |
543 | return; | 544 | return; |
544 | 545 | kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; | |
545 | /* | 546 | if (subcode & 0x0080) { |
546 | * Get the token (= address of the task structure of the affected task). | 547 | /* Get the token (= pid of the affected task). */ |
547 | */ | 548 | pid = sizeof(void *) == 4 ? param32 : param64; |
548 | tsk = *(struct task_struct **) __LC_PFAULT_INTPARM; | 549 | rcu_read_lock(); |
549 | 550 | tsk = find_task_by_pid_ns(pid, &init_pid_ns); | |
551 | if (tsk) | ||
552 | get_task_struct(tsk); | ||
553 | rcu_read_unlock(); | ||
554 | if (!tsk) | ||
555 | return; | ||
556 | } else { | ||
557 | tsk = current; | ||
558 | } | ||
559 | spin_lock(&pfault_lock); | ||
550 | if (subcode & 0x0080) { | 560 | if (subcode & 0x0080) { |
551 | /* signal bit is set -> a page has been swapped in by VM */ | 561 | /* signal bit is set -> a page has been swapped in by VM */ |
552 | if (xchg(&tsk->thread.pfault_wait, -1) != 0) { | 562 | if (tsk->thread.pfault_wait == 1) { |
553 | /* Initial interrupt was faster than the completion | 563 | /* Initial interrupt was faster than the completion |
554 | * interrupt. pfault_wait is valid. Set pfault_wait | 564 | * interrupt. pfault_wait is valid. Set pfault_wait |
555 | * back to zero and wake up the process. This can | 565 | * back to zero and wake up the process. This can |
556 | * safely be done because the task is still sleeping | 566 | * safely be done because the task is still sleeping |
557 | * and can't produce new pfaults. */ | 567 | * and can't produce new pfaults. */ |
558 | tsk->thread.pfault_wait = 0; | 568 | tsk->thread.pfault_wait = 0; |
569 | list_del(&tsk->thread.list); | ||
559 | wake_up_process(tsk); | 570 | wake_up_process(tsk); |
560 | put_task_struct(tsk); | 571 | } else { |
572 | /* Completion interrupt was faster than initial | ||
573 | * interrupt. Set pfault_wait to -1 so the initial | ||
574 | * interrupt doesn't put the task to sleep. */ | ||
575 | tsk->thread.pfault_wait = -1; | ||
561 | } | 576 | } |
577 | put_task_struct(tsk); | ||
562 | } else { | 578 | } else { |
563 | /* signal bit not set -> a real page is missing. */ | 579 | /* signal bit not set -> a real page is missing. */ |
564 | get_task_struct(tsk); | 580 | if (tsk->thread.pfault_wait == -1) { |
565 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
566 | if (xchg(&tsk->thread.pfault_wait, 1) != 0) { | ||
567 | /* Completion interrupt was faster than the initial | 581 | /* Completion interrupt was faster than the initial |
568 | * interrupt (swapped in a -1 for pfault_wait). Set | 582 | * interrupt (pfault_wait == -1). Set pfault_wait |
569 | * pfault_wait back to zero and exit. This can be | 583 | * back to zero and exit. */ |
570 | * done safely because tsk is running in kernel | ||
571 | * mode and can't produce new pfaults. */ | ||
572 | tsk->thread.pfault_wait = 0; | 584 | tsk->thread.pfault_wait = 0; |
573 | set_task_state(tsk, TASK_RUNNING); | 585 | } else { |
574 | put_task_struct(tsk); | 586 | /* Initial interrupt arrived before completion |
575 | } else | 587 | * interrupt. Let the task sleep. */ |
588 | tsk->thread.pfault_wait = 1; | ||
589 | list_add(&tsk->thread.list, &pfault_list); | ||
590 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
576 | set_tsk_need_resched(tsk); | 591 | set_tsk_need_resched(tsk); |
592 | } | ||
577 | } | 593 | } |
594 | spin_unlock(&pfault_lock); | ||
578 | } | 595 | } |
579 | 596 | ||
580 | void __init pfault_irq_init(void) | 597 | static int __cpuinit pfault_cpu_notify(struct notifier_block *self, |
598 | unsigned long action, void *hcpu) | ||
581 | { | 599 | { |
582 | if (!MACHINE_IS_VM) | 600 | struct thread_struct *thread, *next; |
583 | return; | 601 | struct task_struct *tsk; |
584 | 602 | ||
585 | /* | 603 | switch (action) { |
586 | * Try to get pfault pseudo page faults going. | 604 | case CPU_DEAD: |
587 | */ | 605 | case CPU_DEAD_FROZEN: |
588 | if (register_early_external_interrupt(0x2603, pfault_interrupt, | 606 | spin_lock_irq(&pfault_lock); |
589 | &ext_int_pfault) != 0) | 607 | list_for_each_entry_safe(thread, next, &pfault_list, list) { |
590 | panic("Couldn't request external interrupt 0x2603"); | 608 | thread->pfault_wait = 0; |
609 | list_del(&thread->list); | ||
610 | tsk = container_of(thread, struct task_struct, thread); | ||
611 | wake_up_process(tsk); | ||
612 | } | ||
613 | spin_unlock_irq(&pfault_lock); | ||
614 | break; | ||
615 | default: | ||
616 | break; | ||
617 | } | ||
618 | return NOTIFY_OK; | ||
619 | } | ||
591 | 620 | ||
592 | if (pfault_init() == 0) | 621 | static int __init pfault_irq_init(void) |
593 | return; | 622 | { |
623 | int rc; | ||
594 | 624 | ||
595 | /* Tough luck, no pfault. */ | 625 | if (!MACHINE_IS_VM) |
626 | return 0; | ||
627 | rc = register_external_interrupt(0x2603, pfault_interrupt); | ||
628 | if (rc) | ||
629 | goto out_extint; | ||
630 | rc = pfault_init() == 0 ? 0 : -EOPNOTSUPP; | ||
631 | if (rc) | ||
632 | goto out_pfault; | ||
633 | service_subclass_irq_register(); | ||
634 | hotcpu_notifier(pfault_cpu_notify, 0); | ||
635 | return 0; | ||
636 | |||
637 | out_pfault: | ||
638 | unregister_external_interrupt(0x2603, pfault_interrupt); | ||
639 | out_extint: | ||
596 | pfault_disable = 1; | 640 | pfault_disable = 1; |
597 | unregister_early_external_interrupt(0x2603, pfault_interrupt, | 641 | return rc; |
598 | &ext_int_pfault); | ||
599 | } | 642 | } |
600 | #endif | 643 | early_initcall(pfault_irq_init); |
644 | |||
645 | #endif /* CONFIG_PFAULT */ | ||
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c new file mode 100644 index 000000000000..45b405ca2567 --- /dev/null +++ b/arch/s390/mm/gup.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Lockless get_user_pages_fast for s390 | ||
3 | * | ||
4 | * Copyright IBM Corp. 2010 | ||
5 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
6 | */ | ||
7 | #include <linux/sched.h> | ||
8 | #include <linux/mm.h> | ||
9 | #include <linux/hugetlb.h> | ||
10 | #include <linux/vmstat.h> | ||
11 | #include <linux/pagemap.h> | ||
12 | #include <linux/rwsem.h> | ||
13 | #include <asm/pgtable.h> | ||
14 | |||
15 | /* | ||
16 | * The performance critical leaf functions are made noinline otherwise gcc | ||
17 | * inlines everything into a single function which results in too much | ||
18 | * register pressure. | ||
19 | */ | ||
20 | static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr, | ||
21 | unsigned long end, int write, struct page **pages, int *nr) | ||
22 | { | ||
23 | unsigned long mask; | ||
24 | pte_t *ptep, pte; | ||
25 | struct page *page; | ||
26 | |||
27 | mask = (write ? _PAGE_RO : 0) | _PAGE_INVALID | _PAGE_SPECIAL; | ||
28 | |||
29 | ptep = ((pte_t *) pmd_deref(pmd)) + pte_index(addr); | ||
30 | do { | ||
31 | pte = *ptep; | ||
32 | barrier(); | ||
33 | if ((pte_val(pte) & mask) != 0) | ||
34 | return 0; | ||
35 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | ||
36 | page = pte_page(pte); | ||
37 | if (!page_cache_get_speculative(page)) | ||
38 | return 0; | ||
39 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { | ||
40 | put_page(page); | ||
41 | return 0; | ||
42 | } | ||
43 | pages[*nr] = page; | ||
44 | (*nr)++; | ||
45 | |||
46 | } while (ptep++, addr += PAGE_SIZE, addr != end); | ||
47 | |||
48 | return 1; | ||
49 | } | ||
50 | |||
51 | static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr, | ||
52 | unsigned long end, int write, struct page **pages, int *nr) | ||
53 | { | ||
54 | unsigned long mask, result; | ||
55 | struct page *head, *page; | ||
56 | int refs; | ||
57 | |||
58 | result = write ? 0 : _SEGMENT_ENTRY_RO; | ||
59 | mask = result | _SEGMENT_ENTRY_INV; | ||
60 | if ((pmd_val(pmd) & mask) != result) | ||
61 | return 0; | ||
62 | VM_BUG_ON(!pfn_valid(pmd_val(pmd) >> PAGE_SHIFT)); | ||
63 | |||
64 | refs = 0; | ||
65 | head = pmd_page(pmd); | ||
66 | page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT); | ||
67 | do { | ||
68 | VM_BUG_ON(compound_head(page) != head); | ||
69 | pages[*nr] = page; | ||
70 | (*nr)++; | ||
71 | page++; | ||
72 | refs++; | ||
73 | } while (addr += PAGE_SIZE, addr != end); | ||
74 | |||
75 | if (!page_cache_add_speculative(head, refs)) { | ||
76 | *nr -= refs; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | if (unlikely(pmd_val(pmd) != pmd_val(*pmdp))) { | ||
81 | *nr -= refs; | ||
82 | while (refs--) | ||
83 | put_page(head); | ||
84 | } | ||
85 | |||
86 | return 1; | ||
87 | } | ||
88 | |||
89 | |||
90 | static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr, | ||
91 | unsigned long end, int write, struct page **pages, int *nr) | ||
92 | { | ||
93 | unsigned long next; | ||
94 | pmd_t *pmdp, pmd; | ||
95 | |||
96 | pmdp = (pmd_t *) pudp; | ||
97 | #ifdef CONFIG_64BIT | ||
98 | if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) | ||
99 | pmdp = (pmd_t *) pud_deref(pud); | ||
100 | pmdp += pmd_index(addr); | ||
101 | #endif | ||
102 | do { | ||
103 | pmd = *pmdp; | ||
104 | barrier(); | ||
105 | next = pmd_addr_end(addr, end); | ||
106 | if (pmd_none(pmd)) | ||
107 | return 0; | ||
108 | if (unlikely(pmd_huge(pmd))) { | ||
109 | if (!gup_huge_pmd(pmdp, pmd, addr, next, | ||
110 | write, pages, nr)) | ||
111 | return 0; | ||
112 | } else if (!gup_pte_range(pmdp, pmd, addr, next, | ||
113 | write, pages, nr)) | ||
114 | return 0; | ||
115 | } while (pmdp++, addr = next, addr != end); | ||
116 | |||
117 | return 1; | ||
118 | } | ||
119 | |||
120 | static inline int gup_pud_range(pgd_t *pgdp, pgd_t pgd, unsigned long addr, | ||
121 | unsigned long end, int write, struct page **pages, int *nr) | ||
122 | { | ||
123 | unsigned long next; | ||
124 | pud_t *pudp, pud; | ||
125 | |||
126 | pudp = (pud_t *) pgdp; | ||
127 | #ifdef CONFIG_64BIT | ||
128 | if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2) | ||
129 | pudp = (pud_t *) pgd_deref(pgd); | ||
130 | pudp += pud_index(addr); | ||
131 | #endif | ||
132 | do { | ||
133 | pud = *pudp; | ||
134 | barrier(); | ||
135 | next = pud_addr_end(addr, end); | ||
136 | if (pud_none(pud)) | ||
137 | return 0; | ||
138 | if (!gup_pmd_range(pudp, pud, addr, next, write, pages, nr)) | ||
139 | return 0; | ||
140 | } while (pudp++, addr = next, addr != end); | ||
141 | |||
142 | return 1; | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * get_user_pages_fast() - pin user pages in memory | ||
147 | * @start: starting user address | ||
148 | * @nr_pages: number of pages from start to pin | ||
149 | * @write: whether pages will be written to | ||
150 | * @pages: array that receives pointers to the pages pinned. | ||
151 | * Should be at least nr_pages long. | ||
152 | * | ||
153 | * Attempt to pin user pages in memory without taking mm->mmap_sem. | ||
154 | * If not successful, it will fall back to taking the lock and | ||
155 | * calling get_user_pages(). | ||
156 | * | ||
157 | * Returns number of pages pinned. This may be fewer than the number | ||
158 | * requested. If nr_pages is 0 or negative, returns 0. If no pages | ||
159 | * were pinned, returns -errno. | ||
160 | */ | ||
161 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, | ||
162 | struct page **pages) | ||
163 | { | ||
164 | struct mm_struct *mm = current->mm; | ||
165 | unsigned long addr, len, end; | ||
166 | unsigned long next; | ||
167 | pgd_t *pgdp, pgd; | ||
168 | int nr = 0; | ||
169 | |||
170 | start &= PAGE_MASK; | ||
171 | addr = start; | ||
172 | len = (unsigned long) nr_pages << PAGE_SHIFT; | ||
173 | end = start + len; | ||
174 | if (end < start) | ||
175 | goto slow_irqon; | ||
176 | |||
177 | /* | ||
178 | * local_irq_disable() doesn't prevent pagetable teardown, but does | ||
179 | * prevent the pagetables from being freed on s390. | ||
180 | * | ||
181 | * So long as we atomically load page table pointers versus teardown, | ||
182 | * we can follow the address down to the the page and take a ref on it. | ||
183 | */ | ||
184 | local_irq_disable(); | ||
185 | pgdp = pgd_offset(mm, addr); | ||
186 | do { | ||
187 | pgd = *pgdp; | ||
188 | barrier(); | ||
189 | next = pgd_addr_end(addr, end); | ||
190 | if (pgd_none(pgd)) | ||
191 | goto slow; | ||
192 | if (!gup_pud_range(pgdp, pgd, addr, next, write, pages, &nr)) | ||
193 | goto slow; | ||
194 | } while (pgdp++, addr = next, addr != end); | ||
195 | local_irq_enable(); | ||
196 | |||
197 | VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT); | ||
198 | return nr; | ||
199 | |||
200 | { | ||
201 | int ret; | ||
202 | slow: | ||
203 | local_irq_enable(); | ||
204 | slow_irqon: | ||
205 | /* Try to get the remaining pages with get_user_pages */ | ||
206 | start += nr << PAGE_SHIFT; | ||
207 | pages += nr; | ||
208 | |||
209 | down_read(&mm->mmap_sem); | ||
210 | ret = get_user_pages(current, mm, start, | ||
211 | (end - start) >> PAGE_SHIFT, write, 0, pages, NULL); | ||
212 | up_read(&mm->mmap_sem); | ||
213 | |||
214 | /* Have to be a bit careful with return values */ | ||
215 | if (nr > 0) { | ||
216 | if (ret < 0) | ||
217 | ret = nr; | ||
218 | else | ||
219 | ret += nr; | ||
220 | } | ||
221 | |||
222 | return ret; | ||
223 | } | ||
224 | } | ||
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c index f28c43d2f61d..a4d856db9154 100644 --- a/arch/s390/mm/hugetlbpage.c +++ b/arch/s390/mm/hugetlbpage.c | |||
@@ -13,7 +13,6 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |||
13 | pte_t *pteptr, pte_t pteval) | 13 | pte_t *pteptr, pte_t pteval) |
14 | { | 14 | { |
15 | pmd_t *pmdp = (pmd_t *) pteptr; | 15 | pmd_t *pmdp = (pmd_t *) pteptr; |
16 | pte_t shadow_pteval = pteval; | ||
17 | unsigned long mask; | 16 | unsigned long mask; |
18 | 17 | ||
19 | if (!MACHINE_HAS_HPAGE) { | 18 | if (!MACHINE_HAS_HPAGE) { |
@@ -21,18 +20,9 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |||
21 | mask = pte_val(pteval) & | 20 | mask = pte_val(pteval) & |
22 | (_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO); | 21 | (_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO); |
23 | pte_val(pteval) = (_SEGMENT_ENTRY + __pa(pteptr)) | mask; | 22 | pte_val(pteval) = (_SEGMENT_ENTRY + __pa(pteptr)) | mask; |
24 | if (mm->context.noexec) { | ||
25 | pteptr += PTRS_PER_PTE; | ||
26 | pte_val(shadow_pteval) = | ||
27 | (_SEGMENT_ENTRY + __pa(pteptr)) | mask; | ||
28 | } | ||
29 | } | 23 | } |
30 | 24 | ||
31 | pmd_val(*pmdp) = pte_val(pteval); | 25 | pmd_val(*pmdp) = pte_val(pteval); |
32 | if (mm->context.noexec) { | ||
33 | pmdp = get_shadow_table(pmdp); | ||
34 | pmd_val(*pmdp) = pte_val(shadow_pteval); | ||
35 | } | ||
36 | } | 26 | } |
37 | 27 | ||
38 | int arch_prepare_hugepage(struct page *page) | 28 | int arch_prepare_hugepage(struct page *page) |
@@ -68,7 +58,7 @@ void arch_release_hugepage(struct page *page) | |||
68 | ptep = (pte_t *) page[1].index; | 58 | ptep = (pte_t *) page[1].index; |
69 | if (!ptep) | 59 | if (!ptep) |
70 | return; | 60 | return; |
71 | pte_free(&init_mm, ptep); | 61 | page_table_free(&init_mm, (unsigned long *) ptep); |
72 | page[1].index = 0; | 62 | page[1].index = 0; |
73 | } | 63 | } |
74 | 64 | ||
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 30eb6d02ddb8..59b663109d90 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
@@ -38,19 +38,59 @@ | |||
38 | #include <asm/tlbflush.h> | 38 | #include <asm/tlbflush.h> |
39 | #include <asm/sections.h> | 39 | #include <asm/sections.h> |
40 | 40 | ||
41 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | ||
42 | |||
43 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); | 41 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); |
44 | 42 | ||
45 | char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); | 43 | unsigned long empty_zero_page, zero_page_mask; |
46 | EXPORT_SYMBOL(empty_zero_page); | 44 | EXPORT_SYMBOL(empty_zero_page); |
47 | 45 | ||
46 | static unsigned long setup_zero_pages(void) | ||
47 | { | ||
48 | struct cpuid cpu_id; | ||
49 | unsigned int order; | ||
50 | unsigned long size; | ||
51 | struct page *page; | ||
52 | int i; | ||
53 | |||
54 | get_cpu_id(&cpu_id); | ||
55 | switch (cpu_id.machine) { | ||
56 | case 0x9672: /* g5 */ | ||
57 | case 0x2064: /* z900 */ | ||
58 | case 0x2066: /* z900 */ | ||
59 | case 0x2084: /* z990 */ | ||
60 | case 0x2086: /* z990 */ | ||
61 | case 0x2094: /* z9-109 */ | ||
62 | case 0x2096: /* z9-109 */ | ||
63 | order = 0; | ||
64 | break; | ||
65 | case 0x2097: /* z10 */ | ||
66 | case 0x2098: /* z10 */ | ||
67 | default: | ||
68 | order = 2; | ||
69 | break; | ||
70 | } | ||
71 | |||
72 | empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order); | ||
73 | if (!empty_zero_page) | ||
74 | panic("Out of memory in setup_zero_pages"); | ||
75 | |||
76 | page = virt_to_page((void *) empty_zero_page); | ||
77 | split_page(page, order); | ||
78 | for (i = 1 << order; i > 0; i--) { | ||
79 | SetPageReserved(page); | ||
80 | page++; | ||
81 | } | ||
82 | |||
83 | size = PAGE_SIZE << order; | ||
84 | zero_page_mask = (size - 1) & PAGE_MASK; | ||
85 | |||
86 | return 1UL << order; | ||
87 | } | ||
88 | |||
48 | /* | 89 | /* |
49 | * paging_init() sets up the page tables | 90 | * paging_init() sets up the page tables |
50 | */ | 91 | */ |
51 | void __init paging_init(void) | 92 | void __init paging_init(void) |
52 | { | 93 | { |
53 | static const int ssm_mask = 0x04000000L; | ||
54 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | 94 | unsigned long max_zone_pfns[MAX_NR_ZONES]; |
55 | unsigned long pgd_type; | 95 | unsigned long pgd_type; |
56 | 96 | ||
@@ -72,18 +112,17 @@ void __init paging_init(void) | |||
72 | __ctl_load(S390_lowcore.kernel_asce, 1, 1); | 112 | __ctl_load(S390_lowcore.kernel_asce, 1, 1); |
73 | __ctl_load(S390_lowcore.kernel_asce, 7, 7); | 113 | __ctl_load(S390_lowcore.kernel_asce, 7, 7); |
74 | __ctl_load(S390_lowcore.kernel_asce, 13, 13); | 114 | __ctl_load(S390_lowcore.kernel_asce, 13, 13); |
75 | __raw_local_irq_ssm(ssm_mask); | 115 | arch_local_irq_restore(4UL << (BITS_PER_LONG - 8)); |
76 | 116 | ||
77 | atomic_set(&init_mm.context.attach_count, 1); | 117 | atomic_set(&init_mm.context.attach_count, 1); |
78 | 118 | ||
79 | sparse_memory_present_with_active_regions(MAX_NUMNODES); | 119 | sparse_memory_present_with_active_regions(MAX_NUMNODES); |
80 | sparse_init(); | 120 | sparse_init(); |
81 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); | 121 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); |
82 | #ifdef CONFIG_ZONE_DMA | ||
83 | max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS); | 122 | max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS); |
84 | #endif | ||
85 | max_zone_pfns[ZONE_NORMAL] = max_low_pfn; | 123 | max_zone_pfns[ZONE_NORMAL] = max_low_pfn; |
86 | free_area_init_nodes(max_zone_pfns); | 124 | free_area_init_nodes(max_zone_pfns); |
125 | fault_init(); | ||
87 | } | 126 | } |
88 | 127 | ||
89 | void __init mem_init(void) | 128 | void __init mem_init(void) |
@@ -93,14 +132,12 @@ void __init mem_init(void) | |||
93 | max_mapnr = num_physpages = max_low_pfn; | 132 | max_mapnr = num_physpages = max_low_pfn; |
94 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); | 133 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); |
95 | 134 | ||
96 | /* clear the zero-page */ | ||
97 | memset(empty_zero_page, 0, PAGE_SIZE); | ||
98 | |||
99 | /* Setup guest page hinting */ | 135 | /* Setup guest page hinting */ |
100 | cmma_init(); | 136 | cmma_init(); |
101 | 137 | ||
102 | /* this will put all low memory onto the freelists */ | 138 | /* this will put all low memory onto the freelists */ |
103 | totalram_pages += free_all_bootmem(); | 139 | totalram_pages += free_all_bootmem(); |
140 | totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ | ||
104 | 141 | ||
105 | reservedpages = 0; | 142 | reservedpages = 0; |
106 | 143 | ||
@@ -136,7 +173,8 @@ void kernel_map_pages(struct page *page, int numpages, int enable) | |||
136 | pmd = pmd_offset(pud, address); | 173 | pmd = pmd_offset(pud, address); |
137 | pte = pte_offset_kernel(pmd, address); | 174 | pte = pte_offset_kernel(pmd, address); |
138 | if (!enable) { | 175 | if (!enable) { |
139 | ptep_invalidate(&init_mm, address, pte); | 176 | __ptep_ipte(address, pte); |
177 | pte_val(*pte) = _PAGE_TYPE_EMPTY; | ||
140 | continue; | 178 | continue; |
141 | } | 179 | } |
142 | *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW)); | 180 | *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW)); |
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index a8c2af8c650f..51e5cd9b906a 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * using the stura instruction. | 19 | * using the stura instruction. |
20 | * Returns the number of bytes copied or -EFAULT. | 20 | * Returns the number of bytes copied or -EFAULT. |
21 | */ | 21 | */ |
22 | static long probe_kernel_write_odd(void *dst, void *src, size_t size) | 22 | static long probe_kernel_write_odd(void *dst, const void *src, size_t size) |
23 | { | 23 | { |
24 | unsigned long count, aligned; | 24 | unsigned long count, aligned; |
25 | int offset, mask; | 25 | int offset, mask; |
@@ -45,7 +45,7 @@ static long probe_kernel_write_odd(void *dst, void *src, size_t size) | |||
45 | return rc ? rc : count; | 45 | return rc ? rc : count; |
46 | } | 46 | } |
47 | 47 | ||
48 | long probe_kernel_write(void *dst, void *src, size_t size) | 48 | long probe_kernel_write(void *dst, const void *src, size_t size) |
49 | { | 49 | { |
50 | long copied = 0; | 50 | long copied = 0; |
51 | 51 | ||
@@ -71,7 +71,7 @@ int memcpy_real(void *dest, void *src, size_t count) | |||
71 | 71 | ||
72 | if (!count) | 72 | if (!count) |
73 | return 0; | 73 | return 0; |
74 | flags = __raw_local_irq_stnsm(0xf8UL); | 74 | flags = __arch_local_irq_stnsm(0xf8UL); |
75 | asm volatile ( | 75 | asm volatile ( |
76 | "0: mvcle %1,%2,0x0\n" | 76 | "0: mvcle %1,%2,0x0\n" |
77 | "1: jo 0b\n" | 77 | "1: jo 0b\n" |
@@ -82,6 +82,6 @@ int memcpy_real(void *dest, void *src, size_t count) | |||
82 | "+d" (_len2), "=m" (*((long *) dest)) | 82 | "+d" (_len2), "=m" (*((long *) dest)) |
83 | : "m" (*((long *) src)) | 83 | : "m" (*((long *) src)) |
84 | : "cc", "memory"); | 84 | : "cc", "memory"); |
85 | __raw_local_irq_ssm(flags); | 85 | arch_local_irq_restore(flags); |
86 | return rc; | 86 | return rc; |
87 | } | 87 | } |
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 869efbaed3ea..c9a9f7f18188 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c | |||
@@ -27,17 +27,44 @@ | |||
27 | #include <linux/personality.h> | 27 | #include <linux/personality.h> |
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/random.h> | ||
30 | #include <asm/pgalloc.h> | 31 | #include <asm/pgalloc.h> |
31 | #include <asm/compat.h> | 32 | #include <asm/compat.h> |
32 | 33 | ||
34 | static unsigned long stack_maxrandom_size(void) | ||
35 | { | ||
36 | if (!(current->flags & PF_RANDOMIZE)) | ||
37 | return 0; | ||
38 | if (current->personality & ADDR_NO_RANDOMIZE) | ||
39 | return 0; | ||
40 | return STACK_RND_MASK << PAGE_SHIFT; | ||
41 | } | ||
42 | |||
33 | /* | 43 | /* |
34 | * Top of mmap area (just below the process stack). | 44 | * Top of mmap area (just below the process stack). |
35 | * | 45 | * |
36 | * Leave an at least ~128 MB hole. | 46 | * Leave at least a ~32 MB hole. |
37 | */ | 47 | */ |
38 | #define MIN_GAP (128*1024*1024) | 48 | #define MIN_GAP (32*1024*1024) |
39 | #define MAX_GAP (STACK_TOP/6*5) | 49 | #define MAX_GAP (STACK_TOP/6*5) |
40 | 50 | ||
51 | static inline int mmap_is_legacy(void) | ||
52 | { | ||
53 | if (current->personality & ADDR_COMPAT_LAYOUT) | ||
54 | return 1; | ||
55 | if (rlimit(RLIMIT_STACK) == RLIM_INFINITY) | ||
56 | return 1; | ||
57 | return sysctl_legacy_va_layout; | ||
58 | } | ||
59 | |||
60 | static unsigned long mmap_rnd(void) | ||
61 | { | ||
62 | if (!(current->flags & PF_RANDOMIZE)) | ||
63 | return 0; | ||
64 | /* 8MB randomization for mmap_base */ | ||
65 | return (get_random_int() & 0x7ffUL) << PAGE_SHIFT; | ||
66 | } | ||
67 | |||
41 | static inline unsigned long mmap_base(void) | 68 | static inline unsigned long mmap_base(void) |
42 | { | 69 | { |
43 | unsigned long gap = rlimit(RLIMIT_STACK); | 70 | unsigned long gap = rlimit(RLIMIT_STACK); |
@@ -46,22 +73,8 @@ static inline unsigned long mmap_base(void) | |||
46 | gap = MIN_GAP; | 73 | gap = MIN_GAP; |
47 | else if (gap > MAX_GAP) | 74 | else if (gap > MAX_GAP) |
48 | gap = MAX_GAP; | 75 | gap = MAX_GAP; |
49 | 76 | gap &= PAGE_MASK; | |
50 | return STACK_TOP - (gap & PAGE_MASK); | 77 | return STACK_TOP - stack_maxrandom_size() - mmap_rnd() - gap; |
51 | } | ||
52 | |||
53 | static inline int mmap_is_legacy(void) | ||
54 | { | ||
55 | #ifdef CONFIG_64BIT | ||
56 | /* | ||
57 | * Force standard allocation for 64 bit programs. | ||
58 | */ | ||
59 | if (!is_compat_task()) | ||
60 | return 1; | ||
61 | #endif | ||
62 | return sysctl_legacy_va_layout || | ||
63 | (current->personality & ADDR_COMPAT_LAYOUT) || | ||
64 | rlimit(RLIMIT_STACK) == RLIM_INFINITY; | ||
65 | } | 78 | } |
66 | 79 | ||
67 | #ifndef CONFIG_64BIT | 80 | #ifndef CONFIG_64BIT |
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c new file mode 100644 index 000000000000..d013ed39743b --- /dev/null +++ b/arch/s390/mm/pageattr.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 2011 | ||
3 | * Author(s): Jan Glauber <jang@linux.vnet.ibm.com> | ||
4 | */ | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/mm.h> | ||
7 | #include <linux/hugetlb.h> | ||
8 | #include <asm/pgtable.h> | ||
9 | |||
10 | static void change_page_attr(unsigned long addr, int numpages, | ||
11 | pte_t (*set) (pte_t)) | ||
12 | { | ||
13 | pte_t *ptep, pte; | ||
14 | pmd_t *pmdp; | ||
15 | pud_t *pudp; | ||
16 | pgd_t *pgdp; | ||
17 | int i; | ||
18 | |||
19 | for (i = 0; i < numpages; i++) { | ||
20 | pgdp = pgd_offset(&init_mm, addr); | ||
21 | pudp = pud_offset(pgdp, addr); | ||
22 | pmdp = pmd_offset(pudp, addr); | ||
23 | if (pmd_huge(*pmdp)) { | ||
24 | WARN_ON_ONCE(1); | ||
25 | continue; | ||
26 | } | ||
27 | ptep = pte_offset_kernel(pmdp, addr); | ||
28 | |||
29 | pte = *ptep; | ||
30 | pte = set(pte); | ||
31 | __ptep_ipte(addr, ptep); | ||
32 | *ptep = pte; | ||
33 | addr += PAGE_SIZE; | ||
34 | } | ||
35 | } | ||
36 | |||
37 | int set_memory_ro(unsigned long addr, int numpages) | ||
38 | { | ||
39 | change_page_attr(addr, numpages, pte_wrprotect); | ||
40 | return 0; | ||
41 | } | ||
42 | EXPORT_SYMBOL_GPL(set_memory_ro); | ||
43 | |||
44 | int set_memory_rw(unsigned long addr, int numpages) | ||
45 | { | ||
46 | change_page_attr(addr, numpages, pte_mkwrite); | ||
47 | return 0; | ||
48 | } | ||
49 | EXPORT_SYMBOL_GPL(set_memory_rw); | ||
50 | |||
51 | /* not possible */ | ||
52 | int set_memory_nx(unsigned long addr, int numpages) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | EXPORT_SYMBOL_GPL(set_memory_nx); | ||
57 | |||
58 | int set_memory_x(unsigned long addr, int numpages) | ||
59 | { | ||
60 | return 0; | ||
61 | } | ||
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 8d999249d357..37a23c223705 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/quicklist.h> | 17 | #include <linux/quicklist.h> |
18 | #include <linux/rcupdate.h> | ||
18 | 19 | ||
19 | #include <asm/system.h> | 20 | #include <asm/system.h> |
20 | #include <asm/pgtable.h> | 21 | #include <asm/pgtable.h> |
@@ -25,30 +26,10 @@ | |||
25 | 26 | ||
26 | #ifndef CONFIG_64BIT | 27 | #ifndef CONFIG_64BIT |
27 | #define ALLOC_ORDER 1 | 28 | #define ALLOC_ORDER 1 |
28 | #define TABLES_PER_PAGE 4 | 29 | #define FRAG_MASK 0x0f |
29 | #define FRAG_MASK 15UL | ||
30 | #define SECOND_HALVES 10UL | ||
31 | |||
32 | void clear_table_pgstes(unsigned long *table) | ||
33 | { | ||
34 | clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/4); | ||
35 | memset(table + 256, 0, PAGE_SIZE/4); | ||
36 | clear_table(table + 512, _PAGE_TYPE_EMPTY, PAGE_SIZE/4); | ||
37 | memset(table + 768, 0, PAGE_SIZE/4); | ||
38 | } | ||
39 | |||
40 | #else | 30 | #else |
41 | #define ALLOC_ORDER 2 | 31 | #define ALLOC_ORDER 2 |
42 | #define TABLES_PER_PAGE 2 | 32 | #define FRAG_MASK 0x03 |
43 | #define FRAG_MASK 3UL | ||
44 | #define SECOND_HALVES 2UL | ||
45 | |||
46 | void clear_table_pgstes(unsigned long *table) | ||
47 | { | ||
48 | clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2); | ||
49 | memset(table + 256, 0, PAGE_SIZE/2); | ||
50 | } | ||
51 | |||
52 | #endif | 33 | #endif |
53 | 34 | ||
54 | unsigned long VMALLOC_START = VMALLOC_END - VMALLOC_SIZE; | 35 | unsigned long VMALLOC_START = VMALLOC_END - VMALLOC_SIZE; |
@@ -63,37 +44,17 @@ static int __init parse_vmalloc(char *arg) | |||
63 | } | 44 | } |
64 | early_param("vmalloc", parse_vmalloc); | 45 | early_param("vmalloc", parse_vmalloc); |
65 | 46 | ||
66 | unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec) | 47 | unsigned long *crst_table_alloc(struct mm_struct *mm) |
67 | { | 48 | { |
68 | struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER); | 49 | struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER); |
69 | 50 | ||
70 | if (!page) | 51 | if (!page) |
71 | return NULL; | 52 | return NULL; |
72 | page->index = 0; | ||
73 | if (noexec) { | ||
74 | struct page *shadow = alloc_pages(GFP_KERNEL, ALLOC_ORDER); | ||
75 | if (!shadow) { | ||
76 | __free_pages(page, ALLOC_ORDER); | ||
77 | return NULL; | ||
78 | } | ||
79 | page->index = page_to_phys(shadow); | ||
80 | } | ||
81 | spin_lock(&mm->context.list_lock); | ||
82 | list_add(&page->lru, &mm->context.crst_list); | ||
83 | spin_unlock(&mm->context.list_lock); | ||
84 | return (unsigned long *) page_to_phys(page); | 53 | return (unsigned long *) page_to_phys(page); |
85 | } | 54 | } |
86 | 55 | ||
87 | void crst_table_free(struct mm_struct *mm, unsigned long *table) | 56 | void crst_table_free(struct mm_struct *mm, unsigned long *table) |
88 | { | 57 | { |
89 | unsigned long *shadow = get_shadow_table(table); | ||
90 | struct page *page = virt_to_page(table); | ||
91 | |||
92 | spin_lock(&mm->context.list_lock); | ||
93 | list_del(&page->lru); | ||
94 | spin_unlock(&mm->context.list_lock); | ||
95 | if (shadow) | ||
96 | free_pages((unsigned long) shadow, ALLOC_ORDER); | ||
97 | free_pages((unsigned long) table, ALLOC_ORDER); | 58 | free_pages((unsigned long) table, ALLOC_ORDER); |
98 | } | 59 | } |
99 | 60 | ||
@@ -105,10 +66,10 @@ int crst_table_upgrade(struct mm_struct *mm, unsigned long limit) | |||
105 | 66 | ||
106 | BUG_ON(limit > (1UL << 53)); | 67 | BUG_ON(limit > (1UL << 53)); |
107 | repeat: | 68 | repeat: |
108 | table = crst_table_alloc(mm, mm->context.noexec); | 69 | table = crst_table_alloc(mm); |
109 | if (!table) | 70 | if (!table) |
110 | return -ENOMEM; | 71 | return -ENOMEM; |
111 | spin_lock(&mm->page_table_lock); | 72 | spin_lock_bh(&mm->page_table_lock); |
112 | if (mm->context.asce_limit < limit) { | 73 | if (mm->context.asce_limit < limit) { |
113 | pgd = (unsigned long *) mm->pgd; | 74 | pgd = (unsigned long *) mm->pgd; |
114 | if (mm->context.asce_limit <= (1UL << 31)) { | 75 | if (mm->context.asce_limit <= (1UL << 31)) { |
@@ -130,7 +91,7 @@ repeat: | |||
130 | mm->task_size = mm->context.asce_limit; | 91 | mm->task_size = mm->context.asce_limit; |
131 | table = NULL; | 92 | table = NULL; |
132 | } | 93 | } |
133 | spin_unlock(&mm->page_table_lock); | 94 | spin_unlock_bh(&mm->page_table_lock); |
134 | if (table) | 95 | if (table) |
135 | crst_table_free(mm, table); | 96 | crst_table_free(mm, table); |
136 | if (mm->context.asce_limit < limit) | 97 | if (mm->context.asce_limit < limit) |
@@ -172,94 +133,175 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit) | |||
172 | } | 133 | } |
173 | #endif | 134 | #endif |
174 | 135 | ||
136 | static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits) | ||
137 | { | ||
138 | unsigned int old, new; | ||
139 | |||
140 | do { | ||
141 | old = atomic_read(v); | ||
142 | new = old ^ bits; | ||
143 | } while (atomic_cmpxchg(v, old, new) != old); | ||
144 | return new; | ||
145 | } | ||
146 | |||
175 | /* | 147 | /* |
176 | * page table entry allocation/free routines. | 148 | * page table entry allocation/free routines. |
177 | */ | 149 | */ |
150 | #ifdef CONFIG_PGSTE | ||
151 | static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm) | ||
152 | { | ||
153 | struct page *page; | ||
154 | unsigned long *table; | ||
155 | |||
156 | page = alloc_page(GFP_KERNEL|__GFP_REPEAT); | ||
157 | if (!page) | ||
158 | return NULL; | ||
159 | pgtable_page_ctor(page); | ||
160 | atomic_set(&page->_mapcount, 3); | ||
161 | table = (unsigned long *) page_to_phys(page); | ||
162 | clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2); | ||
163 | clear_table(table + PTRS_PER_PTE, 0, PAGE_SIZE/2); | ||
164 | return table; | ||
165 | } | ||
166 | |||
167 | static inline void page_table_free_pgste(unsigned long *table) | ||
168 | { | ||
169 | struct page *page; | ||
170 | |||
171 | page = pfn_to_page(__pa(table) >> PAGE_SHIFT); | ||
172 | pgtable_page_ctor(page); | ||
173 | atomic_set(&page->_mapcount, -1); | ||
174 | __free_page(page); | ||
175 | } | ||
176 | #endif | ||
177 | |||
178 | unsigned long *page_table_alloc(struct mm_struct *mm) | 178 | unsigned long *page_table_alloc(struct mm_struct *mm) |
179 | { | 179 | { |
180 | struct page *page; | 180 | struct page *page; |
181 | unsigned long *table; | 181 | unsigned long *table; |
182 | unsigned long bits; | 182 | unsigned int mask, bit; |
183 | 183 | ||
184 | bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL; | 184 | #ifdef CONFIG_PGSTE |
185 | spin_lock(&mm->context.list_lock); | 185 | if (mm_has_pgste(mm)) |
186 | page = NULL; | 186 | return page_table_alloc_pgste(mm); |
187 | #endif | ||
188 | /* Allocate fragments of a 4K page as 1K/2K page table */ | ||
189 | spin_lock_bh(&mm->context.list_lock); | ||
190 | mask = FRAG_MASK; | ||
187 | if (!list_empty(&mm->context.pgtable_list)) { | 191 | if (!list_empty(&mm->context.pgtable_list)) { |
188 | page = list_first_entry(&mm->context.pgtable_list, | 192 | page = list_first_entry(&mm->context.pgtable_list, |
189 | struct page, lru); | 193 | struct page, lru); |
190 | if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1)) | 194 | table = (unsigned long *) page_to_phys(page); |
191 | page = NULL; | 195 | mask = atomic_read(&page->_mapcount); |
196 | mask = mask | (mask >> 4); | ||
192 | } | 197 | } |
193 | if (!page) { | 198 | if ((mask & FRAG_MASK) == FRAG_MASK) { |
194 | spin_unlock(&mm->context.list_lock); | 199 | spin_unlock_bh(&mm->context.list_lock); |
195 | page = alloc_page(GFP_KERNEL|__GFP_REPEAT); | 200 | page = alloc_page(GFP_KERNEL|__GFP_REPEAT); |
196 | if (!page) | 201 | if (!page) |
197 | return NULL; | 202 | return NULL; |
198 | pgtable_page_ctor(page); | 203 | pgtable_page_ctor(page); |
199 | page->flags &= ~FRAG_MASK; | 204 | atomic_set(&page->_mapcount, 1); |
200 | table = (unsigned long *) page_to_phys(page); | 205 | table = (unsigned long *) page_to_phys(page); |
201 | if (mm->context.has_pgste) | 206 | clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); |
202 | clear_table_pgstes(table); | 207 | spin_lock_bh(&mm->context.list_lock); |
203 | else | ||
204 | clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); | ||
205 | spin_lock(&mm->context.list_lock); | ||
206 | list_add(&page->lru, &mm->context.pgtable_list); | 208 | list_add(&page->lru, &mm->context.pgtable_list); |
209 | } else { | ||
210 | for (bit = 1; mask & bit; bit <<= 1) | ||
211 | table += PTRS_PER_PTE; | ||
212 | mask = atomic_xor_bits(&page->_mapcount, bit); | ||
213 | if ((mask & FRAG_MASK) == FRAG_MASK) | ||
214 | list_del(&page->lru); | ||
207 | } | 215 | } |
208 | table = (unsigned long *) page_to_phys(page); | 216 | spin_unlock_bh(&mm->context.list_lock); |
209 | while (page->flags & bits) { | ||
210 | table += 256; | ||
211 | bits <<= 1; | ||
212 | } | ||
213 | page->flags |= bits; | ||
214 | if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1)) | ||
215 | list_move_tail(&page->lru, &mm->context.pgtable_list); | ||
216 | spin_unlock(&mm->context.list_lock); | ||
217 | return table; | 217 | return table; |
218 | } | 218 | } |
219 | 219 | ||
220 | void page_table_free(struct mm_struct *mm, unsigned long *table) | 220 | void page_table_free(struct mm_struct *mm, unsigned long *table) |
221 | { | 221 | { |
222 | struct page *page; | 222 | struct page *page; |
223 | unsigned long bits; | 223 | unsigned int bit, mask; |
224 | 224 | ||
225 | bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL; | 225 | #ifdef CONFIG_PGSTE |
226 | bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long); | 226 | if (mm_has_pgste(mm)) |
227 | return page_table_free_pgste(table); | ||
228 | #endif | ||
229 | /* Free 1K/2K page table fragment of a 4K page */ | ||
227 | page = pfn_to_page(__pa(table) >> PAGE_SHIFT); | 230 | page = pfn_to_page(__pa(table) >> PAGE_SHIFT); |
228 | spin_lock(&mm->context.list_lock); | 231 | bit = 1 << ((__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t))); |
229 | page->flags ^= bits; | 232 | spin_lock_bh(&mm->context.list_lock); |
230 | if (page->flags & FRAG_MASK) { | 233 | if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK) |
231 | /* Page now has some free pgtable fragments. */ | ||
232 | list_move(&page->lru, &mm->context.pgtable_list); | ||
233 | page = NULL; | ||
234 | } else | ||
235 | /* All fragments of the 4K page have been freed. */ | ||
236 | list_del(&page->lru); | 234 | list_del(&page->lru); |
237 | spin_unlock(&mm->context.list_lock); | 235 | mask = atomic_xor_bits(&page->_mapcount, bit); |
238 | if (page) { | 236 | if (mask & FRAG_MASK) |
237 | list_add(&page->lru, &mm->context.pgtable_list); | ||
238 | spin_unlock_bh(&mm->context.list_lock); | ||
239 | if (mask == 0) { | ||
239 | pgtable_page_dtor(page); | 240 | pgtable_page_dtor(page); |
241 | atomic_set(&page->_mapcount, -1); | ||
240 | __free_page(page); | 242 | __free_page(page); |
241 | } | 243 | } |
242 | } | 244 | } |
243 | 245 | ||
244 | void disable_noexec(struct mm_struct *mm, struct task_struct *tsk) | 246 | #ifdef CONFIG_HAVE_RCU_TABLE_FREE |
247 | |||
248 | static void __page_table_free_rcu(void *table, unsigned bit) | ||
245 | { | 249 | { |
246 | struct page *page; | 250 | struct page *page; |
247 | 251 | ||
248 | spin_lock(&mm->context.list_lock); | 252 | #ifdef CONFIG_PGSTE |
249 | /* Free shadow region and segment tables. */ | 253 | if (bit == FRAG_MASK) |
250 | list_for_each_entry(page, &mm->context.crst_list, lru) | 254 | return page_table_free_pgste(table); |
251 | if (page->index) { | 255 | #endif |
252 | free_pages((unsigned long) page->index, ALLOC_ORDER); | 256 | /* Free 1K/2K page table fragment of a 4K page */ |
253 | page->index = 0; | 257 | page = pfn_to_page(__pa(table) >> PAGE_SHIFT); |
254 | } | 258 | if (atomic_xor_bits(&page->_mapcount, bit) == 0) { |
255 | /* "Free" second halves of page tables. */ | 259 | pgtable_page_dtor(page); |
256 | list_for_each_entry(page, &mm->context.pgtable_list, lru) | 260 | atomic_set(&page->_mapcount, -1); |
257 | page->flags &= ~SECOND_HALVES; | 261 | __free_page(page); |
258 | spin_unlock(&mm->context.list_lock); | 262 | } |
259 | mm->context.noexec = 0; | ||
260 | update_mm(mm, tsk); | ||
261 | } | 263 | } |
262 | 264 | ||
265 | void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table) | ||
266 | { | ||
267 | struct mm_struct *mm; | ||
268 | struct page *page; | ||
269 | unsigned int bit, mask; | ||
270 | |||
271 | mm = tlb->mm; | ||
272 | #ifdef CONFIG_PGSTE | ||
273 | if (mm_has_pgste(mm)) { | ||
274 | table = (unsigned long *) (__pa(table) | FRAG_MASK); | ||
275 | tlb_remove_table(tlb, table); | ||
276 | return; | ||
277 | } | ||
278 | #endif | ||
279 | bit = 1 << ((__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t))); | ||
280 | page = pfn_to_page(__pa(table) >> PAGE_SHIFT); | ||
281 | spin_lock_bh(&mm->context.list_lock); | ||
282 | if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK) | ||
283 | list_del(&page->lru); | ||
284 | mask = atomic_xor_bits(&page->_mapcount, bit | (bit << 4)); | ||
285 | if (mask & FRAG_MASK) | ||
286 | list_add_tail(&page->lru, &mm->context.pgtable_list); | ||
287 | spin_unlock_bh(&mm->context.list_lock); | ||
288 | table = (unsigned long *) (__pa(table) | (bit << 4)); | ||
289 | tlb_remove_table(tlb, table); | ||
290 | } | ||
291 | |||
292 | void __tlb_remove_table(void *_table) | ||
293 | { | ||
294 | void *table = (void *)((unsigned long) _table & PAGE_MASK); | ||
295 | unsigned type = (unsigned long) _table & ~PAGE_MASK; | ||
296 | |||
297 | if (type) | ||
298 | __page_table_free_rcu(table, type); | ||
299 | else | ||
300 | free_pages((unsigned long) table, ALLOC_ORDER); | ||
301 | } | ||
302 | |||
303 | #endif | ||
304 | |||
263 | /* | 305 | /* |
264 | * switch on pgstes for its userspace process (for kvm) | 306 | * switch on pgstes for its userspace process (for kvm) |
265 | */ | 307 | */ |
@@ -273,7 +315,7 @@ int s390_enable_sie(void) | |||
273 | return -EINVAL; | 315 | return -EINVAL; |
274 | 316 | ||
275 | /* Do we have pgstes? if yes, we are done */ | 317 | /* Do we have pgstes? if yes, we are done */ |
276 | if (tsk->mm->context.has_pgste) | 318 | if (mm_has_pgste(tsk->mm)) |
277 | return 0; | 319 | return 0; |
278 | 320 | ||
279 | /* lets check if we are allowed to replace the mm */ | 321 | /* lets check if we are allowed to replace the mm */ |
@@ -312,6 +354,8 @@ int s390_enable_sie(void) | |||
312 | tsk->mm = tsk->active_mm = mm; | 354 | tsk->mm = tsk->active_mm = mm; |
313 | preempt_disable(); | 355 | preempt_disable(); |
314 | update_mm(mm, tsk); | 356 | update_mm(mm, tsk); |
357 | atomic_inc(&mm->context.attach_count); | ||
358 | atomic_dec(&old_mm->context.attach_count); | ||
315 | cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); | 359 | cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); |
316 | preempt_enable(); | 360 | preempt_enable(); |
317 | task_unlock(tsk); | 361 | task_unlock(tsk); |
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 34c43f23b28c..8c1970d1dd91 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c | |||
@@ -95,7 +95,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) | |||
95 | pu_dir = vmem_pud_alloc(); | 95 | pu_dir = vmem_pud_alloc(); |
96 | if (!pu_dir) | 96 | if (!pu_dir) |
97 | goto out; | 97 | goto out; |
98 | pgd_populate_kernel(&init_mm, pg_dir, pu_dir); | 98 | pgd_populate(&init_mm, pg_dir, pu_dir); |
99 | } | 99 | } |
100 | 100 | ||
101 | pu_dir = pud_offset(pg_dir, address); | 101 | pu_dir = pud_offset(pg_dir, address); |
@@ -103,7 +103,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) | |||
103 | pm_dir = vmem_pmd_alloc(); | 103 | pm_dir = vmem_pmd_alloc(); |
104 | if (!pm_dir) | 104 | if (!pm_dir) |
105 | goto out; | 105 | goto out; |
106 | pud_populate_kernel(&init_mm, pu_dir, pm_dir); | 106 | pud_populate(&init_mm, pu_dir, pm_dir); |
107 | } | 107 | } |
108 | 108 | ||
109 | pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0)); | 109 | pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0)); |
@@ -123,7 +123,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) | |||
123 | pt_dir = vmem_pte_alloc(); | 123 | pt_dir = vmem_pte_alloc(); |
124 | if (!pt_dir) | 124 | if (!pt_dir) |
125 | goto out; | 125 | goto out; |
126 | pmd_populate_kernel(&init_mm, pm_dir, pt_dir); | 126 | pmd_populate(&init_mm, pm_dir, pt_dir); |
127 | } | 127 | } |
128 | 128 | ||
129 | pt_dir = pte_offset_kernel(pm_dir, address); | 129 | pt_dir = pte_offset_kernel(pm_dir, address); |
@@ -159,7 +159,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size) | |||
159 | continue; | 159 | continue; |
160 | 160 | ||
161 | if (pmd_huge(*pm_dir)) { | 161 | if (pmd_huge(*pm_dir)) { |
162 | pmd_clear_kernel(pm_dir); | 162 | pmd_clear(pm_dir); |
163 | address += HPAGE_SIZE - PAGE_SIZE; | 163 | address += HPAGE_SIZE - PAGE_SIZE; |
164 | continue; | 164 | continue; |
165 | } | 165 | } |
@@ -192,7 +192,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) | |||
192 | pu_dir = vmem_pud_alloc(); | 192 | pu_dir = vmem_pud_alloc(); |
193 | if (!pu_dir) | 193 | if (!pu_dir) |
194 | goto out; | 194 | goto out; |
195 | pgd_populate_kernel(&init_mm, pg_dir, pu_dir); | 195 | pgd_populate(&init_mm, pg_dir, pu_dir); |
196 | } | 196 | } |
197 | 197 | ||
198 | pu_dir = pud_offset(pg_dir, address); | 198 | pu_dir = pud_offset(pg_dir, address); |
@@ -200,7 +200,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) | |||
200 | pm_dir = vmem_pmd_alloc(); | 200 | pm_dir = vmem_pmd_alloc(); |
201 | if (!pm_dir) | 201 | if (!pm_dir) |
202 | goto out; | 202 | goto out; |
203 | pud_populate_kernel(&init_mm, pu_dir, pm_dir); | 203 | pud_populate(&init_mm, pu_dir, pm_dir); |
204 | } | 204 | } |
205 | 205 | ||
206 | pm_dir = pmd_offset(pu_dir, address); | 206 | pm_dir = pmd_offset(pu_dir, address); |
@@ -208,7 +208,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) | |||
208 | pt_dir = vmem_pte_alloc(); | 208 | pt_dir = vmem_pte_alloc(); |
209 | if (!pt_dir) | 209 | if (!pt_dir) |
210 | goto out; | 210 | goto out; |
211 | pmd_populate_kernel(&init_mm, pm_dir, pt_dir); | 211 | pmd_populate(&init_mm, pm_dir, pt_dir); |
212 | } | 212 | } |
213 | 213 | ||
214 | pt_dir = pte_offset_kernel(pm_dir, address); | 214 | pt_dir = pte_offset_kernel(pm_dir, address); |
diff --git a/arch/s390/oprofile/Makefile b/arch/s390/oprofile/Makefile index 537b2d840e69..524c4b615821 100644 --- a/arch/s390/oprofile/Makefile +++ b/arch/s390/oprofile/Makefile | |||
@@ -6,4 +6,5 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ | |||
6 | oprofilefs.o oprofile_stats.o \ | 6 | oprofilefs.o oprofile_stats.o \ |
7 | timer_int.o ) | 7 | timer_int.o ) |
8 | 8 | ||
9 | oprofile-y := $(DRIVER_OBJS) init.o backtrace.o | 9 | oprofile-y := $(DRIVER_OBJS) init.o backtrace.o |
10 | oprofile-$(CONFIG_64BIT) += hwsampler.o | ||
diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c new file mode 100644 index 000000000000..4552ce40c81a --- /dev/null +++ b/arch/s390/oprofile/hwsampler.c | |||
@@ -0,0 +1,1241 @@ | |||
1 | /** | ||
2 | * arch/s390/oprofile/hwsampler.c | ||
3 | * | ||
4 | * Copyright IBM Corp. 2010 | ||
5 | * Author: Heinz Graalfs <graalfs@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel_stat.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/workqueue.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/notifier.h> | ||
16 | #include <linux/cpu.h> | ||
17 | #include <linux/semaphore.h> | ||
18 | #include <linux/oom.h> | ||
19 | #include <linux/oprofile.h> | ||
20 | |||
21 | #include <asm/lowcore.h> | ||
22 | #include <asm/irq.h> | ||
23 | |||
24 | #include "hwsampler.h" | ||
25 | |||
26 | #define MAX_NUM_SDB 511 | ||
27 | #define MIN_NUM_SDB 1 | ||
28 | |||
29 | #define ALERT_REQ_MASK 0x4000000000000000ul | ||
30 | #define BUFFER_FULL_MASK 0x8000000000000000ul | ||
31 | |||
32 | #define EI_IEA (1 << 31) /* invalid entry address */ | ||
33 | #define EI_ISE (1 << 30) /* incorrect SDBT entry */ | ||
34 | #define EI_PRA (1 << 29) /* program request alert */ | ||
35 | #define EI_SACA (1 << 23) /* sampler authorization change alert */ | ||
36 | #define EI_LSDA (1 << 22) /* loss of sample data alert */ | ||
37 | |||
38 | DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer); | ||
39 | |||
40 | struct hws_execute_parms { | ||
41 | void *buffer; | ||
42 | signed int rc; | ||
43 | }; | ||
44 | |||
45 | DEFINE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer); | ||
46 | EXPORT_PER_CPU_SYMBOL(sampler_cpu_buffer); | ||
47 | |||
48 | static DEFINE_MUTEX(hws_sem); | ||
49 | static DEFINE_MUTEX(hws_sem_oom); | ||
50 | |||
51 | static unsigned char hws_flush_all; | ||
52 | static unsigned int hws_oom; | ||
53 | static struct workqueue_struct *hws_wq; | ||
54 | |||
55 | static unsigned int hws_state; | ||
56 | enum { | ||
57 | HWS_INIT = 1, | ||
58 | HWS_DEALLOCATED, | ||
59 | HWS_STOPPED, | ||
60 | HWS_STARTED, | ||
61 | HWS_STOPPING }; | ||
62 | |||
63 | /* set to 1 if called by kernel during memory allocation */ | ||
64 | static unsigned char oom_killer_was_active; | ||
65 | /* size of SDBT and SDB as of allocate API */ | ||
66 | static unsigned long num_sdbt = 100; | ||
67 | static unsigned long num_sdb = 511; | ||
68 | /* sampling interval (machine cycles) */ | ||
69 | static unsigned long interval; | ||
70 | |||
71 | static unsigned long min_sampler_rate; | ||
72 | static unsigned long max_sampler_rate; | ||
73 | |||
74 | static int ssctl(void *buffer) | ||
75 | { | ||
76 | int cc; | ||
77 | |||
78 | /* set in order to detect a program check */ | ||
79 | cc = 1; | ||
80 | |||
81 | asm volatile( | ||
82 | "0: .insn s,0xB2870000,0(%1)\n" | ||
83 | "1: ipm %0\n" | ||
84 | " srl %0,28\n" | ||
85 | "2:\n" | ||
86 | EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) | ||
87 | : "+d" (cc), "+a" (buffer) | ||
88 | : "m" (*((struct hws_ssctl_request_block *)buffer)) | ||
89 | : "cc", "memory"); | ||
90 | |||
91 | return cc ? -EINVAL : 0 ; | ||
92 | } | ||
93 | |||
94 | static int qsi(void *buffer) | ||
95 | { | ||
96 | int cc; | ||
97 | cc = 1; | ||
98 | |||
99 | asm volatile( | ||
100 | "0: .insn s,0xB2860000,0(%1)\n" | ||
101 | "1: lhi %0,0\n" | ||
102 | "2:\n" | ||
103 | EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) | ||
104 | : "=d" (cc), "+a" (buffer) | ||
105 | : "m" (*((struct hws_qsi_info_block *)buffer)) | ||
106 | : "cc", "memory"); | ||
107 | |||
108 | return cc ? -EINVAL : 0; | ||
109 | } | ||
110 | |||
111 | static void execute_qsi(void *parms) | ||
112 | { | ||
113 | struct hws_execute_parms *ep = parms; | ||
114 | |||
115 | ep->rc = qsi(ep->buffer); | ||
116 | } | ||
117 | |||
118 | static void execute_ssctl(void *parms) | ||
119 | { | ||
120 | struct hws_execute_parms *ep = parms; | ||
121 | |||
122 | ep->rc = ssctl(ep->buffer); | ||
123 | } | ||
124 | |||
125 | static int smp_ctl_ssctl_stop(int cpu) | ||
126 | { | ||
127 | int rc; | ||
128 | struct hws_execute_parms ep; | ||
129 | struct hws_cpu_buffer *cb; | ||
130 | |||
131 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
132 | |||
133 | cb->ssctl.es = 0; | ||
134 | cb->ssctl.cs = 0; | ||
135 | |||
136 | ep.buffer = &cb->ssctl; | ||
137 | smp_call_function_single(cpu, execute_ssctl, &ep, 1); | ||
138 | rc = ep.rc; | ||
139 | if (rc) { | ||
140 | printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu); | ||
141 | dump_stack(); | ||
142 | } | ||
143 | |||
144 | ep.buffer = &cb->qsi; | ||
145 | smp_call_function_single(cpu, execute_qsi, &ep, 1); | ||
146 | |||
147 | if (cb->qsi.es || cb->qsi.cs) { | ||
148 | printk(KERN_EMERG "CPUMF sampling did not stop properly.\n"); | ||
149 | dump_stack(); | ||
150 | } | ||
151 | |||
152 | return rc; | ||
153 | } | ||
154 | |||
155 | static int smp_ctl_ssctl_deactivate(int cpu) | ||
156 | { | ||
157 | int rc; | ||
158 | struct hws_execute_parms ep; | ||
159 | struct hws_cpu_buffer *cb; | ||
160 | |||
161 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
162 | |||
163 | cb->ssctl.es = 1; | ||
164 | cb->ssctl.cs = 0; | ||
165 | |||
166 | ep.buffer = &cb->ssctl; | ||
167 | smp_call_function_single(cpu, execute_ssctl, &ep, 1); | ||
168 | rc = ep.rc; | ||
169 | if (rc) | ||
170 | printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu); | ||
171 | |||
172 | ep.buffer = &cb->qsi; | ||
173 | smp_call_function_single(cpu, execute_qsi, &ep, 1); | ||
174 | |||
175 | if (cb->qsi.cs) | ||
176 | printk(KERN_EMERG "CPUMF sampling was not set inactive.\n"); | ||
177 | |||
178 | return rc; | ||
179 | } | ||
180 | |||
181 | static int smp_ctl_ssctl_enable_activate(int cpu, unsigned long interval) | ||
182 | { | ||
183 | int rc; | ||
184 | struct hws_execute_parms ep; | ||
185 | struct hws_cpu_buffer *cb; | ||
186 | |||
187 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
188 | |||
189 | cb->ssctl.h = 1; | ||
190 | cb->ssctl.tear = cb->first_sdbt; | ||
191 | cb->ssctl.dear = *(unsigned long *) cb->first_sdbt; | ||
192 | cb->ssctl.interval = interval; | ||
193 | cb->ssctl.es = 1; | ||
194 | cb->ssctl.cs = 1; | ||
195 | |||
196 | ep.buffer = &cb->ssctl; | ||
197 | smp_call_function_single(cpu, execute_ssctl, &ep, 1); | ||
198 | rc = ep.rc; | ||
199 | if (rc) | ||
200 | printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu); | ||
201 | |||
202 | ep.buffer = &cb->qsi; | ||
203 | smp_call_function_single(cpu, execute_qsi, &ep, 1); | ||
204 | if (ep.rc) | ||
205 | printk(KERN_ERR "hwsampler: CPU %d CPUMF QSI failed.\n", cpu); | ||
206 | |||
207 | return rc; | ||
208 | } | ||
209 | |||
210 | static int smp_ctl_qsi(int cpu) | ||
211 | { | ||
212 | struct hws_execute_parms ep; | ||
213 | struct hws_cpu_buffer *cb; | ||
214 | |||
215 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
216 | |||
217 | ep.buffer = &cb->qsi; | ||
218 | smp_call_function_single(cpu, execute_qsi, &ep, 1); | ||
219 | |||
220 | return ep.rc; | ||
221 | } | ||
222 | |||
223 | static inline unsigned long *trailer_entry_ptr(unsigned long v) | ||
224 | { | ||
225 | void *ret; | ||
226 | |||
227 | ret = (void *)v; | ||
228 | ret += PAGE_SIZE; | ||
229 | ret -= sizeof(struct hws_trailer_entry); | ||
230 | |||
231 | return (unsigned long *) ret; | ||
232 | } | ||
233 | |||
234 | /* prototypes for external interrupt handler and worker */ | ||
235 | static void hws_ext_handler(unsigned int ext_int_code, | ||
236 | unsigned int param32, unsigned long param64); | ||
237 | |||
238 | static void worker(struct work_struct *work); | ||
239 | |||
240 | static void add_samples_to_oprofile(unsigned cpu, unsigned long *, | ||
241 | unsigned long *dear); | ||
242 | |||
243 | static void init_all_cpu_buffers(void) | ||
244 | { | ||
245 | int cpu; | ||
246 | struct hws_cpu_buffer *cb; | ||
247 | |||
248 | for_each_online_cpu(cpu) { | ||
249 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
250 | memset(cb, 0, sizeof(struct hws_cpu_buffer)); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | static int is_link_entry(unsigned long *s) | ||
255 | { | ||
256 | return *s & 0x1ul ? 1 : 0; | ||
257 | } | ||
258 | |||
259 | static unsigned long *get_next_sdbt(unsigned long *s) | ||
260 | { | ||
261 | return (unsigned long *) (*s & ~0x1ul); | ||
262 | } | ||
263 | |||
264 | static int prepare_cpu_buffers(void) | ||
265 | { | ||
266 | int cpu; | ||
267 | int rc; | ||
268 | struct hws_cpu_buffer *cb; | ||
269 | |||
270 | rc = 0; | ||
271 | for_each_online_cpu(cpu) { | ||
272 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
273 | atomic_set(&cb->ext_params, 0); | ||
274 | cb->worker_entry = 0; | ||
275 | cb->sample_overflow = 0; | ||
276 | cb->req_alert = 0; | ||
277 | cb->incorrect_sdbt_entry = 0; | ||
278 | cb->invalid_entry_address = 0; | ||
279 | cb->loss_of_sample_data = 0; | ||
280 | cb->sample_auth_change_alert = 0; | ||
281 | cb->finish = 0; | ||
282 | cb->oom = 0; | ||
283 | cb->stop_mode = 0; | ||
284 | } | ||
285 | |||
286 | return rc; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * allocate_sdbt() - allocate sampler memory | ||
291 | * @cpu: the cpu for which sampler memory is allocated | ||
292 | * | ||
293 | * A 4K page is allocated for each requested SDBT. | ||
294 | * A maximum of 511 4K pages are allocated for the SDBs in each of the SDBTs. | ||
295 | * Set ALERT_REQ mask in each SDBs trailer. | ||
296 | * Returns zero if successful, <0 otherwise. | ||
297 | */ | ||
298 | static int allocate_sdbt(int cpu) | ||
299 | { | ||
300 | int j, k, rc; | ||
301 | unsigned long *sdbt; | ||
302 | unsigned long sdb; | ||
303 | unsigned long *tail; | ||
304 | unsigned long *trailer; | ||
305 | struct hws_cpu_buffer *cb; | ||
306 | |||
307 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
308 | |||
309 | if (cb->first_sdbt) | ||
310 | return -EINVAL; | ||
311 | |||
312 | sdbt = NULL; | ||
313 | tail = sdbt; | ||
314 | |||
315 | for (j = 0; j < num_sdbt; j++) { | ||
316 | sdbt = (unsigned long *)get_zeroed_page(GFP_KERNEL); | ||
317 | |||
318 | mutex_lock(&hws_sem_oom); | ||
319 | /* OOM killer might have been activated */ | ||
320 | barrier(); | ||
321 | if (oom_killer_was_active || !sdbt) { | ||
322 | if (sdbt) | ||
323 | free_page((unsigned long)sdbt); | ||
324 | |||
325 | goto allocate_sdbt_error; | ||
326 | } | ||
327 | if (cb->first_sdbt == 0) | ||
328 | cb->first_sdbt = (unsigned long)sdbt; | ||
329 | |||
330 | /* link current page to tail of chain */ | ||
331 | if (tail) | ||
332 | *tail = (unsigned long)(void *)sdbt + 1; | ||
333 | |||
334 | mutex_unlock(&hws_sem_oom); | ||
335 | |||
336 | for (k = 0; k < num_sdb; k++) { | ||
337 | /* get and set SDB page */ | ||
338 | sdb = get_zeroed_page(GFP_KERNEL); | ||
339 | |||
340 | mutex_lock(&hws_sem_oom); | ||
341 | /* OOM killer might have been activated */ | ||
342 | barrier(); | ||
343 | if (oom_killer_was_active || !sdb) { | ||
344 | if (sdb) | ||
345 | free_page(sdb); | ||
346 | |||
347 | goto allocate_sdbt_error; | ||
348 | } | ||
349 | *sdbt = sdb; | ||
350 | trailer = trailer_entry_ptr(*sdbt); | ||
351 | *trailer = ALERT_REQ_MASK; | ||
352 | sdbt++; | ||
353 | mutex_unlock(&hws_sem_oom); | ||
354 | } | ||
355 | tail = sdbt; | ||
356 | } | ||
357 | mutex_lock(&hws_sem_oom); | ||
358 | if (oom_killer_was_active) | ||
359 | goto allocate_sdbt_error; | ||
360 | |||
361 | rc = 0; | ||
362 | if (tail) | ||
363 | *tail = (unsigned long) | ||
364 | ((void *)cb->first_sdbt) + 1; | ||
365 | |||
366 | allocate_sdbt_exit: | ||
367 | mutex_unlock(&hws_sem_oom); | ||
368 | return rc; | ||
369 | |||
370 | allocate_sdbt_error: | ||
371 | rc = -ENOMEM; | ||
372 | goto allocate_sdbt_exit; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * deallocate_sdbt() - deallocate all sampler memory | ||
377 | * | ||
378 | * For each online CPU all SDBT trees are deallocated. | ||
379 | * Returns the number of freed pages. | ||
380 | */ | ||
381 | static int deallocate_sdbt(void) | ||
382 | { | ||
383 | int cpu; | ||
384 | int counter; | ||
385 | |||
386 | counter = 0; | ||
387 | |||
388 | for_each_online_cpu(cpu) { | ||
389 | unsigned long start; | ||
390 | unsigned long sdbt; | ||
391 | unsigned long *curr; | ||
392 | struct hws_cpu_buffer *cb; | ||
393 | |||
394 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
395 | |||
396 | if (!cb->first_sdbt) | ||
397 | continue; | ||
398 | |||
399 | sdbt = cb->first_sdbt; | ||
400 | curr = (unsigned long *) sdbt; | ||
401 | start = sdbt; | ||
402 | |||
403 | /* we'll free the SDBT after all SDBs are processed... */ | ||
404 | while (1) { | ||
405 | if (!*curr || !sdbt) | ||
406 | break; | ||
407 | |||
408 | /* watch for link entry reset if found */ | ||
409 | if (is_link_entry(curr)) { | ||
410 | curr = get_next_sdbt(curr); | ||
411 | if (sdbt) | ||
412 | free_page(sdbt); | ||
413 | |||
414 | /* we are done if we reach the start */ | ||
415 | if ((unsigned long) curr == start) | ||
416 | break; | ||
417 | else | ||
418 | sdbt = (unsigned long) curr; | ||
419 | } else { | ||
420 | /* process SDB pointer */ | ||
421 | if (*curr) { | ||
422 | free_page(*curr); | ||
423 | curr++; | ||
424 | } | ||
425 | } | ||
426 | counter++; | ||
427 | } | ||
428 | cb->first_sdbt = 0; | ||
429 | } | ||
430 | return counter; | ||
431 | } | ||
432 | |||
433 | static int start_sampling(int cpu) | ||
434 | { | ||
435 | int rc; | ||
436 | struct hws_cpu_buffer *cb; | ||
437 | |||
438 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
439 | rc = smp_ctl_ssctl_enable_activate(cpu, interval); | ||
440 | if (rc) { | ||
441 | printk(KERN_INFO "hwsampler: CPU %d ssctl failed.\n", cpu); | ||
442 | goto start_exit; | ||
443 | } | ||
444 | |||
445 | rc = -EINVAL; | ||
446 | if (!cb->qsi.es) { | ||
447 | printk(KERN_INFO "hwsampler: CPU %d ssctl not enabled.\n", cpu); | ||
448 | goto start_exit; | ||
449 | } | ||
450 | |||
451 | if (!cb->qsi.cs) { | ||
452 | printk(KERN_INFO "hwsampler: CPU %d ssctl not active.\n", cpu); | ||
453 | goto start_exit; | ||
454 | } | ||
455 | |||
456 | printk(KERN_INFO | ||
457 | "hwsampler: CPU %d, CPUMF Sampling started, interval %lu.\n", | ||
458 | cpu, interval); | ||
459 | |||
460 | rc = 0; | ||
461 | |||
462 | start_exit: | ||
463 | return rc; | ||
464 | } | ||
465 | |||
466 | static int stop_sampling(int cpu) | ||
467 | { | ||
468 | unsigned long v; | ||
469 | int rc; | ||
470 | struct hws_cpu_buffer *cb; | ||
471 | |||
472 | rc = smp_ctl_qsi(cpu); | ||
473 | WARN_ON(rc); | ||
474 | |||
475 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
476 | if (!rc && !cb->qsi.es) | ||
477 | printk(KERN_INFO "hwsampler: CPU %d, already stopped.\n", cpu); | ||
478 | |||
479 | rc = smp_ctl_ssctl_stop(cpu); | ||
480 | if (rc) { | ||
481 | printk(KERN_INFO "hwsampler: CPU %d, ssctl stop error %d.\n", | ||
482 | cpu, rc); | ||
483 | goto stop_exit; | ||
484 | } | ||
485 | |||
486 | printk(KERN_INFO "hwsampler: CPU %d, CPUMF Sampling stopped.\n", cpu); | ||
487 | |||
488 | stop_exit: | ||
489 | v = cb->req_alert; | ||
490 | if (v) | ||
491 | printk(KERN_ERR "hwsampler: CPU %d CPUMF Request alert," | ||
492 | " count=%lu.\n", cpu, v); | ||
493 | |||
494 | v = cb->loss_of_sample_data; | ||
495 | if (v) | ||
496 | printk(KERN_ERR "hwsampler: CPU %d CPUMF Loss of sample data," | ||
497 | " count=%lu.\n", cpu, v); | ||
498 | |||
499 | v = cb->invalid_entry_address; | ||
500 | if (v) | ||
501 | printk(KERN_ERR "hwsampler: CPU %d CPUMF Invalid entry address," | ||
502 | " count=%lu.\n", cpu, v); | ||
503 | |||
504 | v = cb->incorrect_sdbt_entry; | ||
505 | if (v) | ||
506 | printk(KERN_ERR | ||
507 | "hwsampler: CPU %d CPUMF Incorrect SDBT address," | ||
508 | " count=%lu.\n", cpu, v); | ||
509 | |||
510 | v = cb->sample_auth_change_alert; | ||
511 | if (v) | ||
512 | printk(KERN_ERR | ||
513 | "hwsampler: CPU %d CPUMF Sample authorization change," | ||
514 | " count=%lu.\n", cpu, v); | ||
515 | |||
516 | return rc; | ||
517 | } | ||
518 | |||
519 | static int check_hardware_prerequisites(void) | ||
520 | { | ||
521 | if (!test_facility(68)) | ||
522 | return -EOPNOTSUPP; | ||
523 | return 0; | ||
524 | } | ||
525 | /* | ||
526 | * hws_oom_callback() - the OOM callback function | ||
527 | * | ||
528 | * In case the callback is invoked during memory allocation for the | ||
529 | * hw sampler, all obtained memory is deallocated and a flag is set | ||
530 | * so main sampler memory allocation can exit with a failure code. | ||
531 | * In case the callback is invoked during sampling the hw sampler | ||
532 | * is deactivated for all CPUs. | ||
533 | */ | ||
534 | static int hws_oom_callback(struct notifier_block *nfb, | ||
535 | unsigned long dummy, void *parm) | ||
536 | { | ||
537 | unsigned long *freed; | ||
538 | int cpu; | ||
539 | struct hws_cpu_buffer *cb; | ||
540 | |||
541 | freed = parm; | ||
542 | |||
543 | mutex_lock(&hws_sem_oom); | ||
544 | |||
545 | if (hws_state == HWS_DEALLOCATED) { | ||
546 | /* during memory allocation */ | ||
547 | if (oom_killer_was_active == 0) { | ||
548 | oom_killer_was_active = 1; | ||
549 | *freed += deallocate_sdbt(); | ||
550 | } | ||
551 | } else { | ||
552 | int i; | ||
553 | cpu = get_cpu(); | ||
554 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
555 | |||
556 | if (!cb->oom) { | ||
557 | for_each_online_cpu(i) { | ||
558 | smp_ctl_ssctl_deactivate(i); | ||
559 | cb->oom = 1; | ||
560 | } | ||
561 | cb->finish = 1; | ||
562 | |||
563 | printk(KERN_INFO | ||
564 | "hwsampler: CPU %d, OOM notify during CPUMF Sampling.\n", | ||
565 | cpu); | ||
566 | } | ||
567 | } | ||
568 | |||
569 | mutex_unlock(&hws_sem_oom); | ||
570 | |||
571 | return NOTIFY_OK; | ||
572 | } | ||
573 | |||
574 | static struct notifier_block hws_oom_notifier = { | ||
575 | .notifier_call = hws_oom_callback | ||
576 | }; | ||
577 | |||
578 | static int hws_cpu_callback(struct notifier_block *nfb, | ||
579 | unsigned long action, void *hcpu) | ||
580 | { | ||
581 | /* We do not have sampler space available for all possible CPUs. | ||
582 | All CPUs should be online when hw sampling is activated. */ | ||
583 | return (hws_state <= HWS_DEALLOCATED) ? NOTIFY_OK : NOTIFY_BAD; | ||
584 | } | ||
585 | |||
586 | static struct notifier_block hws_cpu_notifier = { | ||
587 | .notifier_call = hws_cpu_callback | ||
588 | }; | ||
589 | |||
590 | /** | ||
591 | * hwsampler_deactivate() - set hardware sampling temporarily inactive | ||
592 | * @cpu: specifies the CPU to be set inactive. | ||
593 | * | ||
594 | * Returns 0 on success, !0 on failure. | ||
595 | */ | ||
596 | int hwsampler_deactivate(unsigned int cpu) | ||
597 | { | ||
598 | /* | ||
599 | * Deactivate hw sampling temporarily and flush the buffer | ||
600 | * by pushing all the pending samples to oprofile buffer. | ||
601 | * | ||
602 | * This function can be called under one of the following conditions: | ||
603 | * Memory unmap, task is exiting. | ||
604 | */ | ||
605 | int rc; | ||
606 | struct hws_cpu_buffer *cb; | ||
607 | |||
608 | rc = 0; | ||
609 | mutex_lock(&hws_sem); | ||
610 | |||
611 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
612 | if (hws_state == HWS_STARTED) { | ||
613 | rc = smp_ctl_qsi(cpu); | ||
614 | WARN_ON(rc); | ||
615 | if (cb->qsi.cs) { | ||
616 | rc = smp_ctl_ssctl_deactivate(cpu); | ||
617 | if (rc) { | ||
618 | printk(KERN_INFO | ||
619 | "hwsampler: CPU %d, CPUMF Deactivation failed.\n", cpu); | ||
620 | cb->finish = 1; | ||
621 | hws_state = HWS_STOPPING; | ||
622 | } else { | ||
623 | hws_flush_all = 1; | ||
624 | /* Add work to queue to read pending samples.*/ | ||
625 | queue_work_on(cpu, hws_wq, &cb->worker); | ||
626 | } | ||
627 | } | ||
628 | } | ||
629 | mutex_unlock(&hws_sem); | ||
630 | |||
631 | if (hws_wq) | ||
632 | flush_workqueue(hws_wq); | ||
633 | |||
634 | return rc; | ||
635 | } | ||
636 | |||
637 | /** | ||
638 | * hwsampler_activate() - activate/resume hardware sampling which was deactivated | ||
639 | * @cpu: specifies the CPU to be set active. | ||
640 | * | ||
641 | * Returns 0 on success, !0 on failure. | ||
642 | */ | ||
643 | int hwsampler_activate(unsigned int cpu) | ||
644 | { | ||
645 | /* | ||
646 | * Re-activate hw sampling. This should be called in pair with | ||
647 | * hwsampler_deactivate(). | ||
648 | */ | ||
649 | int rc; | ||
650 | struct hws_cpu_buffer *cb; | ||
651 | |||
652 | rc = 0; | ||
653 | mutex_lock(&hws_sem); | ||
654 | |||
655 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
656 | if (hws_state == HWS_STARTED) { | ||
657 | rc = smp_ctl_qsi(cpu); | ||
658 | WARN_ON(rc); | ||
659 | if (!cb->qsi.cs) { | ||
660 | hws_flush_all = 0; | ||
661 | rc = smp_ctl_ssctl_enable_activate(cpu, interval); | ||
662 | if (rc) { | ||
663 | printk(KERN_ERR | ||
664 | "CPU %d, CPUMF activate sampling failed.\n", | ||
665 | cpu); | ||
666 | } | ||
667 | } | ||
668 | } | ||
669 | |||
670 | mutex_unlock(&hws_sem); | ||
671 | |||
672 | return rc; | ||
673 | } | ||
674 | |||
675 | static void hws_ext_handler(unsigned int ext_int_code, | ||
676 | unsigned int param32, unsigned long param64) | ||
677 | { | ||
678 | struct hws_cpu_buffer *cb; | ||
679 | |||
680 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CPM]++; | ||
681 | cb = &__get_cpu_var(sampler_cpu_buffer); | ||
682 | atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); | ||
683 | if (hws_wq) | ||
684 | queue_work(hws_wq, &cb->worker); | ||
685 | } | ||
686 | |||
687 | static int check_qsi_on_setup(void) | ||
688 | { | ||
689 | int rc; | ||
690 | unsigned int cpu; | ||
691 | struct hws_cpu_buffer *cb; | ||
692 | |||
693 | for_each_online_cpu(cpu) { | ||
694 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
695 | rc = smp_ctl_qsi(cpu); | ||
696 | WARN_ON(rc); | ||
697 | if (rc) | ||
698 | return -EOPNOTSUPP; | ||
699 | |||
700 | if (!cb->qsi.as) { | ||
701 | printk(KERN_INFO "hwsampler: CPUMF sampling is not authorized.\n"); | ||
702 | return -EINVAL; | ||
703 | } | ||
704 | |||
705 | if (cb->qsi.es) { | ||
706 | printk(KERN_WARNING "hwsampler: CPUMF is still enabled.\n"); | ||
707 | rc = smp_ctl_ssctl_stop(cpu); | ||
708 | if (rc) | ||
709 | return -EINVAL; | ||
710 | |||
711 | printk(KERN_INFO | ||
712 | "CPU %d, CPUMF Sampling stopped now.\n", cpu); | ||
713 | } | ||
714 | } | ||
715 | return 0; | ||
716 | } | ||
717 | |||
718 | static int check_qsi_on_start(void) | ||
719 | { | ||
720 | unsigned int cpu; | ||
721 | int rc; | ||
722 | struct hws_cpu_buffer *cb; | ||
723 | |||
724 | for_each_online_cpu(cpu) { | ||
725 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
726 | rc = smp_ctl_qsi(cpu); | ||
727 | WARN_ON(rc); | ||
728 | |||
729 | if (!cb->qsi.as) | ||
730 | return -EINVAL; | ||
731 | |||
732 | if (cb->qsi.es) | ||
733 | return -EINVAL; | ||
734 | |||
735 | if (cb->qsi.cs) | ||
736 | return -EINVAL; | ||
737 | } | ||
738 | return 0; | ||
739 | } | ||
740 | |||
741 | static void worker_on_start(unsigned int cpu) | ||
742 | { | ||
743 | struct hws_cpu_buffer *cb; | ||
744 | |||
745 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
746 | cb->worker_entry = cb->first_sdbt; | ||
747 | } | ||
748 | |||
749 | static int worker_check_error(unsigned int cpu, int ext_params) | ||
750 | { | ||
751 | int rc; | ||
752 | unsigned long *sdbt; | ||
753 | struct hws_cpu_buffer *cb; | ||
754 | |||
755 | rc = 0; | ||
756 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
757 | sdbt = (unsigned long *) cb->worker_entry; | ||
758 | |||
759 | if (!sdbt || !*sdbt) | ||
760 | return -EINVAL; | ||
761 | |||
762 | if (ext_params & EI_PRA) | ||
763 | cb->req_alert++; | ||
764 | |||
765 | if (ext_params & EI_LSDA) | ||
766 | cb->loss_of_sample_data++; | ||
767 | |||
768 | if (ext_params & EI_IEA) { | ||
769 | cb->invalid_entry_address++; | ||
770 | rc = -EINVAL; | ||
771 | } | ||
772 | |||
773 | if (ext_params & EI_ISE) { | ||
774 | cb->incorrect_sdbt_entry++; | ||
775 | rc = -EINVAL; | ||
776 | } | ||
777 | |||
778 | if (ext_params & EI_SACA) { | ||
779 | cb->sample_auth_change_alert++; | ||
780 | rc = -EINVAL; | ||
781 | } | ||
782 | |||
783 | return rc; | ||
784 | } | ||
785 | |||
786 | static void worker_on_finish(unsigned int cpu) | ||
787 | { | ||
788 | int rc, i; | ||
789 | struct hws_cpu_buffer *cb; | ||
790 | |||
791 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
792 | |||
793 | if (cb->finish) { | ||
794 | rc = smp_ctl_qsi(cpu); | ||
795 | WARN_ON(rc); | ||
796 | if (cb->qsi.es) { | ||
797 | printk(KERN_INFO | ||
798 | "hwsampler: CPU %d, CPUMF Stop/Deactivate sampling.\n", | ||
799 | cpu); | ||
800 | rc = smp_ctl_ssctl_stop(cpu); | ||
801 | if (rc) | ||
802 | printk(KERN_INFO | ||
803 | "hwsampler: CPU %d, CPUMF Deactivation failed.\n", | ||
804 | cpu); | ||
805 | |||
806 | for_each_online_cpu(i) { | ||
807 | if (i == cpu) | ||
808 | continue; | ||
809 | if (!cb->finish) { | ||
810 | cb->finish = 1; | ||
811 | queue_work_on(i, hws_wq, | ||
812 | &cb->worker); | ||
813 | } | ||
814 | } | ||
815 | } | ||
816 | } | ||
817 | } | ||
818 | |||
819 | static void worker_on_interrupt(unsigned int cpu) | ||
820 | { | ||
821 | unsigned long *sdbt; | ||
822 | unsigned char done; | ||
823 | struct hws_cpu_buffer *cb; | ||
824 | |||
825 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
826 | |||
827 | sdbt = (unsigned long *) cb->worker_entry; | ||
828 | |||
829 | done = 0; | ||
830 | /* do not proceed if stop was entered, | ||
831 | * forget the buffers not yet processed */ | ||
832 | while (!done && !cb->stop_mode) { | ||
833 | unsigned long *trailer; | ||
834 | struct hws_trailer_entry *te; | ||
835 | unsigned long *dear = 0; | ||
836 | |||
837 | trailer = trailer_entry_ptr(*sdbt); | ||
838 | /* leave loop if no more work to do */ | ||
839 | if (!(*trailer & BUFFER_FULL_MASK)) { | ||
840 | done = 1; | ||
841 | if (!hws_flush_all) | ||
842 | continue; | ||
843 | } | ||
844 | |||
845 | te = (struct hws_trailer_entry *)trailer; | ||
846 | cb->sample_overflow += te->overflow; | ||
847 | |||
848 | add_samples_to_oprofile(cpu, sdbt, dear); | ||
849 | |||
850 | /* reset trailer */ | ||
851 | xchg((unsigned char *) te, 0x40); | ||
852 | |||
853 | /* advance to next sdb slot in current sdbt */ | ||
854 | sdbt++; | ||
855 | /* in case link bit is set use address w/o link bit */ | ||
856 | if (is_link_entry(sdbt)) | ||
857 | sdbt = get_next_sdbt(sdbt); | ||
858 | |||
859 | cb->worker_entry = (unsigned long)sdbt; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | static void add_samples_to_oprofile(unsigned int cpu, unsigned long *sdbt, | ||
864 | unsigned long *dear) | ||
865 | { | ||
866 | struct hws_data_entry *sample_data_ptr; | ||
867 | unsigned long *trailer; | ||
868 | |||
869 | trailer = trailer_entry_ptr(*sdbt); | ||
870 | if (dear) { | ||
871 | if (dear > trailer) | ||
872 | return; | ||
873 | trailer = dear; | ||
874 | } | ||
875 | |||
876 | sample_data_ptr = (struct hws_data_entry *)(*sdbt); | ||
877 | |||
878 | while ((unsigned long *)sample_data_ptr < trailer) { | ||
879 | struct pt_regs *regs = NULL; | ||
880 | struct task_struct *tsk = NULL; | ||
881 | |||
882 | /* | ||
883 | * Check sampling mode, 1 indicates basic (=customer) sampling | ||
884 | * mode. | ||
885 | */ | ||
886 | if (sample_data_ptr->def != 1) { | ||
887 | /* sample slot is not yet written */ | ||
888 | break; | ||
889 | } else { | ||
890 | /* make sure we don't use it twice, | ||
891 | * the next time the sampler will set it again */ | ||
892 | sample_data_ptr->def = 0; | ||
893 | } | ||
894 | |||
895 | /* Get pt_regs. */ | ||
896 | if (sample_data_ptr->P == 1) { | ||
897 | /* userspace sample */ | ||
898 | unsigned int pid = sample_data_ptr->prim_asn; | ||
899 | rcu_read_lock(); | ||
900 | tsk = pid_task(find_vpid(pid), PIDTYPE_PID); | ||
901 | if (tsk) | ||
902 | regs = task_pt_regs(tsk); | ||
903 | rcu_read_unlock(); | ||
904 | } else { | ||
905 | /* kernelspace sample */ | ||
906 | regs = task_pt_regs(current); | ||
907 | } | ||
908 | |||
909 | mutex_lock(&hws_sem); | ||
910 | oprofile_add_ext_hw_sample(sample_data_ptr->ia, regs, 0, | ||
911 | !sample_data_ptr->P, tsk); | ||
912 | mutex_unlock(&hws_sem); | ||
913 | |||
914 | sample_data_ptr++; | ||
915 | } | ||
916 | } | ||
917 | |||
918 | static void worker(struct work_struct *work) | ||
919 | { | ||
920 | unsigned int cpu; | ||
921 | int ext_params; | ||
922 | struct hws_cpu_buffer *cb; | ||
923 | |||
924 | cb = container_of(work, struct hws_cpu_buffer, worker); | ||
925 | cpu = smp_processor_id(); | ||
926 | ext_params = atomic_xchg(&cb->ext_params, 0); | ||
927 | |||
928 | if (!cb->worker_entry) | ||
929 | worker_on_start(cpu); | ||
930 | |||
931 | if (worker_check_error(cpu, ext_params)) | ||
932 | return; | ||
933 | |||
934 | if (!cb->finish) | ||
935 | worker_on_interrupt(cpu); | ||
936 | |||
937 | if (cb->finish) | ||
938 | worker_on_finish(cpu); | ||
939 | } | ||
940 | |||
941 | /** | ||
942 | * hwsampler_allocate() - allocate memory for the hardware sampler | ||
943 | * @sdbt: number of SDBTs per online CPU (must be > 0) | ||
944 | * @sdb: number of SDBs per SDBT (minimum 1, maximum 511) | ||
945 | * | ||
946 | * Returns 0 on success, !0 on failure. | ||
947 | */ | ||
948 | int hwsampler_allocate(unsigned long sdbt, unsigned long sdb) | ||
949 | { | ||
950 | int cpu, rc; | ||
951 | mutex_lock(&hws_sem); | ||
952 | |||
953 | rc = -EINVAL; | ||
954 | if (hws_state != HWS_DEALLOCATED) | ||
955 | goto allocate_exit; | ||
956 | |||
957 | if (sdbt < 1) | ||
958 | goto allocate_exit; | ||
959 | |||
960 | if (sdb > MAX_NUM_SDB || sdb < MIN_NUM_SDB) | ||
961 | goto allocate_exit; | ||
962 | |||
963 | num_sdbt = sdbt; | ||
964 | num_sdb = sdb; | ||
965 | |||
966 | oom_killer_was_active = 0; | ||
967 | register_oom_notifier(&hws_oom_notifier); | ||
968 | |||
969 | for_each_online_cpu(cpu) { | ||
970 | if (allocate_sdbt(cpu)) { | ||
971 | unregister_oom_notifier(&hws_oom_notifier); | ||
972 | goto allocate_error; | ||
973 | } | ||
974 | } | ||
975 | unregister_oom_notifier(&hws_oom_notifier); | ||
976 | if (oom_killer_was_active) | ||
977 | goto allocate_error; | ||
978 | |||
979 | hws_state = HWS_STOPPED; | ||
980 | rc = 0; | ||
981 | |||
982 | allocate_exit: | ||
983 | mutex_unlock(&hws_sem); | ||
984 | return rc; | ||
985 | |||
986 | allocate_error: | ||
987 | rc = -ENOMEM; | ||
988 | printk(KERN_ERR "hwsampler: CPUMF Memory allocation failed.\n"); | ||
989 | goto allocate_exit; | ||
990 | } | ||
991 | |||
992 | /** | ||
993 | * hwsampler_deallocate() - deallocate hardware sampler memory | ||
994 | * | ||
995 | * Returns 0 on success, !0 on failure. | ||
996 | */ | ||
997 | int hwsampler_deallocate() | ||
998 | { | ||
999 | int rc; | ||
1000 | |||
1001 | mutex_lock(&hws_sem); | ||
1002 | |||
1003 | rc = -EINVAL; | ||
1004 | if (hws_state != HWS_STOPPED) | ||
1005 | goto deallocate_exit; | ||
1006 | |||
1007 | ctl_clear_bit(0, 5); /* set bit 58 CR0 off */ | ||
1008 | deallocate_sdbt(); | ||
1009 | |||
1010 | hws_state = HWS_DEALLOCATED; | ||
1011 | rc = 0; | ||
1012 | |||
1013 | deallocate_exit: | ||
1014 | mutex_unlock(&hws_sem); | ||
1015 | |||
1016 | return rc; | ||
1017 | } | ||
1018 | |||
1019 | unsigned long hwsampler_query_min_interval(void) | ||
1020 | { | ||
1021 | return min_sampler_rate; | ||
1022 | } | ||
1023 | |||
1024 | unsigned long hwsampler_query_max_interval(void) | ||
1025 | { | ||
1026 | return max_sampler_rate; | ||
1027 | } | ||
1028 | |||
1029 | unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu) | ||
1030 | { | ||
1031 | struct hws_cpu_buffer *cb; | ||
1032 | |||
1033 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
1034 | |||
1035 | return cb->sample_overflow; | ||
1036 | } | ||
1037 | |||
1038 | int hwsampler_setup() | ||
1039 | { | ||
1040 | int rc; | ||
1041 | int cpu; | ||
1042 | struct hws_cpu_buffer *cb; | ||
1043 | |||
1044 | mutex_lock(&hws_sem); | ||
1045 | |||
1046 | rc = -EINVAL; | ||
1047 | if (hws_state) | ||
1048 | goto setup_exit; | ||
1049 | |||
1050 | hws_state = HWS_INIT; | ||
1051 | |||
1052 | init_all_cpu_buffers(); | ||
1053 | |||
1054 | rc = check_hardware_prerequisites(); | ||
1055 | if (rc) | ||
1056 | goto setup_exit; | ||
1057 | |||
1058 | rc = check_qsi_on_setup(); | ||
1059 | if (rc) | ||
1060 | goto setup_exit; | ||
1061 | |||
1062 | rc = -EINVAL; | ||
1063 | hws_wq = create_workqueue("hwsampler"); | ||
1064 | if (!hws_wq) | ||
1065 | goto setup_exit; | ||
1066 | |||
1067 | register_cpu_notifier(&hws_cpu_notifier); | ||
1068 | |||
1069 | for_each_online_cpu(cpu) { | ||
1070 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
1071 | INIT_WORK(&cb->worker, worker); | ||
1072 | rc = smp_ctl_qsi(cpu); | ||
1073 | WARN_ON(rc); | ||
1074 | if (min_sampler_rate != cb->qsi.min_sampl_rate) { | ||
1075 | if (min_sampler_rate) { | ||
1076 | printk(KERN_WARNING | ||
1077 | "hwsampler: different min sampler rate values.\n"); | ||
1078 | if (min_sampler_rate < cb->qsi.min_sampl_rate) | ||
1079 | min_sampler_rate = | ||
1080 | cb->qsi.min_sampl_rate; | ||
1081 | } else | ||
1082 | min_sampler_rate = cb->qsi.min_sampl_rate; | ||
1083 | } | ||
1084 | if (max_sampler_rate != cb->qsi.max_sampl_rate) { | ||
1085 | if (max_sampler_rate) { | ||
1086 | printk(KERN_WARNING | ||
1087 | "hwsampler: different max sampler rate values.\n"); | ||
1088 | if (max_sampler_rate > cb->qsi.max_sampl_rate) | ||
1089 | max_sampler_rate = | ||
1090 | cb->qsi.max_sampl_rate; | ||
1091 | } else | ||
1092 | max_sampler_rate = cb->qsi.max_sampl_rate; | ||
1093 | } | ||
1094 | } | ||
1095 | register_external_interrupt(0x1407, hws_ext_handler); | ||
1096 | |||
1097 | hws_state = HWS_DEALLOCATED; | ||
1098 | rc = 0; | ||
1099 | |||
1100 | setup_exit: | ||
1101 | mutex_unlock(&hws_sem); | ||
1102 | return rc; | ||
1103 | } | ||
1104 | |||
1105 | int hwsampler_shutdown() | ||
1106 | { | ||
1107 | int rc; | ||
1108 | |||
1109 | mutex_lock(&hws_sem); | ||
1110 | |||
1111 | rc = -EINVAL; | ||
1112 | if (hws_state == HWS_DEALLOCATED || hws_state == HWS_STOPPED) { | ||
1113 | mutex_unlock(&hws_sem); | ||
1114 | |||
1115 | if (hws_wq) | ||
1116 | flush_workqueue(hws_wq); | ||
1117 | |||
1118 | mutex_lock(&hws_sem); | ||
1119 | |||
1120 | if (hws_state == HWS_STOPPED) { | ||
1121 | ctl_clear_bit(0, 5); /* set bit 58 CR0 off */ | ||
1122 | deallocate_sdbt(); | ||
1123 | } | ||
1124 | if (hws_wq) { | ||
1125 | destroy_workqueue(hws_wq); | ||
1126 | hws_wq = NULL; | ||
1127 | } | ||
1128 | |||
1129 | unregister_external_interrupt(0x1407, hws_ext_handler); | ||
1130 | hws_state = HWS_INIT; | ||
1131 | rc = 0; | ||
1132 | } | ||
1133 | mutex_unlock(&hws_sem); | ||
1134 | |||
1135 | unregister_cpu_notifier(&hws_cpu_notifier); | ||
1136 | |||
1137 | return rc; | ||
1138 | } | ||
1139 | |||
1140 | /** | ||
1141 | * hwsampler_start_all() - start hardware sampling on all online CPUs | ||
1142 | * @rate: specifies the used interval when samples are taken | ||
1143 | * | ||
1144 | * Returns 0 on success, !0 on failure. | ||
1145 | */ | ||
1146 | int hwsampler_start_all(unsigned long rate) | ||
1147 | { | ||
1148 | int rc, cpu; | ||
1149 | |||
1150 | mutex_lock(&hws_sem); | ||
1151 | |||
1152 | hws_oom = 0; | ||
1153 | |||
1154 | rc = -EINVAL; | ||
1155 | if (hws_state != HWS_STOPPED) | ||
1156 | goto start_all_exit; | ||
1157 | |||
1158 | interval = rate; | ||
1159 | |||
1160 | /* fail if rate is not valid */ | ||
1161 | if (interval < min_sampler_rate || interval > max_sampler_rate) | ||
1162 | goto start_all_exit; | ||
1163 | |||
1164 | rc = check_qsi_on_start(); | ||
1165 | if (rc) | ||
1166 | goto start_all_exit; | ||
1167 | |||
1168 | rc = prepare_cpu_buffers(); | ||
1169 | if (rc) | ||
1170 | goto start_all_exit; | ||
1171 | |||
1172 | for_each_online_cpu(cpu) { | ||
1173 | rc = start_sampling(cpu); | ||
1174 | if (rc) | ||
1175 | break; | ||
1176 | } | ||
1177 | if (rc) { | ||
1178 | for_each_online_cpu(cpu) { | ||
1179 | stop_sampling(cpu); | ||
1180 | } | ||
1181 | goto start_all_exit; | ||
1182 | } | ||
1183 | hws_state = HWS_STARTED; | ||
1184 | rc = 0; | ||
1185 | |||
1186 | start_all_exit: | ||
1187 | mutex_unlock(&hws_sem); | ||
1188 | |||
1189 | if (rc) | ||
1190 | return rc; | ||
1191 | |||
1192 | register_oom_notifier(&hws_oom_notifier); | ||
1193 | hws_oom = 1; | ||
1194 | hws_flush_all = 0; | ||
1195 | /* now let them in, 1407 CPUMF external interrupts */ | ||
1196 | ctl_set_bit(0, 5); /* set CR0 bit 58 */ | ||
1197 | |||
1198 | return 0; | ||
1199 | } | ||
1200 | |||
1201 | /** | ||
1202 | * hwsampler_stop_all() - stop hardware sampling on all online CPUs | ||
1203 | * | ||
1204 | * Returns 0 on success, !0 on failure. | ||
1205 | */ | ||
1206 | int hwsampler_stop_all() | ||
1207 | { | ||
1208 | int tmp_rc, rc, cpu; | ||
1209 | struct hws_cpu_buffer *cb; | ||
1210 | |||
1211 | mutex_lock(&hws_sem); | ||
1212 | |||
1213 | rc = 0; | ||
1214 | if (hws_state == HWS_INIT) { | ||
1215 | mutex_unlock(&hws_sem); | ||
1216 | return rc; | ||
1217 | } | ||
1218 | hws_state = HWS_STOPPING; | ||
1219 | mutex_unlock(&hws_sem); | ||
1220 | |||
1221 | for_each_online_cpu(cpu) { | ||
1222 | cb = &per_cpu(sampler_cpu_buffer, cpu); | ||
1223 | cb->stop_mode = 1; | ||
1224 | tmp_rc = stop_sampling(cpu); | ||
1225 | if (tmp_rc) | ||
1226 | rc = tmp_rc; | ||
1227 | } | ||
1228 | |||
1229 | if (hws_wq) | ||
1230 | flush_workqueue(hws_wq); | ||
1231 | |||
1232 | mutex_lock(&hws_sem); | ||
1233 | if (hws_oom) { | ||
1234 | unregister_oom_notifier(&hws_oom_notifier); | ||
1235 | hws_oom = 0; | ||
1236 | } | ||
1237 | hws_state = HWS_STOPPED; | ||
1238 | mutex_unlock(&hws_sem); | ||
1239 | |||
1240 | return rc; | ||
1241 | } | ||
diff --git a/arch/s390/oprofile/hwsampler.h b/arch/s390/oprofile/hwsampler.h new file mode 100644 index 000000000000..1912f3bb190c --- /dev/null +++ b/arch/s390/oprofile/hwsampler.h | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * CPUMF HW sampler functions and internal structures | ||
3 | * | ||
4 | * Copyright IBM Corp. 2010 | ||
5 | * Author(s): Heinz Graalfs <graalfs@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #ifndef HWSAMPLER_H_ | ||
9 | #define HWSAMPLER_H_ | ||
10 | |||
11 | #include <linux/workqueue.h> | ||
12 | |||
13 | struct hws_qsi_info_block /* QUERY SAMPLING information block */ | ||
14 | { /* Bit(s) */ | ||
15 | unsigned int b0_13:14; /* 0-13: zeros */ | ||
16 | unsigned int as:1; /* 14: sampling authorisation control*/ | ||
17 | unsigned int b15_21:7; /* 15-21: zeros */ | ||
18 | unsigned int es:1; /* 22: sampling enable control */ | ||
19 | unsigned int b23_29:7; /* 23-29: zeros */ | ||
20 | unsigned int cs:1; /* 30: sampling activation control */ | ||
21 | unsigned int:1; /* 31: reserved */ | ||
22 | unsigned int bsdes:16; /* 4-5: size of sampling entry */ | ||
23 | unsigned int:16; /* 6-7: reserved */ | ||
24 | unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */ | ||
25 | unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/ | ||
26 | unsigned long tear; /* 24-31: TEAR contents */ | ||
27 | unsigned long dear; /* 32-39: DEAR contents */ | ||
28 | unsigned int rsvrd0; /* 40-43: reserved */ | ||
29 | unsigned int cpu_speed; /* 44-47: CPU speed */ | ||
30 | unsigned long long rsvrd1; /* 48-55: reserved */ | ||
31 | unsigned long long rsvrd2; /* 56-63: reserved */ | ||
32 | }; | ||
33 | |||
34 | struct hws_ssctl_request_block /* SET SAMPLING CONTROLS req block */ | ||
35 | { /* bytes 0 - 7 Bit(s) */ | ||
36 | unsigned int s:1; /* 0: maximum buffer indicator */ | ||
37 | unsigned int h:1; /* 1: part. level reserved for VM use*/ | ||
38 | unsigned long b2_53:52; /* 2-53: zeros */ | ||
39 | unsigned int es:1; /* 54: sampling enable control */ | ||
40 | unsigned int b55_61:7; /* 55-61: - zeros */ | ||
41 | unsigned int cs:1; /* 62: sampling activation control */ | ||
42 | unsigned int b63:1; /* 63: zero */ | ||
43 | unsigned long interval; /* 8-15: sampling interval */ | ||
44 | unsigned long tear; /* 16-23: TEAR contents */ | ||
45 | unsigned long dear; /* 24-31: DEAR contents */ | ||
46 | /* 32-63: */ | ||
47 | unsigned long rsvrd1; /* reserved */ | ||
48 | unsigned long rsvrd2; /* reserved */ | ||
49 | unsigned long rsvrd3; /* reserved */ | ||
50 | unsigned long rsvrd4; /* reserved */ | ||
51 | }; | ||
52 | |||
53 | struct hws_cpu_buffer { | ||
54 | unsigned long first_sdbt; /* @ of 1st SDB-Table for this CP*/ | ||
55 | unsigned long worker_entry; | ||
56 | unsigned long sample_overflow; /* taken from SDB ... */ | ||
57 | struct hws_qsi_info_block qsi; | ||
58 | struct hws_ssctl_request_block ssctl; | ||
59 | struct work_struct worker; | ||
60 | atomic_t ext_params; | ||
61 | unsigned long req_alert; | ||
62 | unsigned long loss_of_sample_data; | ||
63 | unsigned long invalid_entry_address; | ||
64 | unsigned long incorrect_sdbt_entry; | ||
65 | unsigned long sample_auth_change_alert; | ||
66 | unsigned int finish:1; | ||
67 | unsigned int oom:1; | ||
68 | unsigned int stop_mode:1; | ||
69 | }; | ||
70 | |||
71 | struct hws_data_entry { | ||
72 | unsigned int def:16; /* 0-15 Data Entry Format */ | ||
73 | unsigned int R:4; /* 16-19 reserved */ | ||
74 | unsigned int U:4; /* 20-23 Number of unique instruct. */ | ||
75 | unsigned int z:2; /* zeros */ | ||
76 | unsigned int T:1; /* 26 PSW DAT mode */ | ||
77 | unsigned int W:1; /* 27 PSW wait state */ | ||
78 | unsigned int P:1; /* 28 PSW Problem state */ | ||
79 | unsigned int AS:2; /* 29-30 PSW address-space control */ | ||
80 | unsigned int I:1; /* 31 entry valid or invalid */ | ||
81 | unsigned int:16; | ||
82 | unsigned int prim_asn:16; /* primary ASN */ | ||
83 | unsigned long long ia; /* Instruction Address */ | ||
84 | unsigned long long lpp; /* Logical-Partition Program Param. */ | ||
85 | unsigned long long vpp; /* Virtual-Machine Program Param. */ | ||
86 | }; | ||
87 | |||
88 | struct hws_trailer_entry { | ||
89 | unsigned int f:1; /* 0 - Block Full Indicator */ | ||
90 | unsigned int a:1; /* 1 - Alert request control */ | ||
91 | unsigned long:62; /* 2 - 63: Reserved */ | ||
92 | unsigned long overflow; /* 64 - sample Overflow count */ | ||
93 | unsigned long timestamp; /* 16 - time-stamp */ | ||
94 | unsigned long timestamp1; /* */ | ||
95 | unsigned long reserved1; /* 32 -Reserved */ | ||
96 | unsigned long reserved2; /* */ | ||
97 | unsigned long progusage1; /* 48 - reserved for programming use */ | ||
98 | unsigned long progusage2; /* */ | ||
99 | }; | ||
100 | |||
101 | int hwsampler_setup(void); | ||
102 | int hwsampler_shutdown(void); | ||
103 | int hwsampler_allocate(unsigned long sdbt, unsigned long sdb); | ||
104 | int hwsampler_deallocate(void); | ||
105 | unsigned long hwsampler_query_min_interval(void); | ||
106 | unsigned long hwsampler_query_max_interval(void); | ||
107 | int hwsampler_start_all(unsigned long interval); | ||
108 | int hwsampler_stop_all(void); | ||
109 | int hwsampler_deactivate(unsigned int cpu); | ||
110 | int hwsampler_activate(unsigned int cpu); | ||
111 | unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu); | ||
112 | |||
113 | #endif /*HWSAMPLER_H_*/ | ||
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index 7a995113b918..0e358c2cffeb 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c | |||
@@ -4,23 +4,195 @@ | |||
4 | * S390 Version | 4 | * S390 Version |
5 | * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation | 5 | * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation |
6 | * Author(s): Thomas Spatzier (tspat@de.ibm.com) | 6 | * Author(s): Thomas Spatzier (tspat@de.ibm.com) |
7 | * Author(s): Mahesh Salgaonkar (mahesh@linux.vnet.ibm.com) | ||
8 | * Author(s): Heinz Graalfs (graalfs@linux.vnet.ibm.com) | ||
7 | * | 9 | * |
8 | * @remark Copyright 2002 OProfile authors | 10 | * @remark Copyright 2002-2011 OProfile authors |
9 | */ | 11 | */ |
10 | 12 | ||
11 | #include <linux/oprofile.h> | 13 | #include <linux/oprofile.h> |
12 | #include <linux/init.h> | 14 | #include <linux/init.h> |
13 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/oprofile.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/fs.h> | ||
14 | 19 | ||
20 | #include "../../../drivers/oprofile/oprof.h" | ||
15 | 21 | ||
16 | extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); | 22 | extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); |
17 | 23 | ||
18 | int __init oprofile_arch_init(struct oprofile_operations* ops) | 24 | #ifdef CONFIG_64BIT |
25 | |||
26 | #include "hwsampler.h" | ||
27 | |||
28 | #define DEFAULT_INTERVAL 4127518 | ||
29 | |||
30 | #define DEFAULT_SDBT_BLOCKS 1 | ||
31 | #define DEFAULT_SDB_BLOCKS 511 | ||
32 | |||
33 | static unsigned long oprofile_hw_interval = DEFAULT_INTERVAL; | ||
34 | static unsigned long oprofile_min_interval; | ||
35 | static unsigned long oprofile_max_interval; | ||
36 | |||
37 | static unsigned long oprofile_sdbt_blocks = DEFAULT_SDBT_BLOCKS; | ||
38 | static unsigned long oprofile_sdb_blocks = DEFAULT_SDB_BLOCKS; | ||
39 | |||
40 | static int hwsampler_file; | ||
41 | static int hwsampler_running; /* start_mutex must be held to change */ | ||
42 | |||
43 | static struct oprofile_operations timer_ops; | ||
44 | |||
45 | static int oprofile_hwsampler_start(void) | ||
46 | { | ||
47 | int retval; | ||
48 | |||
49 | hwsampler_running = hwsampler_file; | ||
50 | |||
51 | if (!hwsampler_running) | ||
52 | return timer_ops.start(); | ||
53 | |||
54 | retval = hwsampler_allocate(oprofile_sdbt_blocks, oprofile_sdb_blocks); | ||
55 | if (retval) | ||
56 | return retval; | ||
57 | |||
58 | retval = hwsampler_start_all(oprofile_hw_interval); | ||
59 | if (retval) | ||
60 | hwsampler_deallocate(); | ||
61 | |||
62 | return retval; | ||
63 | } | ||
64 | |||
65 | static void oprofile_hwsampler_stop(void) | ||
66 | { | ||
67 | if (!hwsampler_running) { | ||
68 | timer_ops.stop(); | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | hwsampler_stop_all(); | ||
73 | hwsampler_deallocate(); | ||
74 | return; | ||
75 | } | ||
76 | |||
77 | static ssize_t hwsampler_read(struct file *file, char __user *buf, | ||
78 | size_t count, loff_t *offset) | ||
79 | { | ||
80 | return oprofilefs_ulong_to_user(hwsampler_file, buf, count, offset); | ||
81 | } | ||
82 | |||
83 | static ssize_t hwsampler_write(struct file *file, char const __user *buf, | ||
84 | size_t count, loff_t *offset) | ||
85 | { | ||
86 | unsigned long val; | ||
87 | int retval; | ||
88 | |||
89 | if (*offset) | ||
90 | return -EINVAL; | ||
91 | |||
92 | retval = oprofilefs_ulong_from_user(&val, buf, count); | ||
93 | if (retval) | ||
94 | return retval; | ||
95 | |||
96 | if (oprofile_started) | ||
97 | /* | ||
98 | * save to do without locking as we set | ||
99 | * hwsampler_running in start() when start_mutex is | ||
100 | * held | ||
101 | */ | ||
102 | return -EBUSY; | ||
103 | |||
104 | hwsampler_file = val; | ||
105 | |||
106 | return count; | ||
107 | } | ||
108 | |||
109 | static const struct file_operations hwsampler_fops = { | ||
110 | .read = hwsampler_read, | ||
111 | .write = hwsampler_write, | ||
112 | }; | ||
113 | |||
114 | static int oprofile_create_hwsampling_files(struct super_block *sb, | ||
115 | struct dentry *root) | ||
116 | { | ||
117 | struct dentry *hw_dir; | ||
118 | |||
119 | /* reinitialize default values */ | ||
120 | hwsampler_file = 1; | ||
121 | |||
122 | hw_dir = oprofilefs_mkdir(sb, root, "hwsampling"); | ||
123 | if (!hw_dir) | ||
124 | return -EINVAL; | ||
125 | |||
126 | oprofilefs_create_file(sb, hw_dir, "hwsampler", &hwsampler_fops); | ||
127 | oprofilefs_create_ulong(sb, hw_dir, "hw_interval", | ||
128 | &oprofile_hw_interval); | ||
129 | oprofilefs_create_ro_ulong(sb, hw_dir, "hw_min_interval", | ||
130 | &oprofile_min_interval); | ||
131 | oprofilefs_create_ro_ulong(sb, hw_dir, "hw_max_interval", | ||
132 | &oprofile_max_interval); | ||
133 | oprofilefs_create_ulong(sb, hw_dir, "hw_sdbt_blocks", | ||
134 | &oprofile_sdbt_blocks); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int oprofile_hwsampler_init(struct oprofile_operations *ops) | ||
140 | { | ||
141 | if (hwsampler_setup()) | ||
142 | return -ENODEV; | ||
143 | |||
144 | /* | ||
145 | * create hwsampler files only if hwsampler_setup() succeeds. | ||
146 | */ | ||
147 | oprofile_min_interval = hwsampler_query_min_interval(); | ||
148 | if (oprofile_min_interval == 0) | ||
149 | return -ENODEV; | ||
150 | oprofile_max_interval = hwsampler_query_max_interval(); | ||
151 | if (oprofile_max_interval == 0) | ||
152 | return -ENODEV; | ||
153 | |||
154 | /* The initial value should be sane */ | ||
155 | if (oprofile_hw_interval < oprofile_min_interval) | ||
156 | oprofile_hw_interval = oprofile_min_interval; | ||
157 | if (oprofile_hw_interval > oprofile_max_interval) | ||
158 | oprofile_hw_interval = oprofile_max_interval; | ||
159 | |||
160 | if (oprofile_timer_init(ops)) | ||
161 | return -ENODEV; | ||
162 | |||
163 | printk(KERN_INFO "oprofile: using hardware sampling\n"); | ||
164 | |||
165 | memcpy(&timer_ops, ops, sizeof(timer_ops)); | ||
166 | |||
167 | ops->start = oprofile_hwsampler_start; | ||
168 | ops->stop = oprofile_hwsampler_stop; | ||
169 | ops->create_files = oprofile_create_hwsampling_files; | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void oprofile_hwsampler_exit(void) | ||
175 | { | ||
176 | oprofile_timer_exit(); | ||
177 | hwsampler_shutdown(); | ||
178 | } | ||
179 | |||
180 | #endif /* CONFIG_64BIT */ | ||
181 | |||
182 | int __init oprofile_arch_init(struct oprofile_operations *ops) | ||
19 | { | 183 | { |
20 | ops->backtrace = s390_backtrace; | 184 | ops->backtrace = s390_backtrace; |
185 | |||
186 | #ifdef CONFIG_64BIT | ||
187 | return oprofile_hwsampler_init(ops); | ||
188 | #else | ||
21 | return -ENODEV; | 189 | return -ENODEV; |
190 | #endif | ||
22 | } | 191 | } |
23 | 192 | ||
24 | void oprofile_arch_exit(void) | 193 | void oprofile_arch_exit(void) |
25 | { | 194 | { |
195 | #ifdef CONFIG_64BIT | ||
196 | oprofile_hwsampler_exit(); | ||
197 | #endif | ||
26 | } | 198 | } |