Commit 58c1f995 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc

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
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
#define PTREGS_OFF (STACK_BIAS + STACKFRAME_SZ) #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 __CHEETAH_ID 0x003e0014
#define __JALAPENO_ID 0x003e0016 #define __JALAPENO_ID 0x003e0016
#define __SERRANO_ID 0x003e0022 #define __SERRANO_ID 0x003e0022
......
...@@ -589,8 +589,8 @@ user_rtt_fill_64bit: \ ...@@ -589,8 +589,8 @@ user_rtt_fill_64bit: \
restored; \ restored; \
nop; nop; nop; nop; nop; nop; \ nop; nop; nop; nop; nop; 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_dax; \
ba,a,pt %xcc, user_rtt_fill_fixup; \ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \
ba,a,pt %xcc, user_rtt_fill_fixup; ba,a,pt %xcc, user_rtt_fill_fixup;
...@@ -652,8 +652,8 @@ user_rtt_fill_32bit: \ ...@@ -652,8 +652,8 @@ user_rtt_fill_32bit: \
restored; \ restored; \
nop; nop; nop; nop; nop; \ 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_dax; \
ba,a,pt %xcc, user_rtt_fill_fixup; \ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \
ba,a,pt %xcc, user_rtt_fill_fixup; ba,a,pt %xcc, user_rtt_fill_fixup;
......
...@@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg ...@@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg
CFLAGS_REMOVE_pcr.o := -pg CFLAGS_REMOVE_pcr.o := -pg
endif endif
obj-$(CONFIG_SPARC64) += urtt_fill.o
obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o
obj-$(CONFIG_SPARC32) += etrap_32.o obj-$(CONFIG_SPARC32) += etrap_32.o
obj-$(CONFIG_SPARC32) += rtrap_32.o obj-$(CONFIG_SPARC32) += rtrap_32.o
......
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
#include <asm/visasm.h> #include <asm/visasm.h>
#include <asm/processor.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 #ifdef CONFIG_CONTEXT_TRACKING
# define SCHEDULE_USER schedule_user # define SCHEDULE_USER schedule_user
#else #else
...@@ -242,52 +238,17 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ...@@ -242,52 +238,17 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
wrpr %g1, %cwp wrpr %g1, %cwp
ba,a,pt %xcc, user_rtt_fill_64bit ba,a,pt %xcc, user_rtt_fill_64bit
user_rtt_fill_fixup: user_rtt_fill_fixup_dax:
rdpr %cwp, %g1 ba,pt %xcc, user_rtt_fill_fixup_common
add %g1, 1, %g1 mov 1, %g3
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 user_rtt_fill_fixup_mna:
stb %g4, [%g6 + TI_FAULT_CODE] ba,pt %xcc, user_rtt_fill_fixup_common
stx %g5, [%g6 + TI_FAULT_ADDR] mov 2, %g3
mov %g6, %l1 user_rtt_fill_fixup:
wrpr %g0, 0x0, %tl ba,pt %xcc, user_rtt_fill_fixup_common
clr %g3
661: nop
.section .sun4v_1insn_patch, "ax"
.word 661b
SET_GL(0)
.previous
wrpr %g0, RTRAP_PSTATE, %pstate
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_pre_restore: user_rtt_pre_restore:
add %g1, 1, %g1 add %g1, 1, %g1
......
...@@ -138,12 +138,24 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) ...@@ -138,12 +138,24 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
return 0; 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) void do_sigreturn32(struct pt_regs *regs)
{ {
struct signal_frame32 __user *sf; struct signal_frame32 __user *sf;
compat_uptr_t fpu_save; compat_uptr_t fpu_save;
compat_uptr_t rwin_save; compat_uptr_t rwin_save;
unsigned int psr; unsigned int psr, ufp;
unsigned int pc, npc; unsigned int pc, npc;
sigset_t set; sigset_t set;
compat_sigset_t seta; compat_sigset_t seta;
...@@ -158,11 +170,16 @@ void do_sigreturn32(struct pt_regs *regs) ...@@ -158,11 +170,16 @@ void do_sigreturn32(struct pt_regs *regs)
sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP]; sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */ /* 1. Make sure we are not getting garbage from the user */
if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || if (invalid_frame_pointer(sf, sizeof(*sf)))
(((unsigned long) sf) & 3)) goto segv;
if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
goto segv;
if (ufp & 0x7)
goto segv; 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)) __get_user(npc, &sf->info.si_regs.npc))
goto segv; goto segv;
...@@ -227,7 +244,7 @@ void do_sigreturn32(struct pt_regs *regs) ...@@ -227,7 +244,7 @@ void do_sigreturn32(struct pt_regs *regs)
asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
{ {
struct rt_signal_frame32 __user *sf; 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 fpu_save;
compat_uptr_t rwin_save; compat_uptr_t rwin_save;
sigset_t set; sigset_t set;
...@@ -242,11 +259,16 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) ...@@ -242,11 +259,16 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP]; sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */ /* 1. Make sure we are not getting garbage from the user */
if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || if (invalid_frame_pointer(sf, sizeof(*sf)))
(((unsigned long) sf) & 3))
goto segv; 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)) __get_user(npc, &sf->regs.npc))
goto segv; goto segv;
...@@ -307,14 +329,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) ...@@ -307,14 +329,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
force_sig(SIGSEGV, current); 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) static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
{ {
unsigned long sp; unsigned long sp;
......
...@@ -60,10 +60,22 @@ struct rt_signal_frame { ...@@ -60,10 +60,22 @@ struct rt_signal_frame {
#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) #define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
/* 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 inline bool invalid_frame_pointer(void __user *fp, int fplen)
{
if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen))
return true;
return false;
}
asmlinkage void do_sigreturn(struct pt_regs *regs) asmlinkage void do_sigreturn(struct pt_regs *regs)
{ {
unsigned long up_psr, pc, npc, ufp;
struct signal_frame __user *sf; struct signal_frame __user *sf;
unsigned long up_psr, pc, npc;
sigset_t set; sigset_t set;
__siginfo_fpu_t __user *fpu_save; __siginfo_fpu_t __user *fpu_save;
__siginfo_rwin_t __user *rwin_save; __siginfo_rwin_t __user *rwin_save;
...@@ -77,10 +89,13 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) ...@@ -77,10 +89,13 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
sf = (struct signal_frame __user *) regs->u_regs[UREG_FP]; sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */ /* 1. Make sure we are not getting garbage from the user */
if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) if (!invalid_frame_pointer(sf, sizeof(*sf)))
goto segv_and_exit;
if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
goto segv_and_exit; goto segv_and_exit;
if (((unsigned long) sf) & 3) if (ufp & 0x7)
goto segv_and_exit; goto segv_and_exit;
err = __get_user(pc, &sf->info.si_regs.pc); err = __get_user(pc, &sf->info.si_regs.pc);
...@@ -127,7 +142,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) ...@@ -127,7 +142,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
asmlinkage void do_rt_sigreturn(struct pt_regs *regs) asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
{ {
struct rt_signal_frame __user *sf; struct rt_signal_frame __user *sf;
unsigned int psr, pc, npc; unsigned int psr, pc, npc, ufp;
__siginfo_fpu_t __user *fpu_save; __siginfo_fpu_t __user *fpu_save;
__siginfo_rwin_t __user *rwin_save; __siginfo_rwin_t __user *rwin_save;
sigset_t set; sigset_t set;
...@@ -135,8 +150,13 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) ...@@ -135,8 +150,13 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
synchronize_user_stack(); synchronize_user_stack();
sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP]; sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || if (!invalid_frame_pointer(sf, sizeof(*sf)))
(((unsigned long) sf) & 0x03)) goto segv;
if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
goto segv;
if (ufp & 0x7)
goto segv; goto segv;
err = __get_user(pc, &sf->regs.pc); err = __get_user(pc, &sf->regs.pc);
...@@ -178,15 +198,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) ...@@ -178,15 +198,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
} }
/* Checks if the fp is valid */
static inline int invalid_frame_pointer(void __user *fp, int fplen)
{
if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
return 1;
return 0;
}
static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
{ {
unsigned long sp = regs->u_regs[UREG_FP]; unsigned long sp = regs->u_regs[UREG_FP];
......
...@@ -234,6 +234,17 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs) ...@@ -234,6 +234,17 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs)
goto out; goto out;
} }
/* Checks if the fp is valid. We always build rt 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)
{
if (((unsigned long) fp) & 15)
return true;
return false;
}
struct rt_signal_frame { struct rt_signal_frame {
struct sparc_stackf ss; struct sparc_stackf ss;
siginfo_t info; siginfo_t info;
...@@ -246,8 +257,8 @@ struct rt_signal_frame { ...@@ -246,8 +257,8 @@ struct rt_signal_frame {
void do_rt_sigreturn(struct pt_regs *regs) void do_rt_sigreturn(struct pt_regs *regs)
{ {
unsigned long tpc, tnpc, tstate, ufp;
struct rt_signal_frame __user *sf; struct rt_signal_frame __user *sf;
unsigned long tpc, tnpc, tstate;
__siginfo_fpu_t __user *fpu_save; __siginfo_fpu_t __user *fpu_save;
__siginfo_rwin_t __user *rwin_save; __siginfo_rwin_t __user *rwin_save;
sigset_t set; sigset_t set;
...@@ -261,10 +272,16 @@ void do_rt_sigreturn(struct pt_regs *regs) ...@@ -261,10 +272,16 @@ void do_rt_sigreturn(struct pt_regs *regs)
(regs->u_regs [UREG_FP] + STACK_BIAS); (regs->u_regs [UREG_FP] + STACK_BIAS);
/* 1. Make sure we are not getting garbage from the user */ /* 1. Make sure we are not getting garbage from the user */
if (((unsigned long) sf) & 3) if (invalid_frame_pointer(sf))
goto segv;
if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
goto segv; goto segv;
err = get_user(tpc, &sf->regs.tpc); if ((ufp + STACK_BIAS) & 0x7)
goto segv;
err = __get_user(tpc, &sf->regs.tpc);
err |= __get_user(tnpc, &sf->regs.tnpc); err |= __get_user(tnpc, &sf->regs.tnpc);
if (test_thread_flag(TIF_32BIT)) { if (test_thread_flag(TIF_32BIT)) {
tpc &= 0xffffffff; tpc &= 0xffffffff;
...@@ -308,14 +325,6 @@ void do_rt_sigreturn(struct pt_regs *regs) ...@@ -308,14 +325,6 @@ void do_rt_sigreturn(struct pt_regs *regs)
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
} }
/* Checks if the fp is valid */
static int invalid_frame_pointer(void __user *fp)
{
if (((unsigned long) fp) & 15)
return 1;
return 0;
}
static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
{ {
unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
......
...@@ -48,6 +48,10 @@ int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) ...@@ -48,6 +48,10 @@ int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
{ {
int err; int err;
if (((unsigned long) fpu) & 3)
return -EFAULT;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (test_tsk_thread_flag(current, TIF_USEDFPU)) if (test_tsk_thread_flag(current, TIF_USEDFPU))
regs->psr &= ~PSR_EF; regs->psr &= ~PSR_EF;
...@@ -97,7 +101,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp) ...@@ -97,7 +101,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp)
struct thread_info *t = current_thread_info(); struct thread_info *t = current_thread_info();
int i, wsaved, err; int i, wsaved, err;
__get_user(wsaved, &rp->wsaved); if (((unsigned long) rp) & 3)
return -EFAULT;
get_user(wsaved, &rp->wsaved);
if (wsaved > NSWINS) if (wsaved > NSWINS)
return -EFAULT; return -EFAULT;
......
...@@ -37,7 +37,10 @@ int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) ...@@ -37,7 +37,10 @@ int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
unsigned long fprs; unsigned long fprs;
int err; int err;
err = __get_user(fprs, &fpu->si_fprs); if (((unsigned long) fpu) & 7)
return -EFAULT;
err = get_user(fprs, &fpu->si_fprs);
fprs_write(0); fprs_write(0);
regs->tstate &= ~TSTATE_PEF; regs->tstate &= ~TSTATE_PEF;
if (fprs & FPRS_DL) if (fprs & FPRS_DL)
...@@ -72,7 +75,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp) ...@@ -72,7 +75,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp)
struct thread_info *t = current_thread_info(); struct thread_info *t = current_thread_info();
int i, wsaved, err; int i, wsaved, err;
__get_user(wsaved, &rp->wsaved); if (((unsigned long) rp) & 7)
return -EFAULT;
get_user(wsaved, &rp->wsaved);
if (wsaved > NSWINS) if (wsaved > NSWINS)
return -EFAULT; return -EFAULT;
......
#include <asm/thread_info.h>
#include <asm/trap_block.h>
#include <asm/spitfire.h>
#include <asm/ptrace.h>
#include <asm/head.h>
.text
.align 8
.globl user_rtt_fill_fixup_common
user_rtt_fill_fixup_common:
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
mov %g4, %l4
mov %g5, %l5
brnz,pn %g3, 1f
mov %g3, %l3
or %g4, FAULT_CODE_WINFIXUP, %g4
stb %g4, [%g6 + TI_FAULT_CODE]
stx %g5, [%g6 + TI_FAULT_ADDR]
1:
mov %g6, %l1
wrpr %g0, 0x0, %tl
661: nop
.section .sun4v_1insn_patch, "ax"
.word 661b
SET_GL(0)
.previous
wrpr %g0, RTRAP_PSTATE, %pstate
mov %l1, %g6
ldx [%g6 + TI_TASK], %g4
LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
brnz,pn %l3, 1f
nop
call do_sparc64_fault
add %sp, PTREGS_OFF, %o0
ba,pt %xcc, rtrap
nop
1: cmp %g3, 2
bne,pn %xcc, 2f
nop
sethi %hi(tlb_type), %g1
lduw [%g1 + %lo(tlb_type)], %g1
cmp %g1, 3
bne,pt %icc, 1f
add %sp, PTREGS_OFF, %o0
mov %l4, %o2
call sun4v_do_mna
mov %l5, %o1
ba,a,pt %xcc, rtrap
1: mov %l4, %o1
mov %l5, %o2
call mem_address_unaligned
nop
ba,a,pt %xcc, rtrap
2: sethi %hi(tlb_type), %g1
mov %l4, %o1
lduw [%g1 + %lo(tlb_type)], %g1
mov %l5, %o2
cmp %g1, 3
bne,pt %icc, 1f
add %sp, PTREGS_OFF, %o0
call sun4v_data_access_exception
nop
ba,a,pt %xcc, rtrap
1: call spitfire_data_access_exception
nop
ba,a,pt %xcc, rtrap
...@@ -2824,9 +2824,10 @@ void hugetlb_setup(struct pt_regs *regs) ...@@ -2824,9 +2824,10 @@ void hugetlb_setup(struct pt_regs *regs)
* the Data-TLB for huge pages. * the Data-TLB for huge pages.
*/ */
if (tlb_type == cheetah_plus) { if (tlb_type == cheetah_plus) {
bool need_context_reload = false;
unsigned long ctx; unsigned long ctx;
spin_lock(&ctx_alloc_lock); spin_lock_irq(&ctx_alloc_lock);
ctx = mm->context.sparc64_ctx_val; ctx = mm->context.sparc64_ctx_val;
ctx &= ~CTX_PGSZ_MASK; ctx &= ~CTX_PGSZ_MASK;
ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT; ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT;
...@@ -2845,9 +2846,12 @@ void hugetlb_setup(struct pt_regs *regs) ...@@ -2845,9 +2846,12 @@ void hugetlb_setup(struct pt_regs *regs)
* also executing in this address space. * also executing in this address space.
*/ */
mm->context.sparc64_ctx_val = ctx; mm->context.sparc64_ctx_val = ctx;
on_each_cpu(context_reload, mm, 0); need_context_reload = true;
} }
spin_unlock(&ctx_alloc_lock); spin_unlock_irq(&ctx_alloc_lock);
if (need_context_reload)
on_each_cpu(context_reload, mm, 0);
} }
} }
#endif #endif
......
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