Skip to content

Commit

Permalink
Support the MIPS32 / MIPS64 DSP ASE.
Browse files Browse the repository at this point in the history
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Ralf Baechle committed Oct 29, 2005
1 parent 10f650d commit e50c0a8
Show file tree
Hide file tree
Showing 34 changed files with 876 additions and 139 deletions.
26 changes: 23 additions & 3 deletions arch/mips/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void output_thread_info_defines(void)
offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count);
offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit);
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 ", THREAD_SIZE);
constant("#define _THREAD_MASK ", THREAD_MASK);
Expand Down Expand Up @@ -241,6 +241,7 @@ void output_mm_defines(void)
linefeed;
}

#ifdef CONFIG_32BIT
void output_sc_defines(void)
{
text("/* Linux sigcontext offsets. */");
Expand All @@ -252,10 +253,29 @@ void output_sc_defines(void)
offset("#define SC_STATUS ", struct sigcontext, sc_status);
offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
offset("#define SC_CAUSE ", struct sigcontext, sc_cause);
offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr);
offset("#define SC_HI1 ", struct sigcontext, sc_hi1);
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;
}
#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
void output_sc32_defines(void)
Expand Down
19 changes: 18 additions & 1 deletion arch/mips/kernel/branch.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/
int __compute_return_epc(struct pt_regs *regs)
{
unsigned int *addr, bit, fcr31;
unsigned int *addr, bit, fcr31, dspcontrol;
long epc;
union mips_instruction insn;

Expand Down Expand Up @@ -99,6 +99,18 @@ int __compute_return_epc(struct pt_regs *regs)
epc += 8;
regs->cp0_epc = epc;
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;

Expand Down Expand Up @@ -200,4 +212,9 @@ int __compute_return_epc(struct pt_regs *regs)
printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
force_sig(SIGBUS, current);
return -EFAULT;

sigill:
printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
force_sig(SIGBUS, current);
return -EFAULT;
}
3 changes: 3 additions & 0 deletions arch/mips/kernel/cpu-probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)

if (config3 & MIPS_CONF3_SM)
c->ases |= MIPS_ASE_SMARTMIPS;
if (config3 & MIPS_CONF3_DSP)
c->ases |= MIPS_ASE_DSP;

return config3 & MIPS_CONF_M;
}
Expand Down Expand Up @@ -529,6 +531,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
c->cputype = CPU_20KC;
break;
case PRID_IMP_24K:
case PRID_IMP_24KE:
c->cputype = CPU_24K;
break;
case PRID_IMP_25KF:
Expand Down
1 change: 1 addition & 0 deletions arch/mips/kernel/genex.S
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
BUILD_HANDLER watch watch sti verbose /* #23 */
BUILD_HANDLER mcheck mcheck cli verbose /* #24 */
BUILD_HANDLER dsp dsp sti silent /* #26 */
BUILD_HANDLER reserved reserved sti verbose /* others */

#ifdef CONFIG_64BIT
Expand Down
58 changes: 56 additions & 2 deletions arch/mips/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
#include <linux/init.h>
#include <linux/completion.h>

#include <asm/abi.h>
#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
#include <asm/pgtable.h>
#include <asm/system.h>
Expand Down Expand Up @@ -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);

void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
Expand All @@ -70,6 +120,8 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
regs->cp0_status = status;
clear_used_math();
lose_fpu();
if (cpu_has_dsp)
__init_dsp();
regs->cp0_epc = pc;
regs->regs[29] = sp;
current_thread_info()->addr_limit = USER_DS;
Expand All @@ -95,9 +147,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,

preempt_disable();

if (is_fpu_owner()) {
if (is_fpu_owner())
save_fp(p);
}

if (cpu_has_dsp)
save_dsp(p);

preempt_enable();

Expand Down
38 changes: 38 additions & 0 deletions arch/mips/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include <asm/byteorder.h>
#include <asm/cpu.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
#include <asm/mipsregs.h>
#include <asm/pgtable.h>
Expand Down Expand Up @@ -176,6 +177,27 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
write_c0_status(flags);
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:
tmp = 0;
ret = -EIO;
Expand Down Expand Up @@ -248,6 +270,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
else
child->thread.fpu.soft.fcr31 = data;
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:
/* The rest are not allowed. */
ret = -EIO;
Expand Down
38 changes: 38 additions & 0 deletions arch/mips/kernel/ptrace32.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/security.h>

#include <asm/cpu.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
#include <asm/mipsregs.h>
#include <asm/pgtable.h>
Expand Down Expand Up @@ -161,6 +162,27 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
write_c0_status(flags);
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:
tmp = 0;
ret = -EIO;
Expand Down Expand Up @@ -230,6 +252,22 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
else
child->thread.fpu.soft.fcr31 = data;
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:
/* The rest are not allowed. */
ret = -EIO;
Expand Down
5 changes: 1 addition & 4 deletions arch/mips/kernel/r4k_fpu.S
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

.set noreorder
.set mips3
/* Save floating point context */

LEAF(_save_fp_context)
cfc1 t1, fcr31

Expand Down Expand Up @@ -74,9 +74,6 @@ LEAF(_save_fp_context)
EX sdc1 $f28, SC_FPREGS+224(a0)
EX sdc1 $f30, SC_FPREGS+240(a0)
EX sw t1, SC_FPC_CSR(a0)
cfc1 t0, $0 # implementation/version
EX sw t0, SC_FPC_EIR(a0)

jr ra
li v0, 0 # success
END(_save_fp_context)
Expand Down
2 changes: 1 addition & 1 deletion arch/mips/kernel/scall32-o32.S
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ einval: li v0, -EINVAL
sys sys_ni_syscall 0 /* sys_vserver */
sys sys_waitid 5
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_keyctl 5
sys sys_set_thread_area 1
Expand Down
9 changes: 9 additions & 0 deletions arch/mips/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,3 +549,12 @@ int __init fpu_disable(char *s)
}

__setup("nofpu", fpu_disable);

int __init dsp_disable(char *s)
{
cpu_data[0].ases &= ~MIPS_ASE_DSP;

return 1;
}

__setup("nodsp", dsp_disable);
Loading

0 comments on commit e50c0a8

Please sign in to comment.