X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=geekos%2Fsrc%2Fgeekos%2Fmem.c;fp=geekos%2Fsrc%2Fgeekos%2Fmem.c;h=5c8e916304a732c2f69b2c97d15d11fe7e1147e7;hp=0000000000000000000000000000000000000000;hb=ddc16b0737cf58f7aa90a69c6652cdf4090aec51;hpb=626595465a2c6987606a6bc697df65130ad8c2d3 diff --git a/geekos/src/geekos/mem.c b/geekos/src/geekos/mem.c new file mode 100644 index 0000000..5c8e916 --- /dev/null +++ b/geekos/src/geekos/mem.c @@ -0,0 +1,356 @@ + /* + * Physical memory allocation + * Copyright (c) 2001,2003,2004 David H. Hovemeyer + * Copyright (c) 2003, Jeffrey K. Hollingsworth + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * $Revision: 1.13 $ + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "COPYING". + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* ---------------------------------------------------------------------- + * Global data + * ---------------------------------------------------------------------- */ + +/* + * List of Page structures representing each page of physical memory. + */ +struct Page* g_pageList; + +void * g_ramdiskImage; +ulong_t s_ramdiskSize; + + +/* + * Number of pages currently available on the freelist. + */ +uint_t g_freePageCount = 0; + + + +/* + * the disgusting way to get at the memory assigned to a VM + */ +extern ulong_t vm_range_start; +extern ulong_t vm_range_end; +extern ulong_t guest_kernel_start; +extern ulong_t guest_kernel_end; + + + +/* ---------------------------------------------------------------------- + * Private data and functions + * ---------------------------------------------------------------------- */ + +/* + * Defined in paging.c + */ +extern int debugFaults; +#define Debug(args...) if (debugFaults) Print(args) + +/* + * List of pages available for allocation. + */ +static struct Page_List s_freeList; + +/* + * Total number of physical pages. + */ +int unsigned s_numPages; + + + + +/* + * Add a range of pages to the inventory of physical memory. + */ +static void Add_Page_Range(ulong_t start, ulong_t end, int flags) +{ + ulong_t addr; + + PrintBoth("Start: %u (0x%x), End: %u(0x%x) (Type=0x%.4x)\n", (unsigned int)start, start, (unsigned int)end, end, flags); + + KASSERT(Is_Page_Multiple(start)); + KASSERT(Is_Page_Multiple(end)); + KASSERT(start < end); + + //Print("Adding %lu pages\n", (end - start) / PAGE_SIZE); + + for (addr = start; addr < end; addr += PAGE_SIZE) { + // Print("Adding Page at %u\n", (unsigned int)addr); + struct Page *page = Get_Page(addr); + + page->flags = flags; + + if (flags == PAGE_AVAIL) { + /* Add the page to the freelist */ + Add_To_Back_Of_Page_List(&s_freeList, page); + + /* Update free page count */ + ++g_freePageCount; + } else { + Set_Next_In_Page_List(page, 0); + Set_Prev_In_Page_List(page, 0); + } + + } + // Print("%d pages now in freelist\n", g_freePageCount); + +} + +/* ---------------------------------------------------------------------- + * Public functions + * ---------------------------------------------------------------------- */ + +/* + * The linker defines this symbol to indicate the end of + * the executable image. + */ +extern char end; + +/* + * Initialize memory management data structures. + * Enables the use of Alloc_Page() and Free_Page() functions. + */ +void Init_Mem(struct Boot_Info* bootInfo) +{ + ulong_t numPages = bootInfo->memSizeKB >> 2; + ulong_t endOfMem = numPages * PAGE_SIZE; + unsigned numPageListBytes = sizeof(struct Page) * numPages; + ulong_t pageListAddr; + ulong_t pageListEnd; + ulong_t kernEnd; + ulong_t heapAddr; + ulong_t heapEnd; + ulong_t vmmMemEnd; + + + g_ramdiskImage = bootInfo->ramdisk_image; + s_ramdiskSize = bootInfo->ramdisk_size; + ulong_t initrdAddr = 0; + ulong_t initrdEnd = 0; + + + + KASSERT(bootInfo->memSizeKB > 0); + + + /* + * Before we do anything, switch from setup.asm's temporary GDT + * to the kernel's permanent GDT. + */ + Init_GDT(); + + + PrintBoth("Total Memory Size: %u MBytes\n", bootInfo->memSizeKB/1024); + PrintBoth("Page List (at 0x%x) Size: %u bytes\n", &s_freeList, numPageListBytes); + + + /* Memory Layout: + * bios area (1 page reserved) + * kernel_thread_obj (1 page) + * kernel_stack (1 page) + * available space + * available space + * ISA_HOLE_START - ISA_HOLE_END: hardware + * EXTENDED_MEMORY: + * start - end: kernel + * VM Guest (variable pages) + * Heap (512 Pages) + * Page List (variable pages) + * Available Memory for VMM (4096 pages) + * Ramdisk //Zheng 08/03/2008 + * VM Memory (everything else) + */ + + //kernEnd = Round_Up_To_Page((ulong_t)&end); + kernEnd = (ulong_t)&end; + + PrintBoth("Kernel End=%lx\n", kernEnd); + + + /* ************************************************************************************** */ + /* If we have dynamic loading of the guest kernel, we should put the relocation code here */ + /* ************************************************************************************** */ + + kernEnd = Round_Up_To_Page(kernEnd); + heapAddr = kernEnd; + heapEnd = Round_Up_To_Page(heapAddr + KERNEL_HEAP_SIZE); + pageListAddr = heapEnd; + pageListEnd = Round_Up_To_Page(pageListAddr + numPageListBytes); + /* Global variables */ + // These must be set before we can call Add_Page_Range.. + g_pageList = (struct Page*) pageListAddr; + s_numPages = numPages; + /* ** */ + vmmMemEnd = Round_Up_To_Page(pageListEnd + VMM_AVAIL_MEM_SIZE); + + /* + * Zheng 08/03/2008 + * copy the ramdisk to this area + */ + if (s_ramdiskSize > 0) { + initrdAddr = vmmMemEnd; + initrdEnd = Round_Up_To_Page(initrdAddr + s_ramdiskSize); + PrintBoth("mem.c(%d) Move ramdisk(%dB) from %x to %x", __LINE__, s_ramdiskSize, g_ramdiskImage, initrdAddr); + memcpy((ulong_t *)initrdAddr, (ulong_t *)g_ramdiskImage, s_ramdiskSize); + PrintBoth(" done\n"); + PrintBoth("mem.c(%d) Set 0 to unused bytes in the last ramdisk page from %x to %x", __LINE__, initrdAddr+s_ramdiskSize, initrdEnd); + memset((ulong_t *)initrdAddr + s_ramdiskSize, 0, initrdEnd - (initrdAddr + s_ramdiskSize)); + PrintBoth(" done\n"); + } + + + /* + * the disgusting way to get at the memory assigned to a VM + */ + + //vm_range_start = vmmMemEnd; + //vm_range_end = endOfMem; + /* + * Zheng 08/03/2008 + */ + if (s_ramdiskSize > 0) { + vm_range_start = initrdEnd; + vm_range_end = endOfMem; + } + + Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED); // BIOS area + Add_Page_Range(PAGE_SIZE, PAGE_SIZE * 3, PAGE_ALLOCATED); // Intial kernel thread obj + stack + Add_Page_Range(PAGE_SIZE * 3, ISA_HOLE_START, PAGE_AVAIL); // Available space + Add_Page_Range(ISA_HOLE_START, ISA_HOLE_END, PAGE_HW); // Hardware ROMs + Add_Page_Range(KERNEL_START_ADDR, kernEnd, PAGE_KERN); // VMM Kernel + // Add_Page_Range(guest_kernel_start, guestEnd, PAGE_VM); // Guest kernel location + Add_Page_Range(heapAddr, heapEnd, PAGE_HEAP); // Heap + Add_Page_Range(pageListAddr, pageListEnd, PAGE_KERN); // Page List + Add_Page_Range(pageListEnd, vmmMemEnd, PAGE_AVAIL); // Available VMM memory + + + if (s_ramdiskSize > 0) { + /* + * Zheng 08/03/2008 + */ + Add_Page_Range(vmmMemEnd, initrdEnd, PAGE_ALLOCATED); //Ramdisk memory area + // Add_Page_Range(vmmMemEnd, endOfMem, PAGE_VM); // Memory allocated to the VM + // Until we get a more intelligent memory allocator + Add_Page_Range(initrdEnd, endOfMem, PAGE_AVAIL); // Memory allocated to the VM + } else { + Add_Page_Range(vmmMemEnd, endOfMem, PAGE_AVAIL); // Memory allocated to the VM + } + + /* Initialize the kernel heap */ + Init_Heap(heapAddr, KERNEL_HEAP_SIZE); + + PrintBoth("%uKB memory detected, %u pages in freelist, %d bytes in kernel heap\n", + bootInfo->memSizeKB, g_freePageCount, KERNEL_HEAP_SIZE); + + PrintBoth("Memory Layout:\n"); + PrintBoth("%x to %x - BIOS AREA\n", 0, PAGE_SIZE - 1); + PrintBoth("%x to %x - KERNEL_THREAD_OBJ\n", PAGE_SIZE, PAGE_SIZE * 2 - 1); + PrintBoth("%x to %x - KERNEL_STACK\n", PAGE_SIZE * 2, PAGE_SIZE * 3 - 1); + PrintBoth("%lx to %x - FREE\n", PAGE_SIZE * 3, ISA_HOLE_START - 1); + PrintBoth("%x to %x - ISA_HOLE\n", ISA_HOLE_START, ISA_HOLE_END - 1); + PrintBoth("%x to %x - KERNEL CODE + VM_KERNEL\n", KERNEL_START_ADDR, kernEnd - 1); + // PrintBoth("%x to %x - VM_KERNEL\n", kernEnd, guestEnd - 1); + PrintBoth("%x to %x - KERNEL HEAP\n", heapAddr, heapEnd - 1); + PrintBoth("%lx to %lx - PAGE LIST\n", pageListAddr, pageListEnd - 1); + PrintBoth("%lx to %x - FREE\n", pageListEnd, vmmMemEnd - 1); + + + if (s_ramdiskSize > 0) { + /* + * Zheng 08/03/2008 + */ + PrintBoth("%lx to %x - RAMDISK\n", vmmMemEnd, initrdEnd - 1); + + PrintBoth("%lx to %x - GUEST_MEMORY (also free)\n", initrdEnd, endOfMem - 1); + } else { + PrintBoth("%lx to %x - GUEST_MEMORY (also free)\n", vmmMemEnd, endOfMem - 1); + } + +} + +/* + * Initialize the .bss section of the kernel executable image. + */ +void Init_BSS(void) +{ + extern char BSS_START, BSS_END; + + /* Fill .bss with zeroes */ + memset(&BSS_START, '\0', &BSS_END - &BSS_START); + // screen is not inited yet - PAD + // PrintBoth("BSS Inited, BSS_START=%x, BSS_END=%x\n",BSS_START,BSS_END); +} + +/* + * Allocate a page of physical memory. + */ +void* Alloc_Page(void) +{ + struct Page* page; + void *result = 0; + + bool iflag = Begin_Int_Atomic(); + + /* See if we have a free page */ + if (!Is_Page_List_Empty(&s_freeList)) { + /* Remove the first page on the freelist. */ + page = Get_Front_Of_Page_List(&s_freeList); + KASSERT((page->flags & PAGE_ALLOCATED) == 0); + Remove_From_Front_Of_Page_List(&s_freeList); + + /* Mark page as having been allocated. */ + page->flags |= PAGE_ALLOCATED; + g_freePageCount--; + result = (void*) Get_Page_Address(page); + } + + End_Int_Atomic(iflag); + + return result; +} + +/* + * Free a page of physical memory. + */ +void Free_Page(void* pageAddr) +{ + ulong_t addr = (ulong_t) pageAddr; + struct Page* page; + bool iflag; + + iflag = Begin_Int_Atomic(); + + KASSERT(Is_Page_Multiple(addr)); + + /* Get the Page object for this page */ + page = Get_Page(addr); + KASSERT((page->flags & PAGE_ALLOCATED) != 0); + + /* Clear the allocation bit */ + page->flags &= ~(PAGE_ALLOCATED); + + /* Put the page back on the freelist */ + Add_To_Back_Of_Page_List(&s_freeList, page); + g_freePageCount++; + + End_Int_Atomic(iflag); +}