static void set_init_ecc_mtrrs(void) { msr_t msr; int i; disable_cache(); /* First clear all of the msrs to be safe */ for (i = 0; i < MTRR_COUNT; i++) { msr_t zero; zero.lo = zero.hi = 0; wrmsr(MTRRphysBase_MSR(i), zero); wrmsr(MTRRphysMask_MSR(i), zero); } /* Write back cache the first 1MB */ msr.hi = 0x00000000; msr.lo = 0x00000000 | MTRR_TYPE_WRBACK; wrmsr(MTRRphysBase_MSR(0), msr); msr.hi = 0x000000ff; msr.lo = ~((CONFIG_RAMTOP) - 1) | 0x800; wrmsr(MTRRphysMask_MSR(0), msr); /* Set the default type to write combining */ msr.hi = 0x00000000; msr.lo = 0xc00 | MTRR_TYPE_WRCOMB; wrmsr(MTRRdefType_MSR, msr); /* Set TOP_MEM to 4G */ msr.hi = 0x00000001; msr.lo = 0x00000000; wrmsr(TOP_MEM, msr); enable_cache(); }
static void set_var_mtrr(int reg, uint32_t base, uint32_t size, int type) { msr_t basem, maskm; basem.lo = base | type; basem.hi = 0; wrmsr(MTRRphysBase_MSR(reg), basem); maskm.lo = ~(size - 1) | MTRRphysMaskValid; maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1; wrmsr(MTRRphysMask_MSR(reg), maskm); }
static void save_mtrr_state(struct mtrr_state *state) { int i; for (i = 0; i < MTRR_COUNT; i++) { state->mtrrs[i].base = rdmsr(MTRRphysBase_MSR(i)); state->mtrrs[i].mask = rdmsr(MTRRphysMask_MSR(i)); } state->top_mem = rdmsr(TOP_MEM); state->top_mem2 = rdmsr(TOP_MEM2); state->def_type = rdmsr(MTRRdefType_MSR); }
static void set_var_mtrr( unsigned reg, unsigned base, unsigned size, unsigned type) { /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */ /* FIXME: It only support 4G less range */ msr_t basem, maskm; basem.lo = base | type; basem.hi = 0; wrmsr(MTRRphysBase_MSR(reg), basem); maskm.lo = ~(size - 1) | MTRRphysMaskValid; maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1; wrmsr(MTRRphysMask_MSR(reg), maskm); }
static void restore_mtrr_state(struct mtrr_state *state) { int i; disable_cache(); for (i = 0; i < MTRR_COUNT; i++) { wrmsr(MTRRphysBase_MSR(i), state->mtrrs[i].base); wrmsr(MTRRphysMask_MSR(i), state->mtrrs[i].mask); } wrmsr(TOP_MEM, state->top_mem); wrmsr(TOP_MEM2, state->top_mem2); wrmsr(MTRRdefType_MSR, state->def_type); enable_cache(); }
static void set_resume_cache(void) { msr_t msr; /* disable fixed mtrr for now, it will be enabled by mtrr restore */ msr = rdmsr(SYSCFG_MSR); msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn); wrmsr(SYSCFG_MSR, msr); /* Enable caching for 0 - coreboot ram using variable mtrr */ msr.lo = 0 | MTRR_TYPE_WRBACK; msr.hi = 0; wrmsr(MTRRphysBase_MSR(0), msr); msr.lo = ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid; msr.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1; wrmsr(MTRRphysMask_MSR(0), msr); /* Set the default memory type and disable fixed and enable variable MTRRs */ msr.hi = 0; msr.lo = (1 << 11); wrmsr(MTRRdefType_MSR, msr); enable_cache(); }
void mtrr_setup(void) { if (!CONFIG_MTRR_INIT) return; u32 eax, ebx, ecx, edx, cpuid_features; cpuid(1, &eax, &ebx, &ecx, &cpuid_features); if (!(cpuid_features & CPUID_MTRR)) return; if (!(cpuid_features & CPUID_MSR)) return; dprintf(3, "init mtrr\n"); u32 mtrr_cap = rdmsr(MSR_MTRRcap); int vcnt = mtrr_cap & 0xff; int fix = mtrr_cap & 0x100; if (!vcnt || !fix) return; // Disable MTRRs wrmsr_smp(MSR_MTRRdefType, 0); // Set fixed MTRRs union u64b { u8 valb[8]; u64 val; } u; u.val = 0; int i; for (i = 0; i < 8; i++) if (RamSize >= 65536 * (i + 1)) u.valb[i] = MTRR_MEMTYPE_WB; wrmsr_smp(MSR_MTRRfix64K_00000, u.val); u.val = 0; for (i = 0; i < 8; i++) if (RamSize >= 0x80000 + 16384 * (i + 1)) u.valb[i] = MTRR_MEMTYPE_WB; wrmsr_smp(MSR_MTRRfix16K_80000, u.val); wrmsr_smp(MSR_MTRRfix16K_A0000, 0); // 0xA0000-0xC0000 is uncached int j; for (j = 0; j < 8; j++) { u.val = 0; for (i = 0; i < 8; i++) if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1)) u.valb[i] = MTRR_MEMTYPE_WP; wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val); } // Set variable MTRRs int phys_bits = 36; cpuid(0x80000000u, &eax, &ebx, &ecx, &edx); if (eax >= 0x80000008) { /* Get physical bits from leaf 0x80000008 (if available) */ cpuid(0x80000008u, &eax, &ebx, &ecx, &edx); phys_bits = eax & 0xff; } u64 phys_mask = ((1ull << phys_bits) - 1); for (i=0; i<vcnt; i++) { wrmsr_smp(MTRRphysBase_MSR(i), 0); wrmsr_smp(MTRRphysMask_MSR(i), 0); } /* Mark 3.5-4GB as UC, anything not specified defaults to WB */ wrmsr_smp(MTRRphysBase_MSR(0), pcimem_start | MTRR_MEMTYPE_UC); wrmsr_smp(MTRRphysMask_MSR(0) , (-((1ull<<32)-pcimem_start) & phys_mask) | 0x800); // Enable fixed and variable MTRRs; set default type. wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB); }
/* Get the MSR pair relating to a var range */ static void get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr) { rdmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi); rdmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi); }