2 * This file is part of the LinuxBIOS project.
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr);
24 static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType);
26 void CPUMemTyping_D(struct MCTStatStruc *pMCTstat,
27 struct DCTStatStruc *pDCTstatA)
29 /* BSP only. Set the fixed MTRRs for common legacy ranges.
30 * Set TOP_MEM and TOM2.
31 * Set some variable MTRRs with WB Uncacheable type.
34 u32 Bottom32bIO, Bottom40bIO, Cache32bTOP;
39 /* Set temporary top of memory from Node structure data.
40 * Adjust temp top of memory down to accomodate 32-bit IO space.
41 * Bottom40bIO=top of memory, right justified 8 bits
42 * (defines dram versus IO space type)
43 * Bottom32bIO=sub 4GB top of memory, right justified 8 bits
44 * (defines dram versus IO space type)
45 * Cache32bTOP=sub 4GB top of WB cacheable memory,
46 * right justified 8 bits
49 val = mctGet_NVbits(NV_BottomIO);
53 Bottom32bIO = val << (24-8);
55 val = pMCTstat->SysLimit + 1;
58 if(Bottom32bIO >= val)
64 val = mctGet_NVbits(NV_BottomUMA);
74 /*======================================================================
75 Set default values for CPU registers
76 ======================================================================*/
78 /* NOTE : For LinuxBIOS, we don't need to set mtrr enables here because
79 they are still enable from cache_as_ram.inc */
84 _WRMSR(addr, lo, hi); /* 0 - 512K = WB Mem */
86 _WRMSR(addr, lo, hi); /* 512K - 640K = WB Mem */
88 /*======================================================================
89 Set variable MTRR values
90 ======================================================================*/
91 /* NOTE: for LinuxBIOS change from 0x200 to 0x204: LinuxBIOS is using
92 0x200, 0x201 for [1M, CONFIG_TOP_MEM)
93 0x202, 0x203 for ROM Caching
95 addr = 0x204; /* MTRR phys base 2*/
96 /* use TOP_MEM as limit*/
97 /* Limit=TOP_MEM|TOM2*/
99 print_tx("\t CPUMemTyping: Cache32bTOP:", Cache32bTOP);
100 SetMTRRrangeWB_D(0, &Cache32bTOP, &addr);
104 if(addr == -1) /* ran out of MTRRs?*/
105 pMCTstat->GStatus |= 1<<GSB_MTRRshort;
107 pMCTstat->Sub4GCacheTop = Cache32bTOP<<8;
109 /*======================================================================
110 Set TOP_MEM and TOM2 CPU registers
111 ======================================================================*/
114 hi = Bottom32bIO>>24;
115 _WRMSR(addr, lo, hi);
116 print_tx("\t CPUMemTyping: Bottom32bIO:", Bottom32bIO);
117 print_tx("\t CPUMemTyping: Bottom40bIO:", Bottom40bIO);
119 hi = Bottom40bIO >> 24;
120 lo = Bottom40bIO << 8;
121 addr += 3; /* TOM2 */
122 _WRMSR(addr, lo, hi);
124 addr = 0xC0010010; /* SYS_CFG */
125 _RDMSR(addr, &lo, &hi);
127 lo |= (1<<21); /* MtrrTom2En=1 */
128 lo |= (1<<22); /* Tom2ForceMemTypeWB */
130 lo &= ~(1<<21); /* MtrrTom2En=0 */
131 lo &= ~(1<<22); /* Tom2ForceMemTypeWB */
133 _WRMSR(addr, lo, hi);
137 static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr)
140 SetMTRRrange_D(Base, pLimit, pMtrrAddr, 6);
144 static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType)
146 /* Program MTRRs to describe given range as given cache type.
147 * Use MTRR pairs starting with the given MTRRphys Base address,
148 * and use as many as is required up to (excluding) MSR 020C, which
149 * is reserved for OS.
151 * "Limit" in the context of this procedure is not the numerically
152 * correct limit, but rather the Last address+1, for purposes of coding
153 * efficiency and readability. Size of a region is then Limit-Base.
155 * 1. Size of each range must be a power of two
156 * 2. Each range must be naturally aligned (Base is same as size)
158 * There are two code paths: the ascending path and descending path
159 * (analogous to bsf and bsr), where the next limit is a funtion of the
160 * next set bit in a forward or backward sequence of bits (as a function
161 * of the Limit). We start with the ascending path, to ensure that
162 * regions are naturally aligned, then we switch to the descending path
163 * to maximize MTRR usage efficiency. Base=0 is a special case where we
164 * start with the descending path. Correct Mask for region is
165 * 2comp(Size-1)-1, which is 2comp(Limit-Base-1)-1
168 u32 curBase, curLimit, curSize;
172 val = curBase = Base;
175 while((addr >= 0x200) && (addr < 0x20C) && (val < *pLimit)) {
176 /* start with "ascending" code path */
177 /* alignment (largest block size)*/
178 valx = 1 << bsf(curBase);
181 /* largest legal limit, given current non-zero range Base*/
183 if((curBase == 0) || (*pLimit < valx)) {
184 /* flop direction to "descending" code path*/
185 valx = 1<<bsr(*pLimit - curBase);
189 curLimit = valx; /*eax=curBase, edx=curLimit*/
193 /* now program the MTRR */
194 val |= MtrrType; /* set cache type (UC or WB)*/
195 _WRMSR(addr, val, valx); /* prog. MTRR with current region Base*/
196 val = ((~(curSize - 1))+1) - 1; /* Size-1*/ /*Mask=2comp(Size-1)-1*/
197 valx = (val >> 24) | (0xff00); /* GH have 48 bits addr */
199 val |= ( 1 << 11); /* set MTRR valid*/
201 _WRMSR(addr, val, valx); /* prog. MTRR with current region Mask*/
203 curBase = val; /* next Base = current Limit (loop exit)*/
204 addr++; /* next MTRR pair addr */