Commit 3fb4f979 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ enum stack_type {
	STACK_TYPE_IRQ,
	STACK_TYPE_NODAT,
	STACK_TYPE_RESTART,
	STACK_TYPE_MCCK,
};

struct stack_info {
+4 −2
Original line number Diff line number Diff line
@@ -37,10 +37,12 @@ static int diag8_noresponse(int cmdlen)

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 reg3 asm ("3") = (addr_t) response;
	register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
	register unsigned long reg5 asm ("5") = *rlen;
	register unsigned long reg4 asm ("4") = _cmdlen;
	register unsigned long reg5 asm ("5") = _rlen;

	asm volatile(
		"	diag	%2,%0,0x8\n"
+11 −1
Original line number Diff line number Diff line
@@ -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);
}

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)
{
	unsigned long frame_size, top;
@@ -108,7 +117,8 @@ int get_stack_info(unsigned long sp, struct task_struct *task,
	/* Check per-cpu stacks */
	if (!in_irq_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;

recursion_check:
+1 −1
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ void noinstr do_ext_irq(struct pt_regs *regs)

	memcpy(&regs->int_code, &S390_lowcore.ext_cpu_addr, 4);
	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;
	if (from_idle)
+1 −1
Original line number Diff line number Diff line
@@ -354,7 +354,7 @@ static int __init stack_realloc(void)
	if (!new)
		panic("Couldn't allocate machine check stack");
	WRITE_ONCE(S390_lowcore.mcck_stack, new + STACK_INIT_OFFSET);
	memblock_free(old, THREAD_SIZE);
	memblock_free_late(old, THREAD_SIZE);
	return 0;
}
early_initcall(stack_realloc);