mem_encrypt.S 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * AMD Memory Encryption Support
  4. *
  5. * Copyright (C) 2017 Advanced Micro Devices, Inc.
  6. *
  7. * Author: Tom Lendacky <[email protected]>
  8. */
  9. #include <linux/linkage.h>
  10. #include <asm/processor-flags.h>
  11. #include <asm/msr.h>
  12. #include <asm/asm-offsets.h>
  13. .text
  14. .code32
  15. SYM_FUNC_START(get_sev_encryption_bit)
  16. xor %eax, %eax
  17. #ifdef CONFIG_AMD_MEM_ENCRYPT
  18. push %ebx
  19. push %ecx
  20. push %edx
  21. movl $0x80000000, %eax /* CPUID to check the highest leaf */
  22. cpuid
  23. cmpl $0x8000001f, %eax /* See if 0x8000001f is available */
  24. jb .Lno_sev
  25. /*
  26. * Check for the SEV feature:
  27. * CPUID Fn8000_001F[EAX] - Bit 1
  28. * CPUID Fn8000_001F[EBX] - Bits 5:0
  29. * Pagetable bit position used to indicate encryption
  30. */
  31. movl $0x8000001f, %eax
  32. cpuid
  33. bt $1, %eax /* Check if SEV is available */
  34. jnc .Lno_sev
  35. movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */
  36. rdmsr
  37. bt $MSR_AMD64_SEV_ENABLED_BIT, %eax /* Check if SEV is active */
  38. jnc .Lno_sev
  39. movl %ebx, %eax
  40. andl $0x3f, %eax /* Return the encryption bit location */
  41. jmp .Lsev_exit
  42. .Lno_sev:
  43. xor %eax, %eax
  44. .Lsev_exit:
  45. pop %edx
  46. pop %ecx
  47. pop %ebx
  48. #endif /* CONFIG_AMD_MEM_ENCRYPT */
  49. RET
  50. SYM_FUNC_END(get_sev_encryption_bit)
  51. /**
  52. * sev_es_req_cpuid - Request a CPUID value from the Hypervisor using
  53. * the GHCB MSR protocol
  54. *
  55. * @%eax: Register to request (0=EAX, 1=EBX, 2=ECX, 3=EDX)
  56. * @%edx: CPUID Function
  57. *
  58. * Returns 0 in %eax on success, non-zero on failure
  59. * %edx returns CPUID value on success
  60. */
  61. SYM_CODE_START_LOCAL(sev_es_req_cpuid)
  62. shll $30, %eax
  63. orl $0x00000004, %eax
  64. movl $MSR_AMD64_SEV_ES_GHCB, %ecx
  65. wrmsr
  66. rep; vmmcall # VMGEXIT
  67. rdmsr
  68. /* Check response */
  69. movl %eax, %ecx
  70. andl $0x3ffff000, %ecx # Bits [12-29] MBZ
  71. jnz 2f
  72. /* Check return code */
  73. andl $0xfff, %eax
  74. cmpl $5, %eax
  75. jne 2f
  76. /* All good - return success */
  77. xorl %eax, %eax
  78. 1:
  79. RET
  80. 2:
  81. movl $-1, %eax
  82. jmp 1b
  83. SYM_CODE_END(sev_es_req_cpuid)
  84. SYM_CODE_START(startup32_vc_handler)
  85. pushl %eax
  86. pushl %ebx
  87. pushl %ecx
  88. pushl %edx
  89. /* Keep CPUID function in %ebx */
  90. movl %eax, %ebx
  91. /* Check if error-code == SVM_EXIT_CPUID */
  92. cmpl $0x72, 16(%esp)
  93. jne .Lfail
  94. movl $0, %eax # Request CPUID[fn].EAX
  95. movl %ebx, %edx # CPUID fn
  96. call sev_es_req_cpuid # Call helper
  97. testl %eax, %eax # Check return code
  98. jnz .Lfail
  99. movl %edx, 12(%esp) # Store result
  100. movl $1, %eax # Request CPUID[fn].EBX
  101. movl %ebx, %edx # CPUID fn
  102. call sev_es_req_cpuid # Call helper
  103. testl %eax, %eax # Check return code
  104. jnz .Lfail
  105. movl %edx, 8(%esp) # Store result
  106. movl $2, %eax # Request CPUID[fn].ECX
  107. movl %ebx, %edx # CPUID fn
  108. call sev_es_req_cpuid # Call helper
  109. testl %eax, %eax # Check return code
  110. jnz .Lfail
  111. movl %edx, 4(%esp) # Store result
  112. movl $3, %eax # Request CPUID[fn].EDX
  113. movl %ebx, %edx # CPUID fn
  114. call sev_es_req_cpuid # Call helper
  115. testl %eax, %eax # Check return code
  116. jnz .Lfail
  117. movl %edx, 0(%esp) # Store result
  118. /*
  119. * Sanity check CPUID results from the Hypervisor. See comment in
  120. * do_vc_no_ghcb() for more details on why this is necessary.
  121. */
  122. /* Fail if SEV leaf not available in CPUID[0x80000000].EAX */
  123. cmpl $0x80000000, %ebx
  124. jne .Lcheck_sev
  125. cmpl $0x8000001f, 12(%esp)
  126. jb .Lfail
  127. jmp .Ldone
  128. .Lcheck_sev:
  129. /* Fail if SEV bit not set in CPUID[0x8000001f].EAX[1] */
  130. cmpl $0x8000001f, %ebx
  131. jne .Ldone
  132. btl $1, 12(%esp)
  133. jnc .Lfail
  134. .Ldone:
  135. popl %edx
  136. popl %ecx
  137. popl %ebx
  138. popl %eax
  139. /* Remove error code */
  140. addl $4, %esp
  141. /* Jump over CPUID instruction */
  142. addl $2, (%esp)
  143. iret
  144. .Lfail:
  145. /* Send terminate request to Hypervisor */
  146. movl $0x100, %eax
  147. xorl %edx, %edx
  148. movl $MSR_AMD64_SEV_ES_GHCB, %ecx
  149. wrmsr
  150. rep; vmmcall
  151. /* If request fails, go to hlt loop */
  152. hlt
  153. jmp .Lfail
  154. SYM_CODE_END(startup32_vc_handler)
  155. .code64
  156. #include "../../kernel/sev_verify_cbit.S"
  157. .data
  158. #ifdef CONFIG_AMD_MEM_ENCRYPT
  159. .balign 8
  160. SYM_DATA(sme_me_mask, .quad 0)
  161. SYM_DATA(sev_status, .quad 0)
  162. SYM_DATA(sev_check_data, .quad 0)
  163. #endif