|
23 | 23 | *-------------------------------------------------------------------------
|
24 | 24 | * Input Registers:
|
25 | 25 | *
|
26 |
| - * RAX - TDCALL/SEAMCALL Leaf number. |
27 |
| - * RCX,RDX,R8-R11 - TDCALL/SEAMCALL Leaf specific input registers. |
| 26 | + * RAX - TDCALL/SEAMCALL Leaf number. |
| 27 | + * RCX,RDX,RDI,RSI,RBX,R8-R15 - TDCALL/SEAMCALL Leaf specific input registers. |
28 | 28 | *
|
29 | 29 | * Output Registers:
|
30 | 30 | *
|
31 |
| - * RAX - TDCALL/SEAMCALL instruction error code. |
32 |
| - * RCX,RDX,R8-R11 - TDCALL/SEAMCALL Leaf specific output registers. |
| 31 | + * RAX - TDCALL/SEAMCALL instruction error code. |
| 32 | + * RCX,RDX,RDI,RSI,RBX,R8-R15 - TDCALL/SEAMCALL Leaf specific output registers. |
33 | 33 | *
|
34 | 34 | *-------------------------------------------------------------------------
|
| 35 | + * |
| 36 | + * So while the common core (RAX,RCX,RDX,R8-R11) fits nicely in the |
| 37 | + * callee-clobbered registers and even leaves RDI,RSI free to act as a |
| 38 | + * base pointer, some leafs (e.g., VP.ENTER) make a giant mess of things. |
| 39 | + * |
| 40 | + * For simplicity, assume that anything that needs the callee-saved regs |
| 41 | + * also tramples on RDI,RSI. This isn't strictly true, see for example |
| 42 | + * TDH.EXPORT.MEM. |
35 | 43 | */
|
36 |
| -.macro TDX_MODULE_CALL host:req ret=0 |
| 44 | +.macro TDX_MODULE_CALL host:req ret=0 saved=0 |
37 | 45 | FRAME_BEGIN
|
38 | 46 |
|
39 | 47 | /* Move Leaf ID to RAX */
|
|
47 | 55 | movq TDX_MODULE_r10(%rsi), %r10
|
48 | 56 | movq TDX_MODULE_r11(%rsi), %r11
|
49 | 57 |
|
| 58 | +.if \saved |
| 59 | + /* |
| 60 | + * Move additional input regs from the structure. For simplicity |
| 61 | + * assume that anything needs the callee-saved regs also tramples |
| 62 | + * on RDI/RSI (see VP.ENTER). |
| 63 | + */ |
| 64 | + /* Save those callee-saved GPRs as mandated by the x86_64 ABI */ |
| 65 | + pushq %rbx |
| 66 | + pushq %r12 |
| 67 | + pushq %r13 |
| 68 | + pushq %r14 |
| 69 | + pushq %r15 |
| 70 | + |
| 71 | + movq TDX_MODULE_r12(%rsi), %r12 |
| 72 | + movq TDX_MODULE_r13(%rsi), %r13 |
| 73 | + movq TDX_MODULE_r14(%rsi), %r14 |
| 74 | + movq TDX_MODULE_r15(%rsi), %r15 |
| 75 | + movq TDX_MODULE_rbx(%rsi), %rbx |
| 76 | + |
| 77 | +.if \ret |
| 78 | + /* Save the structure pointer as RSI is about to be clobbered */ |
| 79 | + pushq %rsi |
| 80 | +.endif |
| 81 | + |
| 82 | + movq TDX_MODULE_rdi(%rsi), %rdi |
| 83 | + /* RSI needs to be done at last */ |
| 84 | + movq TDX_MODULE_rsi(%rsi), %rsi |
| 85 | +.endif /* \saved */ |
| 86 | + |
50 | 87 | .if \host
|
51 | 88 | seamcall
|
52 | 89 | /*
|
|
66 | 103 | .endif
|
67 | 104 |
|
68 | 105 | .if \ret
|
| 106 | +.if \saved |
| 107 | + /* |
| 108 | + * Restore the structure from stack to save the output registers |
| 109 | + * |
| 110 | + * In case of VP.ENTER returns due to TDVMCALL, all registers are |
| 111 | + * valid thus no register can be used as spare to restore the |
| 112 | + * structure from the stack (see "TDH.VP.ENTER Output Operands |
| 113 | + * Definition on TDCALL(TDG.VP.VMCALL) Following a TD Entry"). |
| 114 | + * For this case, need to make one register as spare by saving it |
| 115 | + * to the stack and then manually load the structure pointer to |
| 116 | + * the spare register. |
| 117 | + * |
| 118 | + * Note for other TDCALLs/SEAMCALLs there are spare registers |
| 119 | + * thus no need for such hack but just use this for all. |
| 120 | + */ |
| 121 | + pushq %rax /* save the TDCALL/SEAMCALL return code */ |
| 122 | + movq 8(%rsp), %rax /* restore the structure pointer */ |
| 123 | + movq %rsi, TDX_MODULE_rsi(%rax) /* save RSI */ |
| 124 | + popq %rax /* restore the return code */ |
| 125 | + popq %rsi /* pop the structure pointer */ |
| 126 | + |
| 127 | + /* Copy additional output regs to the structure */ |
| 128 | + movq %r12, TDX_MODULE_r12(%rsi) |
| 129 | + movq %r13, TDX_MODULE_r13(%rsi) |
| 130 | + movq %r14, TDX_MODULE_r14(%rsi) |
| 131 | + movq %r15, TDX_MODULE_r15(%rsi) |
| 132 | + movq %rbx, TDX_MODULE_rbx(%rsi) |
| 133 | + movq %rdi, TDX_MODULE_rdi(%rsi) |
| 134 | +.endif /* \saved */ |
| 135 | + |
69 | 136 | /* Copy output registers to the structure */
|
70 | 137 | movq %rcx, TDX_MODULE_rcx(%rsi)
|
71 | 138 | movq %rdx, TDX_MODULE_rdx(%rsi)
|
72 | 139 | movq %r8, TDX_MODULE_r8(%rsi)
|
73 | 140 | movq %r9, TDX_MODULE_r9(%rsi)
|
74 | 141 | movq %r10, TDX_MODULE_r10(%rsi)
|
75 | 142 | movq %r11, TDX_MODULE_r11(%rsi)
|
76 |
| -.endif |
| 143 | +.endif /* \ret */ |
| 144 | + |
| 145 | +.if \host && \saved && \ret |
| 146 | + /* |
| 147 | + * Clear registers shared by guest for VP.ENTER to prevent |
| 148 | + * speculative use of guest's values, including those are |
| 149 | + * restored from the stack. |
| 150 | + * |
| 151 | + * See arch/x86/kvm/vmx/vmenter.S: |
| 152 | + * |
| 153 | + * In theory, a L1 cache miss when restoring register from stack |
| 154 | + * could lead to speculative execution with guest's values. |
| 155 | + * |
| 156 | + * Note: RBP/RSP are not used as shared register. RSI has been |
| 157 | + * restored already. |
| 158 | + * |
| 159 | + * XOR is cheap, thus unconditionally do for all leafs. |
| 160 | + */ |
| 161 | + xorl %ecx, %ecx |
| 162 | + xorl %edx, %edx |
| 163 | + xorl %r8d, %r8d |
| 164 | + xorl %r9d, %r9d |
| 165 | + xorl %r10d, %r10d |
| 166 | + xorl %r11d, %r11d |
| 167 | + xorl %r12d, %r12d |
| 168 | + xorl %r13d, %r13d |
| 169 | + xorl %r14d, %r14d |
| 170 | + xorl %r15d, %r15d |
| 171 | + xorl %ebx, %ebx |
| 172 | + xorl %edi, %edi |
| 173 | +.endif /* \host && \ret && \host */ |
77 | 174 |
|
78 | 175 | .if \host
|
79 | 176 | .Lout\@:
|
80 | 177 | .endif
|
| 178 | + |
| 179 | +.if \saved |
| 180 | + /* Restore callee-saved GPRs as mandated by the x86_64 ABI */ |
| 181 | + popq %r15 |
| 182 | + popq %r14 |
| 183 | + popq %r13 |
| 184 | + popq %r12 |
| 185 | + popq %rbx |
| 186 | +.endif /* \saved */ |
| 187 | + |
81 | 188 | FRAME_END
|
82 | 189 | RET
|
83 | 190 |
|
84 | 191 | .if \host
|
85 | 192 | .Lseamcall_vmfailinvalid\@:
|
86 | 193 | mov $TDX_SEAMCALL_VMFAILINVALID, %rax
|
| 194 | +.if \ret && \saved |
| 195 | + /* pop the unused structure pointer back to RSI */ |
| 196 | + popq %rsi |
| 197 | +.endif |
87 | 198 | jmp .Lout\@
|
88 | 199 | .endif /* \host */
|
89 | 200 |
|
|
0 commit comments