abaf22c136f983316d64ad831517fd77eeeefed9
[akaros.git] / kern / arch / i386 / page_alloc.c
1 /* Copyright (c) 2009 The Regents of the University  of California. 
2  * See the COPYRIGHT files at the top of this source tree for full 
3  * license information.
4  * 
5  * Kevin Klues <klueska@cs.berkeley.edu>    
6  */
7
8 #ifdef __SHARC__
9 #pragma nosharc
10 #endif
11
12 #include <sys/queue.h>
13 #include <page_alloc.h>
14 #include <pmap.h>
15 #include <kmalloc.h>
16
17 // llc stands for last-level-cache
18 uint16_t llc_num_colors;
19 page_list_t *COUNT(llc_num_colors) colored_page_free_list = NULL;
20 spinlock_t colored_page_free_list_lock;
21
22 void page_alloc_bootstrap(cache_t* llc) {
23         // Initialize the properties of the last level cache used by this allocator
24         llc_num_colors = get_cache_num_page_colors(llc);
25
26         // Allocate space for the array required to manage the free lists
27         size_t list_size = llc_num_colors*sizeof(page_list_t);
28         colored_page_free_list = (page_list_t*) boot_alloc(list_size, PGSIZE);
29 }
30
31 /*
32  * Initialize the memory free lists.
33  * After this point, ONLY use the functions below
34  * to allocate and deallocate physical memory via the 
35  * page_free_lists. 
36  */
37 void page_alloc_init() 
38 {
39         cache_t* llc = available_caches.llc;
40
41         // First Bootstrap the page alloc process
42         static bool bootstrapped = FALSE;
43         if(!bootstrapped) {
44                 bootstrapped = TRUE;
45                 page_alloc_bootstrap(llc);
46         }
47
48         // Then, initialize the array required to manage the colored page free list
49         for(int i=0; i<llc_num_colors; i++) {
50                 LIST_INIT(&(colored_page_free_list[i]));
51         }
52
53         //  Then, mark the pages already in use by the kernel. 
54         //  1) Mark page 0 as in use.
55         //     This way we preserve the real-mode IDT and BIOS structures
56         //     in case we ever need them.  (Currently we don't, but...)
57         //  2) Mark the rest of base memory as free.
58         //  3) Then comes the IO hole [IOPHYSMEM, EXTPHYSMEM).
59         //     Mark it as in use so that it can never be allocated.      
60         //  4) Then extended memory [EXTPHYSMEM, ...).
61         //     Some of it is in use, some is free.
62         int i;
63         extern char (SNT end)[];
64         physaddr_t physaddr_after_kernel = PADDR(PTRROUNDUP(boot_freemem, PGSIZE));
65
66         pages[0].page_ref = 1;
67         // alloc the second page, since we will need it later to init the other cores
68         // probably need to be smarter about what page we use (make this dynamic) TODO
69         pages[1].page_ref = 1;
70         for (i = 2; i < PPN(IOPHYSMEM); i++) {
71                 pages[i].page_ref = 0;
72                 LIST_INSERT_HEAD(
73                    &(colored_page_free_list[get_page_color(page2ppn(&pages[i]), llc)]),
74                    &pages[i],
75                    page_link
76                 );
77         }
78         for (i = PPN(IOPHYSMEM); i < PPN(EXTPHYSMEM); i++) {
79                 pages[i].page_ref = 1;
80         }
81         for (i = PPN(EXTPHYSMEM); i < PPN(physaddr_after_kernel); i++) {
82                 pages[i].page_ref = 1;
83         }
84         for (i = PPN(physaddr_after_kernel); i < PPN(maxaddrpa); i++) {
85                 pages[i].page_ref = 0;
86                 LIST_INSERT_HEAD(
87                    &(colored_page_free_list[get_page_color(page2ppn(&pages[i]), llc)]),
88                    &pages[i],
89                    page_link
90                 );
91         }
92         // this block out all memory above maxaddrpa.  will need another mechanism
93         // to allocate and map these into the kernel address space
94         for (i = PPN(maxaddrpa); i < npages; i++) {
95                 pages[i].page_ref = 1;
96         }
97 }
98