2 * memory-type region registers.
4 * due to the possibility of extended addresses (for PAE)
5 * as large as 36 bits coming from the e820 memory map and the like,
6 * we'll use vlongs to hold addresses and lengths, even though we don't
7 * implement PAE in Plan 9.
10 #include "../port/lib.h"
18 * MTRR Physical base/mask are indexed by
19 * MTRRPhys{Base|Mask}N = MTRRPhys{Base|Mask}0 + 2*N
21 MTRRPhysBase0 = 0x200,
22 MTRRPhysMask0 = 0x201,
23 MTRRDefaultType = 0x2FF,
27 /* cpuid extended function codes */
28 Exthighfunc = 1ul << 31,
40 CR4PageGlobalEnable = 1 << 7,
41 CR0CacheDisable = 1 << 30,
55 Capvcnt = 0xff, /* mask: # of variable-range MTRRs we have */
56 Capwc = 1<<8, /* flag: have write combining? */
57 Capfix = 1<<10, /* flag: have fixed MTRRs? */
58 Deftype = 0xff, /* default MTRR type */
59 Deffixena = 1<<10, /* fixed-range MTRR enable */
60 Defena = 1<<11, /* MTRR enable */
63 typedef struct Mtrreg Mtrreg;
64 typedef struct Mtrrop Mtrrop;
71 static char *types[] = {
83 static Mtrreg mtrreg[Nmtrr];
88 if(type < 0 || type >= nelem(types))
98 for(p = types; *p != nil; p++)
99 if (strcmp(str, *p) == 0)
108 static vlong mask = -1;
112 cpuid(Exthighfunc, regs);
113 if(regs[0] >= Extaddrsz) { /* ax */
114 cpuid(Extaddrsz, regs);
115 mask = (1LL << (regs[0] & 0xFF)) - 1; /* ax */
123 return (ul & (ul - 1)) == 0;
126 /* true if mtrr is valid */
128 mtrrdec(Mtrreg *mtrr, uvlong *ptr, uvlong *size, int *type)
130 *ptr = mtrr->base & ~(BY2PG-1);
131 *type = mtrr->base & 0xff;
132 *size = (physmask() ^ (mtrr->mask & ~(BY2PG-1))) + 1;
133 return (mtrr->mask >> 11) & 1;
137 mtrrenc(Mtrreg *mtrr, uvlong ptr, uvlong size, int type, int ok)
139 mtrr->base = ptr | (type & 0xff);
140 mtrr->mask = (physmask() & ~(size - 1)) | (ok? 1<<11: 0);
144 * i is the index of the MTRR, and is multiplied by 2 because
145 * mask and base offsets are interleaved.
148 mtrrget(Mtrreg *mtrr, uint i)
150 rdmsr(MTRRPhysBase0 + 2*i, &mtrr->base);
151 rdmsr(MTRRPhysMask0 + 2*i, &mtrr->mask);
155 mtrrput(Mtrreg *mtrr, uint i)
157 wrmsr(MTRRPhysBase0 + 2*i, mtrr->base);
158 wrmsr(MTRRPhysMask0 + 2*i, mtrr->mask);
167 rdmsr(MTRRCap, &cap);
168 vcnt = cap & Capvcnt;
180 for(i = 0; i < vcnt; i++)
181 mtrrget(&mtrreg[i], i);
195 putcr4(cr4 & ~CR4PageGlobalEnable);
198 putcr0(cr0 | CR0CacheDisable);
200 rdmsr(MTRRDefaultType, &def);
201 wrmsr(MTRRDefaultType, def & ~(vlong)Defena);
204 for(i=0; i<vcnt; i++)
205 mtrrput(&mtrreg[i], i);
208 wrmsr(MTRRDefaultType, def);
216 mtrrclock(void) /* called from clock interrupt */
218 static Ref bar1, bar2;
227 * wait for all CPUs to sync here, so that the MTRR setup gets
228 * done at roughly the same time on all processors.
231 while(bar1.ref < conf.nmach)
237 * wait for all CPUs to sync up again, so that we don't continue
238 * executing while the MTRRs are still being set up.
241 while(bar2.ref < conf.nmach)
253 mtrr0(uvlong base, uvlong size, char *tstr)
255 int i, vcnt, slot, type, mtype, mok;
259 if(!(m->cpuiddx & Mtrr))
260 return "mtrrs not supported";
261 if(base & (BY2PG-1) || size & (BY2PG-1) || size == 0)
262 return "mtrr base or size not 4k aligned or zero size";
264 return "mtrr size not power of 2";
265 if(base & (size - 1))
266 return "mtrr base not naturally aligned";
268 if((type = str2type(tstr)) == -1)
269 return "mtrr bad type";
271 rdmsr(MTRRCap, &cap);
272 rdmsr(MTRRDefaultType, &def);
276 return "mtrr unknown type";
279 return "mtrr type wc (write combining) unsupported";
291 for(i = 0; i < vcnt; i++){
292 mok = mtrrdec(&mtrreg[i], &mp, &msize, &mtype);
293 if(slot == -1 && (!mok || mtype == (def & Deftype)))
294 slot = i; /* good, but look further for exact match */
295 if(mok && mp == base && msize == size){
301 return "no free mtrr slots";
303 mtrrenc(&mtrreg[slot], base, size, type, 1);
314 mtrr(uvlong base, uvlong size, char *tstr)
320 err = mtrr0(base, size, tstr);
327 mtrrprint(char *buf, long bufsize)
329 int i, n, vcnt, type;
334 if(!(m->cpuiddx & Mtrr))
336 rdmsr(MTRRDefaultType, &def);
337 n = snprint(buf, bufsize, "cache default %s\n",
338 type2str(def & Deftype));
340 for(i = 0; i < vcnt; i++){
342 if (mtrrdec(&mtrr, &base, &size, &type))
343 n += snprint(buf+n, bufsize-n,
344 "cache 0x%llux %llud %s\n",
345 base, size, type2str(type));
353 static vlong cap0, def0;
356 rdmsr(MTRRCap, &cap);
357 rdmsr(MTRRDefaultType, &def);
367 print("mtrrcap%d: %lluX %lluX\n",
368 m->machno, cap0, cap);
370 print("mtrrdef%d: %lluX %lluX\n",
371 m->machno, def0, def);