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.


code restructuring
[palacios-OLD.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.5 $
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, End: %u  (Type=0x%.4x)\n", (unsigned int)start, (unsigned int)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 guestEnd;
135     ulong_t heapAddr;
136     ulong_t heapEnd;
137     ulong_t vmmMemEnd;
138
139
140     KASSERT(bootInfo->memSizeKB > 0);
141
142
143     /*
144      * Before we do anything, switch from setup.asm's temporary GDT
145      * to the kernel's permanent GDT.
146      */
147     Init_GDT();
148
149
150     PrintBoth("Total Memory Size: %u MBytes\n", bootInfo->memSizeKB/1024);
151     PrintBoth("Page List Size: %u bytes\n", numPageListBytes);
152
153   
154     /* Memory Layout:
155      * bios area (1 page reserved) 
156      * kernel_thread_obj (1 page)
157      * kernel_stack (1 page)
158      * available space
159      * start - end:       kernel
160      * available space
161      * ISA_HOLE_START - ISA_HOLE_END: hardware
162      * EXTENDED_MEMORY:
163      *        VM Guest (variable pages)
164      *        Heap (512 Pages)
165      *        Page List (variable pages)
166      *        Available Memory for VMM (4096 pages)
167      *        VM Memory (everything else)
168      */
169
170     kernEnd = Round_Up_To_Page((ulong_t)&end);
171     PrintBoth("Kernel End=%lx\n", kernEnd);
172
173
174     /* ************************************************************************************** */
175     /* If we have dynamic loading of the guest kernel, we should put the relocation code here */
176     /* ************************************************************************************** */
177
178     guestEnd = Round_Up_To_Page(ISA_HOLE_END + bootInfo->guest_size);
179     heapAddr = guestEnd;
180     heapEnd = Round_Up_To_Page(heapAddr + KERNEL_HEAP_SIZE);
181     pageListAddr = heapEnd;
182     pageListEnd = Round_Up_To_Page(pageListAddr + numPageListBytes);
183     /* Global variables */
184     // These must be set before we can call Add_Page_Range..
185     g_pageList = (struct Page*) pageListAddr;
186     s_numPages = numPages;
187     /* ** */
188     vmmMemEnd = Round_Up_To_Page(pageListEnd + VMM_AVAIL_MEM_SIZE);
189
190
191     /* 
192      *  the disgusting way to get at the memory assigned to a VM
193      */
194     vm_range_start = vmmMemEnd;
195     vm_range_end = endOfMem;
196     guest_kernel_start = ISA_HOLE_END;
197     guest_kernel_end = guestEnd;
198
199     Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED);                        // BIOS area
200     Add_Page_Range(PAGE_SIZE, PAGE_SIZE * 3, PAGE_ALLOCATED);         // Intial kernel thread obj + stack
201     Add_Page_Range(PAGE_SIZE * 3, KERNEL_START_ADDR, PAGE_AVAIL);     // Available space
202     Add_Page_Range(KERNEL_START_ADDR, kernEnd, PAGE_KERN);            // VMM Kernel
203     Add_Page_Range(kernEnd, ISA_HOLE_START, PAGE_AVAIL);              // Available Space
204     Add_Page_Range(ISA_HOLE_START, ISA_HOLE_END, PAGE_HW);            // Hardware ROMs
205     Add_Page_Range(ISA_HOLE_END, guestEnd, PAGE_VM);                  // Guest kernel location
206     Add_Page_Range(heapAddr, heapEnd, PAGE_HEAP);                     // Heap
207     Add_Page_Range(pageListAddr, pageListEnd, PAGE_KERN);              // Page List 
208     Add_Page_Range(pageListEnd, vmmMemEnd, PAGE_AVAIL);                // Available VMM memory
209     Add_Page_Range(vmmMemEnd, endOfMem, PAGE_VM);                      // Memory allocated to the VM
210
211
212
213     /* Initialize the kernel heap */
214     Init_Heap(heapAddr, KERNEL_HEAP_SIZE);
215
216     PrintBoth("%uKB memory detected, %u pages in freelist, %d bytes in kernel heap\n",
217         bootInfo->memSizeKB, g_freePageCount, KERNEL_HEAP_SIZE);
218
219     PrintBoth("Memory Layout:\n");
220     PrintBoth("%x to %x - BIOS AREA\n", 0, PAGE_SIZE - 1);
221     PrintBoth("%x to %x - KERNEL_THREAD_OBJ\n", PAGE_SIZE, PAGE_SIZE * 2 - 1);
222     PrintBoth("%x to %x - KERNEL_STACK\n", PAGE_SIZE * 2, PAGE_SIZE * 3 - 1);
223     PrintBoth("%lx to %x - FREE\n", PAGE_SIZE * 3, KERNEL_START_ADDR - 1);
224     PrintBoth("%x to %x - KERNEL CODE\n", KERNEL_START_ADDR, kernEnd - 1);
225     PrintBoth("%lx to %x - FREE\n", kernEnd, ISA_HOLE_START - 1);
226     PrintBoth("%x to %x - ISA_HOLE\n", ISA_HOLE_START, ISA_HOLE_END - 1);
227     PrintBoth("%x to %x - VM_KERNEL\n", ISA_HOLE_END, guestEnd - 1);
228     PrintBoth("%x to %x - KERNEL HEAP\n", heapAddr, heapEnd - 1);
229     PrintBoth("%lx to %lx - PAGE LIST\n", pageListAddr, pageListEnd - 1);
230     PrintBoth("%lx to %x - FREE\n", pageListEnd, vmmMemEnd - 1);
231     PrintBoth("%lx to %x - GUEST_MEMORY\n", vmmMemEnd, endOfMem - 1);
232 }
233
234 /*
235  * Initialize the .bss section of the kernel executable image.
236  */
237 void Init_BSS(void)
238 {
239     extern char BSS_START, BSS_END;
240
241     /* Fill .bss with zeroes */
242     memset(&BSS_START, '\0', &BSS_END - &BSS_START);
243     PrintBoth("BSS Inited, BSS_START=%x, BSS_END=%x\n",BSS_START,BSS_END);
244 }
245
246 /*
247  * Allocate a page of physical memory.
248  */
249 void* Alloc_Page(void)
250 {
251     struct Page* page;
252     void *result = 0;
253
254     bool iflag = Begin_Int_Atomic();
255
256     /* See if we have a free page */
257     if (!Is_Page_List_Empty(&s_freeList)) {
258         /* Remove the first page on the freelist. */
259         page = Get_Front_Of_Page_List(&s_freeList);
260         KASSERT((page->flags & PAGE_ALLOCATED) == 0);
261         Remove_From_Front_Of_Page_List(&s_freeList);
262
263         /* Mark page as having been allocated. */
264         page->flags |= PAGE_ALLOCATED;
265         g_freePageCount--;
266         result = (void*) Get_Page_Address(page);
267     }
268
269     End_Int_Atomic(iflag);
270
271     return result;
272 }
273
274 /*
275  * Free a page of physical memory.
276  */
277 void Free_Page(void* pageAddr)
278 {
279     ulong_t addr = (ulong_t) pageAddr;
280     struct Page* page;
281     bool iflag;
282
283     iflag = Begin_Int_Atomic();
284
285     KASSERT(Is_Page_Multiple(addr));
286
287     /* Get the Page object for this page */
288     page = Get_Page(addr);
289     KASSERT((page->flags & PAGE_ALLOCATED) != 0);
290
291     /* Clear the allocation bit */
292     page->flags &= ~(PAGE_ALLOCATED);
293
294     /* Put the page back on the freelist */
295     Add_To_Back_Of_Page_List(&s_freeList, page);
296     g_freePageCount++;
297
298     End_Int_Atomic(iflag);
299 }