c4c3892e5aec8059748e5b9c428b0422d202bd07
[coreboot.git] / src / vendorcode / amd / agesa / f14 / Proc / CPU / cahalt.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * HyperTransport features and sequence implementation.
6  *
7  * Implements the external AmdHtInitialize entry point.
8  * Contains routines for directing the sequence of available features.
9  * Mostly, but not exclusively, AGESA_TESTPOINT invocations should be
10  * contained in this file, and not in the feature code.
11  *
12  * From a build option perspective, it may be that a few lines could be removed
13  * from compilation in this file for certain options.  It is considered that
14  * the code savings from this are too small to be of concern and this file
15  * should not have any explicit build option implementation.
16  *
17  * @xrefitem bom "File Content Label" "Release Content"
18  * @e project:      AGESA
19  * @e sub-project:  HyperTransport
20  * @e \$Revision: 35978 $   @e \$Date: 2010-08-07 02:18:50 +0800 (Sat, 07 Aug 2010) $
21  *
22  */
23 /*
24  *****************************************************************************
25  *
26  * Copyright (c) 2011, Advanced Micro Devices, Inc.
27  * All rights reserved.
28  * 
29  * Redistribution and use in source and binary forms, with or without
30  * modification, are permitted provided that the following conditions are met:
31  *     * Redistributions of source code must retain the above copyright
32  *       notice, this list of conditions and the following disclaimer.
33  *     * Redistributions in binary form must reproduce the above copyright
34  *       notice, this list of conditions and the following disclaimer in the
35  *       documentation and/or other materials provided with the distribution.
36  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of 
37  *       its contributors may be used to endorse or promote products derived 
38  *       from this software without specific prior written permission.
39  * 
40  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
44  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
45  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
48  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
49  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50  * 
51  * ***************************************************************************
52  *
53  */
54
55 #include "AGESA.h"
56 #include "cpuRegisters.h"
57 #include "Filecode.h"
58
59  /*----------------------------------------------------------------------------------------
60  *                   D E F I N I T I O N S    A N D    M A C R O S
61  *----------------------------------------------------------------------------------------
62  */
63
64 /*----------------------------------------------------------------------------------------
65  *                  T Y P E D E F S     A N D     S T R U C T U  R E S
66  *----------------------------------------------------------------------------------------
67  */
68
69 // typedef unsigned int   uintptr_t; 
70
71 /*----------------------------------------------------------------------------------------
72  *           P R O T O T Y P E S     O F     L O C A L     F U  N C T I O N S
73  *----------------------------------------------------------------------------------------
74  */
75  
76 VOID
77 ExecuteFinalHltInstruction (
78   IN       UINT32 SharedCore,
79   IN       AP_MTRR_SETTINGS  *ApMtrrSettingsList,
80   IN       AMD_CONFIG_PARAMS *StdHeader
81   );
82  
83 VOID
84 SetIdtr (
85   IN     IDT_BASE_LIMIT *IdtInfo,
86   IN OUT AMD_CONFIG_PARAMS *StdHeaderPtr
87   );
88  
89 VOID
90 GetCsSelector (
91   IN     UINT16 *Selector,
92   IN OUT AMD_CONFIG_PARAMS *StdHeaderPtr
93   );
94  
95 VOID
96 NmiHandler (
97   IN OUT AMD_CONFIG_PARAMS *StdHeaderPtr
98   );
99  
100 VOID
101 ExecuteHltInstruction (
102   IN OUT AMD_CONFIG_PARAMS *StdHeaderPtr
103   );
104  
105 VOID
106 ExecuteWbinvdInstruction (
107   IN       AMD_CONFIG_PARAMS *StdHeader
108   );
109  
110  /*----------------------------------------------------------------------------------------
111  *                          E X P O R T E D    F U N C T I O N S
112  *----------------------------------------------------------------------------------------
113  */
114
115
116 //----------------------------------------------------------------------------
117
118 STATIC
119 VOID
120 PrimaryCoreFunctions (AP_MTRR_SETTINGS  *ApMtrrSettingsList)
121    {
122    UINT64 data;
123    UINT32 msrno;
124    // Configure the MTRRs on the AP so
125    // when it runs remote code it will execute
126    // out of RAM instead of ROM.
127    // Disable MTRRs and turn on modification enable bit
128
129    data = __readmsr (0xC0010010);         // MTRR_SYS_CFG
130    data &= ~(1 << 18);                    // MtrrFixDramEn
131    data &= ~(1 << 20);                    // MtrrVarDramEn
132    data |= (1 << 19);                     // MtrrFixDramModEn
133    data |= (1 << 17);                     // SysUcLockEn
134    
135
136    __writemsr (0xC0010010, data);
137
138    // Set 7FFFh-00000h and 9FFFFh-80000h as WB DRAM
139    __writemsr (0x250, 0x1E1E1E1E1E1E1E1E); // AMD_MTRR_FIX64k_00000
140    __writemsr (0x258, 0x1E1E1E1E1E1E1E1E); // AMD_MTRR_FIX16k_80000
141
142    // Set BFFFFh-A0000h, DFFFFh-C0000h as Uncacheable Memory-mapped IO
143    __writemsr (0x259, 0);                 // AMD_AP_MTRR_FIX16k_A0000
144    __writemsr (0x268, 0);                 // AMD_MTRR_FIX4k_C0000
145    __writemsr (0x269, 0);                 // AMD_MTRR_FIX4k_C8000
146    __writemsr (0x26A, 0);                 // AMD_MTRR_FIX4k_D0000
147    __writemsr (0x26B, 0);                 // AMD_MTRR_FIX4k_D8000
148
149    // Set FFFFFh-E0000h as Uncacheable Memory
150    for (msrno = 0x26C; msrno <= 0x26F; msrno++)
151       __writemsr (msrno, 0x1818181818181818);
152
153    // If IBV provided settings for Fixed-Sized MTRRs,
154    // overwrite the default settings.
155    if ((uintptr_t) ApMtrrSettingsList != 0 && (uintptr_t) ApMtrrSettingsList != 0xFFFFFFFF)
156       {
157       int index;
158       for (index = 0; ApMtrrSettingsList [index].MsrAddr != CPU_LIST_TERMINAL; index++)
159          __writemsr (ApMtrrSettingsList [index].MsrAddr, ApMtrrSettingsList [index].MsrData);
160       }
161
162    // restore variable MTTR6 and MTTR7 to default states
163    for (msrno = 0x20F; msrno <= 0x20C; msrno--)  // decrement so that the pair is disable before the base is cleared
164       __writemsr (msrno, 0);
165
166    // Enable fixed-range and variable-range MTRRs
167    // Set Fixed-Range Enable (FE) and MTRR Enable (E) bits
168    __writemsr (0x2FF, __readmsr (0x2FF) | 0xC00);
169
170    // Enable Top-of-Memory setting
171    // Enable use of RdMem/WrMem bits attributes
172    data = __readmsr (0xC0010010);         // MTRR_SYS_CFG
173    data |= (1 << 18);                     // MtrrFixDramEn
174    data |= (1 << 20);                     // MtrrVarDramEn
175    data &= ~(1 << 19);                    // MtrrFixDramModEn
176    __writemsr (0xC0010010, data);
177    }
178
179 //----------------------------------------------------------------------------
180
181 VOID
182 ExecuteFinalHltInstruction (
183   IN       UINT32 SharedCore,
184   IN       AP_MTRR_SETTINGS  *ApMtrrSettingsList,
185   IN       AMD_CONFIG_PARAMS *StdHeader
186   )
187 {
188    int abcdRegs [4];
189    UINT32 cr0val;
190    UINT64 data;
191
192    cr0val = __readcr0 ();
193    if (SharedCore & 2)
194       {
195       // set CombineCr0Cd and enable cache in CR0
196       __writemsr (MSR_CU_CFG3, __readmsr (MSR_CU_CFG3) | 1ULL << 49);
197       __writecr0 (cr0val & ~0x60000000);
198       }
199    else
200       __writecr0 (cr0val | 0x60000000);
201
202    if (SharedCore & 1) PrimaryCoreFunctions (ApMtrrSettingsList);
203
204    // Make sure not to touch any Shared MSR from this point on
205
206    // Restore settings that were temporarily overridden for the cache as ram phase
207    data = __readmsr (0xC0011022);      // MSR_DC_CFG
208    data &= ~(1 << 4);                  // DC_DIS_SPEC_TLB_RLD
209    data &= ~(1 << 8);                  // DIS_CLR_WBTOL2_SMC_HIT
210    data &= ~(1 << 13);                 // DIS_HW_PF
211    __writemsr (0xC0011022, data);
212
213    data = __readmsr (0xC0011021);      // MSR_IC_CFG - C001_1021
214    data &= ~(1 << 9);                  // IC_DIS_SPEC_TLB_RLD
215    __writemsr (0xC0011021, data);
216
217    // AMD_DISABLE_STACK_FAMILY_HOOK
218    __cpuid (abcdRegs, 1);
219    if ((abcdRegs [0] >> 20) == 1) //-----family 10h (Hydra) only-----
220       {
221       data = __readmsr (0xC0011022);
222       data &= ~(1 << 4);
223       data &= ~(1 << 8);
224       data &= ~(1 << 13);
225       __writemsr (0xC0011022, data);
226       
227       data = __readmsr (0xC0011021);
228       data &= ~(1 << 14);
229       data &= ~(1 << 9);
230       __writemsr (0xC0011021, data);
231       
232       data = __readmsr (0xC001102A);
233       data &= ~(1 << 15);
234       data &= ~(1ull << 35);
235       __writemsr (0xC001102A, data);
236       }
237    else if ((abcdRegs [0] >> 20) == 6) //-----family 15h (Orochi) only-----
238       {
239       data = __readmsr (0xC0011020);
240       data &= ~(1 << 28);
241       __writemsr (0xC0011020, data);
242       
243       data = __readmsr (0xC0011021);
244       data &= ~(1 << 9);
245       __writemsr (0xC0011021, data);
246       
247       data = __readmsr (0xC0011022);
248       data &= ~(1 << 4);
249       data &= ~(1l << 13);
250       __writemsr (0xC0011022, data);
251       }
252
253    for (;;)
254      {
255      _disable ();
256      __halt ();
257      }
258   }
259
260 //----------------------------------------------------------------------------
261
262 /// Structure needed to load the IDTR using the lidt instruction
263
264 VOID
265 SetIdtr (
266   IN     IDT_BASE_LIMIT *IdtInfo,
267   IN OUT AMD_CONFIG_PARAMS *StdHeaderPtr
268   )
269 {
270    __lidt (IdtInfo);
271 }
272
273 //----------------------------------------------------------------------------
274
275 VOID
276 GetCsSelector (
277   IN     UINT16 *Selector,
278   IN OUT AMD_CONFIG_PARAMS *StdHeaderPtr
279   )
280 {
281   static const UINT8 opcode [] = {0x8C, 0xC8, 0xC3}; // mov eax, cs; ret
282   *Selector = ((UINT16 (*)(void)) (size_t) opcode) ();
283 }
284
285 //----------------------------------------------------------------------------
286
287 VOID
288 NmiHandler (
289   IN OUT AMD_CONFIG_PARAMS *StdHeaderPtr
290   )
291 {
292   static const UINT8 opcode [] = {0xCF};  // iret
293   ((void (*)(void)) (size_t) opcode) ();
294 }
295
296 //----------------------------------------------------------------------------
297
298 VOID
299 ExecuteHltInstruction (
300   IN OUT AMD_CONFIG_PARAMS *StdHeaderPtr
301   )
302 {
303   _disable ();
304   __halt ();
305 }
306
307 //---------------------------------------------------------------------------
308
309 VOID
310 ExecuteWbinvdInstruction (
311   IN       AMD_CONFIG_PARAMS *StdHeader
312   )
313 {
314   __wbinvd ();
315 }
316
317 //----------------------------------------------------------------------------