vm_switch.S 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Context switch support for Hexagon
  3. *
  4. * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 and
  8. * only version 2 as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  18. * 02110-1301, USA.
  19. */
  20. #include <asm/asm-offsets.h>
  21. .text
  22. /*
  23. * The register used as a fast-path thread information pointer
  24. * is determined as a kernel configuration option. If it happens
  25. * to be a callee-save register, we're going to be saving and
  26. * restoring it twice here.
  27. *
  28. * This code anticipates a revised ABI where R20-23 are added
  29. * to the set of callee-save registers, but this should be
  30. * backward compatible to legacy tools.
  31. */
  32. /*
  33. * void switch_to(struct task_struct *prev,
  34. * struct task_struct *next, struct task_struct *last);
  35. */
  36. .p2align 2
  37. .globl __switch_to
  38. .type __switch_to, @function
  39. /*
  40. * When we exit the wormhole, we need to store the previous task
  41. * in the new R0's pointer. Technically it should be R2, but they should
  42. * be the same; seems like a legacy thing. In short, don't butcher
  43. * R0, let it go back out unmolested.
  44. */
  45. __switch_to:
  46. /*
  47. * Push callee-saves onto "prev" stack.
  48. * Here, we're sneaky because the LR and FP
  49. * storage of the thread_stack structure
  50. * is automagically allocated by allocframe,
  51. * so we pass struct size less 8.
  52. */
  53. allocframe(#(_SWITCH_STACK_SIZE - 8));
  54. memd(R29+#(_SWITCH_R2726))=R27:26;
  55. memd(R29+#(_SWITCH_R2524))=R25:24;
  56. memd(R29+#(_SWITCH_R2322))=R23:22;
  57. memd(R29+#(_SWITCH_R2120))=R21:20;
  58. memd(R29+#(_SWITCH_R1918))=R19:18;
  59. memd(R29+#(_SWITCH_R1716))=R17:16;
  60. /* Stash thread_info pointer in task_struct */
  61. memw(R0+#_TASK_THREAD_INFO) = THREADINFO_REG;
  62. memw(R0 +#(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP)) = R29;
  63. /* Switch to "next" stack and restore callee saves from there */
  64. R29 = memw(R1 + #(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP));
  65. {
  66. R27:26 = memd(R29+#(_SWITCH_R2726));
  67. R25:24 = memd(R29+#(_SWITCH_R2524));
  68. }
  69. {
  70. R23:22 = memd(R29+#(_SWITCH_R2322));
  71. R21:20 = memd(R29+#(_SWITCH_R2120));
  72. }
  73. {
  74. R19:18 = memd(R29+#(_SWITCH_R1918));
  75. R17:16 = memd(R29+#(_SWITCH_R1716));
  76. }
  77. {
  78. /* THREADINFO_REG is currently one of the callee-saved regs
  79. * above, and so be sure to re-load it last.
  80. */
  81. THREADINFO_REG = memw(R1 + #_TASK_THREAD_INFO);
  82. R31:30 = memd(R29+#_SWITCH_FP);
  83. }
  84. {
  85. R29 = add(R29,#_SWITCH_STACK_SIZE);
  86. jumpr R31;
  87. }
  88. .size __switch_to, .-__switch_to