Commit 195615ec authored by Huacai Chen's avatar Huacai Chen Committed by Thomas Bogendoerfer

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: default avatarHuacai Chen <chenhc@lemote.com>
Signed-off-by: default avatarThomas Bogendoerfer <tsbogend@alpha.franken.de>
parent 4e43e5df
...@@ -22,6 +22,11 @@ KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS)) ...@@ -22,6 +22,11 @@ KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS))
KBUILD_CFLAGS := $(filter-out -fstack-protector, $(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 \ KBUILD_CFLAGS := $(KBUILD_CFLAGS) -D__KERNEL__ -D__DISABLE_EXPORTS \
-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull"
......
...@@ -389,6 +389,13 @@ ...@@ -389,6 +389,13 @@
#define ST0_CU3 0x80000000 #define ST0_CU3 0x80000000
#define ST0_XX 0x80000000 /* MIPS IV naming */ #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) * Bitfields and bit numbers in the coprocessor 0 IntCtl register. (MIPSR2)
*/ */
......
...@@ -450,7 +450,7 @@ ...@@ -450,7 +450,7 @@
*/ */
.macro CLI .macro CLI
mfc0 t0, CP0_STATUS mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | STATMASK li t1, ST0_KERNEL_CUMASK | STATMASK
or t0, t1 or t0, t1
xori t0, STATMASK xori t0, STATMASK
mtc0 t0, CP0_STATUS mtc0 t0, CP0_STATUS
...@@ -463,7 +463,7 @@ ...@@ -463,7 +463,7 @@
*/ */
.macro STI .macro STI
mfc0 t0, CP0_STATUS mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | STATMASK li t1, ST0_KERNEL_CUMASK | STATMASK
or t0, t1 or t0, t1
xori t0, STATMASK & ~1 xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS mtc0 t0, CP0_STATUS
...@@ -477,7 +477,7 @@ ...@@ -477,7 +477,7 @@
*/ */
.macro KMODE .macro KMODE
mfc0 t0, CP0_STATUS 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) #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
andi t2, t0, ST0_IEP andi t2, t0, ST0_IEP
srl t2, 2 srl t2, 2
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
.macro setup_c0_status set clr .macro setup_c0_status set clr
.set push .set push
mfc0 t0, CP0_STATUS mfc0 t0, CP0_STATUS
or t0, ST0_CU0|\set|0x1f|\clr or t0, ST0_KERNEL_CUMASK|\set|0x1f|\clr
xor t0, 0x1f|\clr xor t0, 0x1f|\clr
mtc0 t0, CP0_STATUS mtc0 t0, CP0_STATUS
.set noreorder .set noreorder
......
...@@ -68,7 +68,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) ...@@ -68,7 +68,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
unsigned long status; unsigned long status;
/* New thread loses kernel privileges. */ /* 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; status |= KU_USER;
regs->cp0_status = status; regs->cp0_status = status;
lose_fpu(0); lose_fpu(0);
...@@ -133,7 +133,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, ...@@ -133,7 +133,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
childregs = (struct pt_regs *) childksp - 1; childregs = (struct pt_regs *) childksp - 1;
/* Put the stack after the struct pt_regs. */ /* Put the stack after the struct pt_regs. */
childksp = (unsigned long) childregs; 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)) { if (unlikely(p->flags & PF_KTHREAD)) {
/* kernel thread */ /* kernel thread */
unsigned long status = p->thread.cp0_status; unsigned long status = p->thread.cp0_status;
......
...@@ -2192,7 +2192,7 @@ static void configure_status(void) ...@@ -2192,7 +2192,7 @@ static void configure_status(void)
* flag that some firmware may have left set and the TS bit (for * flag that some firmware may have left set and the TS bit (for
* IP27). Set XX for ISA IV code to work. * 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 #ifdef CONFIG_64BIT
status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX; status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX;
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment