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.


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