1/* SPDX-License-Identifier: GPL-2.0-only */ 2 3#include <cpu/x86/mtrr.h> 4#include <cpu/x86/cr.h> 5#include <cpu/x86/msr.h> 6#include <arch/ram_segs.h> 7 8#include "getsec_mtrr_setup.inc" 9 10.macro PUSH_MSR x 11 movl $(\x), %ecx 12 rdmsr 13 push %eax 14 push %edx 15.endm 16 17.macro POP_MSR x 18 movl $(\x), %ecx 19 pop %edx 20 pop %eax 21 wrmsr 22.endm 23 24.macro CLEAR_MSR x 25 movl $(\x), %ecx 26 xorl %edx, %edx 27 xorl %eax, %eax 28 wrmsr 29.endm 30 31.align 4 32.text 33 34/* 35 * See "SAFER MODE EXTENSIONS REFERENCE." 36 * Chapter "GETSEC[ENTERACCS] - Execute Authenticated Chipset Code" for reference. 37 * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D 38 * 39 * void getsec_enteraccs(uint32_t esi, 40 * uint32_t acm_base, 41 * uint32_t acm_size); 42 */ 43.global getsec_enteraccs 44getsec_enteraccs: 45 46 /* Backup current register state */ 47 pushl %ebp 48 movl %esp, %ebp 49 50 pushal 51 52 movl %cr0, %eax 53 pushl %eax 54 movl %cr4, %eax 55 pushl %eax 56 57 /* Pushed 10 32bit registers */ 58 59 /* Reserve space on stack for GDT */ 60 subl $8, %esp 61 62 PUSH_MSR MTRR_DEF_TYPE_MSR 63 PUSH_MSR IA32_MISC_ENABLE 64 PUSH_MSR MTRR_FIX_64K_00000 65 PUSH_MSR MTRR_FIX_16K_80000 66 PUSH_MSR MTRR_FIX_16K_A0000 67 PUSH_MSR MTRR_FIX_4K_C0000 68 PUSH_MSR MTRR_FIX_4K_C8000 69 PUSH_MSR MTRR_FIX_4K_D0000 70 PUSH_MSR MTRR_FIX_4K_D8000 71 PUSH_MSR MTRR_FIX_4K_E0000 72 PUSH_MSR MTRR_FIX_4K_F0000 73 PUSH_MSR MTRR_FIX_4K_F8000 74 75 /* Push variable MTRRs in ascending order */ 76 77 xorl %ebx, %ebx 78 jmp cond_push_var_mtrrs 79 80body_push_var_mtrrs: 81 82 movl %ebx, %ecx 83 shll %ecx 84 addl $(MTRR_PHYS_BASE(0)), %ecx 85 rdmsr 86 push %eax 87 push %edx 88 incl %ecx /* MTRR_PHYS_MASK */ 89 rdmsr 90 push %eax 91 push %edx 92 93 incl %ebx 94 95cond_push_var_mtrrs: 96 97 movl $(MTRR_CAP_MSR), %ecx 98 rdmsr 99 andl $(0xff), %eax 100 cmp %ebx, %eax 101 jg body_push_var_mtrrs 102 103 /* 104 * Disable cache. 105 * Chapter 2.2.4.3 106 * Intel TXT Software Development Guide (Document: 315168-015) 107 */ 108 movl %cr0, %eax 109 orl $(CR0_CD | CR0_NW), %eax 110 movl %eax, %cr0 111 112 /* Disable all MTRRs */ 113 movl $(MTRR_DEF_TYPE_MSR), %ecx 114 xorl %eax, %eax 115 xorl %edx, %edx 116 wrmsr 117 118 /* 119 * Clear fixed MTRRs. 120 * Chapter 2.2.5.1 121 * Intel TXT Software Development Guide (Document: 315168-015) 122 */ 123 CLEAR_MSR MTRR_FIX_64K_00000 124 CLEAR_MSR MTRR_FIX_16K_80000 125 CLEAR_MSR MTRR_FIX_16K_A0000 126 CLEAR_MSR MTRR_FIX_4K_C0000 127 CLEAR_MSR MTRR_FIX_4K_C8000 128 CLEAR_MSR MTRR_FIX_4K_D0000 129 CLEAR_MSR MTRR_FIX_4K_D8000 130 CLEAR_MSR MTRR_FIX_4K_E0000 131 CLEAR_MSR MTRR_FIX_4K_F0000 132 CLEAR_MSR MTRR_FIX_4K_F8000 133 134 /* 135 * Clear variable MTRRs 136 * Chapter 2.2.5.1 137 * Intel TXT Software Development Guide (Document: 315168-015) 138 */ 139 movl $(MTRR_CAP_MSR), %ecx 140 rdmsr 141 andl $(0xff), %eax 142 movl %eax, %ebx 143 144 xorl %eax, %eax 145 xorl %edx, %edx 146 147 jmp cond_clear_var_mtrrs 148 149body_clear_var_mtrrs: 150 151 decl %ebx 152 movl %ebx, %ecx 153 shll %ecx 154 addl $(MTRR_PHYS_BASE(0)), %ecx 155 wrmsr 156 incl %ecx /* MTRR_PHYS_MASK */ 157 wrmsr 158 159cond_clear_var_mtrrs: 160 161 cmpl $0, %ebx 162 jnz body_clear_var_mtrrs 163 164 /* 165 * Setup BIOS ACM as WB 166 * Chapter A.1.1 167 * Intel TXT Software Development Guide (Document: 315168-015) 168 */ 169 170 /* Determine size of AC module */ 171 movl 12(%ebp), %eax /* %eax = acmbase */ 172 movl $1, %ebx 173 movl 16(%ebp), %ebx /* %ebx = acmsize */ 174 175 /* Round up to page size */ 176 addl $(0xfff), %ebx 177 andl $(~0xfff), %ebx /* Aligned to a page (4 KiB) */ 178 179 /* 180 * Use XMM to store local variables. This code will need to be 181 * used in romstage, and CAR will have been torn down by then. 182 */ 183 movd %eax, %xmm0 /* XMM0: Base address of next MTRR */ 184 movd %ebx, %xmm1 /* XMM1: Remaining size to cache */ 185 186 /* 187 * Important note: The MTRRs must cache less than a page (4 KiB) 188 * of unused memory after the BIOS ACM. Failure to do so will 189 * result in a TXT reset with Class Code 5, Major Error Code 2. 190 * 191 * The caller must have checked that there are enough variable 192 * MTRRs to cache the ACM size prior to invoking this routine. 193 */ 194 SET_UP_MTRRS_FOR_BIOS_ACM 195 196 /* 197 * Now that the variable MTRRs have been set up, enable them. 198 */ 199 movl $(MTRR_DEF_TYPE_MSR), %ecx 200 rdmsr 201 orl $(MTRR_DEF_TYPE_EN), %eax 202 wrmsr 203 204 /* Enable cache - GPF# if not done */ 205 movl %cr0, %eax 206 andl $(~(CR0_CD | CR0_NW)), %eax 207 movl %eax, %cr0 208 209 /* Enable Numeric error - GPE# if not done */ 210 movl %cr0, %eax 211 orl $(CR0_NE), %eax 212 movl %eax, %cr0 213 214 /* Enable SMX and FXSTORE - for getsec */ 215 movl %cr4, %eax 216 orl $(CR4_SMXE | CR4_OSFXSR), %eax 217 movl %eax, %cr4 218 219 /* 220 * Save GDT 221 * Chapter A.1.2 222 * Intel TXT Software Development Guide (Document: 315168-015) 223 */ 224 sgdt -48(%ebp) 225 226 /* Backup stack pointer */ 227 movd %esp, %xmm0 228 movd %ebp, %xmm1 229 230 /* Backup %gs used by cpu_info() */ 231 movl %gs, %eax 232 movd %eax, %xmm2 233 234 /* 235 * Get function arguments. 236 * It's important to pass the exact ACM size as it's used by getsec to verify 237 * the integrity of ACM. Unlike the size for MTRR programming, which needs to 238 * be power of two. 239 * 240 * The following assembly code is based on tboot's tboot/include/txt/smx.h. 241 */ 242 movl 8(%ebp), %esi /* flags */ 243 movl 12(%ebp), %ebx /* acm_base */ 244 movl 16(%ebp), %ecx /* acm_size */ 245 246 movl $0, %edx /* reserved, must be zero */ 247 movl $0, %edi /* must be zero */ 248 movl $2, %eax /* GetSec[ENTERACCS] */ 249 250 getsec 251 252 /* Restore stack pointer */ 253 movd %xmm0, %esp 254 movd %xmm1, %ebp 255 256 /* Reload GDT */ 257 lgdt -48(%ebp) 258 259 /* Set cs */ 260 ljmp $RAM_CODE_SEG, $1f 2611: 262 /* Fix segment registers */ 263 movl $RAM_DATA_SEG, %eax 264 movl %eax, %ds 265 movl %eax, %es 266 movl %eax, %ss 267 movl %eax, %fs 268 /* Restore %gs used by cpu_info */ 269 movd %xmm2, %eax 270 movl %eax, %gs 271 272 /* Disable cache */ 273 movl %cr0, %eax 274 orl $(CR0_CD | CR0_NW), %eax 275 movl %eax, %cr0 276 277 /* Pop variable MTRRs in descending order */ 278 279 movl $(MTRR_CAP_MSR), %ecx 280 rdmsr 281 andl $(0xff), %eax 282 movl %eax, %ebx 283 284 jmp cond_pop_var_mtrrs 285 286body_pop_var_mtrrs: 287 288 decl %ebx 289 movl %ebx, %ecx 290 shll %ecx 291 addl $(MTRR_PHYS_MASK(0)), %ecx 292 pop %edx 293 pop %eax 294 wrmsr 295 decl %ecx /* MTRR_PHYS_BASE */ 296 pop %edx 297 pop %eax 298 wrmsr 299 300cond_pop_var_mtrrs: 301 302 cmpl $0, %ebx 303 jne body_pop_var_mtrrs 304 305 POP_MSR MTRR_FIX_4K_F8000 306 POP_MSR MTRR_FIX_4K_F0000 307 POP_MSR MTRR_FIX_4K_E0000 308 POP_MSR MTRR_FIX_4K_D8000 309 POP_MSR MTRR_FIX_4K_D0000 310 POP_MSR MTRR_FIX_4K_C8000 311 POP_MSR MTRR_FIX_4K_C0000 312 POP_MSR MTRR_FIX_16K_A0000 313 POP_MSR MTRR_FIX_16K_80000 314 POP_MSR MTRR_FIX_64K_00000 315 POP_MSR IA32_MISC_ENABLE 316 POP_MSR MTRR_DEF_TYPE_MSR 317 318 /* Enable cache */ 319 movl %cr0, %eax 320 andl $(~(CR0_CD | CR0_NW)), %eax 321 movl %eax, %cr0 322 323 /* Pop GDT */ 324 addl $8, %esp 325 326 popl %eax 327 movl %eax, %cr4 328 popl %eax 329 movl %eax, %cr0 330 331 popal 332 333 movl %ebp, %esp 334 popl %ebp 335 336 ret 337