]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/arch/x86/mem.cc
License change.
[polintos/scott/priv.git] / kernel / arch / x86 / mem.cc
1 // arch/x86/mem.cc -- x86 paging and misc. memory management
2 //
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
4 // 
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
8 // 
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
14
15 #include <kern/kernel.h>
16 #include <kern/mem.h>
17 #include <kern/pagealloc.h>
18 #include <kern/libc.h>
19
20 // Initial page tables have the first 4 MiB mapped, using large pages.
21
22 __attribute__((aligned(4096))) u32 x86_init_ptbl_l2[1024] = {
23         0x87
24 };
25
26 extern int _end;
27
28 using Mem::PageAllocZone;
29
30 namespace Arch {
31         u64 mem_end;
32         
33         namespace Priv {
34                 #define zonelist(x) ((x) * ((x) + 1) / 2 - 1)
35                 
36                 PageAllocZone pagezones[num_zones];
37                 PageAllocZone *pagezonelists_real[zonelist(num_zones + 1)];
38         }
39         
40         PageAllocZone **pagezonelists[Priv::num_zones];
41
42         uintptr_t next_free_bootmem = reinterpret_cast<uintptr_t>(&_end);
43 }
44
45 namespace Arch {
46 namespace Priv {
47         void early_adjust_mappings()
48         {
49                 using Mem::get_bootmem;
50         
51                 // Clear low-address mapping and invalidate TLB
52                 x86_init_ptbl_l2[0] = 0;
53                 asm volatile("movl %0, %%cr3" : : "r" (kvirt_to_phys(x86_init_ptbl_l2)));
54                 
55                 // Mark the ktext mapping global now that it's not mapped at address
56                 // zero.  FIXME: check for and enable PGE
57                 
58                 x86_init_ptbl_l2[0x200] |= 0x100;
59         }
60
61         void map_physmem()
62         {
63                 using Mem::get_bootmem;
64         
65                 // phys_to_ktext can be used for the first
66                 // 4MiB-minus-size-of-kernel of bootmem allocations.
67         
68                 for (uintptr_t physpage = 1; physpage <= (mem_end - 1) / (4096*1024);
69                      physpage++)
70                 {
71                         uintptr_t virtpage = physpage + (PHYSMEM_START >> 22);
72                         x86_init_ptbl_l2[virtpage & 1023] = (physpage << 22) | 0x187;
73                 }
74                 
75                 size_t pages_size = (mem_end / page_size) * sizeof(Mem::Page);
76                 Mem::pages = static_cast<Mem::Page *>(get_bootmem(pages_size, 4));
77                 Mem::last_page = Mem::pages + pages_size - 1;
78                 bzero(Mem::pages, pages_size);
79                 
80                 int listpos[num_zones];
81                 
82                 for (int i = num_zones - 1; i >= 0; i--) {
83                         listpos[i] = zonelist(i);
84                         pagezonelists[num_zones - 1 - i] = &pagezonelists_real[listpos[i]];
85
86                         u64 rstart = mem_zone_regions[i].start;
87                         u64 rend = mem_zone_regions[i].end;
88                 
89                         if (mem_start <= rend && mem_end >= rstart) {
90                                 if (rstart < mem_start)
91                                         rstart = mem_start;
92                                 if (rend > mem_end)
93                                         rend = mem_end;
94                                 
95                                 ulong page_start = rstart / page_size;
96                                 ulong page_len = (rend - rstart + 1) / page_size;
97                                 
98                                 pagezones[i].init(page_start, page_len);
99                                 
100                                 for (int j = i; j < num_zones; j++) {
101                                         assert(listpos[j] < zonelist(j + 1));
102                                         pagezonelists_real[listpos[j]++] = &pagezones[i];
103                                 }
104                         }
105                 }
106         }
107 }
108 }