aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2012-06-05 03:59:52 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-06-14 03:09:02 -0400
commitfbe765680d1fe9d08187ea4dad5041a7955a2c3a (patch)
treecfa5ba11106bb5535552cf6b29ff6aa81f32c606
parent72f6e3a8bc956fddf6e004ae9b804977d1458e77 (diff)
s390/smp: make absolute lowcore / cpu restart parameter accesses more robust
Setting the cpu restart parameters is done in three different fashions: - directly setting the four parameters individually - copying the four parameters with memcpy (using 4 * sizeof(long)) - copying the four parameters using a private structure In addition code in entry*.S relies on a certain order of the restart members of struct _lowcore. Make all of this more robust to future changes by adding a mem_absolute_assign(dest, val) define, which assigns val to dest using absolute addressing mode. Also the load multiple instructions in entry*.S have been split into separate load instruction so the order of the struct _lowcore members doesn't matter anymore. In addition move the prototypes of memcpy_real/absolute from uaccess.h to processor.h. These memcpy* variants are not related to uaccess at all. string.h doesn't seem to match as well, so lets use processor.h. Also replace the eight byte array in struct _lowcore which represents a misaliged u64 with a u64. The compiler will always create code that handles the misaligned u64 correctly. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/lowcore.h7
-rw-r--r--arch/s390/include/asm/processor.h10
-rw-r--r--arch/s390/include/asm/uaccess.h2
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/entry.S4
-rw-r--r--arch/s390/kernel/entry64.S4
-rw-r--r--arch/s390/kernel/ipl.c15
-rw-r--r--arch/s390/kernel/os_info.c2
-rw-r--r--arch/s390/kernel/setup.c13
-rw-r--r--arch/s390/kernel/smp.c16
10 files changed, 39 insertions, 36 deletions
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 47853debb3b9..a47c6e221a95 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -302,12 +302,7 @@ struct _lowcore {
302 */ 302 */
303 __u64 ipib; /* 0x0e00 */ 303 __u64 ipib; /* 0x0e00 */
304 __u32 ipib_checksum; /* 0x0e08 */ 304 __u32 ipib_checksum; /* 0x0e08 */
305 /* 305 __u64 vmcore_info; /* 0x0e0c */
306 * Because the vmcore_info pointer is not 8 byte aligned it never
307 * should not be accessed directly. For accessing the pointer, first
308 * copy it to a local pointer variable.
309 */
310 __u8 vmcore_info[8]; /* 0x0e0c */
311 __u8 pad_0x0e14[0x0e18-0x0e14]; /* 0x0e14 */ 306 __u8 pad_0x0e14[0x0e18-0x0e14]; /* 0x0e14 */
312 __u64 os_info; /* 0x0e18 */ 307 __u64 os_info; /* 0x0e18 */
313 __u8 pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */ 308 __u8 pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 20d0585cf905..f1700c5c8884 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -348,4 +348,14 @@ extern void (*s390_base_ext_handler_fn)(void);
348 ".previous\n" 348 ".previous\n"
349#endif 349#endif
350 350
351extern int memcpy_real(void *, void *, size_t);
352extern void memcpy_absolute(void *, void *, size_t);
353
354#define mem_assign_absolute(dest, val) { \
355 __typeof__(dest) __tmp = (val); \
356 \
357 BUILD_BUG_ON(sizeof(__tmp) != sizeof(val)); \
358 memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \
359}
360
351#endif /* __ASM_S390_PROCESSOR_H */ 361#endif /* __ASM_S390_PROCESSOR_H */
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 1f3a79bcd262..7e7285179aad 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -381,8 +381,6 @@ clear_user(void __user *to, unsigned long n)
381 return n; 381 return n;
382} 382}
383 383
384extern int memcpy_real(void *, void *, size_t);
385extern void memcpy_absolute(void *, void *, size_t);
386extern int copy_to_user_real(void __user *dest, void *src, size_t count); 384extern int copy_to_user_real(void __user *dest, void *src, size_t count);
387extern int copy_from_user_real(void *dest, void __user *src, size_t count); 385extern int copy_from_user_real(void *dest, void __user *src, size_t count);
388 386
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 83e6edf5cf17..0e974ddd156b 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -131,6 +131,8 @@ int main(void)
131 DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack)); 131 DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack));
132 DEFINE(__LC_RESTART_STACK, offsetof(struct _lowcore, restart_stack)); 132 DEFINE(__LC_RESTART_STACK, offsetof(struct _lowcore, restart_stack));
133 DEFINE(__LC_RESTART_FN, offsetof(struct _lowcore, restart_fn)); 133 DEFINE(__LC_RESTART_FN, offsetof(struct _lowcore, restart_fn));
134 DEFINE(__LC_RESTART_DATA, offsetof(struct _lowcore, restart_data));
135 DEFINE(__LC_RESTART_SOURCE, offsetof(struct _lowcore, restart_source));
134 DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); 136 DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));
135 DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); 137 DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock));
136 DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); 138 DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock));
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 3787f9e6907a..4ea53cd7c8c3 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -724,7 +724,9 @@ ENTRY(restart_int_handler)
724 mvc __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw 724 mvc __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw
725 ahi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack 725 ahi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack
726 xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15) 726 xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
727 lm %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu 727 l %r1,__LC_RESTART_FN # load fn, parm & source cpu
728 l %r2,__LC_RESTART_DATA
729 l %r3,__LC_RESTART_SOURCE
728 ltr %r3,%r3 # test source cpu address 730 ltr %r3,%r3 # test source cpu address
729 jm 1f # negative -> skip source stop 731 jm 1f # negative -> skip source stop
7300: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu 7320: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index d5f02e480e51..2813e831ba32 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -751,7 +751,9 @@ ENTRY(restart_int_handler)
751 mvc __PT_PSW(16,%r15),__LC_RST_OLD_PSW # store restart old psw 751 mvc __PT_PSW(16,%r15),__LC_RST_OLD_PSW # store restart old psw
752 aghi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack 752 aghi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack
753 xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15) 753 xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
754 lmg %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu 754 lg %r1,__LC_RESTART_FN # load fn, parm & source cpu
755 lg %r2,__LC_RESTART_DATA
756 lg %r3,__LC_RESTART_SOURCE
755 ltgr %r3,%r3 # test source cpu address 757 ltgr %r3,%r3 # test source cpu address
756 jm 1f # negative -> skip source stop 758 jm 1f # negative -> skip source stop
7570: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu 7590: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 2f6cfd460cb6..25241cd8ddd8 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -1528,15 +1528,12 @@ static struct shutdown_action __refdata dump_action = {
1528 1528
1529static void dump_reipl_run(struct shutdown_trigger *trigger) 1529static void dump_reipl_run(struct shutdown_trigger *trigger)
1530{ 1530{
1531 struct { 1531 unsigned long ipib = (unsigned long) &reipl_block_actual;
1532 void *addr; 1532 unsigned int csum;
1533 __u32 csum; 1533
1534 } __packed ipib; 1534 csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0);
1535 1535 mem_assign_absolute(S390_lowcore.ipib, ipib);
1536 ipib.csum = csum_partial(reipl_block_actual, 1536 mem_assign_absolute(S390_lowcore.ipib_checksum, csum);
1537 reipl_block_actual->hdr.len, 0);
1538 ipib.addr = reipl_block_actual;
1539 memcpy_absolute(&S390_lowcore.ipib, &ipib, sizeof(ipib));
1540 dump_run(trigger); 1537 dump_run(trigger);
1541} 1538}
1542 1539
diff --git a/arch/s390/kernel/os_info.c b/arch/s390/kernel/os_info.c
index 95fa5ac6c4ce..46480d81df00 100644
--- a/arch/s390/kernel/os_info.c
+++ b/arch/s390/kernel/os_info.c
@@ -60,7 +60,7 @@ void __init os_info_init(void)
60 os_info.version_minor = OS_INFO_VERSION_MINOR; 60 os_info.version_minor = OS_INFO_VERSION_MINOR;
61 os_info.magic = OS_INFO_MAGIC; 61 os_info.magic = OS_INFO_MAGIC;
62 os_info.csum = os_info_csum(&os_info); 62 os_info.csum = os_info_csum(&os_info);
63 memcpy_absolute(&S390_lowcore.os_info, &ptr, sizeof(ptr)); 63 mem_assign_absolute(S390_lowcore.os_info, (unsigned long) ptr);
64} 64}
65 65
66#ifdef CONFIG_CRASH_DUMP 66#ifdef CONFIG_CRASH_DUMP
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 489d1d8d96b0..49158cb19274 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -430,10 +430,11 @@ static void __init setup_lowcore(void)
430 lc->restart_source = -1UL; 430 lc->restart_source = -1UL;
431 431
432 /* Setup absolute zero lowcore */ 432 /* Setup absolute zero lowcore */
433 memcpy_absolute(&S390_lowcore.restart_stack, &lc->restart_stack, 433 mem_assign_absolute(S390_lowcore.restart_stack, lc->restart_stack);
434 4 * sizeof(unsigned long)); 434 mem_assign_absolute(S390_lowcore.restart_fn, lc->restart_fn);
435 memcpy_absolute(&S390_lowcore.restart_psw, &lc->restart_psw, 435 mem_assign_absolute(S390_lowcore.restart_data, lc->restart_data);
436 sizeof(lc->restart_psw)); 436 mem_assign_absolute(S390_lowcore.restart_source, lc->restart_source);
437 mem_assign_absolute(S390_lowcore.restart_psw, lc->restart_psw);
437 438
438 set_prefix((u32)(unsigned long) lc); 439 set_prefix((u32)(unsigned long) lc);
439 lowcore_ptr[0] = lc; 440 lowcore_ptr[0] = lc;
@@ -598,9 +599,7 @@ static void __init setup_memory_end(void)
598static void __init setup_vmcoreinfo(void) 599static void __init setup_vmcoreinfo(void)
599{ 600{
600#ifdef CONFIG_KEXEC 601#ifdef CONFIG_KEXEC
601 unsigned long ptr = paddr_vmcoreinfo_note(); 602 mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
602
603 memcpy_absolute(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr));
604#endif 603#endif
605} 604}
606 605
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index e01408429ad6..dc602a61233f 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -273,26 +273,24 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *),
273 void *data, unsigned long stack) 273 void *data, unsigned long stack)
274{ 274{
275 struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices]; 275 struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices];
276 struct { 276 unsigned long source_cpu = stap();
277 unsigned long stack;
278 void *func;
279 void *data;
280 unsigned long source;
281 } restart = { stack, func, data, stap() };
282 277
283 __load_psw_mask(psw_kernel_bits); 278 __load_psw_mask(psw_kernel_bits);
284 if (pcpu->address == restart.source) 279 if (pcpu->address == source_cpu)
285 func(data); /* should not return */ 280 func(data); /* should not return */
286 /* Stop target cpu (if func returns this stops the current cpu). */ 281 /* Stop target cpu (if func returns this stops the current cpu). */
287 pcpu_sigp_retry(pcpu, SIGP_STOP, 0); 282 pcpu_sigp_retry(pcpu, SIGP_STOP, 0);
288 /* Restart func on the target cpu and stop the current cpu. */ 283 /* Restart func on the target cpu and stop the current cpu. */
289 memcpy_absolute(&lc->restart_stack, &restart, sizeof(restart)); 284 mem_assign_absolute(lc->restart_stack, stack);
285 mem_assign_absolute(lc->restart_fn, (unsigned long) func);
286 mem_assign_absolute(lc->restart_data, (unsigned long) data);
287 mem_assign_absolute(lc->restart_source, source_cpu);
290 asm volatile( 288 asm volatile(
291 "0: sigp 0,%0,%2 # sigp restart to target cpu\n" 289 "0: sigp 0,%0,%2 # sigp restart to target cpu\n"
292 " brc 2,0b # busy, try again\n" 290 " brc 2,0b # busy, try again\n"
293 "1: sigp 0,%1,%3 # sigp stop to current cpu\n" 291 "1: sigp 0,%1,%3 # sigp stop to current cpu\n"
294 " brc 2,1b # busy, try again\n" 292 " brc 2,1b # busy, try again\n"
295 : : "d" (pcpu->address), "d" (restart.source), 293 : : "d" (pcpu->address), "d" (source_cpu),
296 "K" (SIGP_RESTART), "K" (SIGP_STOP) 294 "K" (SIGP_RESTART), "K" (SIGP_STOP)
297 : "0", "1", "cc"); 295 : "0", "1", "cc");
298 for (;;) ; 296 for (;;) ;