Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


imported SEABIOS source tree
[palacios.git] / bios / seabios / 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 #include "xen.h" // usingXen
10
11 #define MSR_MTRRcap                    0x000000fe
12 #define MSR_MTRRfix64K_00000           0x00000250
13 #define MSR_MTRRfix16K_80000           0x00000258
14 #define MSR_MTRRfix16K_A0000           0x00000259
15 #define MSR_MTRRfix4K_C0000            0x00000268
16 #define MSR_MTRRfix4K_C8000            0x00000269
17 #define MSR_MTRRfix4K_D0000            0x0000026a
18 #define MSR_MTRRfix4K_D8000            0x0000026b
19 #define MSR_MTRRfix4K_E0000            0x0000026c
20 #define MSR_MTRRfix4K_E8000            0x0000026d
21 #define MSR_MTRRfix4K_F0000            0x0000026e
22 #define MSR_MTRRfix4K_F8000            0x0000026f
23 #define MSR_MTRRdefType                0x000002ff
24
25 #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
26 #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
27
28 #define MTRR_MEMTYPE_UC 0
29 #define MTRR_MEMTYPE_WC 1
30 #define MTRR_MEMTYPE_WT 4
31 #define MTRR_MEMTYPE_WP 5
32 #define MTRR_MEMTYPE_WB 6
33
34 void mtrr_setup(void)
35 {
36     if (!CONFIG_MTRR_INIT || CONFIG_COREBOOT || usingXen())
37         return;
38
39     u32 eax, ebx, ecx, edx, cpuid_features;
40     cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
41     if (!(cpuid_features & CPUID_MTRR))
42         return;
43     if (!(cpuid_features & CPUID_MSR))
44         return;
45
46     dprintf(3, "init mtrr\n");
47
48     u32 mtrr_cap = rdmsr(MSR_MTRRcap);
49     int vcnt = mtrr_cap & 0xff;
50     int fix = mtrr_cap & 0x100;
51     if (!vcnt || !fix)
52        return;
53
54     // Disable MTRRs
55     wrmsr_smp(MSR_MTRRdefType, 0);
56
57     // Set fixed MTRRs
58     union u64b {
59         u8 valb[8];
60         u64 val;
61     } u;
62     u.val = 0;
63     int i;
64     for (i = 0; i < 8; i++)
65         if (RamSize >= 65536 * (i + 1))
66             u.valb[i] = MTRR_MEMTYPE_WB;
67     wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
68     u.val = 0;
69     for (i = 0; i < 8; i++)
70         if (RamSize >= 0x80000 + 16384 * (i + 1))
71             u.valb[i] = MTRR_MEMTYPE_WB;
72     wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
73     wrmsr_smp(MSR_MTRRfix16K_A0000, 0);   // 0xA0000-0xC0000 is uncached
74     int j;
75     for (j = 0; j < 8; j++) {
76         u.val = 0;
77         for (i = 0; i < 8; i++)
78             if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1))
79                 u.valb[i] = MTRR_MEMTYPE_WP;
80         wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val);
81     }
82
83     // Set variable MTRRs
84     int phys_bits = 36;
85     cpuid(0x80000000u, &eax, &ebx, &ecx, &edx);
86     if (eax >= 0x80000008) {
87             /* Get physical bits from leaf 0x80000008 (if available) */
88             cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
89             phys_bits = eax & 0xff;
90     }
91     u64 phys_mask = ((1ull << phys_bits) - 1);
92     for (i=0; i<vcnt; i++) {
93         wrmsr_smp(MTRRphysBase_MSR(i), 0);
94         wrmsr_smp(MTRRphysMask_MSR(i), 0);
95     }
96     /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
97     wrmsr_smp(MTRRphysBase_MSR(0), BUILD_MAX_HIGHMEM | MTRR_MEMTYPE_UC);
98     wrmsr_smp(MTRRphysMask_MSR(0)
99               , (-((1ull<<32)-BUILD_MAX_HIGHMEM) & phys_mask) | 0x800);
100
101     // Enable fixed and variable MTRRs; set default type.
102     wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB);
103 }