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>
This commit is contained in:
Родитель
72f6e3a8bc
Коммит
fbe765680d
|
@ -302,12 +302,7 @@ struct _lowcore {
|
|||
*/
|
||||
__u64 ipib; /* 0x0e00 */
|
||||
__u32 ipib_checksum; /* 0x0e08 */
|
||||
/*
|
||||
* Because the vmcore_info pointer is not 8 byte aligned it never
|
||||
* should not be accessed directly. For accessing the pointer, first
|
||||
* copy it to a local pointer variable.
|
||||
*/
|
||||
__u8 vmcore_info[8]; /* 0x0e0c */
|
||||
__u64 vmcore_info; /* 0x0e0c */
|
||||
__u8 pad_0x0e14[0x0e18-0x0e14]; /* 0x0e14 */
|
||||
__u64 os_info; /* 0x0e18 */
|
||||
__u8 pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */
|
||||
|
|
|
@ -348,4 +348,14 @@ extern void (*s390_base_ext_handler_fn)(void);
|
|||
".previous\n"
|
||||
#endif
|
||||
|
||||
extern int memcpy_real(void *, void *, size_t);
|
||||
extern void memcpy_absolute(void *, void *, size_t);
|
||||
|
||||
#define mem_assign_absolute(dest, val) { \
|
||||
__typeof__(dest) __tmp = (val); \
|
||||
\
|
||||
BUILD_BUG_ON(sizeof(__tmp) != sizeof(val)); \
|
||||
memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \
|
||||
}
|
||||
|
||||
#endif /* __ASM_S390_PROCESSOR_H */
|
||||
|
|
|
@ -381,8 +381,6 @@ clear_user(void __user *to, unsigned long n)
|
|||
return n;
|
||||
}
|
||||
|
||||
extern int memcpy_real(void *, void *, size_t);
|
||||
extern void memcpy_absolute(void *, void *, size_t);
|
||||
extern int copy_to_user_real(void __user *dest, void *src, size_t count);
|
||||
extern int copy_from_user_real(void *dest, void __user *src, size_t count);
|
||||
|
||||
|
|
|
@ -131,6 +131,8 @@ int main(void)
|
|||
DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack));
|
||||
DEFINE(__LC_RESTART_STACK, offsetof(struct _lowcore, restart_stack));
|
||||
DEFINE(__LC_RESTART_FN, offsetof(struct _lowcore, restart_fn));
|
||||
DEFINE(__LC_RESTART_DATA, offsetof(struct _lowcore, restart_data));
|
||||
DEFINE(__LC_RESTART_SOURCE, offsetof(struct _lowcore, restart_source));
|
||||
DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));
|
||||
DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock));
|
||||
DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock));
|
||||
|
|
|
@ -724,7 +724,9 @@ ENTRY(restart_int_handler)
|
|||
mvc __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw
|
||||
ahi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack
|
||||
xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
|
||||
lm %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu
|
||||
l %r1,__LC_RESTART_FN # load fn, parm & source cpu
|
||||
l %r2,__LC_RESTART_DATA
|
||||
l %r3,__LC_RESTART_SOURCE
|
||||
ltr %r3,%r3 # test source cpu address
|
||||
jm 1f # negative -> skip source stop
|
||||
0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu
|
||||
|
|
|
@ -751,7 +751,9 @@ ENTRY(restart_int_handler)
|
|||
mvc __PT_PSW(16,%r15),__LC_RST_OLD_PSW # store restart old psw
|
||||
aghi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack
|
||||
xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
|
||||
lmg %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu
|
||||
lg %r1,__LC_RESTART_FN # load fn, parm & source cpu
|
||||
lg %r2,__LC_RESTART_DATA
|
||||
lg %r3,__LC_RESTART_SOURCE
|
||||
ltgr %r3,%r3 # test source cpu address
|
||||
jm 1f # negative -> skip source stop
|
||||
0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu
|
||||
|
|
|
@ -1528,15 +1528,12 @@ static struct shutdown_action __refdata dump_action = {
|
|||
|
||||
static void dump_reipl_run(struct shutdown_trigger *trigger)
|
||||
{
|
||||
struct {
|
||||
void *addr;
|
||||
__u32 csum;
|
||||
} __packed ipib;
|
||||
unsigned long ipib = (unsigned long) &reipl_block_actual;
|
||||
unsigned int csum;
|
||||
|
||||
ipib.csum = csum_partial(reipl_block_actual,
|
||||
reipl_block_actual->hdr.len, 0);
|
||||
ipib.addr = reipl_block_actual;
|
||||
memcpy_absolute(&S390_lowcore.ipib, &ipib, sizeof(ipib));
|
||||
csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0);
|
||||
mem_assign_absolute(S390_lowcore.ipib, ipib);
|
||||
mem_assign_absolute(S390_lowcore.ipib_checksum, csum);
|
||||
dump_run(trigger);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ void __init os_info_init(void)
|
|||
os_info.version_minor = OS_INFO_VERSION_MINOR;
|
||||
os_info.magic = OS_INFO_MAGIC;
|
||||
os_info.csum = os_info_csum(&os_info);
|
||||
memcpy_absolute(&S390_lowcore.os_info, &ptr, sizeof(ptr));
|
||||
mem_assign_absolute(S390_lowcore.os_info, (unsigned long) ptr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
|
|
|
@ -430,10 +430,11 @@ static void __init setup_lowcore(void)
|
|||
lc->restart_source = -1UL;
|
||||
|
||||
/* Setup absolute zero lowcore */
|
||||
memcpy_absolute(&S390_lowcore.restart_stack, &lc->restart_stack,
|
||||
4 * sizeof(unsigned long));
|
||||
memcpy_absolute(&S390_lowcore.restart_psw, &lc->restart_psw,
|
||||
sizeof(lc->restart_psw));
|
||||
mem_assign_absolute(S390_lowcore.restart_stack, lc->restart_stack);
|
||||
mem_assign_absolute(S390_lowcore.restart_fn, lc->restart_fn);
|
||||
mem_assign_absolute(S390_lowcore.restart_data, lc->restart_data);
|
||||
mem_assign_absolute(S390_lowcore.restart_source, lc->restart_source);
|
||||
mem_assign_absolute(S390_lowcore.restart_psw, lc->restart_psw);
|
||||
|
||||
set_prefix((u32)(unsigned long) lc);
|
||||
lowcore_ptr[0] = lc;
|
||||
|
@ -598,9 +599,7 @@ static void __init setup_memory_end(void)
|
|||
static void __init setup_vmcoreinfo(void)
|
||||
{
|
||||
#ifdef CONFIG_KEXEC
|
||||
unsigned long ptr = paddr_vmcoreinfo_note();
|
||||
|
||||
memcpy_absolute(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr));
|
||||
mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -273,26 +273,24 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *),
|
|||
void *data, unsigned long stack)
|
||||
{
|
||||
struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices];
|
||||
struct {
|
||||
unsigned long stack;
|
||||
void *func;
|
||||
void *data;
|
||||
unsigned long source;
|
||||
} restart = { stack, func, data, stap() };
|
||||
unsigned long source_cpu = stap();
|
||||
|
||||
__load_psw_mask(psw_kernel_bits);
|
||||
if (pcpu->address == restart.source)
|
||||
if (pcpu->address == source_cpu)
|
||||
func(data); /* should not return */
|
||||
/* Stop target cpu (if func returns this stops the current cpu). */
|
||||
pcpu_sigp_retry(pcpu, SIGP_STOP, 0);
|
||||
/* Restart func on the target cpu and stop the current cpu. */
|
||||
memcpy_absolute(&lc->restart_stack, &restart, sizeof(restart));
|
||||
mem_assign_absolute(lc->restart_stack, stack);
|
||||
mem_assign_absolute(lc->restart_fn, (unsigned long) func);
|
||||
mem_assign_absolute(lc->restart_data, (unsigned long) data);
|
||||
mem_assign_absolute(lc->restart_source, source_cpu);
|
||||
asm volatile(
|
||||
"0: sigp 0,%0,%2 # sigp restart to target cpu\n"
|
||||
" brc 2,0b # busy, try again\n"
|
||||
"1: sigp 0,%1,%3 # sigp stop to current cpu\n"
|
||||
" brc 2,1b # busy, try again\n"
|
||||
: : "d" (pcpu->address), "d" (restart.source),
|
||||
: : "d" (pcpu->address), "d" (source_cpu),
|
||||
"K" (SIGP_RESTART), "K" (SIGP_STOP)
|
||||
: "0", "1", "cc");
|
||||
for (;;) ;
|
||||
|
|
Загрузка…
Ссылка в новой задаче