aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/amd/agesa/cache_as_ram.S
blob: 4f0bb3fd7561bafa1fc61aa85a9562f491159693 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2011 Advanced Micro Devices, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/******************************************************************************
 * AMD Generic Encapsulated Software Architecture
 *
 * $Workfile:: cache_as_ram.S
 *
 * Description: cache_as_ram.S - AGESA Module Entry Point for GCC complier
 *
 ******************************************************************************
 */

#include "gcccar.inc"
#include <cpu/x86/cache.h>
#include <cpu/x86/post_code.h>

.code32
.globl _cache_as_ram_setup, _cache_as_ram_setup_end
.globl chipset_teardown_car

_cache_as_ram_setup:

	/* Preserve BIST. */
	movd	%eax, %mm0

	post_code(0xa0)

	/* enable SSE2 128bit instructions */
	/* Turn on OSFXSR [BIT9] and OSXMMEXCPT [BIT10] onto CR4 register */

	movl	%cr4, %eax
	orl	$(3 << 9), %eax
	movl	%eax, %cr4

	post_code(0xa1)

	AMD_ENABLE_STACK

	/* Align the stack. */
	and	$0xFFFFFFF0, %esp

#ifdef __x86_64__
	/* switch to 64 bit long mode */
	mov	%esi, %ecx
	add	$0, %ecx # core number
	xor	%eax, %eax
	lea	(0x1000+0x23)(%ecx), %edi
	mov	%edi, (%ecx)
	mov	%eax, 4(%ecx)

	lea	0x1000(%ecx), %edi
	movl	$0x000000e3, 0x00(%edi)
	movl	%eax, 0x04(%edi)
	movl	$0x400000e3, 0x08(%edi)
	movl	%eax, 0x0c(%edi)
	movl	$0x800000e3, 0x10(%edi)
	movl	%eax, 0x14(%edi)
	movl	$0xc00000e3, 0x18(%edi)
	movl	%eax, 0x1c(%edi)

	# load ROM based identity mapped page tables
	mov	%ecx, %eax
	mov	%eax, %cr3

	# enable PAE
	mov	%cr4, %eax
	bts	$5, %eax
	mov	%eax, %cr4

	# enable long mode
	mov	$0xC0000080, %ecx
	rdmsr
	bts	$8, %eax
	wrmsr

	# enable paging
	mov	%cr0, %eax
	bts	$31, %eax
	mov	%eax, %cr0

	# use call far to switch to 64-bit code segment
	ljmp	$0x18, $1f
1:

#endif

	call early_all_cores

	/* Must maintain 16-byte stack alignment here. */
	pushl	$0x0
	pushl	$0x0
	pushl	$0x0
	movd	%mm0, %eax		/* bist */
	pushl	%eax
	call	romstage_main

#if CONFIG(POSTCAR_STAGE)

/* We do not return. Execution continues with run_postcar_phase()
 * calling to chipset_teardown_car below.
 */
	jmp	postcar_entry_failure

chipset_teardown_car:

/*
 * Retrieve return address from stack as it will get trashed below if
 * execution is utilizing the cache-as-ram stack.
 */
	pop	%esp

#else

	movl	%eax, %esp

/* Register %esp is new stacktop for remaining of romstage. */

#endif

	/* Disable cache */
	movl	%cr0, %eax
	orl	$CR0_CacheDisable, %eax
	movl	%eax, %cr0

/* Register %esp is preserved in AMD_DISABLE_STACK. */
	AMD_DISABLE_STACK

#if CONFIG(POSTCAR_STAGE)

	jmp	*%esp

#else

	/* enable cache */
	movl	%cr0, %eax
	andl	$0x9fffffff, %eax
	movl	%eax, %cr0

	call	romstage_after_car

#endif

	/* Should never see this postcode */
	post_code(0xaf)

stop:
	hlt
	jmp	stop

/* These are here for linking purposes. */
.weak early_all_cores, romstage_main
early_all_cores:
romstage_main:
postcar_entry_failure:
	/* Should never see this postcode */
	post_code(0xae)
	jmp	stop

_cache_as_ram_setup_end: