Ejemplo n.º 1
0
// TODO: Consider using invalidate page assembly instruction. When mapping a non-null page this is needed to update the hardware cache.
error_t vmmngr_alloc_page_f(virtual_addr base, uint32 flags)
{
	//TODO: cater for memory mapped IO where (in the most simple case) an identity map must be done.
	//TODO: fix this function
	physical_addr addr = base;

	if (vmmngr_is_page_present(base))
		addr = vmmngr_get_phys_addr(base);
	else
	{
		if (base < 0xF0000000)		// memory mapped IO above 3GB
		{
			addr = (physical_addr)pmmngr_alloc_block();
			if (addr == 0)
				return ERROR_OCCUR;
		}

		if (!addr)
		{
			set_last_error(EINVAL, VMEM_BAD_ARGUMENT, EO_VMMNGR);
			return ERROR_OCCUR;
		}
	}

	if (vmmngr_map_page(vmmngr_get_directory(), addr, base, flags) != ERROR_OK)
		return ERROR_OCCUR;

	return ERROR_OK;
}
Ejemplo n.º 2
0
	void TerminateMemoryProcess() {
		
		Process* pProcess = (Process*)List_GetData(ProcessManager::GetInstance()->pProcessQueue, "", 0);					

		if (pProcess->TaskID == PROC_INVALID_ID)
		{
			DebugPrintf("\nsdffdsdsfsd");
			return;
		}

		/* release threads */
		int i = 0;

		Thread* pThread = (Thread*)List_GetData(pProcess->pThreadQueue, "", 0);		
		
		/* get physical address of stack */
		void* stackFrame = vmmngr_getPhysicalAddress(pProcess->pPageDirectory,
			(uint32_t)pThread->initialStack);

		DebugPrintf("\n Plane X : %d, Plane Y : %d", 1, 1);
		/* unmap and release stack memory */
		vmmngr_unmapPhysicalAddress(pProcess->pPageDirectory, (uint32_t)pThread->initialStack);
		//pmmngr_free_block(stackFrame);

		/* unmap and release image memory */
		for (uint32_t page = 0; page < pThread->imageSize / PAGE_SIZE; page++) {
			uint32_t phys = 0;
			uint32_t virt = 0;

			/* get virtual address of page */
			virt = pThread->imageBase + (page * PAGE_SIZE);

			/* get physical address of page */
			phys = (uint32_t)vmmngr_getPhysicalAddress(pProcess->pPageDirectory, virt);

			/* unmap and release page */
			vmmngr_unmapPhysicalAddress(pProcess->pPageDirectory, virt);
			//pmmngr_free_block((void*)phys);
		}		

		/* restore kernel selectors */
		__asm {
			cli
				mov eax, 0x10
				mov ds, ax
				mov es, ax
				mov fs, ax
				mov gs, ax
				sti
		}

		pmmngr_load_PDBR((physical_addr)vmmngr_get_directory());

		/* return to kernel command shell */
		run();

		DebugPrintf("\nExit command recieved; demo halted");
		for (;;);
	}
Ejemplo n.º 3
0
void vmmngr_free_page_addr(virtual_addr addr)
{
	pd_entry* e = vmmngr_pdirectory_lookup_entry(vmmngr_get_directory(), addr);
	ptable* table = (ptable*)pd_entry_get_frame(*e);
	pt_entry* page = vmmngr_ptable_lookup_entry(table, addr);

	vmmngr_free_page(page);
}
Ejemplo n.º 4
0
void page_fault_alloc_page(uint32 area_flags, virtual_addr address)
{
	uint32 flags = page_fault_calculate_present_flags(area_flags);

	if (CHK_BIT(area_flags, MMAP_IDENTITY_MAP))
		vmmngr_map_page(vmmngr_get_directory(), address, address, flags);
	else
		vmmngr_alloc_page_f(address, flags);
}
Ejemplo n.º 5
0
bool vmmngr_is_page_present(virtual_addr addr)
{
	pd_entry* e = vmmngr_pdirectory_lookup_entry(vmmngr_get_directory(), addr);
	if (e == 0 || pd_entry_is_present(*e) == false)
		return false;

	ptable* table = (ptable*)pd_entry_get_frame(*e);
	if (table == 0)
		return false;

	pt_entry* page = vmmngr_ptable_lookup_entry(table, addr);
	if (page == 0 || pt_entry_is_present(*page) == false)
		return false;

	return true;
}
Ejemplo n.º 6
0
physical_addr vmmngr_get_phys_addr(virtual_addr addr)
{
	pd_entry* e = vmmngr_pdirectory_lookup_entry(vmmngr_get_directory(), addr);
	if (!e)
		return 0;

	ptable* table = (ptable*)pd_entry_get_frame(*e);
	pt_entry* page = vmmngr_ptable_lookup_entry(table, addr);
	if (!page)
		return 0;

	physical_addr p_addr = pt_entry_get_frame(*page);

	p_addr += (addr & 0xfff);		// add in-page offset
	return p_addr;
}
Ejemplo n.º 7
0
Process* ProcessManager::CreateSystemProcess()
{
	Process* pProcess = new Process();
	pProcess->TaskID = ProcessManager::GetInstance()->GetNextProcessId();
	pProcess->pPageDirectory = vmmngr_get_directory();
	pProcess->dwProcessType = PROCESS_KERNEL;
	mapKernelSpace(pProcess->pPageDirectory);

	pProcess->dwPriority = 1;
	pProcess->dwRunState = PROCESS_STATE_ACTIVE;

	Thread* pThread = CreateMemoryThread(pProcess, StartRoutine);
	
	List_Add(&pProcess->pThreadQueue, "", pThread);
	List_Add(&pProcessQueue, "", pProcess);

	DebugPrintf("\nCreate Success System Process");

	return pProcess;
}
Ejemplo n.º 8
0
void TerminateProcess () {
	
	Process* cur = ProcessManager::GetInstance()->g_pCurProcess;
	
	if (cur->TaskID == PROC_INVALID_ID)
	{
		DebugPrintf("\nsdffdsdsfsd");
		return;
	}

	/* release threads */
	int i=0;
	//Thread* pThread = ProcessManager::GetInstance()->g_pThread;
	Thread* pThread = (Thread*)List_GetData(cur->pThreadQueue, "", 0);
	List_Delete(&cur->pThreadQueue, "", 0);

	u32int heapAddess = pThread->imageBase + pThread->imageSize + PAGE_SIZE + PAGE_SIZE * 2;
	heapAddess = heapAddess - (heapAddess % PAGE_SIZE);
	for (int i = 0; i < 300; i++)
	{
		uint32_t phys = 0;
		uint32_t virt = 0;

		/* get virtual address of page */
		virt = heapAddess + (i * PAGE_SIZE);

		/* get physical address of page */
		phys = (uint32_t)vmmngr_getPhysicalAddress(cur->pPageDirectory, virt);

		/* unmap and release page */
		vmmngr_unmapPhysicalAddress(cur->pPageDirectory, virt);
	}

	/* unmap and release image memory */
	for (uint32_t page = 0; page < cur->dwPageCount; page++) {
		uint32_t phys = 0;
		uint32_t virt = 0;

		/* get virtual address of page */
		virt = pThread->imageBase + (page * PAGE_SIZE);

		/* get physical address of page */
		phys = (uint32_t)vmmngr_getPhysicalAddress(cur->pPageDirectory, virt);

		/* unmap and release page */
		vmmngr_unmapPhysicalAddress(cur->pPageDirectory, virt);
		//pmmngr_free_block ((void*)phys);
	}

	/* get physical address of stack */
	void* stackFrame = vmmngr_getPhysicalAddress(cur->pPageDirectory,
		(uint32_t)pThread->initialStack);

	/* unmap and release stack memory */
	vmmngr_unmapPhysicalAddress(cur->pPageDirectory, (uint32_t)pThread->initialStack);
	//pmmngr_free_block(stackFrame);

	pmmngr_free_block(cur->pPageDirectory);

	delete pThread;
	delete cur;

	/* restore kernel selectors */
	__asm {
		cli
		mov eax, 0x10
		mov ds, ax
		mov es, ax
		mov fs, ax
		mov gs, ax
		sti
	}

	pmmngr_load_PDBR((physical_addr)vmmngr_get_directory());

	/* return to kernel command shell */
	run ();

	DebugPrintf ("\nExit command recieved; demo halted");
	for (;;);
}
Ejemplo n.º 9
0
void page_fault_bottom(thread_exception te)
{
	thread_exception_print(&te);
	uint32& addr = te.data[0];
	uint32& code = te.data[1];

	serial_printf("PAGE_FALUT: PROC: %u ADDRESS: %h, THREAD: %u, CODE: %h\n", process_get_current()->id, addr, thread_get_current()->id, code);

	if (process_get_current()->contract_spinlock == 1)
		PANIC("PAge fault spinlock is already reserved\n");

	spinlock_acquire(&process_get_current()->contract_spinlock);
	vm_area* p_area = vm_contract_find_area(&thread_get_current()->parent->memory_contract, addr);

	if (p_area == 0)
	{
		serial_printf("could not find address %h in memory contract", addr);
		PANIC("");		// terminate thread and process with SIGSEGV
	}

	vm_area area = *p_area;
	spinlock_release(&process_get_current()->contract_spinlock);

	// tried to acccess inaccessible page
	if ((area.flags & MMAP_PROTECTION) == MMAP_NO_ACCESS)
	{
		serial_printf("address: %h is inaccessible\n", addr);
		PANIC("");
	}

	// tried to write to read-only or inaccessible page
	if (page_fault_error_is_write(code) && (area.flags & MMAP_WRITE) != MMAP_WRITE)
	{
		serial_printf("cannot write to address: %h\n", addr);
		PANIC("");
	}

	// tried to read a write-only or inaccesible page ???what???
	/*if (!page_fault_error_is_write(code) && CHK_BIT(area.flags, MMAP_READ))
	{
		serial_printf("cannot read from address: %h", addr);
		PANIC("");
	}*/

	// if the page is present then a violation happened (we do not implement swap out/shared anonymous yet)
	if (page_fault_error_is_page_present(code) == true)
	{
		serial_printf("memory violation at address: %h with code: %h\n", addr, code);
		serial_printf("area flags: %h\n", area.flags);
		PANIC("");
	}

	// here we found out that the page is not present, so we need to allocate it properly
	if (CHK_BIT(area.flags, MMAP_PRIVATE))
	{
		if (CHK_BIT(area.flags, MMAP_ALLOC_IMMEDIATE))
		{
			// loop through all addresses and map them
			for (virtual_addr address = area.start_addr; address < area.end_addr; address += 4096)
				//if (CHK_BIT(area.flags, MMAP_ANONYMOUS))	ALLOC_IMMEDIATE works only for anonymous (imposed in mmap)
				page_fault_alloc_page(area.flags, address);
		}
		else
		{
			if (CHK_BIT(area.flags, MMAP_ANONYMOUS))
				page_fault_alloc_page(area.flags, addr & (~0xFFF));
			else
			{
				uint32 flags = page_fault_calculate_present_flags(area.flags);
				vmmngr_alloc_page_f(addr & (~0xFFF), flags);

				uint32 read_start = area.offset + ((addr - area.start_addr) / PAGE_SIZE) * PAGE_SIZE;		// file read start
				uint32 read_size = PAGE_SIZE;		// we read one page at a time (not the whole area as this may not be necessary)

				//if (read_start < area.start_addr + PAGE_SIZE)	// we are reading the first page so subtract offset from read_size
				//	read_size -= area.offset;

				serial_printf("gfd: %u, reading at mem: %h, phys: %h file: %h, size: %u\n", area.fd, addr & (~0xfff), vmmngr_get_phys_addr(addr & (~0xfff)),
					read_start, read_size);

				gfe* entry = gft_get(area.fd);
				if (entry == 0)
				{
					serial_printf("area.fd = %u", area.fd);
					PANIC("page fault gfd entry = 0");
				}

				// read one page from the file offset given at the 4KB-aligned fault address 
				if (read_file_global(area.fd, read_start, read_size, addr & (~0xFFF), VFS_CAP_READ | VFS_CAP_CACHE) != read_size)
				{
					serial_printf("read fd: %u\n", area.fd);
					PANIC("mmap anonymous file read less bytes than expected");
				}
			}
		}
	}
	else		// MMAP_SHARED
	{
		if (CHK_BIT(area.flags, MMAP_ANONYMOUS))
			PANIC("A shared area cannot be marked as anonymous yet.");
		else
		{
			// in the shared file mapping the address to read is ignored as data are read only to page cache. 
			uint32 read_start = area.offset + ((addr & (~0xfff)) - area.start_addr);
			gfe* entry = gft_get(area.fd);

			if (read_file_global(area.fd, read_start, PAGE_SIZE, -1, VFS_CAP_READ | VFS_CAP_CACHE) != PAGE_SIZE)
				PANIC("mmap shared file failed");

			virtual_addr used_cache = page_cache_get_buffer(area.fd, read_start / PAGE_SIZE);
			//serial_printf("m%h\n", used_cache);

			uint32 flags = page_fault_calculate_present_flags(area.flags);
			vmmngr_map_page(vmmngr_get_directory(), vmmngr_get_phys_addr(used_cache), addr & (~0xfff), flags/*DEFAULT_FLAGS*/);
			//serial_printf("shared mapping fd: %u, cache: %h, phys cache: %h, read: %u, addr: %h\n", area.fd, used_cache, used_cache, read_start, addr);
		}
	}
}
/**
* Create process
* \param appname Application file name
* \ret Status code
*/
int createProcess (char* appname) {

        IMAGE_DOS_HEADER* dosHeader = 0;
        IMAGE_NT_HEADERS* ntHeaders = 0;
        FILE file;
        pdirectory* addressSpace = 0;
        process* proc = 0;
        thread* mainThread = 0;
        unsigned char* memory = 0;
        unsigned char buf[512];
        uint32_t i = 0;

        /* open file */
        file = volOpenFile (appname);
        if (file.flags == FS_INVALID)
                return 0;
        if (( file.flags & FS_DIRECTORY ) == FS_DIRECTORY)
                return 0;

        /* read 512 bytes into buffer */
        volReadFile ( &file, buf, 512);
		if (! validateImage (buf)) {
			volCloseFile ( &file );
			return 0;
		}
        dosHeader = (IMAGE_DOS_HEADER*)buf;
        ntHeaders = (IMAGE_NT_HEADERS*)(dosHeader->e_lfanew + (uint32_t)buf);

        /* get process virtual address space */
//        addressSpace = vmmngr_createAddressSpace ();
		addressSpace = vmmngr_get_directory ();
		if (!addressSpace) {
                volCloseFile (&file);
                return 0;
        }
		/*
			map kernel space into process address space.
			Only needed if creating new address space
		*/
		//mapKernelSpace (addressSpace);

        /* create PCB */
        proc = getCurrentProcess();
        proc->id            = 1;
        proc->pageDirectory = addressSpace;
        proc->priority      = 1;
        proc->state         = PROCESS_STATE_ACTIVE;
        proc->threadCount   = 1;

		/* create thread descriptor */
        mainThread               = &proc->threads[0];
        mainThread->kernelStack  = 0;
        mainThread->parent       = proc;
        mainThread->priority     = 1;
        mainThread->state        = PROCESS_STATE_ACTIVE;
        mainThread->initialStack = 0;
        mainThread->stackLimit   = (void*) ((uint32_t) mainThread->initialStack + 4096);
		mainThread->imageBase    = ntHeaders->OptionalHeader.ImageBase;
		mainThread->imageSize    = ntHeaders->OptionalHeader.SizeOfImage;
        memset (&mainThread->frame, 0, sizeof (trapFrame));
        mainThread->frame.eip    = ntHeaders->OptionalHeader.AddressOfEntryPoint
                + ntHeaders->OptionalHeader.ImageBase;
        mainThread->frame.flags  = 0x200;

        /* copy our 512 block read above and rest of 4k block */
        memory = (unsigned char*)pmmngr_alloc_block();
        memset (memory, 0, 4096);
        memcpy (memory, buf, 512);

		/* load image into memory */
		for (i=1; i <= mainThread->imageSize/512; i++) {
                if (file.eof == 1)
                        break;
                volReadFile ( &file, memory+512*i, 512);
        }

        /* map page into address space */
        vmmngr_mapPhysicalAddress (proc->pageDirectory,
                ntHeaders->OptionalHeader.ImageBase,
                (uint32_t) memory,
                I86_PTE_PRESENT|I86_PTE_WRITABLE|I86_PTE_USER);

		/* load and map rest of image */
        i = 1;
        while (file.eof != 1) {
                /* allocate new frame */
                unsigned char* cur = (unsigned char*)pmmngr_alloc_block();
                /* read block */
                int curBlock = 0;
                for (curBlock = 0; curBlock < 8; curBlock++) {
                        if (file.eof == 1)
                                break;
                        volReadFile ( &file, cur+512*curBlock, 512);
                }
                /* map page into process address space */
                vmmngr_mapPhysicalAddress (proc->pageDirectory,
                        ntHeaders->OptionalHeader.ImageBase + i*4096,
                        (uint32_t) cur,
                        I86_PTE_PRESENT|I86_PTE_WRITABLE|I86_PTE_USER);
                i++;
        }

		/* Create userspace stack (process esp=0x100000) */
		void* stack =
			(void*) (ntHeaders->OptionalHeader.ImageBase
				+ ntHeaders->OptionalHeader.SizeOfImage + PAGE_SIZE);
		void* stackPhys = (void*) pmmngr_alloc_block ();

		/* map user process stack space */
		vmmngr_mapPhysicalAddress (addressSpace,
				(uint32_t) stack,
				(uint32_t) stackPhys,
				I86_PTE_PRESENT|I86_PTE_WRITABLE|I86_PTE_USER);

		/* final initialization */
		mainThread->initialStack = stack;
        mainThread->frame.esp    = (uint32_t)mainThread->initialStack;
        mainThread->frame.ebp    = mainThread->frame.esp;

		/* close file and return process ID */
		volCloseFile(&file);
        return proc->id;
}