示例#1
0
文件: dma.c 项目: darkwowgamer/toy_OS
void dma_load(uint8_t channel, void *start, int count) {
	KASSERT(PAGE_ALIGNED(start));
	prd_t* table = DMA_PRDS[channel];
	memset(table, 0, sizeof(prd_t));
	/* set up the PRD for this operation */
	table->prd_addr = pt_virt_to_phys((uintptr_t) start);
	table->prd_count = count;
	table->prd_last = 0x8000;
	return;
}
示例#2
0
文件: dma.c 项目: darkwowgamer/toy_OS
void dma_start(uint8_t channel, uint16_t busmaster_addr, int write) {
	uint8_t cmd = 0;
	/* first we need to set the read/write bit */
	if (write == 0) {
		cmd = (1 << 3);
	}
	/* then set the address of the prd */
	outl(busmaster_addr + DMA_PRD, pt_virt_to_phys((uintptr_t)DMA_PRDS[channel]));
	/* then allow all channels of DMA on this busmaster by setting that status register */
	outb(busmaster_addr + DMA_STATUS, inb(busmaster_addr + DMA_STATUS) | 0x60);
	/* then we need to set the start/stop bit */
	cmd |= 0x01;
	outb(busmaster_addr + DMA_COMMAND, cmd);
}
示例#3
0
/*
 * This gets called by _pt_fault_handler in mm/pagetable.c The
 * calling function has already done a lot of error checking for
 * us. In particular it has checked that we are not page faulting
 * while in kernel mode. Make sure you understand why an
 * unexpected page fault in kernel mode is bad in Weenix. You
 * should probably read the _pt_fault_handler function to get a
 * sense of what it is doing.
 *
 * Before you can do anything you need to find the vmarea that
 * contains the address that was faulted on. Make sure to check
 * the permissions on the area to see if the process has
 * permission to do [cause]. If either of these checks does not
 * pass kill the offending process, setting its exit status to
 * EFAULT (normally we would send the SIGSEGV signal, however
 * Weenix does not support signals).
 *
 * Now it is time to find the correct page (don't forget
 * about shadow objects, especially copy-on-write magic!). Make
 * sure that if the user writes to the page it will be handled
 * correctly.
 *
 * Finally call pt_map to have the new mapping placed into the
 * appropriate page table.
 *
 * @param vaddr the address that was accessed to cause the fault
 *
 * @param cause this is the type of operation on the memory
 *              address which caused the fault, possible values
 *              can be found in pagefault.h
 */
void
handle_pagefault(uintptr_t vaddr, uint32_t cause)
{
        /*NOT_YET_IMPLEMENTED("VM: handle_pagefault");*/
	vmmap_t *map = curproc->p_vmmap;
	dbginfo(DBG_ERROR, proc_info, curproc);
	dbginfo(DBG_ERROR, proc_list_info, NULL);
	if(vaddr == NULL){
	}	
	vmarea_t *vma =	vmmap_lookup(map, ADDR_TO_PN(vaddr));
	
	/*uintptr_t pagenum = PAGE_OFFSET(vaddr);*/
	if(vma == NULL ||  !(cause & FAULT_USER)){
		/*XXX permission checks*/
		curproc->p_status = EFAULT;
		proc_kill(curproc, EFAULT);
	}
	pframe_t *pf;
	uintptr_t pagenum =  ADDR_TO_PN(vaddr) - vma->vma_start+vma->vma_off;
	/*XXX handle shadow objects*/	
	/*
	int forWrite = 0;
	if(cause & FAULT_WRITE){
		forWrite = 1;
	}
	*/		
	/*
	if(vma->vma_obj->mmo_shadowed != NULL){
		shadow_lookuppage(vma->vma_obj->mmo_shadowed, pagenum, forWrite,&pf);
	}else{
	*/
		pframe_get(vma->vma_obj, pagenum, &pf);
	/*}*/
	uintptr_t paddr = pt_virt_to_phys((uintptr_t)pf->pf_addr);
	uintptr_t pdflags = PD_PRESENT | PD_WRITE | PD_USER;
	uintptr_t ptflags = PT_PRESENT | PT_WRITE | PT_USER;
	/*XXX tlb flush?*/
	pt_map(curproc->p_pagedir,(uintptr_t)PAGE_ALIGN_DOWN(vaddr), paddr, pdflags, ptflags);

}
示例#4
0
/*
 * This gets called by _pt_fault_handler in mm/pagetable.c The
 * calling function has already done a lot of error checking for
 * us. In particular it has checked that we are not page faulting
 * while in kernel mode. Make sure you understand why an
 * unexpected page fault in kernel mode is bad in Weenix. You
 * should probably read the _pt_fault_handler function to get a
 * sense of what it is doing.
 *
 * Before you can do anything you need to find the vmarea that
 * contains the address that was faulted on. Make sure to check
 * the permissions on the area to see if the process has
 * permission to do [cause]. If either of these checks does not
 * pass kill the offending process, setting its exit status to
 * EFAULT (normally we would send the SIGSEGV signal, however
 * Weenix does not support signals).
 *
 * Now it is time to find the correct page (don't forget
 * about shadow objects, especially copy-on-write magic!). Make
 * sure that if the user writes to the page it will be handled
 * correctly.
 *
 * Finally call pt_map to have the new mapping placed into the
 * appropriate page table.
 *
 * @param vaddr the address that was accessed to cause the fault
 *
 * @param cause this is the type of operation on the memory
 *              address which caused the fault, possible values
 *              can be found in pagefault.h
 */
void
handle_pagefault(uintptr_t vaddr, uint32_t cause)
{

        int forwrite = 0;
        if( vaddr<(USER_MEM_LOW) ||vaddr >= (USER_MEM_HIGH)){
                dbg(DBG_PRINT, "(GRADING3D) ADDRESS NOT VALID \n");
                do_exit(EFAULT);
                return;
        }
        vmarea_t *container = vmmap_lookup(curproc->p_vmmap, ADDR_TO_PN(vaddr));
        if(container == NULL){
          dbg(DBG_PRINT, "(GRADING3D) VMAREA NOT VALID \n");
                do_exit(EFAULT);
                return;
        }
        if(container->vma_prot == PROT_NONE){
          dbg(DBG_PRINT, "(GRADING3D) PROT NOT VALID \n");
                do_exit(EFAULT);
                return;
        }
        if((cause & FAULT_WRITE) && !(container->vma_prot & PROT_WRITE)){
          dbg(DBG_PRINT, "(GRADING3D) CONTAINER PROT NOT VALID \n");
                do_exit(EFAULT);
                return;
        }
        if(!(container->vma_prot & PROT_READ)){
          dbg(DBG_PRINT, "(GRADING3D)  PROT IS NOT PROT READ \n");
                do_exit(EFAULT);
                return;
        }
        int pagenum = ADDR_TO_PN(vaddr)-container->vma_start+container->vma_off;
        pframe_t *pf;
        if((container->vma_prot & PROT_WRITE) && (cause & FAULT_WRITE)){
          dbg(DBG_PRINT, "(GRADING3D) prot write fault write \n");
            int pf_res = pframe_lookup(container->vma_obj, pagenum, 1, &pf);
            if(pf_res<0){
              dbg(DBG_PRINT, "(GRADING3D) pframe lookup failed\n");
                do_exit(EFAULT);
            }
            pframe_dirty(pf);
        }else{
          dbg(DBG_PRINT, "(GRADING3D) prot write fault write else \n");
            int pf_res = pframe_lookup(container->vma_obj, pagenum, forwrite, &pf);
            if(pf_res<0){
              dbg(DBG_PRINT, "(GRADING3D) pframe lookup failed \n");
                do_exit(EFAULT);
            }
        }
        KASSERT(pf);
        dbg(DBG_PRINT, "(GRADING3A 5.a) pf is not NULL\n");
        KASSERT(pf->pf_addr);
        dbg(DBG_PRINT, "(GRADING3A 5.a) pf->addr is not NULL\n");
        uint32_t pdflags = PD_PRESENT | PD_USER;
        uint32_t ptflags = PT_PRESENT | PT_USER;
        if(cause & FAULT_WRITE){
          dbg(DBG_PRINT, "(GRADING3D) cause is fault write \n");
            pdflags = pdflags | PD_WRITE;
            ptflags = ptflags | PT_WRITE;
        }
        int ptmap_res = pt_map(curproc->p_pagedir, (uintptr_t)PAGE_ALIGN_DOWN(vaddr), pt_virt_to_phys((uintptr_t)pf->pf_addr), pdflags, ptflags);
}
示例#5
0
/*
 * This gets called by _pt_fault_handler in mm/pagetable.c The
 * calling function has already done a lot of error checking for
 * us. In particular it has checked that we are not page faulting
 * while in kernel mode. Make sure you understand why an
 * unexpected page fault in kernel mode is bad in Weenix. You
 * should probably read the _pt_fault_handler function to get a
 * sense of what it is doing.
 *
 * Before you can do anything you need to find the vmarea that
 * contains the address that was faulted on. Make sure to check
 * the permissions on the area to see if the process has
 * permission to do [cause]. If either of these checks does not
 * pass kill the offending process, setting its exit status to
 * EFAULT (normally we would send the SIGSEGV signal, however
 * Weenix does not support signals).
 *
 * Now it is time to find the correct page (don't forget
 * about shadow objects, especially copy-on-write magic!). Make
 * sure that if the user writes to the page it will be handled
 * correctly.
 *
 * Finally call pt_map to have the new mapping placed into the
 * appropriate page table.
 *
 * @param vaddr the address that was accessed to cause the fault
 *
 * @param cause this is the type of operation on the memory
 *              address which caused the fault, possible values
 *              can be found in pagefault.h
 */
void handle_pagefault(uintptr_t vaddr, uint32_t cause) {
	/*NOT_YET_IMPLEMENTED("VM: handle_pagefault");*/
	vmarea_t *vma;
	pframe_t *pf;
	int pflags = PD_PRESENT | PD_USER;
	int writeflag = 0;
	dbg(DBG_PRINT, "(GRADING3F)\n");
	if ((vma = vmmap_lookup(curproc->p_vmmap, ADDR_TO_PN(vaddr))) == NULL) {
		dbg(DBG_PRINT, "(GRADING3C 1)\n");
		proc_kill(curproc, EFAULT);
		return;
	}
	/*
	if (vma->vma_prot & PROT_NONE) {
		dbg(DBG_ERROR, "(GRADING3 3)\n");
		proc_kill(curproc, EFAULT);
		return;
	}*/
	if (!((cause & FAULT_WRITE) || (cause & FAULT_EXEC))
			&& !(vma->vma_prot & PROT_READ)) {
		dbg(DBG_PRINT, "(GRADING3D 3)\n");
		proc_kill(curproc, EFAULT);
		return;
	}
	if ((cause & FAULT_WRITE) && !(vma->vma_prot & PROT_WRITE)) {
		dbg(DBG_PRINT, "(GRADING3D 3)\n");
		proc_kill(curproc, EFAULT);
		return;
	}/*
	if ((cause & FAULT_EXEC) && !(vma->vma_prot & PROT_EXEC)) {
		dbg(DBG_ERROR, "(GRADING3 6)\n");
		proc_kill(curproc, EFAULT);
		return;;
	}*/

	if (cause & FAULT_WRITE) {
		dbg(DBG_PRINT, "(GRADING3F)\n");
		writeflag = 1;
	}

	if (pframe_lookup(vma->vma_obj,
	ADDR_TO_PN(vaddr) - vma->vma_start + vma->vma_off, writeflag, &pf) < 0) {
		dbg(DBG_PRINT, "(GRADING3D 4)\n");
		proc_kill(curproc, EFAULT);
		return;
	}
	if (cause & FAULT_WRITE) {
		pframe_pin(pf);
		dbg(DBG_PRINT, "(GRADING3F)\n");
		pframe_dirty(pf);
		/*
		if ( < 0) {
			dbg(DBG_ERROR, "(GRADING3 10)\n");
			pframe_unpin(pf);
			proc_kill(curproc, EFAULT);
			return;
		}*/
		pframe_unpin(pf);
		pflags |= PD_WRITE;
	}

	pt_map(curproc->p_pagedir, (uintptr_t) PAGE_ALIGN_DOWN(vaddr),
			pt_virt_to_phys((uintptr_t) pf->pf_addr), pflags, pflags);

}
示例#6
0
void
handle_pagefault(uintptr_t vaddr, uint32_t cause)
{

   
    pframe_t *pf;
        int ret_val;
        vmarea_t *vma = vmmap_lookup(curproc->p_vmmap, ADDR_TO_PN(vaddr));
        if(vma == NULL)
        {
            dbg(DBG_PRINT,"(GRADING3D 1): No vmarea found\n");
            proc_kill(curproc,EFAULT);
            return;
        }

        if(cause & FAULT_WRITE)
        {
            dbg(DBG_VM,"grade14\n");
            dbg(DBG_PRINT,"(GRADING3D 1),checking permission for writing\n");
            if(vma->vma_prot & PROT_WRITE)
            {
                dbg(DBG_VM,"grade15\n");
                 dbg(DBG_PRINT,"(GRADING3D 1),Vmarea has write permission\n");
                ret_val = pframe_lookup(vma->vma_obj, ADDR_TO_PN(vaddr) - vma->vma_start + vma->vma_off, (cause & FAULT_WRITE),&pf);
                if(ret_val<0)
                {
                    dbg(DBG_VM,"grade16\n");
                    dbg(DBG_PRINT,"(GRADING3D 1),pframe could not be found\n");
                     proc_kill(curproc,EFAULT);
                    return;  
                }
                pframe_dirty(pf);

                KASSERT(pf);
                dbg(DBG_PRINT,"(GRADING3A 5.a),pframe is not NULL\n");
                KASSERT(pf->pf_addr);
                dbg(DBG_PRINT,"(GRADING3A 5.a),pf->pf_addr is not NULL\n");
            }
            else
            {
                dbg(DBG_VM,"grade17\n");
                dbg(DBG_PRINT,"(GRADING3D 1),Vmarea does not have write permission\n"); 
              proc_kill(curproc,EFAULT);
            return;  
            }
            dbg(DBG_VM,"grade18\n");
            dbg(DBG_PRINT,"(GRADING3D 1),Calling pt_map after write\n");
            pt_map(curproc->p_pagedir,(uintptr_t)PAGE_ALIGN_DOWN(vaddr),pt_virt_to_phys((uintptr_t)pf->pf_addr), 
                (PD_WRITE|PD_PRESENT|PD_USER), (PT_WRITE|PT_PRESENT|PT_USER));
        }

        else

            {
                dbg(DBG_VM,"grade19\n");
                dbg(DBG_PRINT,"(GRADING3D 1),checking permission for reading\n");
            if(vma->vma_prot & PROT_READ)
            {
                dbg(DBG_VM,"grade20\n");
                dbg(DBG_PRINT,"(GRADING3D 1),Vmarea has read permission\n");
                ret_val = pframe_lookup(vma->vma_obj, ADDR_TO_PN(vaddr) - vma->vma_start + vma->vma_off, (cause & FAULT_WRITE),&pf);
                if(ret_val<0)
                {
                    dbg(DBG_VM,"grade21\n");
                    dbg(DBG_PRINT,"(GRADING3D 1),pframe could not be found\n");
                     proc_kill(curproc,EFAULT);
                    return;  
                }
                    dbg(DBG_VM,"grade22\n");
                KASSERT(pf);
                dbg(DBG_PRINT,"(GRADING3A 5.a),pframe is not NULL\n");
                KASSERT(pf->pf_addr);
                dbg(DBG_PRINT,"(GRADING3A 5.a),pf->pf_addr is not NULL\n");
            }
            else
            {
                dbg(DBG_VM,"grade23\n");
                dbg(DBG_PRINT,"(GRADING3D 1),Vmarea does not have read permission\n");
              proc_kill(curproc,EFAULT);
            return;  
            }
            dbg(DBG_VM,"grade24\n");
            dbg(DBG_PRINT,"(GRADING3D 1),Calling pt_map after read\n");
            pt_map(curproc->p_pagedir,(uintptr_t)PAGE_ALIGN_DOWN(vaddr),pt_virt_to_phys((uintptr_t)pf->pf_addr), 
               (PD_PRESENT|PD_USER), (PT_PRESENT|PT_USER));
        }


   
}
示例#7
0
/*
 * This gets called by _pt_fault_handler in mm/pagetable.c The
 * calling function has already done a lot of error checking for
 * us. In particular it has checked that we are not page faulting
 * while in kernel mode. Make sure you understand why an
 * unexpected page fault in kernel mode is bad in Weenix. You
 * should probably read the _pt_fault_handler function to get a
 * sense of what it is doing.
 *
 * Before you can do anything you need to find the vmarea that
 * contains the address that was faulted on. Make sure to check
 * the permissions on the area to see if the process has
 * permission to do [cause]. If either of these checks does not
 * pass kill the offending process, setting its exit status to
 * EFAULT (normally we would send the SIGSEGV signal, however
 * Weenix does not support signals).
 *
 * Now it is time to find the correct page (don't forget
 * about shadow objects, especially copy-on-write magic!). Make
 * sure that if the user writes to the page it will be handled
 * correctly.
 *
 * Finally call pt_map to have the new mapping placed into the
 * appropriate page table.
 *
 * @param vaddr the address that was accessed to cause the fault
 *
 * @param cause this is the type of operation on the memory
 *              address which caused the fault, possible values
 *              can be found in pagefault.h
 */
void
handle_pagefault(uintptr_t vaddr, uint32_t cause)
{
        /*NOT_YET_IMPLEMENTED("VM: handle_pagefault");*/
        uint32_t res_vfn=ADDR_TO_PN(vaddr);
        vmarea_t *temp_vmarea=vmmap_lookup(curproc->p_vmmap,res_vfn);
        if(temp_vmarea==NULL)
        {
                proc_kill(curproc,EFAULT);
                return;
                
        } 
        if((cause&FAULT_PRESENT)&&(!(temp_vmarea->vma_prot&PROT_READ)))
        {
                proc_kill(curproc,EFAULT);
                return;
           
        }
        if(cause&FAULT_RESERVED&&(!(temp_vmarea->vma_prot&PROT_NONE)))
        {
                proc_kill(curproc,EFAULT);
                return;
        }
        if(cause&FAULT_EXEC&&(!(temp_vmarea->vma_prot&PROT_EXEC)))
        {
                proc_kill(curproc,EFAULT);
                return;
        }
        if ((cause & FAULT_WRITE)&&!(temp_vmarea->vma_prot & PROT_WRITE)) 
	{
                do_exit(EFAULT);
		return;
	}
        if((cause&FAULT_WRITE)==0) 
	{
		if((temp_vmarea->vma_prot & PROT_READ)==0) 
		{
			do_exit(EFAULT);
		}
	}

        pframe_t *temp_pf_res=NULL;
        uint32_t pagenum=temp_vmarea->vma_off+res_vfn-temp_vmarea->vma_start;

        if(cause & FAULT_WRITE)/*******according to google group:1. pframe_get 2.pt_map(permission!!!)*************/
        {
                int tempres=pframe_lookup(temp_vmarea->vma_obj,pagenum,1, &temp_pf_res);
                if(tempres<0)
                { 
                        proc_kill(curproc,EFAULT);
                        return;
                }
                uintptr_t paddr=pt_virt_to_phys((uintptr_t)temp_pf_res->pf_addr);
                pt_map(curproc->p_pagedir,(uintptr_t)(PN_TO_ADDR(res_vfn)),paddr,PD_PRESENT|PD_WRITE|PD_USER,PT_PRESENT|PT_WRITE|PT_USER);
        }
        else{
                int tempres=pframe_lookup(temp_vmarea->vma_obj,pagenum,0, &temp_pf_res);
                if(tempres<0)
                { 
                        proc_kill(curproc,EFAULT);
                        return;
                }
                uintptr_t paddr=pt_virt_to_phys((uintptr_t)temp_pf_res->pf_addr);
                pt_map(curproc->p_pagedir,(uintptr_t)(PN_TO_ADDR(res_vfn)),paddr,PD_PRESENT|PD_USER,PT_PRESENT|PT_USER);
        }  
}