vm_switch.S 2.3 KB

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