mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-14 21:48:49 +00:00
Merge branch 'arch-sparc' into no-rebases
This commit is contained in:
commit
d042f3135e
@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
|
||||
if (!(test_thread_flag(TIF_32BIT)))
|
||||
if (test_thread_64bit_stack(usp))
|
||||
usp += STACK_BIAS;
|
||||
else
|
||||
|
||||
if (test_thread_flag(TIF_32BIT))
|
||||
usp &= 0xffffffffUL;
|
||||
|
||||
usp -= len;
|
||||
|
@ -258,6 +258,11 @@ static inline bool test_and_clear_restore_sigmask(void)
|
||||
|
||||
#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
|
||||
|
||||
#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0)
|
||||
#define test_thread_64bit_stack(__SP) \
|
||||
((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \
|
||||
false : true)
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
@ -372,7 +372,9 @@ etrap_spill_fixup_64bit: \
|
||||
|
||||
/* Normal 32bit spill */
|
||||
#define SPILL_2_GENERIC(ASI) \
|
||||
srl %sp, 0, %sp; \
|
||||
and %sp, 1, %g3; \
|
||||
brnz,pn %g3, (. - (128 + 4)); \
|
||||
srl %sp, 0, %sp; \
|
||||
stwa %l0, [%sp + %g0] ASI; \
|
||||
mov 0x04, %g3; \
|
||||
stwa %l1, [%sp + %g3] ASI; \
|
||||
@ -398,14 +400,16 @@ etrap_spill_fixup_64bit: \
|
||||
stwa %i6, [%g1 + %g0] ASI; \
|
||||
stwa %i7, [%g1 + %g3] ASI; \
|
||||
saved; \
|
||||
retry; nop; nop; \
|
||||
retry; \
|
||||
b,a,pt %xcc, spill_fixup_dax; \
|
||||
b,a,pt %xcc, spill_fixup_mna; \
|
||||
b,a,pt %xcc, spill_fixup;
|
||||
|
||||
#define SPILL_2_GENERIC_ETRAP \
|
||||
etrap_user_spill_32bit: \
|
||||
srl %sp, 0, %sp; \
|
||||
and %sp, 1, %g3; \
|
||||
brnz,pn %g3, etrap_user_spill_64bit; \
|
||||
srl %sp, 0, %sp; \
|
||||
stwa %l0, [%sp + 0x00] %asi; \
|
||||
stwa %l1, [%sp + 0x04] %asi; \
|
||||
stwa %l2, [%sp + 0x08] %asi; \
|
||||
@ -427,7 +431,7 @@ etrap_user_spill_32bit: \
|
||||
ba,pt %xcc, etrap_save; \
|
||||
wrpr %g1, %cwp; \
|
||||
nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop; \
|
||||
nop; nop; \
|
||||
ba,a,pt %xcc, etrap_spill_fixup_32bit; \
|
||||
ba,a,pt %xcc, etrap_spill_fixup_32bit; \
|
||||
ba,a,pt %xcc, etrap_spill_fixup_32bit;
|
||||
@ -592,7 +596,9 @@ user_rtt_fill_64bit: \
|
||||
|
||||
/* Normal 32bit fill */
|
||||
#define FILL_2_GENERIC(ASI) \
|
||||
srl %sp, 0, %sp; \
|
||||
and %sp, 1, %g3; \
|
||||
brnz,pn %g3, (. - (128 + 4)); \
|
||||
srl %sp, 0, %sp; \
|
||||
lduwa [%sp + %g0] ASI, %l0; \
|
||||
mov 0x04, %g2; \
|
||||
mov 0x08, %g3; \
|
||||
@ -616,14 +622,16 @@ user_rtt_fill_64bit: \
|
||||
lduwa [%g1 + %g3] ASI, %i6; \
|
||||
lduwa [%g1 + %g5] ASI, %i7; \
|
||||
restored; \
|
||||
retry; nop; nop; nop; nop; \
|
||||
retry; nop; nop; \
|
||||
b,a,pt %xcc, fill_fixup_dax; \
|
||||
b,a,pt %xcc, fill_fixup_mna; \
|
||||
b,a,pt %xcc, fill_fixup;
|
||||
|
||||
#define FILL_2_GENERIC_RTRAP \
|
||||
user_rtt_fill_32bit: \
|
||||
srl %sp, 0, %sp; \
|
||||
and %sp, 1, %g3; \
|
||||
brnz,pn %g3, user_rtt_fill_64bit; \
|
||||
srl %sp, 0, %sp; \
|
||||
lduwa [%sp + 0x00] %asi, %l0; \
|
||||
lduwa [%sp + 0x04] %asi, %l1; \
|
||||
lduwa [%sp + 0x08] %asi, %l2; \
|
||||
@ -643,7 +651,7 @@ user_rtt_fill_32bit: \
|
||||
ba,pt %xcc, user_rtt_pre_restore; \
|
||||
restored; \
|
||||
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; \
|
||||
ba,a,pt %xcc, user_rtt_fill_fixup;
|
||||
|
@ -405,8 +405,12 @@
|
||||
#define __NR_setns 337
|
||||
#define __NR_process_vm_readv 338
|
||||
#define __NR_process_vm_writev 339
|
||||
#define __NR_kern_features 340
|
||||
|
||||
#define NR_syscalls 340
|
||||
#define NR_syscalls 341
|
||||
|
||||
/* Bitmask values returned from kern_features system call. */
|
||||
#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001
|
||||
|
||||
#ifdef __32bit_syscall_numbers__
|
||||
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
|
||||
|
@ -1762,15 +1762,25 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
|
||||
|
||||
ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
|
||||
do {
|
||||
struct sparc_stackf32 *usf, sf;
|
||||
unsigned long pc;
|
||||
|
||||
usf = (struct sparc_stackf32 *) ufp;
|
||||
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
|
||||
break;
|
||||
if (thread32_stack_is_64bit(ufp)) {
|
||||
struct sparc_stackf *usf, sf;
|
||||
|
||||
pc = sf.callers_pc;
|
||||
ufp = (unsigned long)sf.fp;
|
||||
ufp += STACK_BIAS;
|
||||
usf = (struct sparc_stackf *) ufp;
|
||||
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
|
||||
break;
|
||||
pc = sf.callers_pc & 0xffffffff;
|
||||
ufp = ((unsigned long) sf.fp) & 0xffffffff;
|
||||
} else {
|
||||
struct sparc_stackf32 *usf, sf;
|
||||
usf = (struct sparc_stackf32 *) ufp;
|
||||
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
|
||||
break;
|
||||
pc = sf.callers_pc;
|
||||
ufp = (unsigned long)sf.fp;
|
||||
}
|
||||
perf_callchain_store(entry, pc);
|
||||
} while (entry->nr < PERF_MAX_STACK_DEPTH);
|
||||
}
|
||||
|
@ -452,13 +452,16 @@ void flush_thread(void)
|
||||
/* It's a bit more tricky when 64-bit tasks are involved... */
|
||||
static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
|
||||
{
|
||||
bool stack_64bit = test_thread_64bit_stack(psp);
|
||||
unsigned long fp, distance, rval;
|
||||
|
||||
if (!(test_thread_flag(TIF_32BIT))) {
|
||||
if (stack_64bit) {
|
||||
csp += STACK_BIAS;
|
||||
psp += STACK_BIAS;
|
||||
__get_user(fp, &(((struct reg_window __user *)psp)->ins[6]));
|
||||
fp += STACK_BIAS;
|
||||
if (test_thread_flag(TIF_32BIT))
|
||||
fp &= 0xffffffff;
|
||||
} else
|
||||
__get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6]));
|
||||
|
||||
@ -472,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
|
||||
rval = (csp - distance);
|
||||
if (copy_in_user((void __user *) rval, (void __user *) psp, distance))
|
||||
rval = 0;
|
||||
else if (test_thread_flag(TIF_32BIT)) {
|
||||
else if (!stack_64bit) {
|
||||
if (put_user(((u32)csp),
|
||||
&(((struct reg_window32 __user *)rval)->ins[6])))
|
||||
rval = 0;
|
||||
@ -507,18 +510,18 @@ void synchronize_user_stack(void)
|
||||
|
||||
flush_user_windows();
|
||||
if ((window = get_thread_wsaved()) != 0) {
|
||||
int winsize = sizeof(struct reg_window);
|
||||
int bias = 0;
|
||||
|
||||
if (test_thread_flag(TIF_32BIT))
|
||||
winsize = sizeof(struct reg_window32);
|
||||
else
|
||||
bias = STACK_BIAS;
|
||||
|
||||
window -= 1;
|
||||
do {
|
||||
unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
|
||||
struct reg_window *rwin = &t->reg_window[window];
|
||||
int winsize = sizeof(struct reg_window);
|
||||
unsigned long sp;
|
||||
|
||||
sp = t->rwbuf_stkptrs[window];
|
||||
|
||||
if (test_thread_64bit_stack(sp))
|
||||
sp += STACK_BIAS;
|
||||
else
|
||||
winsize = sizeof(struct reg_window32);
|
||||
|
||||
if (!copy_to_user((char __user *)sp, rwin, winsize)) {
|
||||
shift_window_buffer(window, get_thread_wsaved() - 1, t);
|
||||
@ -544,13 +547,6 @@ void fault_in_user_windows(void)
|
||||
{
|
||||
struct thread_info *t = current_thread_info();
|
||||
unsigned long window;
|
||||
int winsize = sizeof(struct reg_window);
|
||||
int bias = 0;
|
||||
|
||||
if (test_thread_flag(TIF_32BIT))
|
||||
winsize = sizeof(struct reg_window32);
|
||||
else
|
||||
bias = STACK_BIAS;
|
||||
|
||||
flush_user_windows();
|
||||
window = get_thread_wsaved();
|
||||
@ -558,8 +554,16 @@ void fault_in_user_windows(void)
|
||||
if (likely(window != 0)) {
|
||||
window -= 1;
|
||||
do {
|
||||
unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
|
||||
struct reg_window *rwin = &t->reg_window[window];
|
||||
int winsize = sizeof(struct reg_window);
|
||||
unsigned long sp;
|
||||
|
||||
sp = t->rwbuf_stkptrs[window];
|
||||
|
||||
if (test_thread_64bit_stack(sp))
|
||||
sp += STACK_BIAS;
|
||||
else
|
||||
winsize = sizeof(struct reg_window32);
|
||||
|
||||
if (unlikely(sp & 0x7UL))
|
||||
stack_unaligned(sp);
|
||||
|
@ -151,7 +151,7 @@ static int regwindow64_get(struct task_struct *target,
|
||||
{
|
||||
unsigned long rw_addr = regs->u_regs[UREG_I6];
|
||||
|
||||
if (test_tsk_thread_flag(current, TIF_32BIT)) {
|
||||
if (!test_thread_64bit_stack(rw_addr)) {
|
||||
struct reg_window32 win32;
|
||||
int i;
|
||||
|
||||
@ -176,7 +176,7 @@ static int regwindow64_set(struct task_struct *target,
|
||||
{
|
||||
unsigned long rw_addr = regs->u_regs[UREG_I6];
|
||||
|
||||
if (test_tsk_thread_flag(current, TIF_32BIT)) {
|
||||
if (!test_thread_64bit_stack(rw_addr)) {
|
||||
struct reg_window32 win32;
|
||||
int i;
|
||||
|
||||
|
@ -729,3 +729,8 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage long sys_kern_features(void)
|
||||
{
|
||||
return KERN_FEATURE_MIXED_MODE_STACK;
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ sys_call_table32:
|
||||
.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
|
||||
/*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
|
||||
.word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
|
||||
/*340*/ .word sys_kern_features
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
@ -163,3 +164,4 @@ sys_call_table:
|
||||
.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
|
||||
/*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
|
||||
.word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
|
||||
/*340*/ .word sys_kern_features
|
||||
|
@ -113,21 +113,24 @@ static inline long sign_extend_imm13(long imm)
|
||||
|
||||
static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long value;
|
||||
unsigned long value, fp;
|
||||
|
||||
if (reg < 16)
|
||||
return (!reg ? 0 : regs->u_regs[reg]);
|
||||
|
||||
fp = regs->u_regs[UREG_FP];
|
||||
|
||||
if (regs->tstate & TSTATE_PRIV) {
|
||||
struct reg_window *win;
|
||||
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
|
||||
win = (struct reg_window *)(fp + STACK_BIAS);
|
||||
value = win->locals[reg - 16];
|
||||
} else if (test_thread_flag(TIF_32BIT)) {
|
||||
} else if (!test_thread_64bit_stack(fp)) {
|
||||
struct reg_window32 __user *win32;
|
||||
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
|
||||
win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
|
||||
get_user(value, &win32->locals[reg - 16]);
|
||||
} else {
|
||||
struct reg_window __user *win;
|
||||
win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
|
||||
win = (struct reg_window __user *)(fp + STACK_BIAS);
|
||||
get_user(value, &win->locals[reg - 16]);
|
||||
}
|
||||
return value;
|
||||
@ -135,19 +138,24 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
|
||||
|
||||
static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long fp;
|
||||
|
||||
if (reg < 16)
|
||||
return ®s->u_regs[reg];
|
||||
|
||||
fp = regs->u_regs[UREG_FP];
|
||||
|
||||
if (regs->tstate & TSTATE_PRIV) {
|
||||
struct reg_window *win;
|
||||
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
|
||||
win = (struct reg_window *)(fp + STACK_BIAS);
|
||||
return &win->locals[reg - 16];
|
||||
} else if (test_thread_flag(TIF_32BIT)) {
|
||||
} else if (!test_thread_64bit_stack(fp)) {
|
||||
struct reg_window32 *win32;
|
||||
win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
|
||||
win32 = (struct reg_window32 *)((unsigned long)((u32)fp));
|
||||
return (unsigned long *)&win32->locals[reg - 16];
|
||||
} else {
|
||||
struct reg_window *win;
|
||||
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
|
||||
win = (struct reg_window *)(fp + STACK_BIAS);
|
||||
return &win->locals[reg - 16];
|
||||
}
|
||||
}
|
||||
@ -392,13 +400,15 @@ int handle_popc(u32 insn, struct pt_regs *regs)
|
||||
if (rd)
|
||||
regs->u_regs[rd] = ret;
|
||||
} else {
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
unsigned long fp = regs->u_regs[UREG_FP];
|
||||
|
||||
if (!test_thread_64bit_stack(fp)) {
|
||||
struct reg_window32 __user *win32;
|
||||
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
|
||||
win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
|
||||
put_user(ret, &win32->locals[rd - 16]);
|
||||
} else {
|
||||
struct reg_window __user *win;
|
||||
win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
|
||||
win = (struct reg_window __user *)(fp + STACK_BIAS);
|
||||
put_user(ret, &win->locals[rd - 16]);
|
||||
}
|
||||
}
|
||||
@ -554,7 +564,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)
|
||||
reg[0] = 0;
|
||||
if ((insn & 0x780000) == 0x180000)
|
||||
reg[1] = 0;
|
||||
} else if (test_thread_flag(TIF_32BIT)) {
|
||||
} else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
|
||||
put_user(0, (int __user *) reg);
|
||||
if ((insn & 0x780000) == 0x180000)
|
||||
put_user(0, ((int __user *) reg) + 1);
|
||||
|
@ -149,21 +149,24 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
|
||||
|
||||
static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long value;
|
||||
unsigned long value, fp;
|
||||
|
||||
if (reg < 16)
|
||||
return (!reg ? 0 : regs->u_regs[reg]);
|
||||
|
||||
fp = regs->u_regs[UREG_FP];
|
||||
|
||||
if (regs->tstate & TSTATE_PRIV) {
|
||||
struct reg_window *win;
|
||||
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
|
||||
win = (struct reg_window *)(fp + STACK_BIAS);
|
||||
value = win->locals[reg - 16];
|
||||
} else if (test_thread_flag(TIF_32BIT)) {
|
||||
} else if (!test_thread_64bit_stack(fp)) {
|
||||
struct reg_window32 __user *win32;
|
||||
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
|
||||
win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
|
||||
get_user(value, &win32->locals[reg - 16]);
|
||||
} else {
|
||||
struct reg_window __user *win;
|
||||
win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
|
||||
win = (struct reg_window __user *)(fp + STACK_BIAS);
|
||||
get_user(value, &win->locals[reg - 16]);
|
||||
}
|
||||
return value;
|
||||
@ -172,16 +175,18 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
|
||||
static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long fp = regs->u_regs[UREG_FP];
|
||||
|
||||
BUG_ON(reg < 16);
|
||||
BUG_ON(regs->tstate & TSTATE_PRIV);
|
||||
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
if (!test_thread_64bit_stack(fp)) {
|
||||
struct reg_window32 __user *win32;
|
||||
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
|
||||
win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
|
||||
return (unsigned long __user *)&win32->locals[reg - 16];
|
||||
} else {
|
||||
struct reg_window __user *win;
|
||||
win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
|
||||
win = (struct reg_window __user *)(fp + STACK_BIAS);
|
||||
return &win->locals[reg - 16];
|
||||
}
|
||||
}
|
||||
@ -204,7 +209,7 @@ static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd)
|
||||
} else {
|
||||
unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs);
|
||||
|
||||
if (test_thread_flag(TIF_32BIT))
|
||||
if (!test_thread_64bit_stack(regs->u_regs[UREG_FP]))
|
||||
__put_user((u32)val, (u32 __user *)rd_user);
|
||||
else
|
||||
__put_user(val, rd_user);
|
||||
|
@ -43,6 +43,8 @@ spill_fixup_mna:
|
||||
spill_fixup_dax:
|
||||
TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
ldx [%g6 + TI_FLAGS], %g1
|
||||
andcc %sp, 0x1, %g0
|
||||
movne %icc, 0, %g1
|
||||
andcc %g1, _TIF_32BIT, %g0
|
||||
ldub [%g6 + TI_WSAVED], %g1
|
||||
sll %g1, 3, %g3
|
||||
|
@ -320,7 +320,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap)
|
||||
XR = 0;
|
||||
else if (freg < 16)
|
||||
XR = regs->u_regs[freg];
|
||||
else if (test_thread_flag(TIF_32BIT)) {
|
||||
else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
|
||||
struct reg_window32 __user *win32;
|
||||
flushw_user ();
|
||||
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
|
||||
|
Loading…
x
Reference in New Issue
Block a user