Commit 3fb4f979 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 's390-5.12-6' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Heiko Carstens:

 - fix incorrect dereference of the ext_params2 external interrupt
   parameter, which leads to an instant kernel crash if a pfault
   interrupt occurs.

 - add forgotten stack unwinder support, and fix memory leak for the
   new machine check handler stack.

 - fix inline assembly register clobbering due to KASAN code
   instrumentation.

* tag 's390-5.12-6' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/setup: use memblock_free_late() to free old stack
  s390/irq: fix reading of ext_params2 field from lowcore
  s390/unwind: add machine check handler stack
  s390/cpcmd: fix inline assembly register clobbering
parents e0a472ff ad31a8c0
...@@ -12,6 +12,7 @@ enum stack_type { ...@@ -12,6 +12,7 @@ enum stack_type {
STACK_TYPE_IRQ, STACK_TYPE_IRQ,
STACK_TYPE_NODAT, STACK_TYPE_NODAT,
STACK_TYPE_RESTART, STACK_TYPE_RESTART,
STACK_TYPE_MCCK,
}; };
struct stack_info { struct stack_info {
......
...@@ -37,10 +37,12 @@ static int diag8_noresponse(int cmdlen) ...@@ -37,10 +37,12 @@ static int diag8_noresponse(int cmdlen)
static int diag8_response(int cmdlen, char *response, int *rlen) static int diag8_response(int cmdlen, char *response, int *rlen)
{ {
unsigned long _cmdlen = cmdlen | 0x40000000L;
unsigned long _rlen = *rlen;
register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
register unsigned long reg3 asm ("3") = (addr_t) response; register unsigned long reg3 asm ("3") = (addr_t) response;
register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L; register unsigned long reg4 asm ("4") = _cmdlen;
register unsigned long reg5 asm ("5") = *rlen; register unsigned long reg5 asm ("5") = _rlen;
asm volatile( asm volatile(
" diag %2,%0,0x8\n" " diag %2,%0,0x8\n"
......
...@@ -79,6 +79,15 @@ static bool in_nodat_stack(unsigned long sp, struct stack_info *info) ...@@ -79,6 +79,15 @@ static bool in_nodat_stack(unsigned long sp, struct stack_info *info)
return in_stack(sp, info, STACK_TYPE_NODAT, top - THREAD_SIZE, top); return in_stack(sp, info, STACK_TYPE_NODAT, top - THREAD_SIZE, top);
} }
static bool in_mcck_stack(unsigned long sp, struct stack_info *info)
{
unsigned long frame_size, top;
frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
top = S390_lowcore.mcck_stack + frame_size;
return in_stack(sp, info, STACK_TYPE_MCCK, top - THREAD_SIZE, top);
}
static bool in_restart_stack(unsigned long sp, struct stack_info *info) static bool in_restart_stack(unsigned long sp, struct stack_info *info)
{ {
unsigned long frame_size, top; unsigned long frame_size, top;
...@@ -108,7 +117,8 @@ int get_stack_info(unsigned long sp, struct task_struct *task, ...@@ -108,7 +117,8 @@ int get_stack_info(unsigned long sp, struct task_struct *task,
/* Check per-cpu stacks */ /* Check per-cpu stacks */
if (!in_irq_stack(sp, info) && if (!in_irq_stack(sp, info) &&
!in_nodat_stack(sp, info) && !in_nodat_stack(sp, info) &&
!in_restart_stack(sp, info)) !in_restart_stack(sp, info) &&
!in_mcck_stack(sp, info))
goto unknown; goto unknown;
recursion_check: recursion_check:
......
...@@ -174,7 +174,7 @@ void noinstr do_ext_irq(struct pt_regs *regs) ...@@ -174,7 +174,7 @@ void noinstr do_ext_irq(struct pt_regs *regs)
memcpy(&regs->int_code, &S390_lowcore.ext_cpu_addr, 4); memcpy(&regs->int_code, &S390_lowcore.ext_cpu_addr, 4);
regs->int_parm = S390_lowcore.ext_params; regs->int_parm = S390_lowcore.ext_params;
regs->int_parm_long = *(unsigned long *)S390_lowcore.ext_params2; regs->int_parm_long = S390_lowcore.ext_params2;
from_idle = !user_mode(regs) && regs->psw.addr == (unsigned long)psw_idle_exit; from_idle = !user_mode(regs) && regs->psw.addr == (unsigned long)psw_idle_exit;
if (from_idle) if (from_idle)
......
...@@ -354,7 +354,7 @@ static int __init stack_realloc(void) ...@@ -354,7 +354,7 @@ static int __init stack_realloc(void)
if (!new) if (!new)
panic("Couldn't allocate machine check stack"); panic("Couldn't allocate machine check stack");
WRITE_ONCE(S390_lowcore.mcck_stack, new + STACK_INIT_OFFSET); WRITE_ONCE(S390_lowcore.mcck_stack, new + STACK_INIT_OFFSET);
memblock_free(old, THREAD_SIZE); memblock_free_late(old, THREAD_SIZE);
return 0; return 0;
} }
early_initcall(stack_realloc); early_initcall(stack_realloc);
......
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