Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Heiko Carstens and committed by
Martin Schwidefsky
fbe76568 72f6e3a8

+38 -35
+1 -6
arch/s390/include/asm/lowcore.h
··· 302 302 */ 303 303 __u64 ipib; /* 0x0e00 */ 304 304 __u32 ipib_checksum; /* 0x0e08 */ 305 - /* 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 */ 305 + __u64 vmcore_info; /* 0x0e0c */ 311 306 __u8 pad_0x0e14[0x0e18-0x0e14]; /* 0x0e14 */ 312 307 __u64 os_info; /* 0x0e18 */ 313 308 __u8 pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */
+10
arch/s390/include/asm/processor.h
··· 348 348 ".previous\n" 349 349 #endif 350 350 351 + extern int memcpy_real(void *, void *, size_t); 352 + extern 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 361 #endif /* __ASM_S390_PROCESSOR_H */
-2
arch/s390/include/asm/uaccess.h
··· 381 381 return n; 382 382 } 383 383 384 - extern int memcpy_real(void *, void *, size_t); 385 - extern void memcpy_absolute(void *, void *, size_t); 386 384 extern int copy_to_user_real(void __user *dest, void *src, size_t count); 387 385 extern int copy_from_user_real(void *dest, void __user *src, size_t count); 388 386
+2
arch/s390/kernel/asm-offsets.c
··· 131 131 DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack)); 132 132 DEFINE(__LC_RESTART_STACK, offsetof(struct _lowcore, restart_stack)); 133 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 136 DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); 135 137 DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); 136 138 DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock));
+3 -1
arch/s390/kernel/entry.S
··· 724 724 mvc __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw 725 725 ahi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack 726 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 730 ltr %r3,%r3 # test source cpu address 729 731 jm 1f # negative -> skip source stop 730 732 0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu
+3 -1
arch/s390/kernel/entry64.S
··· 751 751 mvc __PT_PSW(16,%r15),__LC_RST_OLD_PSW # store restart old psw 752 752 aghi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack 753 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 757 ltgr %r3,%r3 # test source cpu address 756 758 jm 1f # negative -> skip source stop 757 759 0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu
+5 -8
arch/s390/kernel/ipl.c
··· 1528 1528 1529 1529 static void dump_reipl_run(struct shutdown_trigger *trigger) 1530 1530 { 1531 - struct { 1532 - void *addr; 1533 - __u32 csum; 1534 - } __packed ipib; 1531 + unsigned long ipib = (unsigned long) &reipl_block_actual; 1532 + unsigned int csum; 1535 1533 1536 - ipib.csum = csum_partial(reipl_block_actual, 1537 - reipl_block_actual->hdr.len, 0); 1538 - ipib.addr = reipl_block_actual; 1539 - memcpy_absolute(&S390_lowcore.ipib, &ipib, sizeof(ipib)); 1534 + csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0); 1535 + mem_assign_absolute(S390_lowcore.ipib, ipib); 1536 + mem_assign_absolute(S390_lowcore.ipib_checksum, csum); 1540 1537 dump_run(trigger); 1541 1538 } 1542 1539
+1 -1
arch/s390/kernel/os_info.c
··· 60 60 os_info.version_minor = OS_INFO_VERSION_MINOR; 61 61 os_info.magic = OS_INFO_MAGIC; 62 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 66 #ifdef CONFIG_CRASH_DUMP
+6 -7
arch/s390/kernel/setup.c
··· 430 430 lc->restart_source = -1UL; 431 431 432 432 /* Setup absolute zero lowcore */ 433 - memcpy_absolute(&S390_lowcore.restart_stack, &lc->restart_stack, 434 - 4 * sizeof(unsigned long)); 435 - memcpy_absolute(&S390_lowcore.restart_psw, &lc->restart_psw, 436 - sizeof(lc->restart_psw)); 433 + mem_assign_absolute(S390_lowcore.restart_stack, lc->restart_stack); 434 + mem_assign_absolute(S390_lowcore.restart_fn, lc->restart_fn); 435 + mem_assign_absolute(S390_lowcore.restart_data, lc->restart_data); 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 439 set_prefix((u32)(unsigned long) lc); 439 440 lowcore_ptr[0] = lc; ··· 599 598 static void __init setup_vmcoreinfo(void) 600 599 { 601 600 #ifdef CONFIG_KEXEC 602 - unsigned long ptr = paddr_vmcoreinfo_note(); 603 - 604 - memcpy_absolute(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr)); 601 + mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note()); 605 602 #endif 606 603 } 607 604
+7 -9
arch/s390/kernel/smp.c
··· 273 273 void *data, unsigned long stack) 274 274 { 275 275 struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices]; 276 - struct { 277 - unsigned long stack; 278 - void *func; 279 - void *data; 280 - unsigned long source; 281 - } restart = { stack, func, data, stap() }; 276 + unsigned long source_cpu = stap(); 282 277 283 278 __load_psw_mask(psw_kernel_bits); 284 - if (pcpu->address == restart.source) 279 + if (pcpu->address == source_cpu) 285 280 func(data); /* should not return */ 286 281 /* Stop target cpu (if func returns this stops the current cpu). */ 287 282 pcpu_sigp_retry(pcpu, SIGP_STOP, 0); 288 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 288 asm volatile( 291 289 "0: sigp 0,%0,%2 # sigp restart to target cpu\n" 292 290 " brc 2,0b # busy, try again\n" 293 291 "1: sigp 0,%1,%3 # sigp stop to current cpu\n" 294 292 " brc 2,1b # busy, try again\n" 295 - : : "d" (pcpu->address), "d" (restart.source), 293 + : : "d" (pcpu->address), "d" (source_cpu), 296 294 "K" (SIGP_RESTART), "K" (SIGP_STOP) 297 295 : "0", "1", "cc"); 298 296 for (;;) ;