Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58c1f995 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sparc fixes from David Miller:
 "sparc64 mmu context allocation and trap return bug fixes"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc:
  sparc64: Fix return from trap window fill crashes.
  sparc: Harden signal return frame checks.
  sparc64: Take ctx_alloc_lock properly in hugetlb_setup().
parents 367d3fd5 7cafc0b8
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -15,6 +15,10 @@

#define	PTREGS_OFF	(STACK_BIAS + STACKFRAME_SZ)

#define	RTRAP_PSTATE		(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
#define	RTRAP_PSTATE_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
#define RTRAP_PSTATE_AG_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)

#define __CHEETAH_ID	0x003e0014
#define __JALAPENO_ID	0x003e0016
#define __SERRANO_ID	0x003e0022
+4 −4
Original line number Diff line number Diff line
@@ -589,8 +589,8 @@ user_rtt_fill_64bit: \
	 restored;					\
	nop; nop; nop; nop; nop; nop;			\
	nop; nop; nop; nop; nop;			\
	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
	ba,a,pt	%xcc, user_rtt_fill_fixup_dax;		\
	ba,a,pt	%xcc, user_rtt_fill_fixup_mna;		\
	ba,a,pt	%xcc, user_rtt_fill_fixup;


@@ -652,8 +652,8 @@ user_rtt_fill_32bit: \
	 restored;					\
	nop; nop; nop; nop; nop;			\
	nop; nop; nop;					\
	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
	ba,a,pt	%xcc, user_rtt_fill_fixup_dax;		\
	ba,a,pt	%xcc, user_rtt_fill_fixup_mna;		\
	ba,a,pt	%xcc, user_rtt_fill_fixup;


+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg
CFLAGS_REMOVE_pcr.o := -pg
endif

obj-$(CONFIG_SPARC64)   += urtt_fill.o
obj-$(CONFIG_SPARC32)   += entry.o wof.o wuf.o
obj-$(CONFIG_SPARC32)   += etrap_32.o
obj-$(CONFIG_SPARC32)   += rtrap_32.o
+9 −48
Original line number Diff line number Diff line
@@ -14,10 +14,6 @@
#include <asm/visasm.h>
#include <asm/processor.h>

#define		RTRAP_PSTATE		(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
#define		RTRAP_PSTATE_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
#define		RTRAP_PSTATE_AG_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)

#ifdef CONFIG_CONTEXT_TRACKING
# define SCHEDULE_USER schedule_user
#else
@@ -242,52 +238,17 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
		 wrpr			%g1, %cwp
		ba,a,pt			%xcc, user_rtt_fill_64bit

user_rtt_fill_fixup:
		rdpr	%cwp, %g1
		add	%g1, 1, %g1
		wrpr	%g1, 0x0, %cwp

		rdpr	%wstate, %g2
		sll	%g2, 3, %g2
		wrpr	%g2, 0x0, %wstate

		/* We know %canrestore and %otherwin are both zero.  */

		sethi	%hi(sparc64_kern_pri_context), %g2
		ldx	[%g2 + %lo(sparc64_kern_pri_context)], %g2
		mov	PRIMARY_CONTEXT, %g1

661:		stxa	%g2, [%g1] ASI_DMMU
		.section .sun4v_1insn_patch, "ax"
		.word	661b
		stxa	%g2, [%g1] ASI_MMU
		.previous

		sethi	%hi(KERNBASE), %g1
		flush	%g1

		or	%g4, FAULT_CODE_WINFIXUP, %g4
		stb	%g4, [%g6 + TI_FAULT_CODE]
		stx	%g5, [%g6 + TI_FAULT_ADDR]

		mov	%g6, %l1
		wrpr	%g0, 0x0, %tl

661:		nop
		.section		.sun4v_1insn_patch, "ax"
		.word			661b
		SET_GL(0)
		.previous
user_rtt_fill_fixup_dax:
		ba,pt	%xcc, user_rtt_fill_fixup_common
		 mov	1, %g3

		wrpr	%g0, RTRAP_PSTATE, %pstate
user_rtt_fill_fixup_mna:
		ba,pt	%xcc, user_rtt_fill_fixup_common
		 mov	2, %g3

		mov	%l1, %g6
		ldx	[%g6 + TI_TASK], %g4
		LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
		call	do_sparc64_fault
		 add	%sp, PTREGS_OFF, %o0
		ba,pt	%xcc, rtrap
		 nop
user_rtt_fill_fixup:
		ba,pt	%xcc, user_rtt_fill_fixup_common
		 clr	%g3

user_rtt_pre_restore:
		add			%g1, 1, %g1
+30 −16
Original line number Diff line number Diff line
@@ -138,12 +138,24 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
	return 0;
}

/* Checks if the fp is valid.  We always build signal frames which are
 * 16-byte aligned, therefore we can always enforce that the restore
 * frame has that property as well.
 */
static bool invalid_frame_pointer(void __user *fp, int fplen)
{
	if ((((unsigned long) fp) & 15) ||
	    ((unsigned long)fp) > 0x100000000ULL - fplen)
		return true;
	return false;
}

void do_sigreturn32(struct pt_regs *regs)
{
	struct signal_frame32 __user *sf;
	compat_uptr_t fpu_save;
	compat_uptr_t rwin_save;
	unsigned int psr;
	unsigned int psr, ufp;
	unsigned int pc, npc;
	sigset_t set;
	compat_sigset_t seta;
@@ -158,11 +170,16 @@ void do_sigreturn32(struct pt_regs *regs)
	sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];

	/* 1. Make sure we are not getting garbage from the user */
	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
	    (((unsigned long) sf) & 3))
	if (invalid_frame_pointer(sf, sizeof(*sf)))
		goto segv;

	if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
		goto segv;

	if (ufp & 0x7)
		goto segv;

	if (get_user(pc, &sf->info.si_regs.pc) ||
	if (__get_user(pc, &sf->info.si_regs.pc) ||
	    __get_user(npc, &sf->info.si_regs.npc))
		goto segv;

@@ -227,7 +244,7 @@ void do_sigreturn32(struct pt_regs *regs)
asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
{
	struct rt_signal_frame32 __user *sf;
	unsigned int psr, pc, npc;
	unsigned int psr, pc, npc, ufp;
	compat_uptr_t fpu_save;
	compat_uptr_t rwin_save;
	sigset_t set;
@@ -242,11 +259,16 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
	sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];

	/* 1. Make sure we are not getting garbage from the user */
	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
	    (((unsigned long) sf) & 3))
	if (invalid_frame_pointer(sf, sizeof(*sf)))
		goto segv;

	if (get_user(pc, &sf->regs.pc) || 
	if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
		goto segv;

	if (ufp & 0x7)
		goto segv;

	if (__get_user(pc, &sf->regs.pc) || 
	    __get_user(npc, &sf->regs.npc))
		goto segv;

@@ -307,14 +329,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
	force_sig(SIGSEGV, current);
}

/* Checks if the fp is valid */
static int invalid_frame_pointer(void __user *fp, int fplen)
{
	if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen)
		return 1;
	return 0;
}

static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
{
	unsigned long sp;
Loading