Commit 2d1b21ec authored by Alexander Gordeev's avatar Alexander Gordeev Committed by Vasily Gorbik

s390/kdump: remove nodat stack restriction for calling nodat functions

To allow calling of DAT-off code from kernel the stack needs
to be switched to nodat_stack (or other stack mapped as 1:1).

Before call_nodat() macro was introduced that was necessary
to provide the very same memory address for STNSM and STOSM
instructions. If the kernel would stay on a random stack
(e.g. a virtually mapped one) then a virtual address provided
for STNSM instruction could differ from the physical address
needed for the corresponding STOSM instruction.

After call_nodat() macro is introduced the kernel stack does
not need to be mapped 1:1 anymore, since the macro stores the
physical memory address of return PSW in a register before
entering DAT-off mode. This way the return LPSWE instruction
is able to pick the correct memory location and restore the
DAT-on mode. That however might fail in case the 16-byte return
PSW happened to cross page boundary: PSW mask and PSW address
could end up in two separate non-contiguous physical pages.

Align the return PSW on 16-byte boundary so it always fits
into a single physical page. As result any stack (including
the virtually mapped one) could be used for calling DAT-off
code and prior switching to nodat_stack becomes unnecessary.
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
Reviewed-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 82caf7ab
...@@ -210,7 +210,9 @@ static __always_inline unsigned long get_stack_pointer(struct task_struct *task, ...@@ -210,7 +210,9 @@ static __always_inline unsigned long get_stack_pointer(struct task_struct *task,
#define call_nodat(nr, rettype, fn, ...) \ #define call_nodat(nr, rettype, fn, ...) \
({ \ ({ \
rettype (*__fn)(CALL_PARM_##nr(__VA_ARGS__)) = (fn); \ rettype (*__fn)(CALL_PARM_##nr(__VA_ARGS__)) = (fn); \
psw_t psw_enter, psw_leave; \ /* aligned since psw_leave must not cross page boundary */ \
psw_t __aligned(16) psw_leave; \
psw_t psw_enter; \
CALL_LARGS_##nr(__VA_ARGS__); \ CALL_LARGS_##nr(__VA_ARGS__); \
CALL_REGS_##nr; \ CALL_REGS_##nr; \
\ \
......
...@@ -112,13 +112,6 @@ static noinline void __machine_kdump(void *image) ...@@ -112,13 +112,6 @@ static noinline void __machine_kdump(void *image)
store_status(__do_machine_kdump, image); store_status(__do_machine_kdump, image);
} }
static int do_start_kdump(struct kimage *image)
{
purgatory_t purgatory = (purgatory_t)image->start;
return call_nodat(1, int, purgatory, int, 0);
}
#endif /* CONFIG_CRASH_DUMP */ #endif /* CONFIG_CRASH_DUMP */
/* /*
...@@ -127,12 +120,10 @@ static int do_start_kdump(struct kimage *image) ...@@ -127,12 +120,10 @@ static int do_start_kdump(struct kimage *image)
static bool kdump_csum_valid(struct kimage *image) static bool kdump_csum_valid(struct kimage *image)
{ {
#ifdef CONFIG_CRASH_DUMP #ifdef CONFIG_CRASH_DUMP
purgatory_t purgatory = (purgatory_t)image->start;
int rc; int rc;
preempt_disable(); rc = call_nodat(1, int, purgatory, int, 0);
rc = call_on_stack(1, S390_lowcore.nodat_stack, int, do_start_kdump,
struct kimage *, image);
preempt_enable();
return rc == 0; return rc == 0;
#else #else
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment