X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=misc%2Ftest_vm%2Fsrc%2Fgeekos%2Fmem.c;fp=misc%2Ftest_vm%2Fsrc%2Fgeekos%2Fmem.c;h=0000000000000000000000000000000000000000;hp=2f44520ab8bc9384c775c0734180f9fd78718762;hb=a70930549d1b741704dd7af4e6bb0e89f6f8a519;hpb=afb634a80f946634454a5d067a92aa600227bd93 diff --git a/misc/test_vm/src/geekos/mem.c b/misc/test_vm/src/geekos/mem.c deleted file mode 100644 index 2f44520..0000000 --- a/misc/test_vm/src/geekos/mem.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Physical memory allocation - * Copyright (c) 2001,2003,2004 David H. Hovemeyer - * Copyright (c) 2003, Jeffrey K. Hollingsworth - * $Revision: 1.1 $ - * - * 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 - -/* ---------------------------------------------------------------------- - * Global data - * ---------------------------------------------------------------------- */ - -/* - * List of Page structures representing each page of physical memory. - */ -struct Page* g_pageList; - -/* - * Number of pages currently available on the freelist. - */ -uint_t g_freePageCount = 0; - -/* ---------------------------------------------------------------------- - * 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; - - KASSERT(Is_Page_Multiple(start)); - KASSERT(Is_Page_Multiple(end)); - KASSERT(start < end); - - for (addr = start; addr < end; addr += PAGE_SIZE) { - 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); - } - - page->clock = 0; - page->vaddr = 0; - page->entry = 0; - } -} - -/* ---------------------------------------------------------------------- - * 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 kernEnd; - - KASSERT(bootInfo->memSizeKB > 0); - - /* - * Before we do anything, switch from setup.asm's temporary GDT - * to the kernel's permanent GDT. - */ - Init_GDT(); - - /* - * We'll put the list of Page objects right after the end - * of the kernel, and mark it as "kernel". This will bootstrap - * us sufficiently that we can start allocating pages and - * keeping track of them. - */ - pageListAddr = Round_Up_To_Page((ulong_t) &end); - g_pageList = (struct Page*) pageListAddr; - kernEnd = Round_Up_To_Page(pageListAddr + numPageListBytes); - s_numPages = numPages; - - - - /* - * The initial kernel thread and its stack are placed - * just beyond the ISA hole. - */ - //KASSERT(ISA_HOLE_END == KERN_THREAD_OBJ); - //KASSERT(KERN_STACK == KERN_THREAD_OBJ + PAGE_SIZE); - - /* - * Memory looks like this: - * 0 - start: available (might want to preserve BIOS data area) - * start - end: kernel - * end - ISA_HOLE_START: available - * ISA_HOLE_START - ISA_HOLE_END: used by hardware (and ROM BIOS?) - * ISA_HOLE_END - HIGHMEM_START: used by initial kernel thread - * HIGHMEM_START - end of memory: available - * (the kernel heap is located at HIGHMEM_START; any unused memory - * beyond that is added to the freelist) - */ - - /* JRL CHANGE - * 0 - PAGE_SIZE: Unused - * PAGE_SIZE - (PAGE_SIZE+8192): init kernel thread stack - * (PAGE_SIZE+8192) - ISA_HOLE_START: Available - * ISA_HOLE_START - ISA_HOLE_END: HW - * ISA_HOLE_END - end: Kernel+PageList - * end - (end+1MB): heap - * (end+1MB) - end of mem: free - * - * - */ - - - Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED); - // Add_Page_Range(PAGE_SIZE, KERNEL_START_ADDR, PAGE_AVAIL); - //Add_Page_Range(KERNEL_START_ADDR, kernEnd, PAGE_KERN); - //Add_Page_Range(kernEnd, ISA_HOLE_START, PAGE_AVAIL); - Add_Page_Range(PAGE_SIZE, PAGE_SIZE + 8192, PAGE_ALLOCATED); - Add_Page_Range(PAGE_SIZE + 8192, ISA_HOLE_START, PAGE_AVAIL); - Add_Page_Range(ISA_HOLE_START, ISA_HOLE_END, PAGE_HW); - //Add_Page_Range(ISA_HOLE_END, HIGHMEM_START, PAGE_ALLOCATED); - Add_Page_Range(HIGHMEM_START, kernEnd, PAGE_KERN); - Add_Page_Range(kernEnd, kernEnd + KERNEL_HEAP_SIZE, PAGE_HEAP); - - Add_Page_Range(kernEnd + KERNEL_HEAP_SIZE, endOfMem, PAGE_AVAIL); - - // Add_Page_Range(HIGHMEM_START, HIGHMEM_START + KERNEL_HEAP_SIZE, PAGE_HEAP); - // Add_Page_Range(HIGHMEM_START + KERNEL_HEAP_SIZE, endOfMem, PAGE_AVAIL); - - /* Initialize the kernel heap */ - // Init_Heap(HIGHMEM_START, KERNEL_HEAP_SIZE); - Init_Heap(kernEnd, KERNEL_HEAP_SIZE); - - Print("%uKB memory detected, %u pages in freelist, %d bytes in kernel heap\n", - bootInfo->memSizeKB, g_freePageCount, KERNEL_HEAP_SIZE); -} - -/* - * 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); -} - -/* - * 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; -} - -/* - * Choose a page to evict. - * Returns null if no pages are available. - */ -static struct Page *Find_Page_To_Page_Out() -{ - int i; - struct Page *curr, *best; - - best = NULL; - - for (i=0; i < s_numPages; i++) { - if ((g_pageList[i].flags & PAGE_PAGEABLE) && - (g_pageList[i].flags & PAGE_ALLOCATED)) { - if (!best) best = &g_pageList[i]; - curr = &g_pageList[i]; - if ((curr->clock < best->clock) && (curr->flags & PAGE_PAGEABLE)) { - best = curr; - } - } - } - - return best; -} - -/** - * Allocate a page of pageable physical memory, to be mapped - * into a user address space. - * - * @param entry pointer to user page table entry which will - * refer to the allocated page - * @param vaddr virtual address where page will be mapped - * in user address space - */ -void* Alloc_Pageable_Page(pte_t *entry, ulong_t vaddr) -{ - bool iflag; - void* paddr = 0; - struct Page* page = 0; - - iflag = Begin_Int_Atomic(); - - KASSERT(!Interrupts_Enabled()); - KASSERT(Is_Page_Multiple(vaddr)); - - paddr = Alloc_Page(); - if (paddr != 0) { - page = Get_Page((ulong_t) paddr); - KASSERT((page->flags & PAGE_PAGEABLE) == 0); - } else { - int pagefileIndex; - - /* Select a page to steal from another process */ - Debug("About to hunt for a page to page out\n"); - page = Find_Page_To_Page_Out(); - KASSERT(page->flags & PAGE_PAGEABLE); - paddr = (void*) Get_Page_Address(page); - Debug("Selected page at addr %p (age = %d)\n", paddr, page->clock); - - /* Find a place on disk for it */ - pagefileIndex = Find_Space_On_Paging_File(); - if (pagefileIndex < 0) - /* No space available in paging file. */ - goto done; - Debug("Free disk page at index %d\n", pagefileIndex); - - /* Make the page temporarily unpageable (can't let another process steal it) */ - page->flags &= ~(PAGE_PAGEABLE); - - /* Lock the page so it cannot be freed while we're writing */ - page->flags |= PAGE_LOCKED; - - /* Write the page to disk. Interrupts are enabled, since the I/O may block. */ - Debug("Writing physical frame %p to paging file at %d\n", paddr, pagefileIndex); - Enable_Interrupts(); - Write_To_Paging_File(paddr, page->vaddr, pagefileIndex); - Disable_Interrupts(); - - /* While we were writing got notification this page isn't even needed anymore */ - if (page->flags & PAGE_ALLOCATED) - { - /* The page is still in use update its bookeping info */ - /* Update page table to reflect the page being on disk */ - page->entry->present = 0; - page->entry->kernelInfo = KINFO_PAGE_ON_DISK; - page->entry->pageBaseAddr = pagefileIndex; /* Remember where it is located! */ - } - else - { - /* The page got freed, don't need bookeeping or it on disk */ - Free_Space_On_Paging_File(pagefileIndex); - - /* Its still allocated though to us now */ - page->flags |= PAGE_ALLOCATED; - } - - /* Unlock the page */ - page->flags &= ~(PAGE_LOCKED); - - /* XXX - flush TLB should only flush the one page */ - Flush_TLB(); - } - - /* Fill in accounting information for page */ - page->flags |= PAGE_PAGEABLE; - page->entry = entry; - page->entry->kernelInfo = 0; - page->vaddr = vaddr; - KASSERT(page->flags & PAGE_ALLOCATED); - -done: - End_Int_Atomic(iflag); - return paddr; -} - -/* - * 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); - - /* When a page is locked, don't free it just let other thread know its not needed */ - if (page->flags & PAGE_LOCKED) - return; - - /* Clear the pageable bit */ - page->flags &= ~(PAGE_PAGEABLE); - - /* Put the page back on the freelist */ - Add_To_Back_Of_Page_List(&s_freeList, page); - g_freePageCount++; - - End_Int_Atomic(iflag); -}