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

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
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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"

+7 −0
Original line number Diff line number Diff line
@@ -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)
 */
+3 −3
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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;
Loading