blob: 6f857dfa0145b28b2431958dcc1c4c7b496462a3 [file] [log] [blame]
Martin Roth4dcd13d2016-02-24 13:53:07 -08001/* vmem.c - MemTest-86
Martin Roth9b1b3352016-02-24 12:27:06 -08002 *
3 * Virtual memory handling (PAE)
4 *
5 * Released under version 2 of the Gnu Public License.
6 * By Chris Brady
7 */
8#include "stdint.h"
9#include "test.h"
10#include "cpuid.h"
11
12extern struct cpu_ident cpu_id;
13
14static unsigned long mapped_win = 1;
15void paging_off(void)
16{
17 if (!cpu_id.fid.bits.pae)
18 return;
19 __asm__ __volatile__ (
20 /* Disable paging */
21 "movl %%cr0, %%eax\n\t"
22 "andl $0x7FFFFFFF, %%eax\n\t"
23 "movl %%eax, %%cr0\n\t"
24 : :
25 : "ax"
Ben Gardner90f7d112016-03-15 15:25:22 -050026 );
Martin Roth9b1b3352016-02-24 12:27:06 -080027}
28
29static void paging_on(void *pdp)
30{
31 if (!cpu_id.fid.bits.pae)
32 return;
Ben Gardner90f7d112016-03-15 15:25:22 -050033 __asm__ __volatile__ (
Martin Roth9b1b3352016-02-24 12:27:06 -080034 /* Load the page table address */
35 "movl %0, %%cr3\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 : "ax"
Ben Gardner90f7d112016-03-15 15:25:22 -050043 );
Martin Roth9b1b3352016-02-24 12:27:06 -080044}
45
46static void paging_on_lm(void *pml)
47{
48 if (!cpu_id.fid.bits.pae)
49 return;
Ben Gardner90f7d112016-03-15 15:25:22 -050050 __asm__ __volatile__ (
Martin Roth9b1b3352016-02-24 12:27:06 -080051 /* Load the page table address */
52 "movl %0, %%cr3\n\t"
53 /* Enable paging */
54 "movl %%cr0, %%eax\n\t"
55 "orl $0x80000000, %%eax\n\t"
56 "movl %%eax, %%cr0\n\t"
57 :
58 : "r" (pml)
59 : "ax"
Ben Gardner90f7d112016-03-15 15:25:22 -050060 );
Martin Roth9b1b3352016-02-24 12:27:06 -080061}
62
63int map_page(unsigned long page)
64{
65 unsigned long i;
66 struct pde {
67 unsigned long addr_lo;
68 unsigned long addr_hi;
69 };
70 extern unsigned char pdp[];
71 extern unsigned char pml4[];
72 extern struct pde pd2[];
73 unsigned long win = page >> 19;
74
75 /* Less than 2 GB so no mapping is required */
76 if (win == 0) {
77 return 0;
78 }
79 if (cpu_id.fid.bits.pae == 0) {
80 /* Fail, we don't have PAE */
81 return -1;
82 }
83 if (cpu_id.fid.bits.lm == 0 && (page > 0x1000000)) {
Ben Gardner90f7d112016-03-15 15:25:22 -050084 /* Fail, we want an address that is out of bounds (> 64GB)
Martin Roth9b1b3352016-02-24 12:27:06 -080085 * for PAE and no long mode (ie. 32 bit CPU).
86 */
87 return -1;
88 }
89 /* Compute the page table entries... */
Ben Gardner90f7d112016-03-15 15:25:22 -050090 for (i = 0; i < 1024; i++) {
Martin Roth9b1b3352016-02-24 12:27:06 -080091 /*-----------------10/30/2004 12:37PM---------------
92 * 0xE3 --
93 * Bit 0 = Present bit. 1 = PDE is present
94 * Bit 1 = Read/Write. 1 = memory is writable
95 * Bit 2 = Supervisor/User. 0 = Supervisor only (CPL 0-2)
96 * Bit 3 = Writethrough. 0 = writeback cache policy
97 * Bit 4 = Cache Disable. 0 = page level cache enabled
98 * Bit 5 = Accessed. 1 = memory has been accessed.
99 * Bit 6 = Dirty. 1 = memory has been written to.
100 * Bit 7 = Page Size. 1 = page size is 2 MBytes
101 * --------------------------------------------------*/
102 pd2[i].addr_lo = ((win & 1) << 31) + ((i & 0x3ff) << 21) + 0xE3;
103 pd2[i].addr_hi = (win >> 1);
104 }
105 paging_off();
106 if (cpu_id.fid.bits.lm == 1) {
107 paging_on_lm(pml4);
108 } else {
109 paging_on(pdp);
110 }
111 mapped_win = win;
112 return 0;
113}
114
115void *mapping(unsigned long page_addr)
116{
117 void *result;
118 if (page_addr < 0x80000) {
119 /* If the address is less than 1GB directly use the address */
120 result = (void *)(page_addr << 12);
Ben Gardner90f7d112016-03-15 15:25:22 -0500121 } else {
Martin Roth9b1b3352016-02-24 12:27:06 -0800122 unsigned long alias;
123 alias = page_addr & 0x7FFFF;
124 alias += 0x80000;
125 result = (void *)(alias << 12);
126 }
127 return result;
128}
129
130void *emapping(unsigned long page_addr)
131{
132 void *result;
133 result = mapping(page_addr -1);
134 /* Fill in the low address bits */
135 result = ((unsigned char *)result) + 0xffc;
136 return result;
137}
138
139unsigned long page_of(void *addr)
140{
141 unsigned long page;
142 page = ((unsigned long)addr) >> 12;
143 if (page >= 0x80000) {
144 page &= 0x7FFFF;
145 page += mapped_win << 19;
146 }
147#if 0
148 cprint(LINE_SCROLL -2, 0, "page_of( )-> ");
149 hprint(LINE_SCROLL -2, 8, ((unsigned long)addr));
150 hprint(LINE_SCROLL -2, 20, page);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800151#endif
Martin Roth9b1b3352016-02-24 12:27:06 -0800152 return page;
153}