diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 39 | ||||
-rw-r--r-- | arch/mips/kernel/genex.S | 14 | ||||
-rw-r--r-- | arch/mips/kernel/head.S | 6 | ||||
-rw-r--r-- | arch/mips/kernel/mips_machine.c | 62 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/ptrace.c | 204 | ||||
-rw-r--r-- | arch/mips/kernel/setup.c | 10 | ||||
-rw-r--r-- | arch/mips/kernel/syscalls/syscall_n32.tbl | 7 | ||||
-rw-r--r-- | arch/mips/kernel/syscalls/syscall_n64.tbl | 3 | ||||
-rw-r--r-- | arch/mips/kernel/syscalls/syscall_o32.tbl | 7 | ||||
-rw-r--r-- | arch/mips/kernel/topology.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 40 | ||||
-rw-r--r-- | arch/mips/kernel/unaligned.c | 27 |
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; |