void __init prom_meminit(void) { struct linux_mdesc *p; #ifdef DEBUG int i = 0; printk("ARCS MEMORY DESCRIPTOR dump:\n"); p = ArcGetMemoryDescriptor(PROM_NULL_MDESC); while(p) { printk("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", i, p, p->base, p->pages, mtypes(p->type)); p = ArcGetMemoryDescriptor(p); i++; } #endif p = PROM_NULL_MDESC; while ((p = ArcGetMemoryDescriptor(p))) { unsigned long base, size; long type; base = p->base << ARC_PAGE_SHIFT; size = p->pages << ARC_PAGE_SHIFT; type = prom_memtype_classify(p->type); add_memory_region(base, size, type); } }
ARC_STATUS JnFsAllocateDescriptor( IN ULONG MemoryType, IN ULONG PageCount, OUT PULONG ActualBase ) /*++ Routine Description: This attempts to find a free section of memory of the requested size and type. It does *not* update the memory descriptor list to reflect a successful allocation. Arguments: MemoryType The type of memory requested. PageCount The number of pages requested. ActualBase A pointer to a variable that receives the base page number of the found section. Return Value: ESUCCESS is returned if the memory descriptor is found. ENOMEM if not. --*/ { PMEMORY_DESCRIPTOR MemoryDescriptor; ULONG MemoryBase; ARC_STATUS ReturnStatus = ENOMEM; // // Find a memory descriptor of the right size // MemoryDescriptor = ArcGetMemoryDescriptor(NULL); while (MemoryDescriptor != NULL) { if ((MemoryDescriptor->MemoryType == MemoryType) && (MemoryDescriptor->PageCount >= PageCount)) { MemoryBase = MemoryDescriptor->BasePage; ReturnStatus = ESUCCESS; break; } MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor); } *ActualBase = MemoryBase; return ReturnStatus; }
BOOLEAN MmInitializeMemoryManager(VOID) { #if DBG const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; #endif TRACE("Initializing Memory Manager.\n"); /* Check the freeldr binary */ MmCheckFreeldrImageFile(); BiosMemoryMap = MachVtbl.GetMemoryMap(&BiosMemoryMapEntryCount); #if DBG // Dump the system memory map TRACE("System Memory Map (Base Address, Length, Type):\n"); while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) { TRACE("%x\t %x\t %s\n", MemoryDescriptor->BasePage * MM_PAGE_SIZE, MemoryDescriptor->PageCount * MM_PAGE_SIZE, MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType)); } #endif // Find address for the page lookup table TotalPagesInLookupTable = MmGetAddressablePageCountIncludingHoles(); PageLookupTableAddress = MmFindLocationForPageLookupTable(TotalPagesInLookupTable); LastFreePageHint = MmHighestPhysicalPage; if (PageLookupTableAddress == 0) { // If we get here then we probably couldn't // find a contiguous chunk of memory big // enough to hold the page lookup table printf("Error initializing memory manager!\n"); return FALSE; } // Initialize the page lookup table MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable); MmUpdateLastFreePageHint(PageLookupTableAddress, TotalPagesInLookupTable); FreePagesInLookupTable = MmCountFreePagesInLookupTable(PageLookupTableAddress, TotalPagesInLookupTable); MmInitializeHeap(PageLookupTableAddress); TRACE("Memory Manager initialized. 0x%x pages available.\n", FreePagesInLookupTable); return TRUE; }
VOID MmInitPageLookupTable(PVOID PageLookupTable, PFN_NUMBER TotalPageCount) { const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; PFN_NUMBER PageLookupTableStartPage; PFN_NUMBER PageLookupTablePageCount; TRACE("MmInitPageLookupTable()\n"); // Mark every page as allocated initially // We will go through and mark pages again according to the memory map // But this will mark any holes not described in the map as allocated MmMarkPagesInLookupTable(PageLookupTable, MmLowestPhysicalPage, TotalPageCount, LoaderFirmwarePermanent); // Parse the whole memory map while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) { // Mark used pages in the lookup table if (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount <= TotalPageCount) { TRACE("Marking pages 0x%lx-0x%lx as type %s\n", MemoryDescriptor->BasePage, MemoryDescriptor->BasePage + MemoryDescriptor->PageCount, MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType)); MmMarkPagesInLookupTable(PageLookupTable, MemoryDescriptor->BasePage, MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType); } else TRACE("Ignoring pages 0x%lx-0x%lx (%s)\n", MemoryDescriptor->BasePage, MemoryDescriptor->BasePage + MemoryDescriptor->PageCount, MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType)); } // Mark the pages that the lookup table occupies as reserved PageLookupTableStartPage = MmGetPageNumberFromAddress(PageLookupTable); PageLookupTablePageCount = MmGetPageNumberFromAddress((PVOID)((ULONG_PTR)PageLookupTable + ROUND_UP(TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM), MM_PAGE_SIZE))) - PageLookupTableStartPage; TRACE("Marking the page lookup table pages as reserved StartPage: 0x%x PageCount: 0x%x\n", PageLookupTableStartPage, PageLookupTablePageCount); MmMarkPagesInLookupTable(PageLookupTable, PageLookupTableStartPage, PageLookupTablePageCount, LoaderFirmwareTemporary); }
PFN_NUMBER MmGetAddressablePageCountIncludingHoles(VOID) { const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; PFN_NUMBER PageCount; // // Go through the whole memory map to get max address // while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) { // // Check if we got a higher end page address // if (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > MmHighestPhysicalPage) { // // Yes, remember it if this is real memory // if (MemoryDescriptor->MemoryType == LoaderFree) MmHighestPhysicalPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount; } // // Check if we got a higher (usable) start page address // if (MemoryDescriptor->BasePage < MmLowestPhysicalPage) { // // Yes, remember it if this is real memory // MmLowestPhysicalPage = MemoryDescriptor->BasePage; } } TRACE("lo/hi %lx %lx\n", MmLowestPhysicalPage, MmHighestPhysicalPage); PageCount = MmHighestPhysicalPage - MmLowestPhysicalPage; TRACE("MmGetAddressablePageCountIncludingHoles() returning 0x%x\n", PageCount); return PageCount; }
PVOID MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount) { const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; SIZE_T PageLookupTableSize; PFN_NUMBER PageLookupTablePages; PFN_NUMBER PageLookupTableStartPage = 0; PVOID PageLookupTableMemAddress = NULL; // Calculate how much pages we need to keep the page lookup table PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM); PageLookupTablePages = PageLookupTableSize / MM_PAGE_SIZE; // Search the highest memory block big enough to contain lookup table while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) { // Continue, if memory is not free if (MemoryDescriptor->MemoryType != LoaderFree) continue; // Continue, if the block is not big enough? if (MemoryDescriptor->PageCount < PageLookupTablePages) continue; // Continue, if it is not at a higher address than previous address if (MemoryDescriptor->BasePage < PageLookupTableStartPage) continue; // Continue, if the address is too high if (MemoryDescriptor->BasePage >= MM_MAX_PAGE) continue; // Memory block is more suitable than the previous one PageLookupTableStartPage = MemoryDescriptor->BasePage; PageLookupTableMemAddress = (PVOID)((ULONG_PTR) (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) * MM_PAGE_SIZE - PageLookupTableSize); } TRACE("MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress); return PageLookupTableMemAddress; }
VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount) { const MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; TYPE_OF_MEMORY MemoryMapPageAllocated; ULONG PageLookupTableStartPage; ULONG PageLookupTablePageCount; TRACE("MmInitPageLookupTable()\n"); // // Mark every page as allocated initially // We will go through and mark pages again according to the memory map // But this will mark any holes not described in the map as allocated // MmMarkPagesInLookupTable(PageLookupTable, MmLowestPhysicalPage, TotalPageCount, LoaderFirmwarePermanent); // // Parse the whole memory map // while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) { // // Convert ARC memory type to loader memory type // switch (MemoryDescriptor->MemoryType) { case MemoryFree: { // // Allocatable memory // MemoryMapPageAllocated = LoaderFree; break; } case MemoryFirmwarePermanent: { // // Firmware permanent memory // MemoryMapPageAllocated = LoaderFirmwarePermanent; break; } case MemoryFirmwareTemporary: { // // Firmware temporary memory // MemoryMapPageAllocated = LoaderFirmwareTemporary; break; } case MemoryLoadedProgram: { // // Bootloader code // MemoryMapPageAllocated = LoaderLoadedProgram; break; } case MemorySpecialMemory: { // // OS Loader Stack // MemoryMapPageAllocated = LoaderOsloaderStack; break; } default: { // // Put something sensible here, which won't be overwritten // MemoryMapPageAllocated = LoaderSpecialMemory; break; } } // // Mark used pages in the lookup table // TRACE("Marking pages as type %d: StartPage: %d PageCount: %d\n", MemoryMapPageAllocated, MemoryDescriptor->BasePage, MemoryDescriptor->PageCount); MmMarkPagesInLookupTable(PageLookupTable, MemoryDescriptor->BasePage, MemoryDescriptor->PageCount, MemoryMapPageAllocated); } // // Mark the pages that the lookup table occupies as reserved // PageLookupTableStartPage = MmGetPageNumberFromAddress(PageLookupTable); PageLookupTablePageCount = MmGetPageNumberFromAddress((PVOID)((ULONG_PTR)PageLookupTable + ROUND_UP(TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM), MM_PAGE_SIZE))) - PageLookupTableStartPage; TRACE("Marking the page lookup table pages as reserved StartPage: %d PageCount: %d\n", PageLookupTableStartPage, PageLookupTablePageCount); MmMarkPagesInLookupTable(PageLookupTable, PageLookupTableStartPage, PageLookupTablePageCount, LoaderFirmwareTemporary); }
PVOID MmFindLocationForPageLookupTable(ULONG TotalPageCount) { const MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; ULONG PageLookupTableSize; ULONG PageLookupTablePages; ULONG PageLookupTableStartPage = 0; PVOID PageLookupTableMemAddress = NULL; // // Calculate how much pages we need to keep the page lookup table // PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM); PageLookupTablePages = PageLookupTableSize / MM_PAGE_SIZE; // // Search the highest memory block big enough to contain lookup table // while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) { // // Is it suitable memory? // if (MemoryDescriptor->MemoryType != MemoryFree) { // // No. Process next descriptor // continue; } // // Is the block big enough? // if (MemoryDescriptor->PageCount < PageLookupTablePages) { // // No. Process next descriptor // continue; } // // Is it at a higher address than previous suitable address? // if (MemoryDescriptor->BasePage < PageLookupTableStartPage) { // // No. Process next descriptor // continue; } // // Can we use this address? // if (MemoryDescriptor->BasePage >= MM_MAX_PAGE) { // // No. Process next descriptor // continue; } // // Memory block is more suitable than the previous one // PageLookupTableStartPage = MemoryDescriptor->BasePage; PageLookupTableMemAddress = (PVOID)((ULONG_PTR) (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) * MM_PAGE_SIZE - PageLookupTableSize); } TRACE("MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress); return PageLookupTableMemAddress; }
ARC_STATUS AlMemoryInitialize ( ULONG StackPages, ULONG HeapPages ) /*++ Routine Description: This routine allocates stack space for the OS loader, initializes heap storage, and initializes the memory allocation list. Arguments: None. Return Value: ESUCCESS is returned if the initialization is successful. Otherwise, ENOMEM is returned. --*/ { PMEMORY_DESCRIPTOR FreeDescriptor; PMEMORY_DESCRIPTOR ProgramDescriptor; // // Find the memory descriptor that describes the allocation for the OS // loader itself. // ProgramDescriptor = NULL; while ((ProgramDescriptor = ArcGetMemoryDescriptor(ProgramDescriptor)) != NULL) { if (ProgramDescriptor->MemoryType == MemoryLoadedProgram) { break; } } // // If a loaded program memory descriptor was found, then it must be // for the OS loader since that is the only program that can be loaded. // If a loaded program memory descriptor was not found, then firmware // is not functioning properly and an unsuccessful status is returned. // if (ProgramDescriptor == NULL) { return ENOMEM; } // // Find the free memory descriptor that is just below the loaded // program in memory. There should be several megabytes of free // memory just preceeding the OS loader. // FreeDescriptor = NULL; while ((FreeDescriptor = ArcGetMemoryDescriptor(FreeDescriptor)) != NULL) { if ((FreeDescriptor->MemoryType == MemoryFree) && (FreeDescriptor->PageCount >= (StackPages+HeapPages))) { break; } } // // If a free memory descriptor was not found that describes the free // memory just below the OS loader, then firmware is not functioning // properly and an unsuccessful status is returned. // if (FreeDescriptor == NULL) { return ENOMEM; } // // Check to determine if enough free memory is available for the OS // loader stack and the heap area. If enough memory is not available, // then return an unsuccessful status. // if (FreeDescriptor->PageCount < (StackPages + HeapPages)) { return ENOMEM; } // // Compute the address of the loader heap, initialize the heap // allocation variables, and zero the heap memory. // AlHeapFree = KSEG0_BASE | ((ProgramDescriptor->BasePage - (StackPages + HeapPages)) << PAGE_SHIFT); AlHeapLimit = AlHeapFree + (HeapPages << PAGE_SHIFT); memset((PVOID)AlHeapFree, 0,HeapPages << PAGE_SHIFT); // // Changed to new heap allocater // if ((HeapHandle = AlRtCreateHeap ( HEAP_ZERO_EXTRA_MEMORY, (PVOID)AlHeapFree, HeapPages << PAGE_SHIFT )) == NULL) return ENOMEM; else return ESUCCESS; }