aboutsummaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Kconfig2
-rw-r--r--arch/mips/bcm47xx/buttons.c10
-rw-r--r--arch/mips/cavium-octeon/octeon-memcpy.S20
-rw-r--r--arch/mips/include/asm/checksum.h2
-rw-r--r--arch/mips/include/asm/spinlock.h8
-rw-r--r--arch/mips/kernel/elf.c2
-rw-r--r--arch/mips/kernel/kgdb.c48
-rw-r--r--arch/mips/kernel/process.c151
-rw-r--r--arch/mips/ralink/rt3883.c4
9 files changed, 161 insertions, 86 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c99e8a32bea4..6cab67f9e552 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1366,7 +1366,7 @@ config CPU_MIPS32_R6
select CPU_SUPPORTS_MSA
select GENERIC_CSUM
select HAVE_KVM
- select MIPS_O32_FP64_SUPPORT
+ select MIPS_O32_FP64_SUPPORT if 32BIT
help
Choose this option to build a kernel for release 6 or later of the
MIPS32 architecture. New MIPS processors, starting with the Warrior
diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c
index 276276a8c6d7..aa9391a61c6c 100644
--- a/arch/mips/bcm47xx/buttons.c
+++ b/arch/mips/bcm47xx/buttons.c
@@ -17,6 +17,12 @@
.active_low = 1, \
}
+#define BCM47XX_GPIO_KEY_H(_gpio, _code) \
+ { \
+ .code = _code, \
+ .gpio = _gpio, \
+ }
+
/* Asus */
static const struct gpio_keys_button
@@ -79,8 +85,8 @@ bcm47xx_buttons_asus_wl500gpv2[] __initconst = {
static const struct gpio_keys_button
bcm47xx_buttons_asus_wl500w[] __initconst = {
- BCM47XX_GPIO_KEY(6, KEY_RESTART),
- BCM47XX_GPIO_KEY(7, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY_H(6, KEY_RESTART),
+ BCM47XX_GPIO_KEY_H(7, KEY_WPS_BUTTON),
};
static const struct gpio_keys_button
diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S
index 64e08df51d65..8b7004132491 100644
--- a/arch/mips/cavium-octeon/octeon-memcpy.S
+++ b/arch/mips/cavium-octeon/octeon-memcpy.S
@@ -208,18 +208,18 @@ EXC( STORE t2, UNIT(6)(dst), s_exc_p10u)
ADD src, src, 16*NBYTES
EXC( STORE t3, UNIT(7)(dst), s_exc_p9u)
ADD dst, dst, 16*NBYTES
-EXC( LOAD t0, UNIT(-8)(src), l_exc_copy)
-EXC( LOAD t1, UNIT(-7)(src), l_exc_copy)
-EXC( LOAD t2, UNIT(-6)(src), l_exc_copy)
-EXC( LOAD t3, UNIT(-5)(src), l_exc_copy)
+EXC( LOAD t0, UNIT(-8)(src), l_exc_copy_rewind16)
+EXC( LOAD t1, UNIT(-7)(src), l_exc_copy_rewind16)
+EXC( LOAD t2, UNIT(-6)(src), l_exc_copy_rewind16)
+EXC( LOAD t3, UNIT(-5)(src), l_exc_copy_rewind16)
EXC( STORE t0, UNIT(-8)(dst), s_exc_p8u)
EXC( STORE t1, UNIT(-7)(dst), s_exc_p7u)
EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u)
EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u)
-EXC( LOAD t0, UNIT(-4)(src), l_exc_copy)
-EXC( LOAD t1, UNIT(-3)(src), l_exc_copy)
-EXC( LOAD t2, UNIT(-2)(src), l_exc_copy)
-EXC( LOAD t3, UNIT(-1)(src), l_exc_copy)
+EXC( LOAD t0, UNIT(-4)(src), l_exc_copy_rewind16)
+EXC( LOAD t1, UNIT(-3)(src), l_exc_copy_rewind16)
+EXC( LOAD t2, UNIT(-2)(src), l_exc_copy_rewind16)
+EXC( LOAD t3, UNIT(-1)(src), l_exc_copy_rewind16)
EXC( STORE t0, UNIT(-4)(dst), s_exc_p4u)
EXC( STORE t1, UNIT(-3)(dst), s_exc_p3u)
EXC( STORE t2, UNIT(-2)(dst), s_exc_p2u)
@@ -383,6 +383,10 @@ done:
nop
END(memcpy)
+l_exc_copy_rewind16:
+ /* Rewind src and dst by 16*NBYTES for l_exc_copy */
+ SUB src, src, 16*NBYTES
+ SUB dst, dst, 16*NBYTES
l_exc_copy:
/*
* Copy bytes from src until faulting load address (or until a
diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h
index 3ceacde5eb6e..17f89f9670b2 100644
--- a/arch/mips/include/asm/checksum.h
+++ b/arch/mips/include/asm/checksum.h
@@ -186,7 +186,9 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr,
" daddu %0, %4 \n"
" dsll32 $1, %0, 0 \n"
" daddu %0, $1 \n"
+ " sltu $1, %0, $1 \n"
" dsra32 %0, %0, 0 \n"
+ " addu %0, $1 \n"
#endif
" .set pop"
: "=r" (sum)
diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index 1fca2e0793dc..9a84aa095b21 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -107,7 +107,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
" andi %[ticket], %[ticket], 0xffff \n"
" bne %[ticket], %[my_ticket], 4f \n"
" subu %[ticket], %[my_ticket], %[ticket] \n"
- "2: \n"
+ "2: .insn \n"
" .subsection 2 \n"
"4: andi %[ticket], %[ticket], 0x1fff \n"
" sll %[ticket], 5 \n"
@@ -182,7 +182,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
" sc %[ticket], %[ticket_ptr] \n"
" beqz %[ticket], 1b \n"
" li %[ticket], 1 \n"
- "2: \n"
+ "2: .insn \n"
" .subsection 2 \n"
"3: b 2b \n"
" li %[ticket], 0 \n"
@@ -362,7 +362,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
" .set reorder \n"
__WEAK_LLSC_MB
" li %2, 1 \n"
- "2: \n"
+ "2: .insn \n"
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
: GCC_OFF_SMALL_ASM() (rw->lock)
: "memory");
@@ -402,7 +402,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
" lui %1, 0x8000 \n"
" sc %1, %0 \n"
" li %2, 1 \n"
- "2: \n"
+ "2: .insn \n"
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp),
"=&r" (ret)
: GCC_OFF_SMALL_ASM() (rw->lock)
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 4a4d9e067c89..3afffc30ee12 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -206,7 +206,7 @@ int arch_check_elf(void *_ehdr, bool has_interpreter,
else if ((prog_req.fr1 && prog_req.frdefault) ||
(prog_req.single && !prog_req.frdefault))
/* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
- state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
+ state->overall_fp_mode = ((raw_current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
cpu_has_mips_r2_r6) ?
FP_FR1 : FP_FR0;
else if (prog_req.fr1)
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index 7afcc2f22c0d..37499a234dc8 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -244,9 +244,6 @@ static int compute_signal(int tt)
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
int reg;
- struct thread_info *ti = task_thread_info(p);
- unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
- struct pt_regs *regs = (struct pt_regs *)ksp - 1;
#if (KGDB_GDB_REG_SIZE == 32)
u32 *ptr = (u32 *)gdb_regs;
#else
@@ -254,25 +251,46 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
#endif
for (reg = 0; reg < 16; reg++)
- *(ptr++) = regs->regs[reg];
+ *(ptr++) = 0;
/* S0 - S7 */
- for (reg = 16; reg < 24; reg++)
- *(ptr++) = regs->regs[reg];
+ *(ptr++) = p->thread.reg16;
+ *(ptr++) = p->thread.reg17;
+ *(ptr++) = p->thread.reg18;
+ *(ptr++) = p->thread.reg19;
+ *(ptr++) = p->thread.reg20;
+ *(ptr++) = p->thread.reg21;
+ *(ptr++) = p->thread.reg22;
+ *(ptr++) = p->thread.reg23;
for (reg = 24; reg < 28; reg++)
*(ptr++) = 0;
/* GP, SP, FP, RA */
- for (reg = 28; reg < 32; reg++)
- *(ptr++) = regs->regs[reg];
-
- *(ptr++) = regs->cp0_status;
- *(ptr++) = regs->lo;
- *(ptr++) = regs->hi;
- *(ptr++) = regs->cp0_badvaddr;
- *(ptr++) = regs->cp0_cause;
- *(ptr++) = regs->cp0_epc;
+ *(ptr++) = (long)p;
+ *(ptr++) = p->thread.reg29;
+ *(ptr++) = p->thread.reg30;
+ *(ptr++) = p->thread.reg31;
+
+ *(ptr++) = p->thread.cp0_status;
+
+ /* lo, hi */
+ *(ptr++) = 0;
+ *(ptr++) = 0;
+
+ /*
+ * BadVAddr, Cause
+ * Ideally these would come from the last exception frame up the stack
+ * but that requires unwinding, otherwise we can't know much for sure.
+ */
+ *(ptr++) = 0;
+ *(ptr++) = 0;
+
+ /*
+ * PC
+ * use return address (RA), i.e. the moment after return from resume()
+ */
+ *(ptr++) = p->thread.reg31;
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 44a6f25e902e..fc537d1b649d 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -191,11 +191,9 @@ struct mips_frame_info {
#define J_TARGET(pc,target) \
(((unsigned long)(pc) & 0xf0000000) | ((target) << 2))
-static inline int is_ra_save_ins(union mips_instruction *ip)
+static inline int is_ra_save_ins(union mips_instruction *ip, int *poff)
{
#ifdef CONFIG_CPU_MICROMIPS
- union mips_instruction mmi;
-
/*
* swsp ra,offset
* swm16 reglist,offset(sp)
@@ -205,29 +203,71 @@ static inline int is_ra_save_ins(union mips_instruction *ip)
*
* microMIPS is way more fun...
*/
- if (mm_insn_16bit(ip->halfword[0])) {
- mmi.word = (ip->halfword[0] << 16);
- return (mmi.mm16_r5_format.opcode == mm_swsp16_op &&
- mmi.mm16_r5_format.rt == 31) ||
- (mmi.mm16_m_format.opcode == mm_pool16c_op &&
- mmi.mm16_m_format.func == mm_swm16_op);
+ if (mm_insn_16bit(ip->halfword[1])) {
+ switch (ip->mm16_r5_format.opcode) {
+ case mm_swsp16_op:
+ if (ip->mm16_r5_format.rt != 31)
+ return 0;
+
+ *poff = ip->mm16_r5_format.simmediate;
+ *poff = (*poff << 2) / sizeof(ulong);
+ return 1;
+
+ case mm_pool16c_op:
+ switch (ip->mm16_m_format.func) {
+ case mm_swm16_op:
+ *poff = ip->mm16_m_format.imm;
+ *poff += 1 + ip->mm16_m_format.rlist;
+ *poff = (*poff << 2) / sizeof(ulong);
+ return 1;
+
+ default:
+ return 0;
+ }
+
+ default:
+ return 0;
+ }
}
- else {
- mmi.halfword[0] = ip->halfword[1];
- mmi.halfword[1] = ip->halfword[0];
- return (mmi.mm_m_format.opcode == mm_pool32b_op &&
- mmi.mm_m_format.rd > 9 &&
- mmi.mm_m_format.base == 29 &&
- mmi.mm_m_format.func == mm_swm32_func) ||
- (mmi.i_format.opcode == mm_sw32_op &&
- mmi.i_format.rs == 29 &&
- mmi.i_format.rt == 31);
+
+ switch (ip->i_format.opcode) {
+ case mm_sw32_op:
+ if (ip->i_format.rs != 29)
+ return 0;
+ if (ip->i_format.rt != 31)
+ return 0;
+
+ *poff = ip->i_format.simmediate / sizeof(ulong);
+ return 1;
+
+ case mm_pool32b_op:
+ switch (ip->mm_m_format.func) {
+ case mm_swm32_func:
+ if (ip->mm_m_format.rd < 0x10)
+ return 0;
+ if (ip->mm_m_format.base != 29)
+ return 0;
+
+ *poff = ip->mm_m_format.simmediate;
+ *poff += (ip->mm_m_format.rd & 0xf) * sizeof(u32);
+ *poff /= sizeof(ulong);
+ return 1;
+ default:
+ return 0;
+ }
+
+ default:
+ return 0;
}
#else
/* sw / sd $ra, offset($sp) */
- return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
- ip->i_format.rs == 29 &&
- ip->i_format.rt == 31;
+ if ((ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
+ ip->i_format.rs == 29 && ip->i_format.rt == 31) {
+ *poff = ip->i_format.simmediate / sizeof(ulong);
+ return 1;
+ }
+
+ return 0;
#endif
}
@@ -242,13 +282,16 @@ static inline int is_jump_ins(union mips_instruction *ip)
*
* microMIPS is kind of more fun...
*/
- union mips_instruction mmi;
-
- mmi.word = (ip->halfword[0] << 16);
+ if (mm_insn_16bit(ip->halfword[1])) {
+ if ((ip->mm16_r5_format.opcode == mm_pool16c_op &&
+ (ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op))
+ return 1;
+ return 0;
+ }
- if ((mmi.mm16_r5_format.opcode == mm_pool16c_op &&
- (mmi.mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op) ||
- ip->j_format.opcode == mm_jal32_op)
+ if (ip->j_format.opcode == mm_j32_op)
+ return 1;
+ if (ip->j_format.opcode == mm_jal32_op)
return 1;
if (ip->r_format.opcode != mm_pool32a_op ||
ip->r_format.func != mm_pool32axf_op)
@@ -276,15 +319,13 @@ static inline int is_sp_move_ins(union mips_instruction *ip)
*
* microMIPS is not more fun...
*/
- if (mm_insn_16bit(ip->halfword[0])) {
- union mips_instruction mmi;
-
- mmi.word = (ip->halfword[0] << 16);
- return (mmi.mm16_r3_format.opcode == mm_pool16d_op &&
- mmi.mm16_r3_format.simmediate && mm_addiusp_func) ||
- (mmi.mm16_r5_format.opcode == mm_pool16d_op &&
- mmi.mm16_r5_format.rt == 29);
+ if (mm_insn_16bit(ip->halfword[1])) {
+ return (ip->mm16_r3_format.opcode == mm_pool16d_op &&
+ ip->mm16_r3_format.simmediate && mm_addiusp_func) ||
+ (ip->mm16_r5_format.opcode == mm_pool16d_op &&
+ ip->mm16_r5_format.rt == 29);
}
+
return ip->mm_i_format.opcode == mm_addiu32_op &&
ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29;
#else
@@ -299,30 +340,36 @@ static inline int is_sp_move_ins(union mips_instruction *ip)
static int get_frame_info(struct mips_frame_info *info)
{
-#ifdef CONFIG_CPU_MICROMIPS
- union mips_instruction *ip = (void *) (((char *) info->func) - 1);
-#else
- union mips_instruction *ip = info->func;
-#endif
- unsigned max_insns = info->func_size / sizeof(union mips_instruction);
- unsigned i;
+ bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
+ union mips_instruction insn, *ip, *ip_end;
+ const unsigned int max_insns = 128;
+ unsigned int i;
info->pc_offset = -1;
info->frame_size = 0;
+ ip = (void *)msk_isa16_mode((ulong)info->func);
if (!ip)
goto err;
- if (max_insns == 0)
- max_insns = 128U; /* unknown function size */
- max_insns = min(128U, max_insns);
+ ip_end = (void *)ip + info->func_size;
- for (i = 0; i < max_insns; i++, ip++) {
+ for (i = 0; i < max_insns && ip < ip_end; i++, ip++) {
+ if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
+ insn.halfword[0] = 0;
+ insn.halfword[1] = ip->halfword[0];
+ } else if (is_mmips) {
+ insn.halfword[0] = ip->halfword[1];
+ insn.halfword[1] = ip->halfword[0];
+ } else {
+ insn.word = ip->word;
+ }
- if (is_jump_ins(ip))
+ if (is_jump_ins(&insn))
break;
+
if (!info->frame_size) {
- if (is_sp_move_ins(ip))
+ if (is_sp_move_ins(&insn))
{
#ifdef CONFIG_CPU_MICROMIPS
if (mm_insn_16bit(ip->halfword[0]))
@@ -345,11 +392,9 @@ static int get_frame_info(struct mips_frame_info *info)
}
continue;
}
- if (info->pc_offset == -1 && is_ra_save_ins(ip)) {
- info->pc_offset =
- ip->i_format.simmediate / sizeof(long);
+ if (info->pc_offset == -1 &&
+ is_ra_save_ins(&insn, &info->pc_offset))
break;
- }
}
if (info->frame_size && info->pc_offset >= 0) /* nested */
return 0;
diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c
index 86a535c770d8..5bda39fea483 100644
--- a/arch/mips/ralink/rt3883.c
+++ b/arch/mips/ralink/rt3883.c
@@ -36,7 +36,7 @@ static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) };
static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) };
static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) };
static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) };
-static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna a", 0, 35, 3) };
+static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna g", 0, 35, 3) };
static struct rt2880_pmx_func pci_func[] = {
FUNC("pci-dev", 0, 40, 32),
FUNC("pci-host2", 1, 40, 32),
@@ -44,7 +44,7 @@ static struct rt2880_pmx_func pci_func[] = {
FUNC("pci-fnc", 3, 40, 32)
};
static struct rt2880_pmx_func ge1_func[] = { FUNC("ge1", 0, 72, 12) };
-static struct rt2880_pmx_func ge2_func[] = { FUNC("ge1", 0, 84, 12) };
+static struct rt2880_pmx_func ge2_func[] = { FUNC("ge2", 0, 84, 12) };
static struct rt2880_pmx_group rt3883_pinmux_data[] = {
GRP("i2c", i2c_func, 1, RT3883_GPIO_MODE_I2C),