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