Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added memory region generated page tables, and removed all the ugliness that was...
[palacios.git] / palacios / src / geekos / mem.c
1 /*
2  * Physical memory allocation
3  * Copyright (c) 2001,2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
4  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
5  * $Revision: 1.4 $
6  * 
7  * This is free software.  You are permitted to use,
8  * redistribute, and modify it as specified in the file "COPYING".
9  */
10
11 #include <geekos/defs.h>
12 #include <geekos/ktypes.h>
13 #include <geekos/kassert.h>
14 #include <geekos/bootinfo.h>
15 #include <geekos/gdt.h>
16 #include <geekos/screen.h>
17 #include <geekos/int.h>
18 #include <geekos/malloc.h>
19 #include <geekos/string.h>
20 #include <geekos/mem.h>
21
22 #include <geekos/serial.h>
23 #include <geekos/debug.h>
24
25 /* ----------------------------------------------------------------------
26  * Global data
27  * ---------------------------------------------------------------------- */
28
29 /*
30  * List of Page structures representing each page of physical memory.
31  */
32 struct Page* g_pageList;
33
34 /*
35  * Number of pages currently available on the freelist.
36  */
37 uint_t g_freePageCount = 0;
38
39 /* ----------------------------------------------------------------------
40  * Private data and functions
41  * ---------------------------------------------------------------------- */
42
43 /*
44  * Defined in paging.c
45  */
46 extern int debugFaults;
47 #define Debug(args...) if (debugFaults) Print(args)
48
49 /*
50  * List of pages available for allocation.
51  */
52 static struct Page_List s_freeList;
53
54 /*
55  * Total number of physical pages.
56  */
57 int unsigned s_numPages;
58
59 /*
60  * Add a range of pages to the inventory of physical memory.
61  */
62 static void Add_Page_Range(ulong_t start, ulong_t end, int flags)
63 {
64     ulong_t addr;
65
66     PrintBoth("Start: %u, End: %u  (Type=0x%.4x)\n", (unsigned int)start, (unsigned int)end, flags);
67
68     KASSERT(Is_Page_Multiple(start));
69     KASSERT(Is_Page_Multiple(end));
70     KASSERT(start < end);
71
72     //Print("Adding %lu pages\n", (end - start) / PAGE_SIZE);
73
74     for (addr = start; addr < end; addr += PAGE_SIZE) {
75       //      Print("Adding Page at %u\n", (unsigned int)addr);
76         struct Page *page = Get_Page(addr);
77
78         page->flags = flags;
79
80         if (flags == PAGE_AVAIL) {
81             /* Add the page to the freelist */
82             Add_To_Back_Of_Page_List(&s_freeList, page);
83
84             /* Update free page count */
85             ++g_freePageCount;
86         } else {
87             Set_Next_In_Page_List(page, 0);
88             Set_Prev_In_Page_List(page, 0);
89         }
90
91     }
92     //   Print("%d pages now in freelist\n", g_freePageCount);
93
94 }
95
96 /* ----------------------------------------------------------------------
97  * Public functions
98  * ---------------------------------------------------------------------- */
99
100 /*
101  * The linker defines this symbol to indicate the end of
102  * the executable image.
103  */
104 extern char end;
105
106 /*
107  * Initialize memory management data structures.
108  * Enables the use of Alloc_Page() and Free_Page() functions.
109  */
110 void Init_Mem(struct Boot_Info* bootInfo)
111 {
112     ulong_t numPages = bootInfo->memSizeKB >> 2;
113     ulong_t endOfMem = numPages * PAGE_SIZE;
114     unsigned numPageListBytes = sizeof(struct Page) * numPages;
115     ulong_t pageListAddr;
116     ulong_t pageListEnd;
117     ulong_t kernEnd;
118     ulong_t guestEnd;
119     ulong_t heapAddr;
120     ulong_t heapEnd;
121     ulong_t vmmMemEnd;
122
123
124     KASSERT(bootInfo->memSizeKB > 0);
125
126
127     /*
128      * Before we do anything, switch from setup.asm's temporary GDT
129      * to the kernel's permanent GDT.
130      */
131     Init_GDT();
132
133
134     PrintBoth("Total Memory Size: %u MBytes\n", bootInfo->memSizeKB/1024);
135     PrintBoth("Page List Size: %u bytes\n", numPageListBytes);
136
137   
138     /* Memory Layout:
139      * bios area (1 page reserved) 
140      * kernel_thread_obj (1 page)
141      * kernel_stack (1 page)
142      * available space
143      * start - end:       kernel
144      * available space
145      * ISA_HOLE_START - ISA_HOLE_END: hardware
146      * EXTENDED_MEMORY:
147      *        VM Guest (variable pages)
148      *        Heap (512 Pages)
149      *        Page List (variable pages)
150      *        Available Memory for VMM (4096 pages)
151      *        VM Memory (everything else)
152      */
153
154     kernEnd = Round_Up_To_Page((ulong_t)&end);
155     PrintBoth("Kernel End=%lx\n", kernEnd);
156
157
158     /* ************************************************************************************** */
159     /* If we have dynamic loading of the guest kernel, we should put the relocation code here */
160     /* ************************************************************************************** */
161
162     guestEnd = Round_Up_To_Page(ISA_HOLE_END + bootInfo->guest_size);
163     heapAddr = guestEnd;
164     heapEnd = Round_Up_To_Page(heapAddr + KERNEL_HEAP_SIZE);
165     pageListAddr = heapEnd;
166     pageListEnd = Round_Up_To_Page(pageListAddr + numPageListBytes);
167     /* Global variables */
168     // These must be set before we can call Add_Page_Range..
169     g_pageList = (struct Page*) pageListAddr;
170     s_numPages = numPages;
171     /* ** */
172     vmmMemEnd = Round_Up_To_Page(pageListEnd + VMM_AVAIL_MEM_SIZE);
173
174
175
176
177     Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED);                        // BIOS area
178     Add_Page_Range(PAGE_SIZE, PAGE_SIZE * 3, PAGE_ALLOCATED);         // Intial kernel thread obj + stack
179     Add_Page_Range(PAGE_SIZE * 3, KERNEL_START_ADDR, PAGE_AVAIL);     // Available space
180     Add_Page_Range(KERNEL_START_ADDR, kernEnd, PAGE_KERN);            // VMM Kernel
181     Add_Page_Range(kernEnd, ISA_HOLE_START, PAGE_AVAIL);              // Available Space
182     Add_Page_Range(ISA_HOLE_START, ISA_HOLE_END, PAGE_HW);            // Hardware ROMs
183     Add_Page_Range(ISA_HOLE_END, guestEnd, PAGE_VM);                  // Guest kernel location
184     Add_Page_Range(heapAddr, heapEnd, PAGE_HEAP);                     // Heap
185     Add_Page_Range(pageListAddr, pageListEnd, PAGE_KERN);              // Page List 
186     Add_Page_Range(pageListEnd, vmmMemEnd, PAGE_AVAIL);                // Available VMM memory
187     Add_Page_Range(vmmMemEnd, endOfMem, PAGE_VM);                      // Memory allocated to the VM
188
189
190
191     /* Initialize the kernel heap */
192     Init_Heap(heapAddr, KERNEL_HEAP_SIZE);
193
194     PrintBoth("%uKB memory detected, %u pages in freelist, %d bytes in kernel heap\n",
195         bootInfo->memSizeKB, g_freePageCount, KERNEL_HEAP_SIZE);
196
197     PrintBoth("Memory Layout:\n");
198     PrintBoth("%x to %x - BIOS AREA\n", 0, PAGE_SIZE - 1);
199     PrintBoth("%x to %x - KERNEL_THREAD_OBJ\n", PAGE_SIZE, PAGE_SIZE * 2 - 1);
200     PrintBoth("%x to %x - KERNEL_STACK\n", PAGE_SIZE * 2, PAGE_SIZE * 3 - 1);
201     PrintBoth("%lx to %x - FREE\n", PAGE_SIZE * 3, KERNEL_START_ADDR - 1);
202     PrintBoth("%x to %x - KERNEL CODE\n", KERNEL_START_ADDR, kernEnd - 1);
203     PrintBoth("%lx to %x - FREE\n", kernEnd, ISA_HOLE_START - 1);
204     PrintBoth("%x to %x - ISA_HOLE\n", ISA_HOLE_START, ISA_HOLE_END - 1);
205     PrintBoth("%x to %x - VM_KERNEL\n", ISA_HOLE_END, guestEnd - 1);
206     PrintBoth("%x to %x - KERNEL HEAP\n", heapAddr, heapEnd - 1);
207     PrintBoth("%lx to %lx - PAGE LIST\n", pageListAddr, pageListEnd - 1);
208     PrintBoth("%lx to %x - FREE\n", pageListEnd, vmmMemEnd - 1);
209     PrintBoth("%lx to %x - GUEST_MEMORY\n", vmmMemEnd, endOfMem - 1);
210 }
211
212 /*
213  * Initialize the .bss section of the kernel executable image.
214  */
215 void Init_BSS(void)
216 {
217     extern char BSS_START, BSS_END;
218
219     /* Fill .bss with zeroes */
220     memset(&BSS_START, '\0', &BSS_END - &BSS_START);
221     PrintBoth("BSS Inited, BSS_START=%x, BSS_END=%x\n",BSS_START,BSS_END);
222 }
223
224 /*
225  * Allocate a page of physical memory.
226  */
227 void* Alloc_Page(void)
228 {
229     struct Page* page;
230     void *result = 0;
231
232     bool iflag = Begin_Int_Atomic();
233
234     /* See if we have a free page */
235     if (!Is_Page_List_Empty(&s_freeList)) {
236         /* Remove the first page on the freelist. */
237         page = Get_Front_Of_Page_List(&s_freeList);
238         KASSERT((page->flags & PAGE_ALLOCATED) == 0);
239         Remove_From_Front_Of_Page_List(&s_freeList);
240
241         /* Mark page as having been allocated. */
242         page->flags |= PAGE_ALLOCATED;
243         g_freePageCount--;
244         result = (void*) Get_Page_Address(page);
245     }
246
247     End_Int_Atomic(iflag);
248
249     return result;
250 }
251
252 /*
253  * Free a page of physical memory.
254  */
255 void Free_Page(void* pageAddr)
256 {
257     ulong_t addr = (ulong_t) pageAddr;
258     struct Page* page;
259     bool iflag;
260
261     iflag = Begin_Int_Atomic();
262
263     KASSERT(Is_Page_Multiple(addr));
264
265     /* Get the Page object for this page */
266     page = Get_Page(addr);
267     KASSERT((page->flags & PAGE_ALLOCATED) != 0);
268
269     /* Clear the allocation bit */
270     page->flags &= ~(PAGE_ALLOCATED);
271
272     /* Put the page back on the freelist */
273     Add_To_Back_Of_Page_List(&s_freeList, page);
274     g_freePageCount++;
275
276     End_Int_Atomic(iflag);
277 }