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.


Release 1.0
[palacios.git] / geekos / 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  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
6  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
7  * $Revision: 1.13 $
8  * 
9  * This is free software.  You are permitted to use,
10  * redistribute, and modify it as specified in the file "COPYING".
11  */
12
13 #include <geekos/defs.h>
14 #include <geekos/ktypes.h>
15 #include <geekos/kassert.h>
16 #include <geekos/bootinfo.h>
17 #include <geekos/gdt.h>
18 #include <geekos/screen.h>
19 #include <geekos/int.h>
20 #include <geekos/malloc.h>
21 #include <geekos/string.h>
22 #include <geekos/mem.h>
23
24 #include <geekos/serial.h>
25 #include <geekos/debug.h>
26
27
28 /* ----------------------------------------------------------------------
29  * Global data
30  * ---------------------------------------------------------------------- */
31
32 /*
33  * List of Page structures representing each page of physical memory.
34  */
35 struct Page* g_pageList;
36
37 void * g_ramdiskImage;
38 ulong_t s_ramdiskSize;
39
40
41 /*
42  * Number of pages currently available on the freelist.
43  */
44 uint_t g_freePageCount = 0;
45
46
47
48 /* 
49  *  the disgusting way to get at the memory assigned to a VM
50  */
51 extern ulong_t vm_range_start;
52 extern ulong_t vm_range_end;
53 extern ulong_t guest_kernel_start;
54 extern ulong_t guest_kernel_end;
55
56
57
58 /* ----------------------------------------------------------------------
59  * Private data and functions
60  * ---------------------------------------------------------------------- */
61
62 /*
63  * Defined in paging.c
64  */
65 extern int debugFaults;
66 #define Debug(args...) if (debugFaults) Print(args)
67
68 /*
69  * List of pages available for allocation.
70  */
71 static struct Page_List s_freeList;
72
73 /*
74  * Total number of physical pages.
75  */
76 int unsigned s_numPages;
77
78
79
80
81 /*
82  * Add a range of pages to the inventory of physical memory.
83  */
84 static void Add_Page_Range(ulong_t start, ulong_t end, int flags)
85 {
86     ulong_t addr;
87
88     PrintBoth("Start: %u (0x%x), End: %u(0x%x)  (Type=0x%.4x)\n", (unsigned int)start, start, (unsigned int)end, end, flags);
89
90     KASSERT(Is_Page_Multiple(start));
91     KASSERT(Is_Page_Multiple(end));
92     KASSERT(start < end);
93
94     //Print("Adding %lu pages\n", (end - start) / PAGE_SIZE);
95
96     for (addr = start; addr < end; addr += PAGE_SIZE) {
97       //      Print("Adding Page at %u\n", (unsigned int)addr);
98         struct Page *page = Get_Page(addr);
99
100         page->flags = flags;
101
102         if (flags == PAGE_AVAIL) {
103             /* Add the page to the freelist */
104             Add_To_Back_Of_Page_List(&s_freeList, page);
105
106             /* Update free page count */
107             ++g_freePageCount;
108         } else {
109             Set_Next_In_Page_List(page, 0);
110             Set_Prev_In_Page_List(page, 0);
111         }
112
113     }
114     //   Print("%d pages now in freelist\n", g_freePageCount);
115
116 }
117
118 /* ----------------------------------------------------------------------
119  * Public functions
120  * ---------------------------------------------------------------------- */
121
122 /*
123  * The linker defines this symbol to indicate the end of
124  * the executable image.
125  */
126 extern char end;
127
128 /*
129  * Initialize memory management data structures.
130  * Enables the use of Alloc_Page() and Free_Page() functions.
131  */
132 void Init_Mem(struct Boot_Info* bootInfo)
133 {
134     ulong_t numPages = bootInfo->memSizeKB >> 2;
135     ulong_t endOfMem = numPages * PAGE_SIZE;
136     unsigned numPageListBytes = sizeof(struct Page) * numPages;
137     ulong_t pageListAddr;
138     ulong_t pageListEnd;
139     ulong_t kernEnd;
140     ulong_t heapAddr;
141     ulong_t heapEnd;
142     ulong_t vmmMemEnd;
143
144
145     g_ramdiskImage = bootInfo->ramdisk_image;
146     s_ramdiskSize = bootInfo->ramdisk_size;
147     ulong_t initrdAddr = 0;
148     ulong_t initrdEnd = 0;
149
150     
151
152     KASSERT(bootInfo->memSizeKB > 0);
153
154
155     /*
156      * Before we do anything, switch from setup.asm's temporary GDT
157      * to the kernel's permanent GDT.
158      */
159     Init_GDT();
160
161
162     PrintBoth("Total Memory Size: %u MBytes\n", bootInfo->memSizeKB/1024);
163     PrintBoth("Page List (at 0x%x) Size: %u bytes\n", &s_freeList, numPageListBytes);
164
165   
166     /* Memory Layout:
167      * bios area (1 page reserved) 
168      * kernel_thread_obj (1 page)
169      * kernel_stack (1 page)
170      * available space
171      * available space
172      * ISA_HOLE_START - ISA_HOLE_END: hardware
173      * EXTENDED_MEMORY:
174      *        start - end:       kernel
175      *        VM Guest (variable pages)
176      *        Heap (512 Pages)
177      *        Page List (variable pages)
178      *        Available Memory for VMM (4096 pages)
179      *        Ramdisk //Zheng 08/03/2008
180      *        VM Memory (everything else)
181      */
182
183     //kernEnd = Round_Up_To_Page((ulong_t)&end);
184     kernEnd = (ulong_t)&end;
185
186     PrintBoth("Kernel End=%lx\n", kernEnd);
187
188
189     /* ************************************************************************************** */
190     /* If we have dynamic loading of the guest kernel, we should put the relocation code here */
191     /* ************************************************************************************** */
192
193     kernEnd = Round_Up_To_Page(kernEnd);
194     heapAddr = kernEnd;
195     heapEnd = Round_Up_To_Page(heapAddr + KERNEL_HEAP_SIZE);
196     pageListAddr = heapEnd;
197     pageListEnd = Round_Up_To_Page(pageListAddr + numPageListBytes);
198     /* Global variables */
199     // These must be set before we can call Add_Page_Range..
200     g_pageList = (struct Page*) pageListAddr;
201     s_numPages = numPages;
202     /* ** */
203     vmmMemEnd = Round_Up_To_Page(pageListEnd + VMM_AVAIL_MEM_SIZE);
204
205     /*
206      * Zheng 08/03/2008
207      * copy the ramdisk to this area 
208      */
209     if (s_ramdiskSize > 0) {
210       initrdAddr = vmmMemEnd;
211       initrdEnd = Round_Up_To_Page(initrdAddr + s_ramdiskSize);
212       PrintBoth("mem.c(%d) Move ramdisk(%dB) from %x to %x", __LINE__, s_ramdiskSize, g_ramdiskImage, initrdAddr);
213       memcpy((ulong_t *)initrdAddr, (ulong_t *)g_ramdiskImage, s_ramdiskSize);
214       PrintBoth(" done\n");
215       PrintBoth("mem.c(%d) Set 0 to unused bytes in the last ramdisk page from %x to %x", __LINE__, initrdAddr+s_ramdiskSize, initrdEnd);
216       memset((ulong_t *)initrdAddr + s_ramdiskSize, 0, initrdEnd - (initrdAddr + s_ramdiskSize));
217       PrintBoth(" done\n");
218     }
219
220     
221     /* 
222      *  the disgusting way to get at the memory assigned to a VM
223      */
224     
225     //vm_range_start = vmmMemEnd;
226     //vm_range_end = endOfMem;
227     /*
228      * Zheng 08/03/2008
229      */
230     if (s_ramdiskSize > 0) {
231       vm_range_start = initrdEnd;
232       vm_range_end = endOfMem;    
233     }
234
235     Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED);                        // BIOS area
236     Add_Page_Range(PAGE_SIZE, PAGE_SIZE * 3, PAGE_ALLOCATED);         // Intial kernel thread obj + stack
237     Add_Page_Range(PAGE_SIZE * 3, ISA_HOLE_START, PAGE_AVAIL);     // Available space
238     Add_Page_Range(ISA_HOLE_START, ISA_HOLE_END, PAGE_HW);            // Hardware ROMs
239     Add_Page_Range(KERNEL_START_ADDR, kernEnd, PAGE_KERN);            // VMM Kernel
240     //    Add_Page_Range(guest_kernel_start, guestEnd, PAGE_VM);                  // Guest kernel location
241     Add_Page_Range(heapAddr, heapEnd, PAGE_HEAP);                     // Heap
242     Add_Page_Range(pageListAddr, pageListEnd, PAGE_KERN);             // Page List 
243     Add_Page_Range(pageListEnd, vmmMemEnd, PAGE_AVAIL);               // Available VMM memory
244
245
246     if (s_ramdiskSize > 0) {
247       /*
248        * Zheng 08/03/2008
249        */
250       Add_Page_Range(vmmMemEnd, initrdEnd, PAGE_ALLOCATED);              //Ramdisk memory area      
251       //    Add_Page_Range(vmmMemEnd, endOfMem, PAGE_VM);                // Memory allocated to the VM
252       // Until we get a more intelligent memory allocator
253       Add_Page_Range(initrdEnd, endOfMem, PAGE_AVAIL);                   // Memory allocated to the VM
254     } else {
255       Add_Page_Range(vmmMemEnd, endOfMem, PAGE_AVAIL);                   // Memory allocated to the VM
256     }
257
258     /* Initialize the kernel heap */
259     Init_Heap(heapAddr, KERNEL_HEAP_SIZE);
260
261     PrintBoth("%uKB memory detected, %u pages in freelist, %d bytes in kernel heap\n",
262         bootInfo->memSizeKB, g_freePageCount, KERNEL_HEAP_SIZE);
263
264     PrintBoth("Memory Layout:\n");
265     PrintBoth("%x to %x - BIOS AREA\n", 0, PAGE_SIZE - 1);
266     PrintBoth("%x to %x - KERNEL_THREAD_OBJ\n", PAGE_SIZE, PAGE_SIZE * 2 - 1);
267     PrintBoth("%x to %x - KERNEL_STACK\n", PAGE_SIZE * 2, PAGE_SIZE * 3 - 1);
268     PrintBoth("%lx to %x - FREE\n", PAGE_SIZE * 3, ISA_HOLE_START - 1);
269     PrintBoth("%x to %x - ISA_HOLE\n", ISA_HOLE_START, ISA_HOLE_END - 1);
270     PrintBoth("%x to %x - KERNEL CODE + VM_KERNEL\n", KERNEL_START_ADDR, kernEnd - 1);
271     //    PrintBoth("%x to %x - VM_KERNEL\n", kernEnd, guestEnd - 1);
272     PrintBoth("%x to %x - KERNEL HEAP\n", heapAddr, heapEnd - 1);
273     PrintBoth("%lx to %lx - PAGE LIST\n", pageListAddr, pageListEnd - 1);
274     PrintBoth("%lx to %x - FREE\n", pageListEnd, vmmMemEnd - 1);
275
276
277     if (s_ramdiskSize > 0) {
278       /*
279        * Zheng 08/03/2008
280        */
281       PrintBoth("%lx to %x - RAMDISK\n", vmmMemEnd, initrdEnd - 1);
282       
283       PrintBoth("%lx to %x - GUEST_MEMORY (also free)\n", initrdEnd, endOfMem - 1);
284     } else {
285       PrintBoth("%lx to %x - GUEST_MEMORY (also free)\n", vmmMemEnd, endOfMem - 1);
286     }
287     
288 }
289
290 /*
291  * Initialize the .bss section of the kernel executable image.
292  */
293 void Init_BSS(void)
294 {
295     extern char BSS_START, BSS_END;
296
297     /* Fill .bss with zeroes */
298     memset(&BSS_START, '\0', &BSS_END - &BSS_START);
299     // screen is not inited yet - PAD
300     // PrintBoth("BSS Inited, BSS_START=%x, BSS_END=%x\n",BSS_START,BSS_END);
301 }
302
303 /*
304  * Allocate a page of physical memory.
305  */
306 void* Alloc_Page(void)
307 {
308     struct Page* page;
309     void *result = 0;
310
311     bool iflag = Begin_Int_Atomic();
312
313     /* See if we have a free page */
314     if (!Is_Page_List_Empty(&s_freeList)) {
315         /* Remove the first page on the freelist. */
316         page = Get_Front_Of_Page_List(&s_freeList);
317         KASSERT((page->flags & PAGE_ALLOCATED) == 0);
318         Remove_From_Front_Of_Page_List(&s_freeList);
319
320         /* Mark page as having been allocated. */
321         page->flags |= PAGE_ALLOCATED;
322         g_freePageCount--;
323         result = (void*) Get_Page_Address(page);
324     }
325
326     End_Int_Atomic(iflag);
327
328     return result;
329 }
330
331 /*
332  * Free a page of physical memory.
333  */
334 void Free_Page(void* pageAddr)
335 {
336     ulong_t addr = (ulong_t) pageAddr;
337     struct Page* page;
338     bool iflag;
339
340     iflag = Begin_Int_Atomic();
341
342     KASSERT(Is_Page_Multiple(addr));
343
344     /* Get the Page object for this page */
345     page = Get_Page(addr);
346     KASSERT((page->flags & PAGE_ALLOCATED) != 0);
347
348     /* Clear the allocation bit */
349     page->flags &= ~(PAGE_ALLOCATED);
350
351     /* Put the page back on the freelist */
352     Add_To_Back_Of_Page_List(&s_freeList, page);
353     g_freePageCount++;
354
355     End_Int_Atomic(iflag);
356 }