aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile1
-rw-r--r--arch/mips/kernel/cpu-probe.c39
-rw-r--r--arch/mips/kernel/genex.S14
-rw-r--r--arch/mips/kernel/head.S6
-rw-r--r--arch/mips/kernel/mips_machine.c62
-rw-r--r--arch/mips/kernel/process.c5
-rw-r--r--arch/mips/kernel/ptrace.c204
-rw-r--r--arch/mips/kernel/setup.c10
-rw-r--r--arch/mips/kernel/syscalls/syscall_n32.tbl7
-rw-r--r--arch/mips/kernel/syscalls/syscall_n64.tbl3
-rw-r--r--arch/mips/kernel/syscalls/syscall_o32.tbl7
-rw-r--r--arch/mips/kernel/topology.c2
-rw-r--r--arch/mips/kernel/traps.c40
-rw-r--r--arch/mips/kernel/unaligned.c27
14 files changed, 177 insertions, 250 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 8c7a043295ed..13a26d254829 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -93,7 +93,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_EARLY_PRINTK_8250) += early_printk_8250.o
obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
-obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
obj-$(CONFIG_MIPSR2_TO_R6_EMULATOR) += mips-r2-to-r6-emul.o
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index def1659fe262..e2955f1f6316 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -635,14 +635,14 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, enum ftlb_flags flags)
config = read_c0_config6();
if (flags & FTLB_EN)
- config |= MIPS_CONF6_MTI_FTLBEN;
+ config |= MTI_CONF6_FTLBEN;
else
- config &= ~MIPS_CONF6_MTI_FTLBEN;
+ config &= ~MTI_CONF6_FTLBEN;
if (flags & FTLB_SET_PROB) {
- config &= ~(3 << MIPS_CONF6_MTI_FTLBP_SHIFT);
+ config &= ~(3 << MTI_CONF6_FTLBP_SHIFT);
config |= calculate_ftlb_probability(c)
- << MIPS_CONF6_MTI_FTLBP_SHIFT;
+ << MTI_CONF6_FTLBP_SHIFT;
}
write_c0_config6(config);
@@ -662,10 +662,10 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, enum ftlb_flags flags)
config = read_c0_config6();
if (flags & FTLB_EN)
/* Enable FTLB */
- write_c0_config6(config & ~MIPS_CONF6_LOONGSON_FTLBDIS);
+ write_c0_config6(config & ~LOONGSON_CONF6_FTLBDIS);
else
/* Disable FTLB */
- write_c0_config6(config | MIPS_CONF6_LOONGSON_FTLBDIS);
+ write_c0_config6(config | LOONGSON_CONF6_FTLBDIS);
break;
default:
return 1;
@@ -1827,6 +1827,19 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
default:
break;
}
+
+ /* Recent MIPS cores use the implementation-dependent ExcCode 16 for
+ * cache/FTLB parity exceptions.
+ */
+ switch (__get_cpu_type(c->cputype)) {
+ case CPU_PROAPTIV:
+ case CPU_P5600:
+ case CPU_P6600:
+ case CPU_I6400:
+ case CPU_I6500:
+ c->options |= MIPS_CPU_FTLBPAREX;
+ break;
+ }
}
static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
@@ -2030,6 +2043,9 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
{
decode_configs(c);
+ /* All Loongson processors covered here define ExcCode 16 as GSExc. */
+ c->options |= MIPS_CPU_GSEXCEX;
+
switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_LOONGSON_64R: /* Loongson-64 Reduced */
switch (c->processor_id & PRID_REV_MASK) {
@@ -2110,6 +2126,8 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
BUG_ON(!__builtin_constant_p(cpu_has_counter) || cpu_has_counter);
switch (c->processor_id & PRID_IMP_MASK) {
+
+ /* XBurst®1 with MXU1.0/MXU1.1 SIMD ISA */
case PRID_IMP_XBURST_REV1:
/*
@@ -2148,12 +2166,20 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
break;
}
fallthrough;
+
+ /* XBurst®1 with MXU2.0 SIMD ISA */
case PRID_IMP_XBURST_REV2:
c->cputype = CPU_XBURST;
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
__cpu_name[cpu] = "Ingenic XBurst";
break;
+ /* XBurst®2 with MXU2.1 SIMD ISA */
+ case PRID_IMP_XBURST2:
+ c->cputype = CPU_XBURST;
+ __cpu_name[cpu] = "Ingenic XBurst II";
+ break;
+
default:
panic("Unknown Ingenic Processor ID!");
break;
@@ -2299,6 +2325,7 @@ void cpu_probe(void)
case PRID_COMP_LOONGSON:
cpu_probe_loongson(c, cpu);
break;
+ case PRID_COMP_INGENIC_13:
case PRID_COMP_INGENIC_D0:
case PRID_COMP_INGENIC_D1:
case PRID_COMP_INGENIC_E1:
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index a1b966f3578e..bcce32a3de10 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -498,6 +498,19 @@ NESTED(nmi_handler, PT_SIZE, sp)
KMODE
.endm
+ .macro __build_clear_gsexc
+ .set push
+ /*
+ * We need to specify a selector to access the CP0.Diag1 (GSCause)
+ * register. All GSExc-equipped processors have MIPS32.
+ */
+ .set mips32
+ mfc0 a1, CP0_DIAGNOSTIC1
+ .set pop
+ TRACE_IRQS_ON
+ STI
+ .endm
+
.macro __BUILD_silent exception
.endm
@@ -556,6 +569,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
BUILD_HANDLER fpe fpe fpe silent /* #15 */
#endif
BUILD_HANDLER ftlb ftlb none silent /* #16 */
+ BUILD_HANDLER gsexc gsexc gsexc silent /* #16 */
BUILD_HANDLER msa msa sti silent /* #21 */
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
#ifdef CONFIG_HARDWARE_WATCHPOINTS
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 3b02ffe46304..7dd234e788e6 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -111,6 +111,12 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
move t2, a1
beq a0, t1, dtb_found
+#ifdef CONFIG_BUILTIN_DTB
+ PTR_LA t2, __dtb_start
+ PTR_LA t1, __dtb_end
+ bne t1, t2, dtb_found
+#endif /* CONFIG_BUILTIN_DTB */
+
li t2, 0
dtb_found:
#endif /* CONFIG_USE_OF */
diff --git a/arch/mips/kernel/mips_machine.c b/arch/mips/kernel/mips_machine.c
deleted file mode 100644
index 4c509641723c..000000000000
--- a/arch/mips/kernel/mips_machine.c
+++ /dev/null
@@ -1,62 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
- */
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/mips_machine.h>
-#include <asm/prom.h>
-
-static struct mips_machine *mips_machine __initdata;
-
-#define for_each_machine(mach) \
- for ((mach) = (struct mips_machine *)&__mips_machines_start; \
- (mach) && \
- (unsigned long)(mach) < (unsigned long)&__mips_machines_end; \
- (mach)++)
-
-__init int mips_machtype_setup(char *id)
-{
- struct mips_machine *mach;
-
- for_each_machine(mach) {
- if (mach->mach_id == NULL)
- continue;
-
- if (strcmp(mach->mach_id, id) == 0) {
- mips_machtype = mach->mach_type;
- return 0;
- }
- }
-
- pr_err("MIPS: no machine found for id '%s', supported machines:\n", id);
- pr_err("%-24s %s\n", "id", "name");
- for_each_machine(mach)
- pr_err("%-24s %s\n", mach->mach_id, mach->mach_name);
-
- return 1;
-}
-
-__setup("machtype=", mips_machtype_setup);
-
-__init void mips_machine_setup(void)
-{
- struct mips_machine *mach;
-
- for_each_machine(mach) {
- if (mips_machtype == mach->mach_type) {
- mips_machine = mach;
- break;
- }
- }
-
- if (!mips_machine)
- return;
-
- mips_set_machine_name(mips_machine->mach_name);
-
- if (mips_machine->mach_setup)
- mips_machine->mach_setup();
-}
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index ff5320b79100..f5dc316a826a 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -119,8 +119,9 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
/*
* Copy architecture-specific thread state
*/
-int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
- unsigned long kthread_arg, struct task_struct *p, unsigned long tls)
+int copy_thread(unsigned long clone_flags, unsigned long usp,
+ unsigned long kthread_arg, struct task_struct *p,
+ unsigned long tls)
{
struct thread_info *ti = task_thread_info(p);
struct pt_regs *childregs, *regs = current_pt_regs();
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 2a61641c680b..db7c5be1d4a3 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -210,15 +210,13 @@ int ptrace_set_watch_regs(struct task_struct *child,
static int gpr32_get(struct task_struct *target,
const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- void *kbuf, void __user *ubuf)
+ struct membuf to)
{
struct pt_regs *regs = task_pt_regs(target);
u32 uregs[ELF_NGREG] = {};
mips_dump_regs32(uregs, regs);
- return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
- sizeof(uregs));
+ return membuf_write(&to, uregs, sizeof(uregs));
}
static int gpr32_set(struct task_struct *target,
@@ -277,15 +275,13 @@ static int gpr32_set(struct task_struct *target,
static int gpr64_get(struct task_struct *target,
const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- void *kbuf, void __user *ubuf)
+ struct membuf to)
{
struct pt_regs *regs = task_pt_regs(target);
u64 uregs[ELF_NGREG] = {};
mips_dump_regs64(uregs, regs);
- return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
- sizeof(uregs));
+ return membuf_write(&to, uregs, sizeof(uregs));
}
static int gpr64_set(struct task_struct *target,
@@ -408,13 +404,11 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
* !CONFIG_CPU_HAS_MSA variant. FP context's general register slots
* correspond 1:1 to buffer slots. Only general registers are copied.
*/
-static int fpr_get_fpa(struct task_struct *target,
- unsigned int *pos, unsigned int *count,
- void **kbuf, void __user **ubuf)
+static void fpr_get_fpa(struct task_struct *target,
+ struct membuf *to)
{
- return user_regset_copyout(pos, count, kbuf, ubuf,
- &target->thread.fpu,
- 0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
+ membuf_write(to, &target->thread.fpu,
+ NUM_FPU_REGS * sizeof(elf_fpreg_t));
}
/*
@@ -423,25 +417,13 @@ static int fpr_get_fpa(struct task_struct *target,
* general register slots are copied to buffer slots. Only general
* registers are copied.
*/
-static int fpr_get_msa(struct task_struct *target,
- unsigned int *pos, unsigned int *count,
- void **kbuf, void __user **ubuf)
+static void fpr_get_msa(struct task_struct *target, struct membuf *to)
{
unsigned int i;
- u64 fpr_val;
- int err;
-
- BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
- for (i = 0; i < NUM_FPU_REGS; i++) {
- fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
- err = user_regset_copyout(pos, count, kbuf, ubuf,
- &fpr_val, i * sizeof(elf_fpreg_t),
- (i + 1) * sizeof(elf_fpreg_t));
- if (err)
- return err;
- }
- return 0;
+ BUILD_BUG_ON(sizeof(u64) != sizeof(elf_fpreg_t));
+ for (i = 0; i < NUM_FPU_REGS; i++)
+ membuf_store(to, get_fpr64(&target->thread.fpu.fpr[i], 0));
}
/*
@@ -451,31 +433,16 @@ static int fpr_get_msa(struct task_struct *target,
*/
static int fpr_get(struct task_struct *target,
const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- void *kbuf, void __user *ubuf)
+ struct membuf to)
{
- const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
- const int fir_pos = fcr31_pos + sizeof(u32);
- int err;
-
if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
- err = fpr_get_fpa(target, &pos, &count, &kbuf, &ubuf);
+ fpr_get_fpa(target, &to);
else
- err = fpr_get_msa(target, &pos, &count, &kbuf, &ubuf);
- if (err)
- return err;
-
- err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- &target->thread.fpu.fcr31,
- fcr31_pos, fcr31_pos + sizeof(u32));
- if (err)
- return err;
+ fpr_get_msa(target, &to);
- err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- &boot_cpu_data.fpu_id,
- fir_pos, fir_pos + sizeof(u32));
-
- return err;
+ membuf_write(&to, &target->thread.fpu.fcr31, sizeof(u32));
+ membuf_write(&to, &boot_cpu_data.fpu_id, sizeof(u32));
+ return 0;
}
/*
@@ -576,14 +543,9 @@ static int fpr_set(struct task_struct *target,
/* Copy the FP mode setting to the supplied NT_MIPS_FP_MODE buffer. */
static int fp_mode_get(struct task_struct *target,
const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- void *kbuf, void __user *ubuf)
+ struct membuf to)
{
- int fp_mode;
-
- fp_mode = mips_get_process_fp_mode(target);
- return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &fp_mode, 0,
- sizeof(fp_mode));
+ return membuf_store(&to, (int)mips_get_process_fp_mode(target));
}
/*
@@ -630,13 +592,12 @@ struct msa_control_regs {
unsigned int msacsr;
};
-static int copy_pad_fprs(struct task_struct *target,
+static void copy_pad_fprs(struct task_struct *target,
const struct user_regset *regset,
- unsigned int *ppos, unsigned int *pcount,
- void **pkbuf, void __user **pubuf,
+ struct membuf *to,
unsigned int live_sz)
{
- int i, j, start, start_pad, err;
+ int i, j;
unsigned long long fill = ~0ull;
unsigned int cp_sz, pad_sz;
@@ -644,28 +605,16 @@ static int copy_pad_fprs(struct task_struct *target,
pad_sz = regset->size - cp_sz;
WARN_ON(pad_sz % sizeof(fill));
- i = start = err = 0;
- for (; i < NUM_FPU_REGS; i++, start += regset->size) {
- err |= user_regset_copyout(ppos, pcount, pkbuf, pubuf,
- &target->thread.fpu.fpr[i],
- start, start + cp_sz);
-
- start_pad = start + cp_sz;
- for (j = 0; j < (pad_sz / sizeof(fill)); j++) {
- err |= user_regset_copyout(ppos, pcount, pkbuf, pubuf,
- &fill, start_pad,
- start_pad + sizeof(fill));
- start_pad += sizeof(fill);
- }
+ for (i = 0; i < NUM_FPU_REGS; i++) {
+ membuf_write(to, &target->thread.fpu.fpr[i], cp_sz);
+ for (j = 0; j < (pad_sz / sizeof(fill)); j++)
+ membuf_store(to, fill);
}
-
- return err;
}
static int msa_get(struct task_struct *target,
const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- void *kbuf, void __user *ubuf)
+ struct membuf to)
{
const unsigned int wr_size = NUM_FPU_REGS * regset->size;
const struct msa_control_regs ctrl_regs = {
@@ -674,32 +623,23 @@ static int msa_get(struct task_struct *target,
.msair = boot_cpu_data.msa_id,
.msacsr = target->thread.fpu.msacsr,
};
- int err;
if (!tsk_used_math(target)) {
/* The task hasn't used FP or MSA, fill with 0xff */
- err = copy_pad_fprs(target, regset, &pos, &count,
- &kbuf, &ubuf, 0);
+ copy_pad_fprs(target, regset, &to, 0);
} else if (!test_tsk_thread_flag(target, TIF_MSA_CTX_LIVE)) {
/* Copy scalar FP context, fill the rest with 0xff */
- err = copy_pad_fprs(target, regset, &pos, &count,
- &kbuf, &ubuf, 8);
+ copy_pad_fprs(target, regset, &to, 8);
} else if (sizeof(target->thread.fpu.fpr[0]) == regset->size) {
/* Trivially copy the vector registers */
- err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- &target->thread.fpu.fpr,
- 0, wr_size);
+ membuf_write(&to, &target->thread.fpu.fpr, wr_size);
} else {
/* Copy as much context as possible, fill the rest with 0xff */
- err = copy_pad_fprs(target, regset, &pos, &count,
- &kbuf, &ubuf,
- sizeof(target->thread.fpu.fpr[0]));
+ copy_pad_fprs(target, regset, &to,
+ sizeof(target->thread.fpu.fpr[0]));
}
- err |= user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- &ctrl_regs, wr_size,
- wr_size + sizeof(ctrl_regs));
- return err;
+ return membuf_write(&to, &ctrl_regs, sizeof(ctrl_regs));
}
static int msa_set(struct task_struct *target,
@@ -752,34 +692,20 @@ static int msa_set(struct task_struct *target,
*/
static int dsp32_get(struct task_struct *target,
const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- void *kbuf, void __user *ubuf)
+ struct membuf to)
{
- unsigned int start, num_regs, i;
u32 dspregs[NUM_DSP_REGS + 1];
+ unsigned int i;
- BUG_ON(count % sizeof(u32));
+ BUG_ON(to.left % sizeof(u32));
if (!cpu_has_dsp)
return -EIO;
- start = pos / sizeof(u32);
- num_regs = count / sizeof(u32);
-
- if (start + num_regs > NUM_DSP_REGS + 1)
- return -EIO;
-
- for (i = start; i < num_regs; i++)
- switch (i) {
- case 0 ... NUM_DSP_REGS - 1:
- dspregs[i] = target->thread.dsp.dspr[i];
- break;
- case NUM_DSP_REGS:
- dspregs[i] = target->thread.dsp.dspcontrol;
- break;
- }
- return user_regset_copyout(&pos, &count, &kbuf, &ubuf, dspregs, 0,
- sizeof(dspregs));
+ for (i = 0; i < NUM_DSP_REGS; i++)
+ dspregs[i] = target->thread.dsp.dspr[i];
+ dspregs[NUM_DSP_REGS] = target->thread.dsp.dspcontrol;
+ return membuf_write(&to, dspregs, sizeof(dspregs));
}
/*
@@ -832,34 +758,20 @@ static int dsp32_set(struct task_struct *target,
*/
static int dsp64_get(struct task_struct *target,
const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- void *kbuf, void __user *ubuf)
+ struct membuf to)
{
- unsigned int start, num_regs, i;
u64 dspregs[NUM_DSP_REGS + 1];
+ unsigned int i;
- BUG_ON(count % sizeof(u64));
+ BUG_ON(to.left % sizeof(u64));
if (!cpu_has_dsp)
return -EIO;
- start = pos / sizeof(u64);
- num_regs = count / sizeof(u64);
-
- if (start + num_regs > NUM_DSP_REGS + 1)
- return -EIO;
-
- for (i = start; i < num_regs; i++)
- switch (i) {
- case 0 ... NUM_DSP_REGS - 1:
- dspregs[i] = target->thread.dsp.dspr[i];
- break;
- case NUM_DSP_REGS:
- dspregs[i] = target->thread.dsp.dspcontrol;
- break;
- }
- return user_regset_copyout(&pos, &count, &kbuf, &ubuf, dspregs, 0,
- sizeof(dspregs));
+ for (i = 0; i < NUM_DSP_REGS; i++)
+ dspregs[i] = target->thread.dsp.dspr[i];
+ dspregs[NUM_DSP_REGS] = target->thread.dsp.dspcontrol;
+ return membuf_write(&to, dspregs, sizeof(dspregs));
}
/*
@@ -1018,7 +930,7 @@ static const struct user_regset mips_regsets[] = {
.n = ELF_NGREG,
.size = sizeof(unsigned int),
.align = sizeof(unsigned int),
- .get = gpr32_get,
+ .regset_get = gpr32_get,
.set = gpr32_set,
},
[REGSET_DSP] = {
@@ -1026,7 +938,7 @@ static const struct user_regset mips_regsets[] = {
.n = NUM_DSP_REGS + 1,
.size = sizeof(u32),
.align = sizeof(u32),
- .get = dsp32_get,
+ .regset_get = dsp32_get,
.set = dsp32_set,
.active = dsp_active,
},
@@ -1036,7 +948,7 @@ static const struct user_regset mips_regsets[] = {
.n = ELF_NFPREG,
.size = sizeof(elf_fpreg_t),
.align = sizeof(elf_fpreg_t),
- .get = fpr_get,
+ .regset_get = fpr_get,
.set = fpr_set,
},
[REGSET_FP_MODE] = {
@@ -1044,7 +956,7 @@ static const struct user_regset mips_regsets[] = {
.n = 1,
.size = sizeof(int),
.align = sizeof(int),
- .get = fp_mode_get,
+ .regset_get = fp_mode_get,
.set = fp_mode_set,
},
#endif
@@ -1054,7 +966,7 @@ static const struct user_regset mips_regsets[] = {
.n = NUM_FPU_REGS + 1,
.size = 16,
.align = 16,
- .get = msa_get,
+ .regset_get = msa_get,
.set = msa_set,
},
#endif
@@ -1078,7 +990,7 @@ static const struct user_regset mips64_regsets[] = {
.n = ELF_NGREG,
.size = sizeof(unsigned long),
.align = sizeof(unsigned long),
- .get = gpr64_get,
+ .regset_get = gpr64_get,
.set = gpr64_set,
},
[REGSET_DSP] = {
@@ -1086,7 +998,7 @@ static const struct user_regset mips64_regsets[] = {
.n = NUM_DSP_REGS + 1,
.size = sizeof(u64),
.align = sizeof(u64),
- .get = dsp64_get,
+ .regset_get = dsp64_get,
.set = dsp64_set,
.active = dsp_active,
},
@@ -1096,7 +1008,7 @@ static const struct user_regset mips64_regsets[] = {
.n = 1,
.size = sizeof(int),
.align = sizeof(int),
- .get = fp_mode_get,
+ .regset_get = fp_mode_get,
.set = fp_mode_set,
},
[REGSET_FPR] = {
@@ -1104,7 +1016,7 @@ static const struct user_regset mips64_regsets[] = {
.n = ELF_NFPREG,
.size = sizeof(elf_fpreg_t),
.align = sizeof(elf_fpreg_t),
- .get = fpr_get,
+ .regset_get = fpr_get,
.set = fpr_set,
},
#endif
@@ -1114,7 +1026,7 @@ static const struct user_regset mips64_regsets[] = {
.n = NUM_FPU_REGS + 1,
.size = 16,
.align = 16,
- .get = msa_get,
+ .regset_get = msa_get,
.set = msa_set,
},
#endif
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 7b537fa2035d..bf5f5acab0a8 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -371,14 +371,6 @@ static void __init bootmem_init(void)
#endif
}
-
- /*
- * In any case the added to the memblock memory regions
- * (highmem/lowmem, available/reserved, etc) are considered
- * as present, so inform sparsemem about them.
- */
- memblocks_present();
-
/*
* Reserve initrd memory if needed.
*/
@@ -497,7 +489,7 @@ static void __init mips_parse_crashkernel(void)
if (ret != 0 || crash_size <= 0)
return;
- if (!memblock_find_in_range(crash_base, crash_base + crash_size, crash_size, 0)) {
+ if (!memblock_find_in_range(crash_base, crash_base + crash_size, crash_size, 1)) {
pr_warn("Invalid memory region reserved for crash kernel\n");
return;
}
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
index f777141f5256..f9df9edb67a4 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
@@ -60,8 +60,8 @@
50 n32 getsockname sys_getsockname
51 n32 getpeername sys_getpeername
52 n32 socketpair sys_socketpair
-53 n32 setsockopt compat_sys_setsockopt
-54 n32 getsockopt compat_sys_getsockopt
+53 n32 setsockopt sys_setsockopt
+54 n32 getsockopt sys_getsockopt
55 n32 clone __sys_clone
56 n32 fork __sys_fork
57 n32 execve compat_sys_execve
@@ -159,7 +159,7 @@
149 n32 munlockall sys_munlockall
150 n32 vhangup sys_vhangup
151 n32 pivot_root sys_pivot_root
-152 n32 _sysctl compat_sys_sysctl
+152 n32 _sysctl sys_ni_syscall
153 n32 prctl sys_prctl
154 n32 adjtimex sys_adjtimex_time32
155 n32 setrlimit compat_sys_setrlimit
@@ -374,6 +374,7 @@
433 n32 fspick sys_fspick
434 n32 pidfd_open sys_pidfd_open
435 n32 clone3 __sys_clone3
+436 n32 close_range sys_close_range
437 n32 openat2 sys_openat2
438 n32 pidfd_getfd sys_pidfd_getfd
439 n32 faccessat2 sys_faccessat2
diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
index da8c76394e17..557f9954a2b9 100644
--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
@@ -159,7 +159,7 @@
149 n64 munlockall sys_munlockall
150 n64 vhangup sys_vhangup
151 n64 pivot_root sys_pivot_root
-152 n64 _sysctl sys_sysctl
+152 n64 _sysctl sys_ni_syscall
153 n64 prctl sys_prctl
154 n64 adjtimex sys_adjtimex
155 n64 setrlimit sys_setrlimit
@@ -350,6 +350,7 @@
433 n64 fspick sys_fspick
434 n64 pidfd_open sys_pidfd_open
435 n64 clone3 __sys_clone3
+436 n64 close_range sys_close_range
437 n64 openat2 sys_openat2
438 n64 pidfd_getfd sys_pidfd_getfd
439 n64 faccessat2 sys_faccessat2
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
index 13280625d312..195b43cf27c8 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -164,7 +164,7 @@
150 o32 unused150 sys_ni_syscall
151 o32 getsid sys_getsid
152 o32 fdatasync sys_fdatasync
-153 o32 _sysctl sys_sysctl compat_sys_sysctl
+153 o32 _sysctl sys_ni_syscall
154 o32 mlock sys_mlock
155 o32 munlock sys_munlock
156 o32 mlockall sys_mlockall
@@ -184,7 +184,7 @@
170 o32 connect sys_connect
171 o32 getpeername sys_getpeername
172 o32 getsockname sys_getsockname
-173 o32 getsockopt sys_getsockopt compat_sys_getsockopt
+173 o32 getsockopt sys_getsockopt sys_getsockopt
174 o32 listen sys_listen
175 o32 recv sys_recv compat_sys_recv
176 o32 recvfrom sys_recvfrom compat_sys_recvfrom
@@ -192,7 +192,7 @@
178 o32 send sys_send
179 o32 sendmsg sys_sendmsg compat_sys_sendmsg
180 o32 sendto sys_sendto
-181 o32 setsockopt sys_setsockopt compat_sys_setsockopt
+181 o32 setsockopt sys_setsockopt sys_setsockopt
182 o32 shutdown sys_shutdown
183 o32 socket sys_socket
184 o32 socketpair sys_socketpair
@@ -423,6 +423,7 @@
433 o32 fspick sys_fspick
434 o32 pidfd_open sys_pidfd_open
435 o32 clone3 __sys_clone3
+436 o32 close_range sys_close_range
437 o32 openat2 sys_openat2
438 o32 pidfd_getfd sys_pidfd_getfd
439 o32 faccessat2 sys_faccessat2
diff --git a/arch/mips/kernel/topology.c b/arch/mips/kernel/topology.c
index cd3e1f82e1a5..08ad6371fbe0 100644
--- a/arch/mips/kernel/topology.c
+++ b/arch/mips/kernel/topology.c
@@ -20,7 +20,7 @@ static int __init topology_init(void)
for_each_present_cpu(i) {
struct cpu *c = &per_cpu(cpu_devices, i);
- c->hotpluggable = 1;
+ c->hotpluggable = !!i;
ret = register_cpu(c, i);
if (ret)
printk(KERN_WARNING "topology_init: register_cpu %d "
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index f655af68176c..38aa07ccdbcc 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -90,6 +90,7 @@ extern asmlinkage void handle_tr(void);
extern asmlinkage void handle_msa_fpe(void);
extern asmlinkage void handle_fpe(void);
extern asmlinkage void handle_ftlb(void);
+extern asmlinkage void handle_gsexc(void);
extern asmlinkage void handle_msa(void);
extern asmlinkage void handle_mdmx(void);
extern asmlinkage void handle_watch(void);
@@ -1680,7 +1681,7 @@ __setup("nol2par", nol2parity);
* Some MIPS CPUs can enable/disable for cache parity detection, but do
* it different ways.
*/
-static inline void parity_protection_init(void)
+static inline __init void parity_protection_init(void)
{
#define ERRCTL_PE 0x80000000
#define ERRCTL_L2P 0x00800000
@@ -1902,6 +1903,37 @@ asmlinkage void do_ftlb(void)
cache_parity_error();
}
+asmlinkage void do_gsexc(struct pt_regs *regs, u32 diag1)
+{
+ u32 exccode = (diag1 & LOONGSON_DIAG1_EXCCODE) >>
+ LOONGSON_DIAG1_EXCCODE_SHIFT;
+ enum ctx_state prev_state;
+
+ prev_state = exception_enter();
+
+ switch (exccode) {
+ case 0x08:
+ /* Undocumented exception, will trigger on certain
+ * also-undocumented instructions accessible from userspace.
+ * Processor state is not otherwise corrupted, but currently
+ * we don't know how to proceed. Maybe there is some
+ * undocumented control flag to enable the instructions?
+ */
+ force_sig(SIGILL);
+ break;
+
+ default:
+ /* None of the other exceptions, documented or not, have
+ * further details given; none are encountered in the wild
+ * either. Panic in case some of them turn out to be fatal.
+ */
+ show_regs(regs);
+ panic("Unhandled Loongson exception - GSCause = %08x", diag1);
+ }
+
+ exception_exit(prev_state);
+}
+
/*
* SDBBP EJTAG debug exception handler.
* We skip the instruction and return to the next instruction.
@@ -2457,7 +2489,11 @@ void __init trap_init(void)
if (cpu_has_fpu && !cpu_has_nofpuex)
set_except_vector(EXCCODE_FPE, handle_fpe);
- set_except_vector(MIPS_EXCCODE_TLBPAR, handle_ftlb);
+ if (cpu_has_ftlbparex)
+ set_except_vector(MIPS_EXCCODE_TLBPAR, handle_ftlb);
+
+ if (cpu_has_gsexcex)
+ set_except_vector(LOONGSON_EXCCODE_GSEXC, handle_gsexc);
if (cpu_has_rixiex) {
set_except_vector(EXCCODE_TLBRI, tlb_do_page_fault_0);
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 0adce604fa44..126a5f3f4e4c 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -191,17 +191,16 @@ static void emulate_load_store_insn(struct pt_regs *regs,
* memory, so we need to "switch" the address limit to
* user space, so that address check can work properly.
*/
- seg = get_fs();
- set_fs(USER_DS);
+ seg = force_uaccess_begin();
switch (insn.spec3_format.func) {
case lhe_op:
if (!access_ok(addr, 2)) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto sigbus;
}
LoadHWE(addr, value, res);
if (res) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto fault;
}
compute_return_epc(regs);
@@ -209,12 +208,12 @@ static void emulate_load_store_insn(struct pt_regs *regs,
break;
case lwe_op:
if (!access_ok(addr, 4)) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto sigbus;
}
LoadWE(addr, value, res);
if (res) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto fault;
}
compute_return_epc(regs);
@@ -222,12 +221,12 @@ static void emulate_load_store_insn(struct pt_regs *regs,
break;
case lhue_op:
if (!access_ok(addr, 2)) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto sigbus;
}
LoadHWUE(addr, value, res);
if (res) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto fault;
}
compute_return_epc(regs);
@@ -235,35 +234,35 @@ static void emulate_load_store_insn(struct pt_regs *regs,
break;
case she_op:
if (!access_ok(addr, 2)) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto sigbus;
}
compute_return_epc(regs);
value = regs->regs[insn.spec3_format.rt];
StoreHWE(addr, value, res);
if (res) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto fault;
}
break;
case swe_op:
if (!access_ok(addr, 4)) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto sigbus;
}
compute_return_epc(regs);
value = regs->regs[insn.spec3_format.rt];
StoreWE(addr, value, res);
if (res) {
- set_fs(seg);
+ force_uaccess_end(seg);
goto fault;
}
break;
default:
- set_fs(seg);
+ force_uaccess_end(seg);
goto sigill;
}
- set_fs(seg);
+ force_uaccess_end(seg);
}
#endif
break;