root/arch/hexagon/kernel/vm_switch.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /*
   3  * Context switch support for Hexagon
   4  *
   5  * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
   6  */
   7 
   8 #include <asm/asm-offsets.h>
   9 
  10 .text
  11 
  12 /*
  13  * The register used as a fast-path thread information pointer
  14  * is determined as a kernel configuration option.  If it happens
  15  * to be a callee-save register, we're going to be saving and
  16  * restoring it twice here.
  17  *
  18  * This code anticipates a revised ABI where R20-23 are added
  19  * to the set of callee-save registers, but this should be
  20  * backward compatible to legacy tools.
  21  */
  22 
  23 
  24 /*
  25  *      void switch_to(struct task_struct *prev,
  26  *              struct task_struct *next, struct task_struct *last);
  27  */
  28         .p2align 2
  29         .globl __switch_to
  30         .type   __switch_to, @function
  31 
  32 /*
  33  * When we exit the wormhole, we need to store the previous task
  34  * in the new R0's pointer.  Technically it should be R2, but they should
  35  * be the same; seems like a legacy thing.  In short, don't butcher
  36  * R0, let it go back out unmolested.
  37  */
  38 
  39 __switch_to:
  40         /*
  41          * Push callee-saves onto "prev" stack.
  42          * Here, we're sneaky because the LR and FP
  43          * storage of the thread_stack structure
  44          * is automagically allocated by allocframe,
  45          * so we pass struct size less 8.
  46          */
  47         allocframe(#(_SWITCH_STACK_SIZE - 8));
  48         memd(R29+#(_SWITCH_R2726))=R27:26;
  49         memd(R29+#(_SWITCH_R2524))=R25:24;
  50         memd(R29+#(_SWITCH_R2322))=R23:22;
  51         memd(R29+#(_SWITCH_R2120))=R21:20;
  52         memd(R29+#(_SWITCH_R1918))=R19:18;
  53         memd(R29+#(_SWITCH_R1716))=R17:16;
  54         /* Stash thread_info pointer in task_struct */
  55         memw(R0+#_TASK_THREAD_INFO) = THREADINFO_REG;
  56         memw(R0 +#(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP)) = R29;
  57         /* Switch to "next" stack and restore callee saves from there */
  58         R29 = memw(R1 + #(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP));
  59         {
  60             R27:26 = memd(R29+#(_SWITCH_R2726));
  61             R25:24 = memd(R29+#(_SWITCH_R2524));
  62         }
  63         {
  64             R23:22 = memd(R29+#(_SWITCH_R2322));
  65             R21:20 = memd(R29+#(_SWITCH_R2120));
  66         }
  67         {
  68             R19:18 = memd(R29+#(_SWITCH_R1918));
  69             R17:16 = memd(R29+#(_SWITCH_R1716));
  70         }
  71         {
  72             /* THREADINFO_REG is currently one of the callee-saved regs
  73              * above, and so be sure to re-load it last.
  74              */
  75             THREADINFO_REG = memw(R1 + #_TASK_THREAD_INFO);
  76             R31:30 = memd(R29+#_SWITCH_FP);
  77         }
  78         {
  79             R29 = add(R29,#_SWITCH_STACK_SIZE);
  80             jumpr R31;
  81         }
  82         .size   __switch_to, .-__switch_to

/* [<][>][^][v][top][bottom][index][help] */