- Moved hlt() to it's own header.
[coreboot.git] / src / cpu / p6 / pgtbl.c
1 #include <console/console.h>
2 #include <smp/start_stop.h>
3 #include <cpu/p6/pgtbl.h>
4
5 static void paging_off(void)
6 {
7         __asm__ __volatile__ (
8                 /* Disable paging */
9                 "movl   %%cr0, %%eax\n\t"
10                 "andl   $0x7FFFFFFF, %%eax\n\t"
11                 "movl   %%eax, %%cr0\n\t"
12                 /* Disable pae */
13                 "movl   %%cr4, %%eax\n\t"
14                 "andl   $0xFFFFFFDF, %%eax\n\t"
15                 :
16                 :
17                 : "eax"
18                 );
19 }
20
21 static void paging_on(void *pdp)
22 {
23         __asm__ __volatile__(
24                 /* Load the page table address */
25                 "movl   %0, %%cr3\n\t"
26                 /* Enable pae */
27                 "movl   %%cr4, %%eax\n\t"
28                 "orl    $0x00000020, %%eax\n\t"
29                 "movl   %%eax, %%cr4\n\t"
30                 /* Enable paging */
31                 "movl   %%cr0, %%eax\n\t"
32                 "orl    $0x80000000, %%eax\n\t"
33                 "movl   %%eax, %%cr0\n\t"
34                 :
35                 : "r" (pdp)
36                 : "eax"
37                 );
38 }
39
40 void *map_2M_page(int cpu_index, unsigned long page) 
41 {
42         struct pde {
43                 uint32_t addr_lo;
44                 uint32_t addr_hi;
45         } __attribute__ ((packed));
46         struct pg_table {
47                 struct pde pd[2048];
48                 struct pde pdp[512];
49         } __attribute__ ((packed));
50         static struct pg_table pgtbl[CONFIG_MAX_CPUS] __attribute__ ((aligned(4096)));
51         static unsigned long mapped_window[CONFIG_MAX_CPUS];
52         unsigned long window;
53         void *result;
54         int i;
55         if ((cpu_index < 0) || (cpu_index >= CONFIG_MAX_CPUS)) {
56                 return MAPPING_ERROR;
57         }
58         window = page >> 10;
59         if (window != mapped_window[cpu_index]) {
60                 paging_off();
61                 if (window > 1) {
62                         struct pde *pd, *pdp;
63                         /* Point the page directory pointers at the page directories */
64                         memset(&pgtbl[cpu_index].pdp, 0, sizeof(pgtbl[cpu_index].pdp));
65                         pd = pgtbl[cpu_index].pd;
66                         pdp = pgtbl[cpu_index].pdp;
67                         pdp[0].addr_lo = ((uint32_t)&pd[512*0])|1;
68                         pdp[1].addr_lo = ((uint32_t)&pd[512*1])|1;
69                         pdp[2].addr_lo = ((uint32_t)&pd[512*2])|1;
70                         pdp[3].addr_lo = ((uint32_t)&pd[512*3])|1;
71                         /* The first half of the page table is identity mapped */
72                         for(i = 0; i < 1024; i++) {
73                                 pd[i].addr_lo = ((i & 0x3ff) << 21)| 0xE3;
74                                 pd[i].addr_hi = 0;
75                         }
76                         /* The second half of the page table holds the mapped page */
77                         for(i = 1024; i < 2048; i++) {
78                                 pd[i].addr_lo = ((window & 1) << 31) | ((i & 0x3ff) << 21) | 0xE3;
79                                 pd[i].addr_hi = (window >> 1);
80                         }
81                         paging_on(pdp);
82                 }
83                 mapped_window[cpu_index] = window;
84         }
85         if (window == 0) {
86                 result = (void *)(page << 21);
87         } else {
88                 result = (void *)(0x80000000 | ((page & 0x3ff) << 21));
89         }
90         return result;
91 }