system_call.S 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * AT_SYSINFO entry point
  3. */
  4. #include <asm/dwarf2.h>
  5. #include <asm/cpufeatures.h>
  6. #include <asm/alternative-asm.h>
  7. /*
  8. * First get the common code for the sigreturn entry points.
  9. * This must come first.
  10. */
  11. #include "sigreturn.S"
  12. .text
  13. .globl __kernel_vsyscall
  14. .type __kernel_vsyscall,@function
  15. ALIGN
  16. __kernel_vsyscall:
  17. CFI_STARTPROC
  18. /*
  19. * Reshuffle regs so that all of any of the entry instructions
  20. * will preserve enough state.
  21. *
  22. * A really nice entry sequence would be:
  23. * pushl %edx
  24. * pushl %ecx
  25. * movl %esp, %ecx
  26. *
  27. * Unfortunately, naughty Android versions between July and December
  28. * 2015 actually hardcode the traditional Linux SYSENTER entry
  29. * sequence. That is severely broken for a number of reasons (ask
  30. * anyone with an AMD CPU, for example). Nonetheless, we try to keep
  31. * it working approximately as well as it ever worked.
  32. *
  33. * This link may eludicate some of the history:
  34. * https://android-review.googlesource.com/#/q/Iac3295376d61ef83e713ac9b528f3b50aa780cd7
  35. * personally, I find it hard to understand what's going on there.
  36. *
  37. * Note to future user developers: DO NOT USE SYSENTER IN YOUR CODE.
  38. * Execute an indirect call to the address in the AT_SYSINFO auxv
  39. * entry. That is the ONLY correct way to make a fast 32-bit system
  40. * call on Linux. (Open-coding int $0x80 is also fine, but it's
  41. * slow.)
  42. */
  43. pushl %ecx
  44. CFI_ADJUST_CFA_OFFSET 4
  45. CFI_REL_OFFSET ecx, 0
  46. pushl %edx
  47. CFI_ADJUST_CFA_OFFSET 4
  48. CFI_REL_OFFSET edx, 0
  49. pushl %ebp
  50. CFI_ADJUST_CFA_OFFSET 4
  51. CFI_REL_OFFSET ebp, 0
  52. #define SYSENTER_SEQUENCE "movl %esp, %ebp; sysenter"
  53. #define SYSCALL_SEQUENCE "movl %ecx, %ebp; syscall"
  54. #ifdef CONFIG_X86_64
  55. /* If SYSENTER (Intel) or SYSCALL32 (AMD) is available, use it. */
  56. ALTERNATIVE_2 "", SYSENTER_SEQUENCE, X86_FEATURE_SYSENTER32, \
  57. SYSCALL_SEQUENCE, X86_FEATURE_SYSCALL32
  58. #else
  59. ALTERNATIVE "", SYSENTER_SEQUENCE, X86_FEATURE_SEP
  60. #endif
  61. /* Enter using int $0x80 */
  62. int $0x80
  63. GLOBAL(int80_landing_pad)
  64. /*
  65. * Restore EDX and ECX in case they were clobbered. EBP is not
  66. * clobbered (the kernel restores it), but it's cleaner and
  67. * probably faster to pop it than to adjust ESP using addl.
  68. */
  69. popl %ebp
  70. CFI_RESTORE ebp
  71. CFI_ADJUST_CFA_OFFSET -4
  72. popl %edx
  73. CFI_RESTORE edx
  74. CFI_ADJUST_CFA_OFFSET -4
  75. popl %ecx
  76. CFI_RESTORE ecx
  77. CFI_ADJUST_CFA_OFFSET -4
  78. ret
  79. CFI_ENDPROC
  80. .size __kernel_vsyscall,.-__kernel_vsyscall
  81. .previous