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

Commit e50c0a8f authored by Ralf Baechle's avatar Ralf Baechle
Browse files

Support the MIPS32 / MIPS64 DSP ASE.

parent 10f650db
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -241,6 +241,7 @@ void output_mm_defines(void)
	linefeed;
}

#ifdef CONFIG_32BIT
void output_sc_defines(void)
{
	text("/* Linux sigcontext offsets. */");
@@ -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)
+18 −1
Original line number Diff line number Diff line
@@ -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;

@@ -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;

@@ -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 −0
Original line number Diff line number Diff line
@@ -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;
}
@@ -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:
+1 −0
Original line number Diff line number Diff line
@@ -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
+56 −2
Original line number Diff line number Diff line
@@ -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>
@@ -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)
@@ -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;
@@ -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();

Loading