3 #define MSR_MTRRCAP 0xfe
4 #define MSR_MTRRDEFTYPE 0x2ff
5 #define MSR_MTRRBASE(x) (0x200 | ((x) << 1))
6 #define MSR_MTRRMASK(x) (0x201 | ((x) << 1))
7 #define MTRRDEF_EN 0x800
8 #define MTRRCAP_HAVE_WC 0x400
9 #define MTRRMASK_VALID 0x800
11 static const char *mtrr_type_name(int type);
12 static void print_mtrr(void);
15 int get_page_memtype(uint32_t addr, int num_ranges)
21 for(i=0; i<num_ranges; i++) {
22 get_msr(MSR_MTRRMASK(i), &rlow, &rhigh);
23 if(!(rlow & MTRRMASK_VALID)) {
26 mask = rlow & 0xfffff000;
28 get_msr(MSR_MTRRBASE(i), &rlow, &rhigh);
29 base = rlow & 0xfffff000;
31 if((addr & mask) == (base & mask)) {
36 get_msr(MSR_MTRRDEFTYPE, &rlow, &rhigh);
40 int check_wrcomb_enabled(uint32_t addr, int len, int num_ranges)
43 if(get_page_memtype(addr, num_ranges) != MTRR_WC) {
52 int alloc_mtrr(int num_ranges)
57 for(i=0; i<num_ranges; i++) {
58 get_msr(MSR_MTRRMASK(i), &rlow, &rhigh);
59 if(!(rlow & MTRRMASK_VALID)) {
66 void enable_wrcomb(uint32_t addr, int len)
72 if(len <= 0 || (addr | (uint32_t)len) & 0xfff) {
73 errormsg("failed to enable write combining, unaligned range: %p/%x\n",
74 (void*)addr, (unsigned int)len);
78 get_msr(MSR_MTRRCAP, &rlow, &rhigh);
79 num_ranges = rlow & 0xff;
81 infomsg("enable_wrcomb: addr=%p len=%x\n", (void*)addr, (unsigned int)len);
83 if(!(rlow & MTRRCAP_HAVE_WC)) {
84 errormsg("failed to enable write combining, processor doesn't support it\n");
88 if(check_wrcomb_enabled(addr, len, num_ranges)) {
92 if((mtrr = alloc_mtrr(num_ranges)) == -1) {
93 errormsg("failed to enable write combining, no free MTRRs\n");
103 mask = ~mask & 0xfffff000;
105 infomsg(" ... mask: %08x\n", (unsigned int)mask);
108 get_msr(MSR_MTRRDEFTYPE, &def, &rhigh);
109 set_msr(MSR_MTRRDEFTYPE, def & ~MTRRDEF_EN, rhigh);
111 set_msr(MSR_MTRRBASE(mtrr), addr | MTRR_WC, 0);
112 set_msr(MSR_MTRRMASK(mtrr), mask | MTRRMASK_VALID, 0);
114 set_msr(MSR_MTRRDEFTYPE, def | MTRRDEF_EN, 0);
118 static const char *mtrr_names[] = { "N/A", "W C", "N/A", "N/A", "W T", "W P", "W B" };
120 static const char *mtrr_type_name(int type)
122 if(type < 0 || type >= sizeof mtrr_names / sizeof *mtrr_names) {
123 return mtrr_names[0];
125 return mtrr_names[type];
128 static void print_mtrr(void)
131 uint32_t rlow, rhigh, base, mask;
133 get_msr(MSR_MTRRCAP, &rlow, &rhigh);
134 num_ranges = rlow & 0xff;
136 for(i=0; i<num_ranges; i++) {
137 get_msr(MSR_MTRRBASE(i), &base, &rhigh);
138 get_msr(MSR_MTRRMASK(i), &mask, &rhigh);
140 if(mask & MTRRMASK_VALID) {
141 infomsg("mtrr%d: base %p, mask %08x type %s\n", i, (void*)(base & 0xfffff000),
142 (unsigned int)(mask & 0xfffff000), mtrr_type_name(base & 0xff));
144 infomsg("mtrr%d unused (%08x/%08x)\n", i, (unsigned int)base,