1/* SPDX-License-Identifier: GPL-2.0-only */ 2 3#include <cpu/x86/cr.h> 4#include <cpu/x86/mtrr.h> 5#include <cpu/x86/msr.h> 6 7#include "getsec_mtrr_setup.inc" 8 9#define NO_EVICT_MODE 0x2e0 10 11.align 4 12.text 13 14/* 15 * void getsec_sclean(const uint32_t acm_base, const uint32_t acm_size); 16 */ 17.global getsec_sclean 18getsec_sclean: 19 /* 20 * At this point, it is certain that the BIOS ACM will be run. 21 * This requires tearing down CAR, which cannot be undone. 22 * 23 * From here onwards, the only way out is to reset the system. 24 */ 25 26 /* Enable SMXE, SSE and debug extensions */ 27 movl %cr4, %eax 28 orl $(CR4_OSFXSR | CR4_DE | CR4_SMXE), %eax 29 movl %eax, %cr4 30 31 /* 32 * Save arguments into SSE registers. We need to tear down CAR 33 * before launching the BIOS ACM, which will destroy the stack. 34 */ 35 movd 4(%esp), %xmm2 /* acm_base */ 36 movd 8(%esp), %xmm3 /* acm_size */ 37 38 /* Disable cache */ 39 movl %cr0, %eax 40 orl $(CR0_CD | CR0_NE), %eax 41 andl $(~(CR0_NW)), %eax 42 movl %eax, %cr0 43 44 /* Invalidate the cache */ 45 invd 46 47 /* Disable MTRRs */ 48 movl $(MTRR_DEF_TYPE_MSR), %ecx 49 xorl %eax, %eax 50 xorl %edx, %edx 51 wrmsr 52 53 /* Disable NEM, needs to be done in two steps */ 54 movl $NO_EVICT_MODE, %ecx 55 rdmsr 56 andl $~2, %eax /* Clear NEM Run bit */ 57 wrmsr 58 andl $~1, %eax /* Clear NEM Setup bit */ 59 wrmsr 60 61 /* Invalidate the cache, again */ 62 invd 63 64 /* 65 * Clear variable MTRRs 66 * Chapter 2.2.5.1 67 * Intel TXT Software Development Guide (Document: 315168-015) 68 */ 69 movl $(MTRR_CAP_MSR), %ecx 70 rdmsr 71 andl $(0xff), %eax 72 movl %eax, %ebx 73 74 xorl %eax, %eax 75 xorl %edx, %edx 76 77 jmp cond_clear_var_mtrrs 78 79body_clear_var_mtrrs: 80 81 decl %ebx 82 movl %ebx, %ecx 83 shll %ecx 84 addl $(MTRR_PHYS_BASE(0)), %ecx 85 wrmsr 86 incl %ecx /* MTRR_PHYS_MASK */ 87 wrmsr 88 89cond_clear_var_mtrrs: 90 91 cmpl $0, %ebx 92 jnz body_clear_var_mtrrs 93 94 /* 95 * Setup BIOS ACM as WB 96 * Chapter A.1.1 97 * Intel TXT Software Development Guide (Document: 315168-015) 98 */ 99 100 /* Determine size of AC module */ 101 movd %xmm2, %eax /* acm_base */ 102 movd %xmm3, %ebx /* acm_size */ 103 104 /* Round up to page size */ 105 addl $(0xfff), %ebx 106 andl $(~0xfff), %ebx /* Aligned to a page (4 KiB) */ 107 108 /* Use SSE registers to store local variables */ 109 movd %eax, %xmm0 110 movd %ebx, %xmm1 111 112 /* 113 * Important note: The MTRRs must cache less than a page (4 KiB) 114 * of unused memory after the BIOS ACM. Not doing so on Haswell 115 * will cause a TXT reset with Class Code 5, Major Error Code 2. 116 * 117 * The caller must have checked that there are enough variable 118 * MTRRs to cache the ACM size prior to invoking this routine. 119 */ 120 SET_UP_MTRRS_FOR_BIOS_ACM 121 122 /* Enable variable MTRRs */ 123 movl $MTRR_DEF_TYPE_MSR, %ecx 124 rdmsr 125 orl $MTRR_DEF_TYPE_EN, %eax 126 wrmsr 127 128 /* Enable cache - CR0_NW is and stays clear */ 129 movl %cr0, %eax 130 andl $~(CR0_CD), %eax 131 movl %eax, %cr0 132 133 /* 134 * Get function arguments. 135 * It's important to pass the exact ACM size as it's used by getsec to verify 136 * the integrity of ACM. Unlike the size for MTRR programming, which needs to 137 * be power of two. 138 * 139 * Note: Do not forget that CAR has been torn down, so the stack doesn't exist. 140 */ 141 movl $2, %eax /* GETSEC[ENTERACCS] */ 142 movd %xmm2, %ebx /* acm_base */ 143 movd %xmm3, %ecx /* acm_size */ 144 movl $0, %edx /* reserved, must be zero */ 145 movl $0, %edi /* must be zero */ 146 movl $0, %esi /* SCLEAN */ 147 148 getsec 149 150 /* 151 * The platform state after SCLEAN is undefined. The only sane 152 * thing to do afterwards is to reset the platform. Note that 153 * the BIOS ACM should already reset the platform, so this code 154 * may not always be reached, but keep it here just to be sure. 155 */ 156#if 1 157 movw $0xcf8, %dx 158 movl $0x8000F8AC, %eax 159 outl %eax, %dx 160 161 movw $0xcfc, %dx 162 inl %dx, %eax 163 andl $~(1 << 20), %eax 164 outl %eax, %dx 165#endif 166 167 movw $0xcf9, %dx 168 movb $0, %al 169 outb %al, %dx 170 171 movw $0xcf9, %dx 172 movb $0x0e, %al 173 outb %al, %dx 174 175 cli 176 177 hlt 178 179 ret 180