blob: 0944e158e232d67252c2da569aa258386f37ebbb [file] [log] [blame]
Angel Pons5725ee42020-10-21 00:23:29 +02001/* 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
Angel Pons5725ee42020-10-21 00:23:29 +02009#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