entry_64_fred.S 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * The actual FRED entry points.
  4. */
  5. #include <linux/export.h>
  6. #include <asm/asm.h>
  7. #include <asm/fred.h>
  8. #include <asm/segment.h>
  9. #include "calling.h"
  10. .code64
  11. .section .noinstr.text, "ax"
  12. .macro FRED_ENTER
  13. UNWIND_HINT_END_OF_STACK
  14. ENDBR
  15. PUSH_AND_CLEAR_REGS
  16. movq %rsp, %rdi /* %rdi -> pt_regs */
  17. .endm
  18. .macro FRED_EXIT
  19. UNWIND_HINT_REGS
  20. POP_REGS
  21. .endm
  22. /*
  23. * The new RIP value that FRED event delivery establishes is
  24. * IA32_FRED_CONFIG & ~FFFH for events that occur in ring 3.
  25. * Thus the FRED ring 3 entry point must be 4K page aligned.
  26. */
  27. .align 4096
  28. SYM_CODE_START_NOALIGN(asm_fred_entrypoint_user)
  29. FRED_ENTER
  30. call fred_entry_from_user
  31. SYM_INNER_LABEL(asm_fred_exit_user, SYM_L_GLOBAL)
  32. FRED_EXIT
  33. 1: ERETU
  34. _ASM_EXTABLE_TYPE(1b, asm_fred_entrypoint_user, EX_TYPE_ERETU)
  35. SYM_CODE_END(asm_fred_entrypoint_user)
  36. /*
  37. * The new RIP value that FRED event delivery establishes is
  38. * (IA32_FRED_CONFIG & ~FFFH) + 256 for events that occur in
  39. * ring 0, i.e., asm_fred_entrypoint_user + 256.
  40. */
  41. .org asm_fred_entrypoint_user + 256, 0xcc
  42. SYM_CODE_START_NOALIGN(asm_fred_entrypoint_kernel)
  43. FRED_ENTER
  44. call fred_entry_from_kernel
  45. FRED_EXIT
  46. ERETS
  47. SYM_CODE_END(asm_fred_entrypoint_kernel)
  48. #if IS_ENABLED(CONFIG_KVM_INTEL)
  49. SYM_FUNC_START(asm_fred_entry_from_kvm)
  50. push %rbp
  51. mov %rsp, %rbp
  52. UNWIND_HINT_SAVE
  53. /*
  54. * Both IRQ and NMI from VMX can be handled on current task stack
  55. * because there is no need to protect from reentrancy and the call
  56. * stack leading to this helper is effectively constant and shallow
  57. * (relatively speaking). Do the same when FRED is active, i.e., no
  58. * need to check current stack level for a stack switch.
  59. *
  60. * Emulate the FRED-defined redzone and stack alignment.
  61. */
  62. sub $(FRED_CONFIG_REDZONE_AMOUNT << 6), %rsp
  63. and $FRED_STACK_FRAME_RSP_MASK, %rsp
  64. /*
  65. * Start to push a FRED stack frame, which is always 64 bytes:
  66. *
  67. * +--------+-----------------+
  68. * | Bytes | Usage |
  69. * +--------+-----------------+
  70. * | 63:56 | Reserved |
  71. * | 55:48 | Event Data |
  72. * | 47:40 | SS + Event Info |
  73. * | 39:32 | RSP |
  74. * | 31:24 | RFLAGS |
  75. * | 23:16 | CS + Aux Info |
  76. * | 15:8 | RIP |
  77. * | 7:0 | Error Code |
  78. * +--------+-----------------+
  79. */
  80. push $0 /* Reserved, must be 0 */
  81. push $0 /* Event data, 0 for IRQ/NMI */
  82. push %rdi /* fred_ss handed in by the caller */
  83. push %rbp
  84. pushf
  85. mov $__KERNEL_CS, %rax
  86. push %rax
  87. /*
  88. * Unlike the IDT event delivery, FRED _always_ pushes an error code
  89. * after pushing the return RIP, thus the CALL instruction CANNOT be
  90. * used here to push the return RIP, otherwise there is no chance to
  91. * push an error code before invoking the IRQ/NMI handler.
  92. *
  93. * Use LEA to get the return RIP and push it, then push an error code.
  94. */
  95. lea 1f(%rip), %rax
  96. push %rax /* Return RIP */
  97. push $0 /* Error code, 0 for IRQ/NMI */
  98. PUSH_AND_CLEAR_REGS clear_bp=0 unwind_hint=0
  99. movq %rsp, %rdi /* %rdi -> pt_regs */
  100. call __fred_entry_from_kvm /* Call the C entry point */
  101. POP_REGS
  102. ERETS
  103. 1:
  104. /*
  105. * Objtool doesn't understand what ERETS does, this hint tells it that
  106. * yes, we'll reach here and with what stack state. A save/restore pair
  107. * isn't strictly needed, but it's the simplest form.
  108. */
  109. UNWIND_HINT_RESTORE
  110. pop %rbp
  111. RET
  112. SYM_FUNC_END(asm_fred_entry_from_kvm)
  113. EXPORT_SYMBOL_GPL(asm_fred_entry_from_kvm);
  114. #endif