xref: /aosp_15_r20/external/coreboot/src/security/intel/txt/getsec_sclean.S (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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