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.


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