Forward port bochs smp changes; rename smpdetect.c to smp.c.
[seabios.git] / src / mtrr.c
1 // Initialize MTRRs - mostly useful on KVM.
2 //
3 // Copyright (C) 2006 Fabrice Bellard
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "util.h" // dprintf
8 #include "biosvar.h" // GET_EBDA
9
10 #define MSR_MTRRcap                    0x000000fe
11 #define MSR_MTRRfix64K_00000           0x00000250
12 #define MSR_MTRRfix16K_80000           0x00000258
13 #define MSR_MTRRfix16K_A0000           0x00000259
14 #define MSR_MTRRfix4K_C0000            0x00000268
15 #define MSR_MTRRfix4K_C8000            0x00000269
16 #define MSR_MTRRfix4K_D0000            0x0000026a
17 #define MSR_MTRRfix4K_D8000            0x0000026b
18 #define MSR_MTRRfix4K_E0000            0x0000026c
19 #define MSR_MTRRfix4K_E8000            0x0000026d
20 #define MSR_MTRRfix4K_F0000            0x0000026e
21 #define MSR_MTRRfix4K_F8000            0x0000026f
22 #define MSR_MTRRdefType                0x000002ff
23
24 #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
25 #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
26
27 void mtrr_setup(void)
28 {
29     if (CONFIG_COREBOOT)
30         return;
31
32     u32 eax, ebx, ecx, cpuid_features;
33     cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
34     if (!(cpuid_features & CPUID_MTRR))
35         return;
36     if (!(cpuid_features & CPUID_MSR))
37         return;
38
39     dprintf(3, "init mtrr\n");
40
41     int i, vcnt, fix, wc;
42     u32 ram_size = GET_GLOBAL(RamSize);
43     u32 mtrr_cap;
44     union {
45         u8 valb[8];
46         u64 val;
47     } u;
48
49     mtrr_cap = rdmsr(MSR_MTRRcap);
50     vcnt = mtrr_cap & 0xff;
51     fix = mtrr_cap & 0x100;
52     wc = mtrr_cap & 0x400;
53     if (!vcnt || !fix)
54        return;
55     u.val = 0;
56     for (i = 0; i < 8; ++i)
57         if (ram_size >= 65536 * (i + 1))
58             u.valb[i] = 6;
59     wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
60     u.val = 0;
61     for (i = 0; i < 8; ++i)
62         if (ram_size >= 65536 * 8 + 16384 * (i + 1))
63             u.valb[i] = 6;
64     wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
65     wrmsr_smp(MSR_MTRRfix16K_A0000, 0);
66     wrmsr_smp(MSR_MTRRfix4K_C0000, 0);
67     wrmsr_smp(MSR_MTRRfix4K_C8000, 0);
68     wrmsr_smp(MSR_MTRRfix4K_D0000, 0);
69     wrmsr_smp(MSR_MTRRfix4K_D8000, 0);
70     wrmsr_smp(MSR_MTRRfix4K_E0000, 0);
71     wrmsr_smp(MSR_MTRRfix4K_E8000, 0);
72     wrmsr_smp(MSR_MTRRfix4K_F0000, 0);
73     wrmsr_smp(MSR_MTRRfix4K_F8000, 0);
74     /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
75     wrmsr_smp(MTRRphysBase_MSR(0), 0xe0000000ull | 0);
76     wrmsr_smp(MTRRphysMask_MSR(0), ~(0x20000000ull - 1) | 0x800);
77     wrmsr_smp(MSR_MTRRdefType, 0xc06);
78 }