MIPS: Loongson-3: Enable COP2 usage in kernel
authorHuacai Chen <chenhc@lemote.com>
Mon, 21 Sep 2020 09:12:27 +0000 (17:12 +0800)
committerThomas Bogendoerfer <tsbogend@alpha.franken.de>
Mon, 21 Sep 2020 20:15:03 +0000 (22:15 +0200)
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>
arch/mips/boot/compressed/Makefile
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/stackframe.h
arch/mips/kernel/head.S
arch/mips/kernel/process.c
arch/mips/kernel/traps.c

index 9a9ba77b745ee6910ce477a55a737f89c0a42904..d66511825fe1e9d2245231eec3b2918b28e845e6 100644 (file)
@@ -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"
 
index 3a7379b8f31cd589dfaad3bf5bd7dd8cb1a0f0dd..a0e8ae5497b61775ed67f87987f6337297bdce96 100644 (file)
 #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)
  */
index 3e8d2aaf96af1d2bdaddbf6ea0fc60ae6a6d2229..aa430a6c68b2421e07c26e9ccc0471f7daa33ad4 100644 (file)
  */
                .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
  */
                .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
  */
                .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
index 7dd234e788e63ec4945d6fd8b3f03f208fc17ebe..61b73580b87742bed18690c53cec73838cc93b63 100644 (file)
@@ -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
index f5dc316a826a041b9bd1b71e31e6d25af6edaf3c..b36297ee2b37827c00a1904dfd2d5dfd14843a7b 100644 (file)
@@ -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;
index 38aa07ccdbcc25758ac931f8909a22971a7f3b8f..14225b616119f9a563a10e4f3afae72d03f2e98c 100644 (file)
@@ -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