BXE: min->MIN, plus an spatch
[akaros.git] / kern / arch / x86 / pmap.c
1 /* Copyright (c) 2009 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Physical memory managment, common to 32 and 64 bit */
6
7 #include <arch/x86.h>
8 #include <arch/arch.h>
9 #include <arch/mmu.h>
10 #include <arch/apic.h>
11
12 #include <error.h>
13 #include <sys/queue.h>
14
15 #include <atomic.h>
16 #include <string.h>
17 #include <assert.h>
18 #include <pmap.h>
19 #include <kclock.h>
20 #include <env.h>
21 #include <stdio.h>
22 #include <kmalloc.h>
23 #include <page_alloc.h>
24
25 static int nvram_read(int r)
26 {
27         return mc146818_read(r) | (mc146818_read(r + 1) << 8);
28 }
29
30 bool enable_pse(void)
31 {
32         uint32_t edx, cr4;
33         cpuid(0x1, 0x0, 0, 0, 0, &edx);
34         if (edx & CPUID_PSE_SUPPORT) {
35                 cr4 = rcr4();
36                 cr4 |= CR4_PSE;
37                 lcr4(cr4);
38                 return 1;
39         } else
40                 return 0;
41 }
42
43 // could consider having an API to allow these to dynamically change
44 // MTRRs are for physical, static ranges.  PAT are linear, more granular, and 
45 // more dynamic
46 void setup_default_mtrrs(barrier_t* smp_barrier)
47 {
48         // disable interrupts
49         int8_t state = 0;
50         disable_irqsave(&state);
51         // barrier - if we're meant to do this for all cores, we'll be 
52         // passed a pointer to an initialized barrier
53         if (smp_barrier)
54                 waiton_barrier(smp_barrier);
55         
56         // disable caching      cr0: set CD and clear NW
57         lcr0((rcr0() | CR0_CD) & ~CR0_NW);
58         // flush caches
59         cache_flush();
60         // flush tlb
61         tlb_flush_global();
62         // disable MTRRs, and sets default type to WB (06)
63 #ifndef CONFIG_NOMTRRS 
64         write_msr(IA32_MTRR_DEF_TYPE, 0x00000006);
65
66         // Now we can actually safely adjust the MTRRs
67         // MTRR for IO Holes (note these are 64 bit values we are writing)
68         // 0x000a0000 - 0x000c0000 : VGA - WC 0x01
69         write_msr(IA32_MTRR_PHYSBASE0, PTE_ADDR(VGAPHYSMEM) | 0x01);
70         // if we need to have a full 64bit val, use the UINT64 macro
71         write_msr(IA32_MTRR_PHYSMASK0, 0x0000000ffffe0800);
72         // 0x000c0000 - 0x00100000 : IO devices (and ROM BIOS) - UC 0x00
73         write_msr(IA32_MTRR_PHYSBASE1, PTE_ADDR(DEVPHYSMEM) | 0x00);
74         write_msr(IA32_MTRR_PHYSMASK1, 0x0000000ffffc0800);
75         // APIC/IOAPIC holes
76         /* Going to skip them, since we set their mode using PAT when we 
77          * map them in 
78          */
79         // make sure all other MTRR ranges are disabled (should be unnecessary)
80         write_msr(IA32_MTRR_PHYSMASK2, 0);
81         write_msr(IA32_MTRR_PHYSMASK3, 0);
82         write_msr(IA32_MTRR_PHYSMASK4, 0);
83         write_msr(IA32_MTRR_PHYSMASK5, 0);
84         write_msr(IA32_MTRR_PHYSMASK6, 0);
85         write_msr(IA32_MTRR_PHYSMASK7, 0);
86
87         // keeps default type to WB (06), turns MTRRs on, and turns off fixed ranges
88         write_msr(IA32_MTRR_DEF_TYPE, 0x00000806);
89 #endif  
90         // reflush caches and TLB
91         cache_flush();
92         tlb_flush_global();
93         // turn on caching
94         lcr0(rcr0() & ~(CR0_CD | CR0_NW));
95         // barrier
96         if (smp_barrier)
97                 waiton_barrier(smp_barrier);
98         // enable interrupts
99         enable_irqsave(&state);
100 }
101
102 /* Flushes a TLB, including global pages.  We should always have the CR4_PGE
103  * flag set, but just in case, we'll check.  Toggling this bit flushes the TLB.
104  */
105 void tlb_flush_global(void)
106 {
107         uint32_t cr4 = rcr4();
108         if (cr4 & CR4_PGE) {
109                 lcr4(cr4 & ~CR4_PGE);
110                 lcr4(cr4);
111         } else 
112                 lcr3(rcr3());
113 }