mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Support the MIPS32 / MIPS64 DSP ASE.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
@@ -95,7 +95,7 @@ void output_thread_info_defines(void)
|
|||||||
offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count);
|
offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count);
|
||||||
offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit);
|
offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit);
|
||||||
offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block);
|
offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block);
|
||||||
offset("#define TI_TP_VALUE ", struct thread_info, tp_value);
|
offset("#define TI_TP_VALUE ", struct thread_info, tp_value);
|
||||||
constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
|
constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
|
||||||
constant("#define _THREAD_SIZE ", THREAD_SIZE);
|
constant("#define _THREAD_SIZE ", THREAD_SIZE);
|
||||||
constant("#define _THREAD_MASK ", THREAD_MASK);
|
constant("#define _THREAD_MASK ", THREAD_MASK);
|
||||||
@@ -241,6 +241,7 @@ void output_mm_defines(void)
|
|||||||
linefeed;
|
linefeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_32BIT
|
||||||
void output_sc_defines(void)
|
void output_sc_defines(void)
|
||||||
{
|
{
|
||||||
text("/* Linux sigcontext offsets. */");
|
text("/* Linux sigcontext offsets. */");
|
||||||
@@ -252,10 +253,29 @@ void output_sc_defines(void)
|
|||||||
offset("#define SC_STATUS ", struct sigcontext, sc_status);
|
offset("#define SC_STATUS ", struct sigcontext, sc_status);
|
||||||
offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
|
offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
|
||||||
offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
|
offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
|
||||||
offset("#define SC_CAUSE ", struct sigcontext, sc_cause);
|
offset("#define SC_HI1 ", struct sigcontext, sc_hi1);
|
||||||
offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr);
|
offset("#define SC_LO1 ", struct sigcontext, sc_lo1);
|
||||||
|
offset("#define SC_HI2 ", struct sigcontext, sc_hi2);
|
||||||
|
offset("#define SC_LO2 ", struct sigcontext, sc_lo2);
|
||||||
|
offset("#define SC_HI3 ", struct sigcontext, sc_hi3);
|
||||||
|
offset("#define SC_LO3 ", struct sigcontext, sc_lo3);
|
||||||
linefeed;
|
linefeed;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
|
void output_sc_defines(void)
|
||||||
|
{
|
||||||
|
text("/* Linux sigcontext offsets. */");
|
||||||
|
offset("#define SC_REGS ", struct sigcontext, sc_regs);
|
||||||
|
offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
|
||||||
|
offset("#define SC_MDHI ", struct sigcontext, sc_hi);
|
||||||
|
offset("#define SC_MDLO ", struct sigcontext, sc_lo);
|
||||||
|
offset("#define SC_PC ", struct sigcontext, sc_pc);
|
||||||
|
offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
|
||||||
|
linefeed;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_MIPS32_COMPAT
|
#ifdef CONFIG_MIPS32_COMPAT
|
||||||
void output_sc32_defines(void)
|
void output_sc32_defines(void)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
int __compute_return_epc(struct pt_regs *regs)
|
int __compute_return_epc(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
unsigned int *addr, bit, fcr31;
|
unsigned int *addr, bit, fcr31, dspcontrol;
|
||||||
long epc;
|
long epc;
|
||||||
union mips_instruction insn;
|
union mips_instruction insn;
|
||||||
|
|
||||||
@@ -99,6 +99,18 @@ int __compute_return_epc(struct pt_regs *regs)
|
|||||||
epc += 8;
|
epc += 8;
|
||||||
regs->cp0_epc = epc;
|
regs->cp0_epc = epc;
|
||||||
break;
|
break;
|
||||||
|
case bposge32_op:
|
||||||
|
if (!cpu_has_dsp)
|
||||||
|
goto sigill;
|
||||||
|
|
||||||
|
dspcontrol = rddsp(0x01);
|
||||||
|
|
||||||
|
if (dspcontrol >= 32) {
|
||||||
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
|
} else
|
||||||
|
epc += 8;
|
||||||
|
regs->cp0_epc = epc;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -200,4 +212,9 @@ unaligned:
|
|||||||
printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
|
printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
|
||||||
force_sig(SIGBUS, current);
|
force_sig(SIGBUS, current);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
sigill:
|
||||||
|
printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
|
||||||
|
force_sig(SIGBUS, current);
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -482,6 +482,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
|
|||||||
|
|
||||||
if (config3 & MIPS_CONF3_SM)
|
if (config3 & MIPS_CONF3_SM)
|
||||||
c->ases |= MIPS_ASE_SMARTMIPS;
|
c->ases |= MIPS_ASE_SMARTMIPS;
|
||||||
|
if (config3 & MIPS_CONF3_DSP)
|
||||||
|
c->ases |= MIPS_ASE_DSP;
|
||||||
|
|
||||||
return config3 & MIPS_CONF_M;
|
return config3 & MIPS_CONF_M;
|
||||||
}
|
}
|
||||||
@@ -529,6 +531,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
|
|||||||
c->cputype = CPU_20KC;
|
c->cputype = CPU_20KC;
|
||||||
break;
|
break;
|
||||||
case PRID_IMP_24K:
|
case PRID_IMP_24K:
|
||||||
|
case PRID_IMP_24KE:
|
||||||
c->cputype = CPU_24K;
|
c->cputype = CPU_24K;
|
||||||
break;
|
break;
|
||||||
case PRID_IMP_25KF:
|
case PRID_IMP_25KF:
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
|
|||||||
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
|
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
|
||||||
BUILD_HANDLER watch watch sti verbose /* #23 */
|
BUILD_HANDLER watch watch sti verbose /* #23 */
|
||||||
BUILD_HANDLER mcheck mcheck cli verbose /* #24 */
|
BUILD_HANDLER mcheck mcheck cli verbose /* #24 */
|
||||||
|
BUILD_HANDLER dsp dsp sti silent /* #26 */
|
||||||
BUILD_HANDLER reserved reserved sti verbose /* others */
|
BUILD_HANDLER reserved reserved sti verbose /* others */
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
|
|||||||
@@ -25,8 +25,10 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
|
|
||||||
|
#include <asm/abi.h>
|
||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/dsp.h>
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
@@ -54,6 +56,54 @@ ATTRIB_NORET void cpu_idle(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
|
||||||
|
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Native o32 and N64 ABI without DSP ASE
|
||||||
|
*/
|
||||||
|
extern void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
|
||||||
|
int signr, sigset_t *set);
|
||||||
|
extern void setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
|
||||||
|
int signr, sigset_t *set, siginfo_t *info);
|
||||||
|
|
||||||
|
struct mips_abi mips_abi = {
|
||||||
|
.do_signal = do_signal,
|
||||||
|
#ifdef CONFIG_TRAD_SIGNALS
|
||||||
|
.setup_frame = setup_frame,
|
||||||
|
#endif
|
||||||
|
.setup_rt_frame = setup_rt_frame
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_MIPS32_O32
|
||||||
|
/*
|
||||||
|
* o32 compatibility on 64-bit kernels, without DSP ASE
|
||||||
|
*/
|
||||||
|
extern void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
|
||||||
|
int signr, sigset_t *set);
|
||||||
|
extern void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
|
||||||
|
int signr, sigset_t *set, siginfo_t *info);
|
||||||
|
|
||||||
|
struct mips_abi mips_abi_32 = {
|
||||||
|
.do_signal = do_signal32,
|
||||||
|
.setup_frame = setup_frame_32,
|
||||||
|
.setup_rt_frame = setup_rt_frame_32
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_MIPS32_O32 */
|
||||||
|
|
||||||
|
#ifdef CONFIG_MIPS32_N32
|
||||||
|
/*
|
||||||
|
* N32 on 64-bit kernels, without DSP ASE
|
||||||
|
*/
|
||||||
|
extern void setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs,
|
||||||
|
int signr, sigset_t *set, siginfo_t *info);
|
||||||
|
|
||||||
|
struct mips_abi mips_abi_n32 = {
|
||||||
|
.do_signal = do_signal,
|
||||||
|
.setup_rt_frame = setup_rt_frame_n32
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_MIPS32_N32 */
|
||||||
|
|
||||||
asmlinkage void ret_from_fork(void);
|
asmlinkage void ret_from_fork(void);
|
||||||
|
|
||||||
void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
|
void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
|
||||||
@@ -70,6 +120,8 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
|
|||||||
regs->cp0_status = status;
|
regs->cp0_status = status;
|
||||||
clear_used_math();
|
clear_used_math();
|
||||||
lose_fpu();
|
lose_fpu();
|
||||||
|
if (cpu_has_dsp)
|
||||||
|
__init_dsp();
|
||||||
regs->cp0_epc = pc;
|
regs->cp0_epc = pc;
|
||||||
regs->regs[29] = sp;
|
regs->regs[29] = sp;
|
||||||
current_thread_info()->addr_limit = USER_DS;
|
current_thread_info()->addr_limit = USER_DS;
|
||||||
@@ -95,9 +147,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
|
|||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
|
||||||
if (is_fpu_owner()) {
|
if (is_fpu_owner())
|
||||||
save_fp(p);
|
save_fp(p);
|
||||||
}
|
|
||||||
|
if (cpu_has_dsp)
|
||||||
|
save_dsp(p);
|
||||||
|
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/dsp.h>
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
#include <asm/mipsregs.h>
|
#include <asm/mipsregs.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
@@ -176,6 +177,27 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
|
|||||||
write_c0_status(flags);
|
write_c0_status(flags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DSP_BASE ... DSP_BASE + 5:
|
||||||
|
if (!cpu_has_dsp) {
|
||||||
|
tmp = 0;
|
||||||
|
ret = -EIO;
|
||||||
|
goto out_tsk;
|
||||||
|
}
|
||||||
|
if (child->thread.dsp.used_dsp) {
|
||||||
|
dspreg_t *dregs = __get_dsp_regs(child);
|
||||||
|
tmp = (unsigned long) (dregs[addr - DSP_BASE]);
|
||||||
|
} else {
|
||||||
|
tmp = -1; /* DSP registers yet used */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DSP_CONTROL:
|
||||||
|
if (!cpu_has_dsp) {
|
||||||
|
tmp = 0;
|
||||||
|
ret = -EIO;
|
||||||
|
goto out_tsk;
|
||||||
|
}
|
||||||
|
tmp = child->thread.dsp.dspcontrol;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
tmp = 0;
|
tmp = 0;
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
@@ -248,6 +270,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
|
|||||||
else
|
else
|
||||||
child->thread.fpu.soft.fcr31 = data;
|
child->thread.fpu.soft.fcr31 = data;
|
||||||
break;
|
break;
|
||||||
|
case DSP_BASE ... DSP_BASE + 5:
|
||||||
|
if (!cpu_has_dsp) {
|
||||||
|
ret = -EIO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dspreg_t *dregs = __get_dsp_regs(child);
|
||||||
|
dregs[addr - DSP_BASE] = data;
|
||||||
|
break;
|
||||||
|
case DSP_CONTROL:
|
||||||
|
if (!cpu_has_dsp) {
|
||||||
|
ret = -EIO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
child->thread.dsp.dspcontrol = data;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* The rest are not allowed. */
|
/* The rest are not allowed. */
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
|
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/dsp.h>
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
#include <asm/mipsregs.h>
|
#include <asm/mipsregs.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
@@ -161,6 +162,27 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
|
|||||||
write_c0_status(flags);
|
write_c0_status(flags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DSP_BASE ... DSP_BASE + 5:
|
||||||
|
if (!cpu_has_dsp) {
|
||||||
|
tmp = 0;
|
||||||
|
ret = -EIO;
|
||||||
|
goto out_tsk;
|
||||||
|
}
|
||||||
|
if (child->thread.dsp.used_dsp) {
|
||||||
|
dspreg_t *dregs = __get_dsp_regs(child);
|
||||||
|
tmp = (unsigned long) (dregs[addr - DSP_BASE]);
|
||||||
|
} else {
|
||||||
|
tmp = -1; /* DSP registers yet used */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DSP_CONTROL:
|
||||||
|
if (!cpu_has_dsp) {
|
||||||
|
tmp = 0;
|
||||||
|
ret = -EIO;
|
||||||
|
goto out_tsk;
|
||||||
|
}
|
||||||
|
tmp = child->thread.dsp.dspcontrol;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
tmp = 0;
|
tmp = 0;
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
@@ -230,6 +252,22 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
|
|||||||
else
|
else
|
||||||
child->thread.fpu.soft.fcr31 = data;
|
child->thread.fpu.soft.fcr31 = data;
|
||||||
break;
|
break;
|
||||||
|
case DSP_BASE ... DSP_BASE + 5:
|
||||||
|
if (!cpu_has_dsp) {
|
||||||
|
ret = -EIO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dspreg_t *dregs = __get_dsp_regs(child);
|
||||||
|
dregs[addr - DSP_BASE] = data;
|
||||||
|
break;
|
||||||
|
case DSP_CONTROL:
|
||||||
|
if (!cpu_has_dsp) {
|
||||||
|
ret = -EIO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
child->thread.dsp.dspcontrol = data;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* The rest are not allowed. */
|
/* The rest are not allowed. */
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
.set noreorder
|
.set noreorder
|
||||||
.set mips3
|
.set mips3
|
||||||
/* Save floating point context */
|
|
||||||
LEAF(_save_fp_context)
|
LEAF(_save_fp_context)
|
||||||
cfc1 t1, fcr31
|
cfc1 t1, fcr31
|
||||||
|
|
||||||
@@ -74,9 +74,6 @@ LEAF(_save_fp_context)
|
|||||||
EX sdc1 $f28, SC_FPREGS+224(a0)
|
EX sdc1 $f28, SC_FPREGS+224(a0)
|
||||||
EX sdc1 $f30, SC_FPREGS+240(a0)
|
EX sdc1 $f30, SC_FPREGS+240(a0)
|
||||||
EX sw t1, SC_FPC_CSR(a0)
|
EX sw t1, SC_FPC_CSR(a0)
|
||||||
cfc1 t0, $0 # implementation/version
|
|
||||||
EX sw t0, SC_FPC_EIR(a0)
|
|
||||||
|
|
||||||
jr ra
|
jr ra
|
||||||
li v0, 0 # success
|
li v0, 0 # success
|
||||||
END(_save_fp_context)
|
END(_save_fp_context)
|
||||||
|
|||||||
@@ -620,7 +620,7 @@ einval: li v0, -EINVAL
|
|||||||
sys sys_ni_syscall 0 /* sys_vserver */
|
sys sys_ni_syscall 0 /* sys_vserver */
|
||||||
sys sys_waitid 5
|
sys sys_waitid 5
|
||||||
sys sys_ni_syscall 0 /* available, was setaltroot */
|
sys sys_ni_syscall 0 /* available, was setaltroot */
|
||||||
sys sys_add_key 5
|
sys sys_add_key 5 /* 4280 */
|
||||||
sys sys_request_key 4
|
sys sys_request_key 4
|
||||||
sys sys_keyctl 5
|
sys sys_keyctl 5
|
||||||
sys sys_set_thread_area 1
|
sys sys_set_thread_area 1
|
||||||
|
|||||||
@@ -549,3 +549,12 @@ int __init fpu_disable(char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
__setup("nofpu", fpu_disable);
|
__setup("nofpu", fpu_disable);
|
||||||
|
|
||||||
|
int __init dsp_disable(char *s)
|
||||||
|
{
|
||||||
|
cpu_data[0].ases &= ~MIPS_ASE_DSP;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__setup("nodsp", dsp_disable);
|
||||||
|
|||||||
@@ -8,13 +8,14 @@
|
|||||||
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
|
setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
err |= __put_user(regs->cp0_epc, &sc->sc_pc);
|
err |= __put_user(regs->cp0_epc, &sc->sc_pc);
|
||||||
err |= __put_user(regs->cp0_status, &sc->sc_status);
|
|
||||||
|
|
||||||
#define save_gp_reg(i) do { \
|
#define save_gp_reg(i) do { \
|
||||||
err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
|
err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
|
||||||
@@ -30,10 +31,32 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
|
|||||||
save_gp_reg(31);
|
save_gp_reg(31);
|
||||||
#undef save_gp_reg
|
#undef save_gp_reg
|
||||||
|
|
||||||
|
#ifdef CONFIG_32BIT
|
||||||
err |= __put_user(regs->hi, &sc->sc_mdhi);
|
err |= __put_user(regs->hi, &sc->sc_mdhi);
|
||||||
err |= __put_user(regs->lo, &sc->sc_mdlo);
|
err |= __put_user(regs->lo, &sc->sc_mdlo);
|
||||||
err |= __put_user(regs->cp0_cause, &sc->sc_cause);
|
if (cpu_has_dsp) {
|
||||||
err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
|
err |= __put_user(mfhi1(), &sc->sc_hi1);
|
||||||
|
err |= __put_user(mflo1(), &sc->sc_lo1);
|
||||||
|
err |= __put_user(mfhi2(), &sc->sc_hi2);
|
||||||
|
err |= __put_user(mflo2(), &sc->sc_lo2);
|
||||||
|
err |= __put_user(mfhi3(), &sc->sc_hi3);
|
||||||
|
err |= __put_user(mflo3(), &sc->sc_lo3);
|
||||||
|
err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
|
err |= __put_user(regs->hi, &sc->sc_hi[0]);
|
||||||
|
err |= __put_user(regs->lo, &sc->sc_lo[0]);
|
||||||
|
if (cpu_has_dsp) {
|
||||||
|
err |= __put_user(mfhi1(), &sc->sc_hi[1]);
|
||||||
|
err |= __put_user(mflo1(), &sc->sc_lo[1]);
|
||||||
|
err |= __put_user(mfhi2(), &sc->sc_hi[2]);
|
||||||
|
err |= __put_user(mflo2(), &sc->sc_lo[2]);
|
||||||
|
err |= __put_user(mfhi3(), &sc->sc_hi[3]);
|
||||||
|
err |= __put_user(mflo3(), &sc->sc_lo[3]);
|
||||||
|
err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
err |= __put_user(!!used_math(), &sc->sc_used_math);
|
err |= __put_user(!!used_math(), &sc->sc_used_math);
|
||||||
|
|
||||||
@@ -61,15 +84,40 @@ out:
|
|||||||
static inline int
|
static inline int
|
||||||
restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
|
restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
|
||||||
{
|
{
|
||||||
int err = 0;
|
|
||||||
unsigned int used_math;
|
unsigned int used_math;
|
||||||
|
unsigned long treg;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
/* Always make any pending restarted system calls return -EINTR */
|
/* Always make any pending restarted system calls return -EINTR */
|
||||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
|
|
||||||
err |= __get_user(regs->cp0_epc, &sc->sc_pc);
|
err |= __get_user(regs->cp0_epc, &sc->sc_pc);
|
||||||
|
#ifdef CONFIG_32BIT
|
||||||
err |= __get_user(regs->hi, &sc->sc_mdhi);
|
err |= __get_user(regs->hi, &sc->sc_mdhi);
|
||||||
err |= __get_user(regs->lo, &sc->sc_mdlo);
|
err |= __get_user(regs->lo, &sc->sc_mdlo);
|
||||||
|
if (cpu_has_dsp) {
|
||||||
|
err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
|
err |= __get_user(regs->hi, &sc->sc_hi[0]);
|
||||||
|
err |= __get_user(regs->lo, &sc->sc_lo[0]);
|
||||||
|
if (cpu_has_dsp) {
|
||||||
|
err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define restore_gp_reg(i) do { \
|
#define restore_gp_reg(i) do { \
|
||||||
err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
|
err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
|
||||||
|
|||||||
+10
-42
@@ -21,6 +21,7 @@
|
|||||||
#include <linux/unistd.h>
|
#include <linux/unistd.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
|
||||||
|
#include <asm/abi.h>
|
||||||
#include <asm/asm.h>
|
#include <asm/asm.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
|
|
||||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||||
|
|
||||||
static int do_signal(sigset_t *oldset, struct pt_regs *regs);
|
int do_signal(sigset_t *oldset, struct pt_regs *regs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Atomically swap in the new signal mask, and wait for a signal.
|
* Atomically swap in the new signal mask, and wait for a signal.
|
||||||
@@ -216,7 +217,7 @@ _sys_sigreturn(nabi_no_regargs struct pt_regs regs)
|
|||||||
badframe:
|
badframe:
|
||||||
force_sig(SIGSEGV, current);
|
force_sig(SIGSEGV, current);
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CONFIG_TRAD_SIGNALS */
|
||||||
|
|
||||||
save_static_function(sys_rt_sigreturn);
|
save_static_function(sys_rt_sigreturn);
|
||||||
__attribute_used__ noinline static void
|
__attribute_used__ noinline static void
|
||||||
@@ -262,7 +263,7 @@ badframe:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TRAD_SIGNALS
|
#ifdef CONFIG_TRAD_SIGNALS
|
||||||
static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
|
void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
|
||||||
int signr, sigset_t *set)
|
int signr, sigset_t *set)
|
||||||
{
|
{
|
||||||
struct sigframe *frame;
|
struct sigframe *frame;
|
||||||
@@ -318,7 +319,7 @@ give_sigsegv:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
|
void setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
|
||||||
int signr, sigset_t *set, siginfo_t *info)
|
int signr, sigset_t *set, siginfo_t *info)
|
||||||
{
|
{
|
||||||
struct rt_sigframe *frame;
|
struct rt_sigframe *frame;
|
||||||
@@ -410,22 +411,10 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
|
|||||||
|
|
||||||
regs->regs[0] = 0; /* Don't deal with this again. */
|
regs->regs[0] = 0; /* Don't deal with this again. */
|
||||||
|
|
||||||
#ifdef CONFIG_TRAD_SIGNALS
|
if (sig_uses_siginfo(ka))
|
||||||
if (ka->sa.sa_flags & SA_SIGINFO) {
|
current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
|
||||||
#else
|
|
||||||
if (1) {
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_MIPS32_N32
|
|
||||||
if ((current->thread.mflags & MF_ABI_MASK) == MF_N32)
|
|
||||||
setup_rt_frame_n32 (ka, regs, sig, oldset, info);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
setup_rt_frame(ka, regs, sig, oldset, info);
|
|
||||||
}
|
|
||||||
#ifdef CONFIG_TRAD_SIGNALS
|
|
||||||
else
|
else
|
||||||
setup_frame(ka, regs, sig, oldset);
|
current->thread.abi->setup_frame(ka, regs, sig, oldset);
|
||||||
#endif
|
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||||
@@ -435,21 +424,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
|
|||||||
spin_unlock_irq(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
|
int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||||
extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
|
|
||||||
|
|
||||||
static int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
struct k_sigaction ka;
|
struct k_sigaction ka;
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
int signr;
|
int signr;
|
||||||
|
|
||||||
#ifdef CONFIG_BINFMT_ELF32
|
|
||||||
if ((current->thread.mflags & MF_ABI_MASK) == MF_O32) {
|
|
||||||
return do_signal32(oldset, regs);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want the common case to go fast, which is why we may in certain
|
* We want the common case to go fast, which is why we may in certain
|
||||||
* cases get here from kernel mode. Just return without doing anything
|
* cases get here from kernel mode. Just return without doing anything
|
||||||
@@ -501,18 +481,6 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
|
|||||||
{
|
{
|
||||||
/* deal with pending signal delivery */
|
/* deal with pending signal delivery */
|
||||||
if (thread_info_flags & _TIF_SIGPENDING) {
|
if (thread_info_flags & _TIF_SIGPENDING) {
|
||||||
#ifdef CONFIG_BINFMT_ELF32
|
current->thread.abi->do_signal(oldset, regs);
|
||||||
if (likely((current->thread.mflags & MF_ABI_MASK) == MF_O32)) {
|
|
||||||
do_signal32(oldset, regs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_BINFMT_IRIX
|
|
||||||
if (unlikely(current->personality != PER_LINUX)) {
|
|
||||||
do_irix_signal(oldset, regs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
do_signal(oldset, regs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
|
||||||
|
#include <asm/abi.h>
|
||||||
#include <asm/asm.h>
|
#include <asm/asm.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
@@ -334,8 +335,9 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
|
|||||||
|
|
||||||
static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
|
static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
|
||||||
{
|
{
|
||||||
|
u32 used_math;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
__u32 used_math;
|
s32 treg;
|
||||||
|
|
||||||
/* Always make any pending restarted system calls return -EINTR */
|
/* Always make any pending restarted system calls return -EINTR */
|
||||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
@@ -343,6 +345,15 @@ static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
|
|||||||
err |= __get_user(regs->cp0_epc, &sc->sc_pc);
|
err |= __get_user(regs->cp0_epc, &sc->sc_pc);
|
||||||
err |= __get_user(regs->hi, &sc->sc_mdhi);
|
err |= __get_user(regs->hi, &sc->sc_mdhi);
|
||||||
err |= __get_user(regs->lo, &sc->sc_mdlo);
|
err |= __get_user(regs->lo, &sc->sc_mdlo);
|
||||||
|
if (cpu_has_dsp) {
|
||||||
|
err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
|
||||||
|
err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
#define restore_gp_reg(i) do { \
|
#define restore_gp_reg(i) do { \
|
||||||
err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
|
err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
|
||||||
@@ -562,8 +573,15 @@ static inline int setup_sigcontext32(struct pt_regs *regs,
|
|||||||
|
|
||||||
err |= __put_user(regs->hi, &sc->sc_mdhi);
|
err |= __put_user(regs->hi, &sc->sc_mdhi);
|
||||||
err |= __put_user(regs->lo, &sc->sc_mdlo);
|
err |= __put_user(regs->lo, &sc->sc_mdlo);
|
||||||
err |= __put_user(regs->cp0_cause, &sc->sc_cause);
|
if (cpu_has_dsp) {
|
||||||
err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
|
err |= __put_user(rddsp(DSP_MASK), &sc->sc_hi1);
|
||||||
|
err |= __put_user(mfhi1(), &sc->sc_hi1);
|
||||||
|
err |= __put_user(mflo1(), &sc->sc_lo1);
|
||||||
|
err |= __put_user(mfhi2(), &sc->sc_hi2);
|
||||||
|
err |= __put_user(mflo2(), &sc->sc_lo2);
|
||||||
|
err |= __put_user(mfhi3(), &sc->sc_hi3);
|
||||||
|
err |= __put_user(mflo3(), &sc->sc_lo3);
|
||||||
|
}
|
||||||
|
|
||||||
err |= __put_user(!!used_math(), &sc->sc_used_math);
|
err |= __put_user(!!used_math(), &sc->sc_used_math);
|
||||||
|
|
||||||
@@ -613,7 +631,7 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
|||||||
return (void *)((sp - frame_size) & ALMASK);
|
return (void *)((sp - frame_size) & ALMASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
|
void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
|
||||||
int signr, sigset_t *set)
|
int signr, sigset_t *set)
|
||||||
{
|
{
|
||||||
struct sigframe *frame;
|
struct sigframe *frame;
|
||||||
@@ -666,9 +684,7 @@ give_sigsegv:
|
|||||||
force_sigsegv(signr, current);
|
force_sigsegv(signr, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void setup_rt_frame(struct k_sigaction * ka,
|
void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
|
||||||
struct pt_regs *regs, int signr,
|
|
||||||
sigset_t *set, siginfo_t *info)
|
|
||||||
{
|
{
|
||||||
struct rt_sigframe32 *frame;
|
struct rt_sigframe32 *frame;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -759,9 +775,9 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
|
|||||||
regs->regs[0] = 0; /* Don't deal with this again. */
|
regs->regs[0] = 0; /* Don't deal with this again. */
|
||||||
|
|
||||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||||
setup_rt_frame(ka, regs, sig, oldset, info);
|
current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
|
||||||
else
|
else
|
||||||
setup_frame(ka, regs, sig, oldset);
|
current->thread.abi->setup_frame(ka, regs, sig, oldset);
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||||
|
|||||||
+33
-16
@@ -25,6 +25,7 @@
|
|||||||
#include <asm/branch.h>
|
#include <asm/branch.h>
|
||||||
#include <asm/break.h>
|
#include <asm/break.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/dsp.h>
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
#include <asm/module.h>
|
#include <asm/module.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
@@ -54,6 +55,7 @@ extern asmlinkage void handle_tr(void);
|
|||||||
extern asmlinkage void handle_fpe(void);
|
extern asmlinkage void handle_fpe(void);
|
||||||
extern asmlinkage void handle_mdmx(void);
|
extern asmlinkage void handle_mdmx(void);
|
||||||
extern asmlinkage void handle_watch(void);
|
extern asmlinkage void handle_watch(void);
|
||||||
|
extern asmlinkage void handle_dsp(void);
|
||||||
extern asmlinkage void handle_mcheck(void);
|
extern asmlinkage void handle_mcheck(void);
|
||||||
extern asmlinkage void handle_reserved(void);
|
extern asmlinkage void handle_reserved(void);
|
||||||
|
|
||||||
@@ -775,6 +777,14 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
|
|||||||
(regs->cp0_status & ST0_TS) ? "" : "not ");
|
(regs->cp0_status & ST0_TS) ? "" : "not ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asmlinkage void do_dsp(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
if (cpu_has_dsp)
|
||||||
|
panic("Unexpected DSP exception\n");
|
||||||
|
|
||||||
|
force_sig(SIGILL, current);
|
||||||
|
}
|
||||||
|
|
||||||
asmlinkage void do_reserved(struct pt_regs *regs)
|
asmlinkage void do_reserved(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -984,9 +994,12 @@ void __init per_cpu_trap_init(void)
|
|||||||
#endif
|
#endif
|
||||||
if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
|
if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
|
||||||
status_set |= ST0_XX;
|
status_set |= ST0_XX;
|
||||||
change_c0_status(ST0_CU|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
|
change_c0_status(ST0_CU|ST0_MX|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
|
||||||
status_set);
|
status_set);
|
||||||
|
|
||||||
|
if (cpu_has_dsp)
|
||||||
|
set_c0_status(ST0_MX);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some MIPS CPUs have a dedicated interrupt vector which reduces the
|
* Some MIPS CPUs have a dedicated interrupt vector which reduces the
|
||||||
* interrupt processing overhead. Use it where available.
|
* interrupt processing overhead. Use it where available.
|
||||||
@@ -1078,21 +1091,6 @@ void __init trap_init(void)
|
|||||||
set_except_vector(11, handle_cpu);
|
set_except_vector(11, handle_cpu);
|
||||||
set_except_vector(12, handle_ov);
|
set_except_vector(12, handle_ov);
|
||||||
set_except_vector(13, handle_tr);
|
set_except_vector(13, handle_tr);
|
||||||
set_except_vector(22, handle_mdmx);
|
|
||||||
|
|
||||||
if (cpu_has_fpu && !cpu_has_nofpuex)
|
|
||||||
set_except_vector(15, handle_fpe);
|
|
||||||
|
|
||||||
if (cpu_has_mcheck)
|
|
||||||
set_except_vector(24, handle_mcheck);
|
|
||||||
|
|
||||||
if (cpu_has_vce)
|
|
||||||
/* Special exception: R4[04]00 uses also the divec space. */
|
|
||||||
memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
|
|
||||||
else if (cpu_has_4kex)
|
|
||||||
memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
|
|
||||||
else
|
|
||||||
memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
|
|
||||||
|
|
||||||
if (current_cpu_data.cputype == CPU_R6000 ||
|
if (current_cpu_data.cputype == CPU_R6000 ||
|
||||||
current_cpu_data.cputype == CPU_R6000A) {
|
current_cpu_data.cputype == CPU_R6000A) {
|
||||||
@@ -1108,6 +1106,25 @@ void __init trap_init(void)
|
|||||||
//set_except_vector(15, handle_ndc);
|
//set_except_vector(15, handle_ndc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpu_has_fpu && !cpu_has_nofpuex)
|
||||||
|
set_except_vector(15, handle_fpe);
|
||||||
|
|
||||||
|
set_except_vector(22, handle_mdmx);
|
||||||
|
|
||||||
|
if (cpu_has_mcheck)
|
||||||
|
set_except_vector(24, handle_mcheck);
|
||||||
|
|
||||||
|
if (cpu_has_dsp)
|
||||||
|
set_except_vector(26, handle_dsp);
|
||||||
|
|
||||||
|
if (cpu_has_vce)
|
||||||
|
/* Special exception: R4[04]00 uses also the divec space. */
|
||||||
|
memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
|
||||||
|
else if (cpu_has_4kex)
|
||||||
|
memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
|
||||||
|
else
|
||||||
|
memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
|
||||||
|
|
||||||
signal_init();
|
signal_init();
|
||||||
#ifdef CONFIG_MIPS32_COMPAT
|
#ifdef CONFIG_MIPS32_COMPAT
|
||||||
signal32_init();
|
signal32_init();
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 by Ralf Baechle
|
||||||
|
* Copyright (C) 2005 MIPS Technologies, Inc.
|
||||||
|
*/
|
||||||
|
#ifndef _ASM_ABI_H
|
||||||
|
#define _ASM_ABI_H
|
||||||
|
|
||||||
|
#include <asm/signal.h>
|
||||||
|
#include <asm/siginfo.h>
|
||||||
|
|
||||||
|
struct mips_abi {
|
||||||
|
int (* const do_signal)(sigset_t *oldset, struct pt_regs *regs);
|
||||||
|
int (* const setup_frame)(struct k_sigaction * ka,
|
||||||
|
struct pt_regs *regs, int signr,
|
||||||
|
sigset_t *set);
|
||||||
|
int (* const setup_rt_frame)(struct k_sigaction * ka,
|
||||||
|
struct pt_regs *regs, int signr,
|
||||||
|
sigset_t *set, siginfo_t *info);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _ASM_ABI_H */
|
||||||
@@ -105,6 +105,10 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef cpu_has_dsp
|
||||||
|
#define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Certain CPUs may throw bizarre exceptions if not the whole cacheline
|
* Certain CPUs may throw bizarre exceptions if not the whole cacheline
|
||||||
* contains valid instructions. For these we ensure proper alignment of
|
* contains valid instructions. For these we ensure proper alignment of
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
#define PRID_IMP_4KEMPR2 0x9100
|
#define PRID_IMP_4KEMPR2 0x9100
|
||||||
#define PRID_IMP_4KSD 0x9200
|
#define PRID_IMP_4KSD 0x9200
|
||||||
#define PRID_IMP_24K 0x9300
|
#define PRID_IMP_24K 0x9300
|
||||||
|
#define PRID_IMP_24KE 0x9600
|
||||||
|
|
||||||
#define PRID_IMP_UNKNOWN 0xff00
|
#define PRID_IMP_UNKNOWN 0xff00
|
||||||
|
|
||||||
@@ -232,5 +233,6 @@
|
|||||||
#define MIPS_ASE_MDMX 0x00000002 /* MIPS digital media extension */
|
#define MIPS_ASE_MDMX 0x00000002 /* MIPS digital media extension */
|
||||||
#define MIPS_ASE_MIPS3D 0x00000004 /* MIPS-3D */
|
#define MIPS_ASE_MIPS3D 0x00000004 /* MIPS-3D */
|
||||||
#define MIPS_ASE_SMARTMIPS 0x00000008 /* SmartMIPS */
|
#define MIPS_ASE_SMARTMIPS 0x00000008 /* SmartMIPS */
|
||||||
|
#define MIPS_ASE_DSP 0x00000010 /* Signal Processing ASE */
|
||||||
|
|
||||||
#endif /* _ASM_CPU_H */
|
#endif /* _ASM_CPU_H */
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Mips Technologies
|
||||||
|
* Author: Chris Dearman, chris@mips.com derived from fpu.h
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*/
|
||||||
|
#ifndef _ASM_DSP_H
|
||||||
|
#define _ASM_DSP_H
|
||||||
|
|
||||||
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/cpu-features.h>
|
||||||
|
#include <asm/hazards.h>
|
||||||
|
#include <asm/mipsregs.h>
|
||||||
|
|
||||||
|
#define DSP_DEFAULT 0x00000000
|
||||||
|
#define DSP_MASK 0x1f
|
||||||
|
|
||||||
|
#define __enable_dsp_hazard() \
|
||||||
|
do { \
|
||||||
|
asm("_ehb"); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static inline void __init_dsp(void)
|
||||||
|
{
|
||||||
|
mthi1(0);
|
||||||
|
mtlo1(0);
|
||||||
|
mthi2(0);
|
||||||
|
mtlo2(0);
|
||||||
|
mthi3(0);
|
||||||
|
mtlo3(0);
|
||||||
|
wrdsp(DSP_DEFAULT, DSP_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void init_dsp(void)
|
||||||
|
{
|
||||||
|
if (cpu_has_dsp)
|
||||||
|
__init_dsp();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __save_dsp(tsk) \
|
||||||
|
do { \
|
||||||
|
tsk->thread.dsp.dspr[0] = mfhi1(); \
|
||||||
|
tsk->thread.dsp.dspr[1] = mflo1(); \
|
||||||
|
tsk->thread.dsp.dspr[2] = mfhi2(); \
|
||||||
|
tsk->thread.dsp.dspr[3] = mflo2(); \
|
||||||
|
tsk->thread.dsp.dspr[4] = mfhi3(); \
|
||||||
|
tsk->thread.dsp.dspr[5] = mflo3(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define save_dsp(tsk) \
|
||||||
|
do { \
|
||||||
|
if (cpu_has_dsp) \
|
||||||
|
__save_dsp(tsk); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define __restore_dsp(tsk) \
|
||||||
|
do { \
|
||||||
|
mthi1(tsk->thread.dsp.dspr[0]); \
|
||||||
|
mtlo1(tsk->thread.dsp.dspr[1]); \
|
||||||
|
mthi2(tsk->thread.dsp.dspr[2]); \
|
||||||
|
mtlo2(tsk->thread.dsp.dspr[3]); \
|
||||||
|
mthi3(tsk->thread.dsp.dspr[4]); \
|
||||||
|
mtlo3(tsk->thread.dsp.dspr[5]); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define restore_dsp(tsk) \
|
||||||
|
do { \
|
||||||
|
if (cpu_has_dsp) \
|
||||||
|
__restore_dsp(tsk); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define __get_dsp_regs(tsk) \
|
||||||
|
({ \
|
||||||
|
if (tsk == current) \
|
||||||
|
__save_dsp(current); \
|
||||||
|
\
|
||||||
|
tsk->thread.dsp.dspr; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#endif /* _ASM_DSP_H */
|
||||||
+62
-19
@@ -193,33 +193,76 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
|
|||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
struct mips_abi;
|
||||||
|
|
||||||
|
extern struct mips_abi mips_abi;
|
||||||
|
extern struct mips_abi mips_abi_32;
|
||||||
|
extern struct mips_abi mips_abi_n32;
|
||||||
|
|
||||||
#ifdef CONFIG_32BIT
|
#ifdef CONFIG_32BIT
|
||||||
|
|
||||||
#define SET_PERSONALITY(ex, ibcs2) \
|
#define SET_PERSONALITY(ex, ibcs2) \
|
||||||
do { \
|
do { \
|
||||||
if (ibcs2) \
|
if (ibcs2) \
|
||||||
set_personality(PER_SVR4); \
|
set_personality(PER_SVR4); \
|
||||||
set_personality(PER_LINUX); \
|
set_personality(PER_LINUX); \
|
||||||
|
\
|
||||||
|
current->thread.abi = &mips_abi; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif /* CONFIG_32BIT */
|
#endif /* CONFIG_32BIT */
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
|
|
||||||
#define SET_PERSONALITY(ex, ibcs2) \
|
#ifdef CONFIG_MIPS32_N32
|
||||||
do { current->thread.mflags &= ~MF_ABI_MASK; \
|
#define __SET_PERSONALITY32_N32() \
|
||||||
if ((ex).e_ident[EI_CLASS] == ELFCLASS32) { \
|
do { \
|
||||||
if ((((ex).e_flags & EF_MIPS_ABI2) != 0) && \
|
current->thread.mflags |= MF_N32; \
|
||||||
((ex).e_flags & EF_MIPS_ABI) == 0) \
|
current->thread.abi = &mips_abi_n32; \
|
||||||
current->thread.mflags |= MF_N32; \
|
} while (0)
|
||||||
else \
|
#else
|
||||||
current->thread.mflags |= MF_O32; \
|
#define __SET_PERSONALITY32_N32() \
|
||||||
} else \
|
do { } while (0)
|
||||||
current->thread.mflags |= MF_N64; \
|
#endif
|
||||||
if (ibcs2) \
|
|
||||||
set_personality(PER_SVR4); \
|
#ifdef CONFIG_MIPS32_O32
|
||||||
else if (current->personality != PER_LINUX32) \
|
#define __SET_PERSONALITY32_O32() \
|
||||||
set_personality(PER_LINUX); \
|
do { \
|
||||||
|
current->thread.mflags |= MF_O32; \
|
||||||
|
current->thread.abi = &mips_abi_32; \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define __SET_PERSONALITY32_O32() \
|
||||||
|
do { } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_MIPS32_COMPAT
|
||||||
|
#define __SET_PERSONALITY32(ex) \
|
||||||
|
do { \
|
||||||
|
if ((((ex).e_flags & EF_MIPS_ABI2) != 0) && \
|
||||||
|
((ex).e_flags & EF_MIPS_ABI) == 0) \
|
||||||
|
__SET_PERSONALITY32_N32(); \
|
||||||
|
else \
|
||||||
|
__SET_PERSONALITY32_O32(); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define __SET_PERSONALITY32(ex) do { } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SET_PERSONALITY(ex, ibcs2) \
|
||||||
|
do { \
|
||||||
|
current->thread.mflags &= ~MF_ABI_MASK; \
|
||||||
|
if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
|
||||||
|
__SET_PERSONALITY32(ex); \
|
||||||
|
else { \
|
||||||
|
current->thread.mflags |= MF_N64; \
|
||||||
|
current->thread.abi = &mips_abi; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (ibcs2) \
|
||||||
|
set_personality(PER_SVR4); \
|
||||||
|
else if (current->personality != PER_LINUX32) \
|
||||||
|
set_personality(PER_LINUX); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif /* CONFIG_64BIT */
|
#endif /* CONFIG_64BIT */
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ enum rt_op {
|
|||||||
spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07,
|
spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07,
|
||||||
tgei_op, tgeiu_op, tlti_op, tltiu_op,
|
tgei_op, tgeiu_op, tlti_op, tltiu_op,
|
||||||
teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op,
|
teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op,
|
||||||
bltzal_op, bgezal_op, bltzall_op, bgezall_op
|
bltzal_op, bgezal_op, bltzall_op, bgezall_op,
|
||||||
/*
|
rt_op_0x14, rt_op_0x15, rt_op_0x16, rt_op_0x17,
|
||||||
* The others (0x14 - 0x1f) are unused.
|
rt_op_0x18, rt_op_0x19, rt_op_0x1a, rt_op_0x1b,
|
||||||
*/
|
bposge32_op, rt_op_0x1d, rt_op_0x1e, rt_op_0x1f
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user