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.


b7ae0266f6180d915d43a4faf793a56272a8d635
[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  * $Revision: 1.13 $
7  * 
8  * This is free software.  You are permitted to use,
9  * redistribute, and modify it as specified in the file "COPYING".
10  */
11
12 #include <geekos/defs.h>
13 #include <geekos/ktypes.h>
14 #include <geekos/kassert.h>
15 #include <geekos/bootinfo.h>
16 #include <geekos/gdt.h>
17 #include <geekos/screen.h>
18 #include <geekos/int.h>
19 #include <geekos/malloc.h>
20 #include <geekos/string.h>
21 #include <geekos/mem.h>
22
23 #include <geekos/serial.h>
24 #include <geekos/debug.h>
25
26
27 /* ----------------------------------------------------------------------
28  * Global data
29  * ---------------------------------------------------------------------- */
30
31 /*
32  * List of Page structures representing each page of physical memory.
33  */
34 struct Page* g_pageList;
35
36 #ifdef RAMDISK_BOOT
37 ulong_t g_ramdiskImage;
38 ulong_t s_ramdiskSize;
39 #endif
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     /*Zheng 08/03/2008*/    
145 #ifdef RAMDISK_BOOT
146     g_ramdiskImage = bootInfo->ramdisk_image;
147     s_ramdiskSize = bootInfo->ramdisk_size;
148     ulong_t initrdAddr;
149     ulong_t initrdEnd;
150 #endif
151     
152
153     KASSERT(bootInfo->memSizeKB > 0);
154
155
156     /*
157      * Before we do anything, switch from setup.asm's temporary GDT
158      * to the kernel's permanent GDT.
159      */
160     Init_GDT();
161
162
163     PrintBoth("Total Memory Size: %u MBytes\n", bootInfo->memSizeKB/1024);
164     PrintBoth("Page List (at 0x%x) Size: %u bytes\n", &s_freeList, numPageListBytes);
165
166   
167     /* Memory Layout:
168      * bios area (1 page reserved) 
169      * kernel_thread_obj (1 page)
170      * kernel_stack (1 page)
171      * available space
172      * available space
173      * ISA_HOLE_START - ISA_HOLE_END: hardware
174      * EXTENDED_MEMORY:
175      *        start - end:       kernel
176      *        VM Guest (variable pages)
177      *        Heap (512 Pages)
178      *        Page List (variable pages)
179      *        Available Memory for VMM (4096 pages)
180      *        Ramdisk //Zheng 08/03/2008
181      *        VM Memory (everything else)
182      */
183
184     //kernEnd = Round_Up_To_Page((ulong_t)&end);
185     kernEnd = (ulong_t)&end;
186
187     PrintBoth("Kernel End=%lx\n", kernEnd);
188
189
190     /* ************************************************************************************** */
191     /* If we have dynamic loading of the guest kernel, we should put the relocation code here */
192     /* ************************************************************************************** */
193
194     kernEnd = Round_Up_To_Page(kernEnd);
195     heapAddr = kernEnd;
196     heapEnd = Round_Up_To_Page(heapAddr + KERNEL_HEAP_SIZE);
197     pageListAddr = heapEnd;
198     pageListEnd = Round_Up_To_Page(pageListAddr + numPageListBytes);
199     /* Global variables */
200     // These must be set before we can call Add_Page_Range..
201     g_pageList = (struct Page*) pageListAddr;
202     s_numPages = numPages;
203     /* ** */
204     vmmMemEnd = Round_Up_To_Page(pageListEnd + VMM_AVAIL_MEM_SIZE);
205
206 #ifdef RAMDISK_BOOT
207     /*
208      * Zheng 08/03/2008
209      * copy the ramdisk to this area 
210      */
211
212     initrdAddr = vmmMemEnd;
213     initrdEnd = Round_Up_To_Page(initrdAddr + s_ramdiskSize);
214     PrintBoth("mem.c(%d) Move ramdisk(%dB) from %x to %x", __LINE__, s_ramdiskSize, g_ramdiskImage, initrdAddr);
215     memcpy((ulong_t *)initrdAddr, (ulong_t *)g_ramdiskImage, s_ramdiskSize);
216     PrintBoth(" done\n");
217     PrintBoth("mem.c(%d) Set 0 to unused bytes in the last ramdisk page from %x to %x", __LINE__, initrdAddr+s_ramdiskSize, initrdEnd);
218     memset((ulong_t *)initrdAddr+s_ramdiskSize, 0, initrdEnd-(initrdAddr+s_ramdiskSize));
219     PrintBoth(" done\n");
220     /*
221      * Zheng 08/03/2008
222      */
223     vm_range_start = initrdEnd;
224     vm_range_end = endOfMem;
225 #else
226     
227     /* 
228      *  the disgusting way to get at the memory assigned to a VM
229      */
230     
231     vm_range_start = vmmMemEnd;
232     vm_range_end = endOfMem;
233     
234 #endif
235
236     Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED);                        // BIOS area
237     Add_Page_Range(PAGE_SIZE, PAGE_SIZE * 3, PAGE_ALLOCATED);         // Intial kernel thread obj + stack
238     Add_Page_Range(PAGE_SIZE * 3, ISA_HOLE_START, PAGE_AVAIL);     // Available space
239     Add_Page_Range(ISA_HOLE_START, ISA_HOLE_END, PAGE_HW);            // Hardware ROMs
240     Add_Page_Range(KERNEL_START_ADDR, kernEnd, PAGE_KERN);            // VMM Kernel
241     //    Add_Page_Range(guest_kernel_start, guestEnd, PAGE_VM);                  // Guest kernel location
242     Add_Page_Range(heapAddr, heapEnd, PAGE_HEAP);                     // Heap
243     Add_Page_Range(pageListAddr, pageListEnd, PAGE_KERN);             // Page List 
244     Add_Page_Range(pageListEnd, vmmMemEnd, PAGE_AVAIL);               // Available VMM memory
245
246 #ifdef RAMDISK_BOOT
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 #endif
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 #ifdef RAMDISK_BOOT
277     /*
278      * Zheng 08/03/2008
279      */
280     PrintBoth("%lx to %x - RAMDISK\n", vmmMemEnd, initrdEnd - 1);
281
282     PrintBoth("%lx to %x - GUEST_MEMORY (also free)\n", initrdEnd, endOfMem - 1);
283 #else
284     PrintBoth("%lx to %x - GUEST_MEMORY (also free)\n", vmmMemEnd, endOfMem - 1);
285 #endif
286 }
287
288 /*
289  * Initialize the .bss section of the kernel executable image.
290  */
291 void Init_BSS(void)
292 {
293     extern char BSS_START, BSS_END;
294
295     /* Fill .bss with zeroes */
296     memset(&BSS_START, '\0', &BSS_END - &BSS_START);
297     // screen is not inited yet - PAD
298     // PrintBoth("BSS Inited, BSS_START=%x, BSS_END=%x\n",BSS_START,BSS_END);
299 }
300
301 /*
302  * Allocate a page of physical memory.
303  */
304 void* Alloc_Page(void)
305 {
306     struct Page* page;
307     void *result = 0;
308
309     bool iflag = Begin_Int_Atomic();
310
311     /* See if we have a free page */
312     if (!Is_Page_List_Empty(&s_freeList)) {
313         /* Remove the first page on the freelist. */
314         page = Get_Front_Of_Page_List(&s_freeList);
315         KASSERT((page->flags & PAGE_ALLOCATED) == 0);
316         Remove_From_Front_Of_Page_List(&s_freeList);
317
318         /* Mark page as having been allocated. */
319         page->flags |= PAGE_ALLOCATED;
320         g_freePageCount--;
321         result = (void*) Get_Page_Address(page);
322     }
323
324     End_Int_Atomic(iflag);
325
326     return result;
327 }
328
329 /*
330  * Free a page of physical memory.
331  */
332 void Free_Page(void* pageAddr)
333 {
334     ulong_t addr = (ulong_t) pageAddr;
335     struct Page* page;
336     bool iflag;
337
338     iflag = Begin_Int_Atomic();
339
340     KASSERT(Is_Page_Multiple(addr));
341
342     /* Get the Page object for this page */
343     page = Get_Page(addr);
344     KASSERT((page->flags & PAGE_ALLOCATED) != 0);
345
346     /* Clear the allocation bit */
347     page->flags &= ~(PAGE_ALLOCATED);
348
349     /* Put the page back on the freelist */
350     Add_To_Back_Of_Page_List(&s_freeList, page);
351     g_freePageCount++;
352
353     End_Int_Atomic(iflag);
354 }