Exemple #1
0
			void SetUseMask(BufferPage page, bool available)
			{
				auto useMaskPageBits = 8 * sizeof(vuint64_t);
				auto useMaskPageIndex = page.index / (useMaskPageBits * useMaskPageItemCount);
				auto useMaskPageBitIndex = page.index % (useMaskPageBits * useMaskPageItemCount);
				auto useMaskPageItem = INDEX_USEMASK_USEMASKBEGIN + useMaskPageBitIndex / useMaskPageBits;
				auto useMaskPageShift = useMaskPageBitIndex % useMaskPageBits;
				bool newPage = false;

				BufferPage useMaskPage = BufferPage::Invalid();

				if (useMaskPageIndex == useMaskPages.Count())
				{
					newPage = true;
					BufferPage lastPage{useMaskPages[useMaskPageIndex - 1]};
					useMaskPage = AppendPage();
					useMaskPages.Add(useMaskPage.index);

					auto pageDesc = MapPage(lastPage);
					vuint64_t* numbers = (vuint64_t*)pageDesc->address;
					numbers[INDEX_USEMASK_NEXTUSEMASKPAGE] = useMaskPage.index;
					msync(numbers, pageSize, MS_SYNC);
				}
				else
				{
					useMaskPage.index = useMaskPages[useMaskPageIndex];
				}

				auto pageDesc = MapPage(useMaskPage);
				vuint64_t* numbers = (vuint64_t*)pageDesc->address;
				if (newPage)
				{
					numbers[INDEX_USEMASK_NEXTUSEMASKPAGE] = INDEX_INVALID;
				}

				auto& item = numbers[useMaskPageItem];
				if (available)
				{
					vuint64_t mask = ((vuint64_t)1) << useMaskPageShift;
					item |= mask;
				}
				else
				{
					vuint64_t mask = ~(((vuint64_t)1) << useMaskPageShift);
					item &= mask;
				}
				msync(numbers, pageSize, MS_SYNC);
			}
Exemple #2
0
			void InitializeEmptySource()
			{
				initialPages.Clear();
				useMaskPages.Clear();

				{
					BufferPage page{INDEX_PAGE_INITIAL};
					auto pageDesc = MapPage(page);
					vuint64_t* numbers = (vuint64_t*)pageDesc->address;
					memset(numbers, 0, pageSize);
					numbers[INDEX_INITIAL_NEXTINITIALPAGE] = INDEX_INVALID;
					numbers[INDEX_INITIAL_FREEPAGEITEMS] = 0;
					msync(numbers, pageSize, MS_SYNC);
					initialPages.Add(page.index);
					activeInitialPageIndex = 0;
					totalPageCount = 3;
				}
				{
					BufferPage page{INDEX_PAGE_USEMASK};
					auto pageDesc = MapPage(page);
					vuint64_t* numbers = (vuint64_t*)pageDesc->address;
					memset(numbers, 0, pageSize);
					numbers[INDEX_USEMASK_NEXTUSEMASKPAGE] = INDEX_INVALID;
					msync(numbers, pageSize, MS_SYNC);
					useMaskPages.Add(page.index);
				}
				{
					BufferPage page{INDEX_PAGE_INDEX};
					MapPage(page);
				}

				{
					BufferPage page{INDEX_PAGE_INITIAL};
					SetUseMask(page, true);
				}
				{
					BufferPage page{INDEX_PAGE_USEMASK};
					SetUseMask(page, true);
				}
				{
					BufferPage page{INDEX_PAGE_INDEX};
					SetUseMask(page, true);
				}
			}
Exemple #3
0
			void InitializeExistingSource()
			{
				initialPages.Clear();
				useMaskPages.Clear();
				{
					struct stat fileState;
					fstat(fileDescriptor, &fileState);
					totalPageCount = fileState.st_size / pageSize;
				}
				{
					BufferPage page{INDEX_PAGE_INITIAL};
					
					while(page.index != INDEX_INVALID)
					{
						initialPages.Add(page.index);
						auto pageDesc = MapPage(page);
						vuint64_t* numbers = (vuint64_t*)pageDesc->address;
						page.index = numbers[INDEX_INITIAL_NEXTINITIALPAGE];

						if (numbers[INDEX_INITIAL_FREEPAGEITEMS] != 0)
						{
							activeInitialPageIndex = initialPages.Count() - 1;
						}
					}
					
					if (activeInitialPageIndex == -1)
					{
						activeInitialPageIndex = 0;
					}
				}
				{
					BufferPage page{INDEX_PAGE_USEMASK};
					
					while(page.index != INDEX_INVALID)
					{
						useMaskPages.Add(page.index);
						auto pageDesc = MapPage(page);
						vuint64_t* numbers = (vuint64_t*)pageDesc->address;
						page.index = numbers[INDEX_USEMASK_NEXTUSEMASKPAGE];
					}
				}
			}
Exemple #4
0
			void PushFreePage(BufferPage page)
			{
				BufferPage initialPage{initialPages[activeInitialPageIndex]};
				auto pageDesc = MapPage(initialPage);
				vuint64_t* numbers = (vuint64_t*)pageDesc->address;
				vuint64_t& count = numbers[INDEX_INITIAL_FREEPAGEITEMS];
				if (count == initialPageItemCount)
				{
					if (activeInitialPageIndex == initialPages.Count() - 1)
					{
						BufferPage newInitialPage{totalPageCount};
						numbers[INDEX_INITIAL_NEXTINITIALPAGE] = newInitialPage.index;
						msync(numbers, pageSize, MS_SYNC);

						auto newPageDesc = MapPage(newInitialPage);
						numbers = (vuint64_t*)newPageDesc->address;
						memset(numbers, 0, pageSize);
						numbers[INDEX_INITIAL_NEXTINITIALPAGE] = INDEX_INVALID;
						numbers[INDEX_INITIAL_FREEPAGEITEMS] = 1;
						numbers[INDEX_INITIAL_FREEPAGEITEMBEGIN] = page.index;
						msync(numbers, pageSize, MS_SYNC);
						initialPages.Add(newInitialPage.index);
						SetUseMask(newInitialPage, true);
					}
					else
					{
						BufferPage newInitialPage{initialPages[activeInitialPageIndex + 1]};
						auto newPageDesc = MapPage(newInitialPage);
						numbers = (vuint64_t*)newPageDesc->address;
						numbers[INDEX_INITIAL_FREEPAGEITEMS] = 1;
						numbers[INDEX_INITIAL_FREEPAGEITEMBEGIN] = page.index;
						msync(numbers, pageSize, MS_SYNC);
					}
					activeInitialPageIndex++;
				}
				else
				{
					numbers[INDEX_INITIAL_FREEPAGEITEMBEGIN + count] = page.index;
					count++;
					msync(numbers, pageSize, MS_SYNC);
				}
			}
Exemple #5
0
			BufferPage AppendPage()
			{
				BufferPage page{totalPageCount};
				if (auto pageDesc = MapPage(page))
				{
					SetUseMask(page, true);
					return page;
				}
				else
				{
					return BufferPage::Invalid();
				}
			}
Exemple #6
0
void
load_exec(UID pid, const char *exec) {
    void *exec_loc = NULL;
    uint64_t exec_size = 0;

    Initrd_GetFile(exec, &exec_loc, &exec_size);

    uint64_t orig_exec_size = exec_size;
    exec_size += EXEC_ENTRY_POINT % PAGE_SIZE;

    if(exec_size % PAGE_SIZE)
        exec_size += (PAGE_SIZE - exec_size % PAGE_SIZE);

    //Map the executable into the process
    ProcessInformation *pinfo = NULL;
    if(GetProcessReference(pid, &pinfo) != ProcessErrors_None)
        return;



    for(uint32_t i = 0; i < exec_size / PAGE_SIZE; i++) {

        uint64_t p_addr = AllocatePhysicalPage();
        uint64_t v_addr = (EXEC_ENTRY_POINT - EXEC_ENTRY_POINT % PAGE_SIZE) + i * PAGE_SIZE;

        MapPage(pinfo->PageTable,
                p_addr,
                v_addr,
                PAGE_SIZE,
                CachingModeWriteBack,
                MemoryAllocationType_Application,
                MemoryAllocationFlags_Read | MemoryAllocationFlags_Write | MemoryAllocationFlags_User | MemoryAllocationFlags_Exec | MemoryAllocationFlags_Present);

    }


    uint8_t* write_target = (uint8_t*)SetupTemporaryWriteMap(pinfo->PageTable,
                            EXEC_ENTRY_POINT - (EXEC_ENTRY_POINT % PAGE_SIZE),
                            exec_size);

    memcpy(write_target + (EXEC_ENTRY_POINT % PAGE_SIZE), exec_loc, orig_exec_size);

    UninstallTemporaryWriteMap((uint64_t)write_target, exec_size);


    CreateThread(pid, ThreadPermissionLevel_User, (ThreadEntryPoint)EXEC_ENTRY_POINT, NULL);

    StartProcess(pid);
    return;
}
Exemple #7
0
			bool GetUseMask(BufferPage page)
			{
				auto useMaskPageBits = 8 * sizeof(vuint64_t);
				auto useMaskPageIndex = page.index / (useMaskPageBits * useMaskPageItemCount);
				auto useMaskPageBitIndex = page.index % (useMaskPageBits * useMaskPageItemCount);
				auto useMaskPageItem = INDEX_USEMASK_USEMASKBEGIN + useMaskPageBitIndex / useMaskPageBits;
				auto useMaskPageShift = useMaskPageBitIndex % useMaskPageBits;

				BufferPage useMaskPage{useMaskPages[useMaskPageIndex]};
				auto pageDesc = MapPage(useMaskPage);
				vuint64_t* numbers = (vuint64_t*)pageDesc->address;
				auto& item = numbers[useMaskPageItem];
				bool result = ((item >> useMaskPageShift) & ((vuint64_t)1)) == 1;
				msync(numbers, pageSize, MS_SYNC);
				return result;
			}
Exemple #8
0
			void* LockPage(BufferPage page)override
			{
				if (page.index >= totalPageCount)
				{
					return nullptr;
				}
				if (!GetUseMask(page)) return nullptr;
				if (auto pageDesc = MapPage(page))
				{
					if (pageDesc->locked) return nullptr;
					pageDesc->locked = true;
					return pageDesc->address;
				}
				else
				{
					return nullptr;
				}
			}
Exemple #9
0
			BufferPage PopFreePage()
			{
				BufferPage page = BufferPage::Invalid();
				BufferPage initialPage{initialPages[activeInitialPageIndex]};
				auto pageDesc = MapPage(initialPage);
				vuint64_t* numbers = (vuint64_t*)pageDesc->address;
				vuint64_t& count = numbers[INDEX_INITIAL_FREEPAGEITEMS];

				if (count == 0 && initialPage.index == INDEX_PAGE_INITIAL)
				{
					return page;
				}
				count--;
				page.index = numbers[INDEX_INITIAL_FREEPAGEITEMBEGIN + count];
				msync(numbers, pageSize, MS_SYNC);

				if (count == 0)
				{
					activeInitialPageIndex--;
				}
				return page;
			}
Exemple #10
0
void VirtMemManager::ResolvePageFault(uintptr fault_address, bool write_error, bool protection_error, bool user_mode)
{
	// If its a page not present fault, check for a matching section
	if(!protection_error) {
		int i, c;
		c = CurrentThread->proc->Sections->Count();
		Section::Extent ae;
		ae.Lower = fault_address;
		ae.Upper = fault_address;

		protection_error = true; // Set this back to false if we find a valid section

		for(i = 0; i < c; i++) {
			Section::Extent se;
			Section &s = CurrentThread->proc->Sections->GetItem(i);
			if(s.CheckExtents(&se)) {
				if(ae == se) {
					// Its part of this section.  Allow expanding sections
					if(s.Flags & Section::AutoExpand) {
						if((fault_address < s.Base) && ((s.Base - fault_address) <= s.ExpandDown)) {
							s.ExpandDown -= (s.Base - fault_address);
							s.Base = fault_address;
							protection_error = false;
						}
						if((fault_address >= (s.Base + s.Length)) && ((fault_address - (s.Base + s.Length)) <= s.ExpandUp)) {
							s.ExpandUp -= (fault_address - (s.Base + s.Length));
							s.Length = fault_address - s.Base + 1;
							protection_error = false;
						}
					} 
					if((fault_address >= s.Base) && (fault_address < (s.Base + s.Length)))
						protection_error = false;

					if(!protection_error) {
						// Map the page
						physaddr_t paddr = NULL;
						if(s.Flags & Section::Bits)
							paddr = (fault_address - s.Base + s.MemSource) & GetPageMask();
		
						MapPage(fault_address & GetPageMask(), NULL, false, NULL,
							(fault_address - s.Base + s.MemSource) & GetPageMask(),
							(s.Flags & Section::KernelSection) ? false : true,
							(s.Flags & Section::Write) ? true : false);

						break;
					}
				}
			}
		}
	}
			
	// Check for errors
	if(protection_error) {
		// A bad error
		a.kconsole->Printf("PAGE FAULT! Invalid attempt by ");
		if(user_mode)
			a.kconsole->Printf("process ");
		else
			a.kconsole->Printf("kernel ");
		a.kconsole->Printf("to ");
		if(write_error)
			a.kconsole->Printf("write to ");
		else
			a.kconsole->Printf("read from ");
		a.kconsole->Printf("address %x whilst executing %s\n", fault_address, CurrentThread->proc->name);
		a.Panic();		
	}
}