Merge branch 'drm-fixes-3.16' of git://people.freedesktop.org/~agd5f/linux
[cascardo/linux.git] / arch / mips / kernel / octeon_switch.S
index 029e002..f654768 100644 (file)
  * Copyright (C) 2000 MIPS Technologies, Inc.
  *    written by Carsten Langgaard, carstenl@mips.com
  */
-#include <asm/asm.h>
-#include <asm/cachectl.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsregs.h>
-#include <asm/asm-offsets.h>
-#include <asm/pgtable-bits.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/thread_info.h>
-
-#include <asm/asmmacro.h>
-
-/*
- * Offset to the current process status flags, the first 32 bytes of the
- * stack are not used.
- */
-#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
 
+#define USE_ALTERNATE_RESUME_IMPL 1
+       .set push
+       .set arch=mips64r2
+#include "r4k_switch.S"
+       .set pop
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
  *                    struct thread_info *next_ti, int usedfpu)
        cpu_save_nonscratch a0
        LONG_S  ra, THREAD_REG31(a0)
 
+       /*
+        * check if we need to save FPU registers
+        */
+       PTR_L   t3, TASK_THREAD_INFO(a0)
+       LONG_L  t0, TI_FLAGS(t3)
+       li      t1, _TIF_USEDFPU
+       and     t2, t0, t1
+       beqz    t2, 1f
+       nor     t1, zero, t1
+
+       and     t0, t0, t1
+       LONG_S  t0, TI_FLAGS(t3)
+
+       /*
+        * clear saved user stack CU1 bit
+        */
+       LONG_L  t0, ST_OFF(t3)
+       li      t1, ~ST0_CU1
+       and     t0, t0, t1
+       LONG_S  t0, ST_OFF(t3)
+
+       .set push
+       .set arch=mips64r2
+       fpu_save_double a0 t0 t1                # c0_status passed in t0
+                                               # clobbers t1
+       .set pop
+1:
+
+       /* check if we need to save COP2 registers */
+       PTR_L   t2, TASK_THREAD_INFO(a0)
+       LONG_L  t0, ST_OFF(t2)
+       bbit0   t0, 30, 1f
+
+       /* Disable COP2 in the stored process state */
+       li      t1, ST0_CU2
+       xor     t0, t1
+       LONG_S  t0, ST_OFF(t2)
+
+       /* Enable COP2 so we can save it */
+       mfc0    t0, CP0_STATUS
+       or      t0, t1
+       mtc0    t0, CP0_STATUS
+
+       /* Save COP2 */
+       daddu   a0, THREAD_CP2
+       jal octeon_cop2_save
+       dsubu   a0, THREAD_CP2
+
+       /* Disable COP2 now that we are done */
+       mfc0    t0, CP0_STATUS
+       li      t1, ST0_CU2
+       xor     t0, t1
+       mtc0    t0, CP0_STATUS
+
+1:
 #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
        /* Check if we need to store CVMSEG state */
        mfc0    t0, $11,7       /* CvmMemCtl */
        move    $28, a2
        cpu_restore_nonscratch a1
 
-#if (_THREAD_SIZE - 32) < 0x8000
-       PTR_ADDIU       t0, $28, _THREAD_SIZE - 32
-#else
-       PTR_LI          t0, _THREAD_SIZE - 32
-       PTR_ADDU        t0, $28
-#endif
+       PTR_ADDU        t0, $28, _THREAD_SIZE - 32
        set_saved_sp    t0, t1, t2
 
        mfc0    t1, CP0_STATUS          /* Do we really need this? */