#ifdef ARC_DW2_UNWIND_AS_CFI
 
-#define CFI_STARTPROC  .cfi_startproc
-#define CFI_ENDPROC    .cfi_endproc
-#define CFI_DEF_CFA    .cfi_def_cfa
-#define CFI_REGISTER   .cfi_register
-#define CFI_REL_OFFSET .cfi_rel_offset
-#define CFI_UNDEFINED  .cfi_undefined
+#define CFI_STARTPROC          .cfi_startproc
+#define CFI_ENDPROC            .cfi_endproc
+#define CFI_DEF_CFA            .cfi_def_cfa
+#define CFI_DEF_CFA_OFFSET     .cfi_def_cfa_offset
+#define CFI_DEF_CFA_REGISTER   .cfi_def_cfa_register
+#define CFI_OFFSET             .cfi_offset
+#define CFI_REL_OFFSET         .cfi_rel_offset
+#define CFI_REGISTER           .cfi_register
+#define CFI_RESTORE            .cfi_restore
+#define CFI_UNDEFINED          .cfi_undefined
 
 #else
 
 #define CFI_IGNORE     #
 
-#define CFI_STARTPROC  CFI_IGNORE
-#define CFI_ENDPROC    CFI_IGNORE
-#define CFI_DEF_CFA    CFI_IGNORE
-#define CFI_REGISTER   CFI_IGNORE
-#define CFI_REL_OFFSET CFI_IGNORE
-#define CFI_UNDEFINED  CFI_IGNORE
+#define CFI_STARTPROC          CFI_IGNORE
+#define CFI_ENDPROC            CFI_IGNORE
+#define CFI_DEF_CFA            CFI_IGNORE
+#define CFI_DEF_CFA_OFFSET     CFI_IGNORE
+#define CFI_DEF_CFA_REGISTER   CFI_IGNORE
+#define CFI_OFFSET             CFI_IGNORE
+#define CFI_REL_OFFSET         CFI_IGNORE
+#define CFI_REGISTER           CFI_IGNORE
+#define CFI_RESTORE            CFI_IGNORE
+#define CFI_UNDEFINED          CFI_IGNORE
 
 #endif /* !ARC_DW2_UNWIND_AS_CFI */
 
 
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * Vineetg: Aug 2009
- *  -"C" version of lowest level context switch asm macro called by schedular
- *   gcc doesn't generate the dward CFI info for hand written asm, hence can't
- *   backtrace out of it (e.g. tasks sleeping in kernel).
- *   So we cheat a bit by writing almost similar code in inline-asm.
- *  -This is a hacky way of doing things, but there is no other simple way.
- *   I don't want/intend to extend unwinding code to understand raw asm
- */
-
-#include <asm/asm-offsets.h>
-#include <asm/switch_to.h>
-#include <linux/sched/debug.h>
-
-#define KSP_WORD_OFF   ((TASK_THREAD + THREAD_KSP) / 4)
-
-struct task_struct *__sched
-__switch_to(struct task_struct *prev_task, struct task_struct *next_task)
-{
-       unsigned int tmp;
-       unsigned int prev = (unsigned int)prev_task;
-       unsigned int next = (unsigned int)next_task;
-
-       __asm__ __volatile__(
-               /* FP/BLINK save generated by gcc (standard function prologue */
-               "st.a    r13, [sp, -4]   \n\t"
-               "st.a    r14, [sp, -4]   \n\t"
-               "st.a    r15, [sp, -4]   \n\t"
-               "st.a    r16, [sp, -4]   \n\t"
-               "st.a    r17, [sp, -4]   \n\t"
-               "st.a    r18, [sp, -4]   \n\t"
-               "st.a    r19, [sp, -4]   \n\t"
-               "st.a    r20, [sp, -4]   \n\t"
-               "st.a    r21, [sp, -4]   \n\t"
-               "st.a    r22, [sp, -4]   \n\t"
-               "st.a    r23, [sp, -4]   \n\t"
-               "st.a    r24, [sp, -4]   \n\t"
-               "st.a    r25, [sp, -4]   \n\t"
-
-               /* set ksp of outgoing task in tsk->thread.ksp */
-#if KSP_WORD_OFF <= 255
-               "st.as   sp, [%3, %1]    \n\t"
-#else
-               /*
-                * Workaround for NR_CPUS=4k
-                * %1 is bigger than 255 (S9 offset for st.as)
-                */
-               "add2    r24, %3, %1     \n\t"
-               "st      sp, [r24]       \n\t"
-#endif
-
-               /*
-                * setup _current_task with incoming tsk.
-                * optionally, set caching reg to that as well
-                * For SMP extra work to get to &_current_task[cpu]
-                * (open coded SET_CURR_TASK_ON_CPU)
-                */
-#ifndef CONFIG_SMP
-               "st  %2, [@_current_task]       \n\t"
-#else
-               "lr   r24, [identity]           \n\t"
-               "lsr  r24, r24, 8               \n\t"
-               "bmsk r24, r24, 7               \n\t"
-               "add2 r24, @_current_task, r24  \n\t"
-               "st   %2,  [r24]                \n\t"
-#endif
-#ifdef CONFIG_ARC_CURR_IN_REG
-               "mov gp, %2   \n\t"
-#endif
-
-               /* get ksp of incoming task from tsk->thread.ksp */
-               "ld.as  sp, [%2, %1]   \n\t"
-
-               /* start loading it's CALLEE reg file */
-               "ld.ab   r25, [sp, 4]   \n\t"
-               "ld.ab   r24, [sp, 4]   \n\t"
-               "ld.ab   r23, [sp, 4]   \n\t"
-               "ld.ab   r22, [sp, 4]   \n\t"
-               "ld.ab   r21, [sp, 4]   \n\t"
-               "ld.ab   r20, [sp, 4]   \n\t"
-               "ld.ab   r19, [sp, 4]   \n\t"
-               "ld.ab   r18, [sp, 4]   \n\t"
-               "ld.ab   r17, [sp, 4]   \n\t"
-               "ld.ab   r16, [sp, 4]   \n\t"
-               "ld.ab   r15, [sp, 4]   \n\t"
-               "ld.ab   r14, [sp, 4]   \n\t"
-               "ld.ab   r13, [sp, 4]   \n\t"
-
-               /* last (ret value) = prev : although for ARC it mov r0, r0 */
-               "mov     %0, %3        \n\t"
-
-               /* FP/BLINK restore generated by gcc (standard func epilogue */
-
-               : "=r"(tmp)
-               : "n"(KSP_WORD_OFF), "r"(next), "r"(prev)
-               : "blink"
-       );
-
-       return (struct task_struct *)tmp;
-}
 
 
 #define KSP_WORD_OFF   ((TASK_THREAD + THREAD_KSP) / 4)
 
-;################### Low Level Context Switch ##########################
+; IN
+;  - r0: prev task (also current)
+;  - r1: next task
+; OUT
+;  - r0: prev task (so r0 not touched)
 
        .section .sched.text,"ax",@progbits
-       .align 4
-       .global __switch_to
-       .type   __switch_to, @function
-__switch_to:
-       CFI_STARTPROC
-
-       /* Save regs on kernel mode stack of task */
-       st.a    blink, [sp, -4]
-       st.a    fp, [sp, -4]
+ENTRY_CFI(__switch_to)
+
+       /* save kernel stack frame regs of @prev task */
+       push    blink
+       CFI_DEF_CFA_OFFSET 4
+       CFI_OFFSET r31, -4
+
+       push    fp
+       CFI_DEF_CFA_OFFSET 8
+       CFI_OFFSET r27, -8
+
+       mov     fp, sp
+       CFI_DEF_CFA_REGISTER r27
+
+       /* kernel mode callee regs of @prev */
        SAVE_CALLEE_SAVED_KERNEL
 
-       /* Save the now KSP in task->thread.ksp */
+       /* save final SP to @prev->thread.ksp */
 #if KSP_WORD_OFF  <= 255
        st.as  sp, [r0, KSP_WORD_OFF]
 #else
        /* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */
-       add2    r24, r0, KSP_WORD_OFF
-       st      sp, [r24]
+       add2    r10, r0, KSP_WORD_OFF
+       st      sp, [r10]
 #endif
-       /*
-       * Return last task in r0 (return reg)
-       * On ARC, Return reg = First Arg reg = r0.
-       * Since we already have last task in r0,
-       * don't need to do anything special to return it
-       */
-
-       /*
-        * switch to new task, contained in r1
-        * Temp reg r3 is required to get the ptr to store val
-        */
-       SET_CURR_TASK_ON_CPU  r1, r3
-
-       /* reload SP with kernel mode stack pointer in task->thread.ksp */
-       ld.as  sp, [r1, KSP_WORD_OFF]
-
-       /* restore the registers */
+       /* update @next in _current_task[] and GP register caching it */
+       SET_CURR_TASK_ON_CPU  r1, r10
+
+       /* load SP from @next->thread.ksp */
+       ld.as   sp, [r1, KSP_WORD_OFF]
+
+       /* restore callee regs, stack frame regs of @next */
        RESTORE_CALLEE_SAVED_KERNEL
-       ld.ab   fp, [sp, 4]
-       ld.ab   blink, [sp, 4]
-       j       [blink]
 
+       pop     fp
+       CFI_RESTORE r27
+       CFI_DEF_CFA r28, 4
+
+       pop     blink
+       CFI_RESTORE r31
+       CFI_DEF_CFA_OFFSET 0
+
+       j      [blink]
 END_CFI(__switch_to)