summaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
authorHuacai Chen <chenhc@lemote.com>2020-09-21 17:12:27 +0800
committerThomas Bogendoerfer <tsbogend@alpha.franken.de>2020-09-21 22:15:03 +0200
commit195615ecc8309082a524433cf552eda722b26c1c (patch)
tree08d25c30f8af71ab927275237f96e6fdd4b0abfe /arch/mips
parent4e43e5df5850ca8300180f422727e42a5065aaaa (diff)
MIPS: Loongson-3: Enable COP2 usage in kernel
Loongson-3's COP2 is Multi-Media coprocessor, it is disabled in kernel mode by default. However, gslq/gssq (16-bytes load/store instructions) overrides the instruction format of lwc2/swc2. If we wan't to use gslq/ gssq for optimization in kernel, we should enable COP2 usage in kernel. Please pay attention that in this patch we only enable COP2 in kernel, which means it will lose ST0_CU2 when a process go to user space (try to use COP2 in user space will trigger an exception and then grab COP2, which is similar to FPU). And as a result, we need to modify the context switching code because the new scheduled process doesn't contain ST0_CU2 in its THERAD_STATUS probably. For zboot, we disable gslq/gssq be generated by toolchain. Signed-off-by: Huacai Chen <chenhc@lemote.com> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/boot/compressed/Makefile5
-rw-r--r--arch/mips/include/asm/mipsregs.h7
-rw-r--r--arch/mips/include/asm/stackframe.h6
-rw-r--r--arch/mips/kernel/head.S2
-rw-r--r--arch/mips/kernel/process.c4
-rw-r--r--arch/mips/kernel/traps.c2
6 files changed, 19 insertions, 7 deletions
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 9a9ba77b745e..d66511825fe1 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -22,6 +22,11 @@ KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS))
KBUILD_CFLAGS := $(filter-out -fstack-protector, $(KBUILD_CFLAGS))
+# Disable lq/sq in zboot
+ifdef CONFIG_CPU_LOONGSON64
+KBUILD_CFLAGS := $(filter-out -march=loongson3a, $(KBUILD_CFLAGS)) -march=mips64r2
+endif
+
KBUILD_CFLAGS := $(KBUILD_CFLAGS) -D__KERNEL__ -D__DISABLE_EXPORTS \
-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull"
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 3a7379b8f31c..a0e8ae5497b6 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -389,6 +389,13 @@
#define ST0_CU3 0x80000000
#define ST0_XX 0x80000000 /* MIPS IV naming */
+/* in-kernel enabled CUs */
+#ifdef CONFIG_CPU_LOONGSON64
+#define ST0_KERNEL_CUMASK (ST0_CU0 | ST0_CU2)
+#else
+#define ST0_KERNEL_CUMASK ST0_CU0
+#endif
+
/*
* Bitfields and bit numbers in the coprocessor 0 IntCtl register. (MIPSR2)
*/
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 3e8d2aaf96af..aa430a6c68b2 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -450,7 +450,7 @@
*/
.macro CLI
mfc0 t0, CP0_STATUS
- li t1, ST0_CU0 | STATMASK
+ li t1, ST0_KERNEL_CUMASK | STATMASK
or t0, t1
xori t0, STATMASK
mtc0 t0, CP0_STATUS
@@ -463,7 +463,7 @@
*/
.macro STI
mfc0 t0, CP0_STATUS
- li t1, ST0_CU0 | STATMASK
+ li t1, ST0_KERNEL_CUMASK | STATMASK
or t0, t1
xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS
@@ -477,7 +477,7 @@
*/
.macro KMODE
mfc0 t0, CP0_STATUS
- li t1, ST0_CU0 | (STATMASK & ~1)
+ li t1, ST0_KERNEL_CUMASK | (STATMASK & ~1)
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
andi t2, t0, ST0_IEP
srl t2, 2
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 7dd234e788e6..61b73580b877 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -35,7 +35,7 @@
.macro setup_c0_status set clr
.set push
mfc0 t0, CP0_STATUS
- or t0, ST0_CU0|\set|0x1f|\clr
+ or t0, ST0_KERNEL_CUMASK|\set|0x1f|\clr
xor t0, 0x1f|\clr
mtc0 t0, CP0_STATUS
.set noreorder
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index f5dc316a826a..b36297ee2b37 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -68,7 +68,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
unsigned long status;
/* New thread loses kernel privileges. */
- status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_FR|KU_MASK);
+ status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_CU2|ST0_FR|KU_MASK);
status |= KU_USER;
regs->cp0_status = status;
lose_fpu(0);
@@ -133,7 +133,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
childregs = (struct pt_regs *) childksp - 1;
/* Put the stack after the struct pt_regs. */
childksp = (unsigned long) childregs;
- p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
+ p->thread.cp0_status = (read_c0_status() & ~(ST0_CU2|ST0_CU1)) | ST0_KERNEL_CUMASK;
if (unlikely(p->flags & PF_KTHREAD)) {
/* kernel thread */
unsigned long status = p->thread.cp0_status;
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 38aa07ccdbcc..14225b616119 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -2192,7 +2192,7 @@ static void configure_status(void)
* flag that some firmware may have left set and the TS bit (for
* IP27). Set XX for ISA IV code to work.
*/
- unsigned int status_set = ST0_CU0;
+ unsigned int status_set = ST0_KERNEL_CUMASK;
#ifdef CONFIG_64BIT
status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX;
#endif