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.


build reorganization
[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 ulong_t 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;
148     ulong_t initrdEnd;
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
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     vm_range_start = initrdEnd;
231     vm_range_end = endOfMem;    
232
233
234     Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED);                        // BIOS area
235     Add_Page_Range(PAGE_SIZE, PAGE_SIZE * 3, PAGE_ALLOCATED);         // Intial kernel thread obj + stack
236     Add_Page_Range(PAGE_SIZE * 3, ISA_HOLE_START, PAGE_AVAIL);     // Available space
237     Add_Page_Range(ISA_HOLE_START, ISA_HOLE_END, PAGE_HW);            // Hardware ROMs
238     Add_Page_Range(KERNEL_START_ADDR, kernEnd, PAGE_KERN);            // VMM Kernel
239     //    Add_Page_Range(guest_kernel_start, guestEnd, PAGE_VM);                  // Guest kernel location
240     Add_Page_Range(heapAddr, heapEnd, PAGE_HEAP);                     // Heap
241     Add_Page_Range(pageListAddr, pageListEnd, PAGE_KERN);             // Page List 
242     Add_Page_Range(pageListEnd, vmmMemEnd, PAGE_AVAIL);               // Available VMM memory
243
244 #ifdef RAMDISK_BOOT
245     /*
246      * Zheng 08/03/2008
247      */
248     Add_Page_Range(vmmMemEnd, initrdEnd, PAGE_ALLOCATED);              //Ramdisk memory area      
249     //    Add_Page_Range(vmmMemEnd, endOfMem, PAGE_VM);                // Memory allocated to the VM
250     // Until we get a more intelligent memory allocator
251     Add_Page_Range(initrdEnd, endOfMem, PAGE_AVAIL);                   // Memory allocated to the VM
252 #else
253     Add_Page_Range(vmmMemEnd, endOfMem, PAGE_AVAIL);                   // Memory allocated to the VM
254 #endif
255
256     /* Initialize the kernel heap */
257     Init_Heap(heapAddr, KERNEL_HEAP_SIZE);
258
259     PrintBoth("%uKB memory detected, %u pages in freelist, %d bytes in kernel heap\n",
260         bootInfo->memSizeKB, g_freePageCount, KERNEL_HEAP_SIZE);
261
262     PrintBoth("Memory Layout:\n");
263     PrintBoth("%x to %x - BIOS AREA\n", 0, PAGE_SIZE - 1);
264     PrintBoth("%x to %x - KERNEL_THREAD_OBJ\n", PAGE_SIZE, PAGE_SIZE * 2 - 1);
265     PrintBoth("%x to %x - KERNEL_STACK\n", PAGE_SIZE * 2, PAGE_SIZE * 3 - 1);
266     PrintBoth("%lx to %x - FREE\n", PAGE_SIZE * 3, ISA_HOLE_START - 1);
267     PrintBoth("%x to %x - ISA_HOLE\n", ISA_HOLE_START, ISA_HOLE_END - 1);
268     PrintBoth("%x to %x - KERNEL CODE + VM_KERNEL\n", KERNEL_START_ADDR, kernEnd - 1);
269     //    PrintBoth("%x to %x - VM_KERNEL\n", kernEnd, guestEnd - 1);
270     PrintBoth("%x to %x - KERNEL HEAP\n", heapAddr, heapEnd - 1);
271     PrintBoth("%lx to %lx - PAGE LIST\n", pageListAddr, pageListEnd - 1);
272     PrintBoth("%lx to %x - FREE\n", pageListEnd, vmmMemEnd - 1);
273
274 #ifdef RAMDISK_BOOT
275     /*
276      * Zheng 08/03/2008
277      */
278     PrintBoth("%lx to %x - RAMDISK\n", vmmMemEnd, initrdEnd - 1);
279
280     PrintBoth("%lx to %x - GUEST_MEMORY (also free)\n", initrdEnd, endOfMem - 1);
281 #else
282     PrintBoth("%lx to %x - GUEST_MEMORY (also free)\n", vmmMemEnd, endOfMem - 1);
283 #endif
284 }
285
286 /*
287  * Initialize the .bss section of the kernel executable image.
288  */
289 void Init_BSS(void)
290 {
291     extern char BSS_START, BSS_END;
292
293     /* Fill .bss with zeroes */
294     memset(&BSS_START, '\0', &BSS_END - &BSS_START);
295     // screen is not inited yet - PAD
296     // PrintBoth("BSS Inited, BSS_START=%x, BSS_END=%x\n",BSS_START,BSS_END);
297 }
298
299 /*
300  * Allocate a page of physical memory.
301  */
302 void* Alloc_Page(void)
303 {
304     struct Page* page;
305     void *result = 0;
306
307     bool iflag = Begin_Int_Atomic();
308
309     /* See if we have a free page */
310     if (!Is_Page_List_Empty(&s_freeList)) {
311         /* Remove the first page on the freelist. */
312         page = Get_Front_Of_Page_List(&s_freeList);
313         KASSERT((page->flags & PAGE_ALLOCATED) == 0);
314         Remove_From_Front_Of_Page_List(&s_freeList);
315
316         /* Mark page as having been allocated. */
317         page->flags |= PAGE_ALLOCATED;
318         g_freePageCount--;
319         result = (void*) Get_Page_Address(page);
320     }
321
322     End_Int_Atomic(iflag);
323
324     return result;
325 }
326
327 /*
328  * Free a page of physical memory.
329  */
330 void Free_Page(void* pageAddr)
331 {
332     ulong_t addr = (ulong_t) pageAddr;
333     struct Page* page;
334     bool iflag;
335
336     iflag = Begin_Int_Atomic();
337
338     KASSERT(Is_Page_Multiple(addr));
339
340     /* Get the Page object for this page */
341     page = Get_Page(addr);
342     KASSERT((page->flags & PAGE_ALLOCATED) != 0);
343
344     /* Clear the allocation bit */
345     page->flags &= ~(PAGE_ALLOCATED);
346
347     /* Put the page back on the freelist */
348     Add_To_Back_Of_Page_List(&s_freeList, page);
349     g_freePageCount++;
350
351     End_Int_Atomic(iflag);
352 }