示例#1
0
/*
 * This function implements the munmap(2) syscall.
 *
 * As with do_mmap() it should perform the required error checking,
 * before calling upon vmmap_remove() to do most of the work.
 * Remember to clear the TLB.
 */
int
do_munmap(void *addr, size_t len)
{
        /*NOT_YET_IMPLEMENTED("VM: do_munmap");
        return -1;*/
	  	dbg(DBG_PRINT,"go into do_mumap\n");
		if((uint32_t)addr % PAGE_SIZE)
		{
			dbg(DBG_PRINT,"(GRADING3C)\n");
			return -EINVAL;
		}
		if(len <= 0||len > 0xc0000000)
	    {
			dbg(DBG_PRINT,"(GRADING3C)\n");
	    	return -EINVAL;
	   	}
		KASSERT(PAGE_ALIGNED(addr));
	  	if(((uint32_t)addr < USER_MEM_LOW) || ((uint32_t)addr > USER_MEM_HIGH) || ((uint32_t)addr+len > USER_MEM_HIGH))
	    {
			dbg(DBG_PRINT,"(GRADING3C)\n");
	    	return -EINVAL;
	    }

		vmmap_remove( curproc->p_vmmap, ADDR_TO_PN(addr), ((len - 1)/PAGE_SIZE  + 1));

		tlb_flush_all();

	  	KASSERT(NULL != curproc->p_pagedir);
	  	dbg(DBG_PRINT,"(GRADING3A 2.b)\n");

	  	return 0;
}
示例#2
0
文件: Memory.cpp 项目: armizh/Fnx
void X86Memory::mapRemote(X86Process *p, Address pageTabAddr,
			  Address pageDirAddr, ulong prot)
{
    /* Map remote page directory and page table. */
    myPageDir[DIRENTRY(pageDirAddr)] =
	p->getPageDirectory() | (PAGE_PRESENT|PAGE_RW|PAGE_PINNED|prot);
    remPageTab = PAGETABADDR_FROM(pageTabAddr, PAGETABFROM_REMOTE);
    
    /* Refresh entire TLB cache. */
    tlb_flush_all();
}
示例#3
0
/*
 * The implementation of fork(2). Once this works,
 * you're practically home free. This is what the
 * entirety of Weenix has been leading up to.
 * Go forth and conquer.
 */
int
do_fork(struct regs *regs)
{
        /*NOT_YET_IMPLEMENTED("VM: do_fork");*/
        KASSERT(regs != NULL);
        dbg(DBG_PRINT, "(GRADING3A 7.a)\n");
        KASSERT(curproc != NULL);
        dbg(DBG_PRINT, "(GRADING3A 7.a)\n");
        KASSERT(curproc->p_state == PROC_RUNNING);
        dbg(DBG_PRINT, "(GRADING3A 7.a)\n");

        proc_t *childproc=proc_create("childproc");
        KASSERT(childproc);

        vmmap_t *cmap=vmmap_clone(curproc->p_vmmap);
        cmap->vmm_proc=childproc;
        vmmap_destroy(childproc->p_vmmap);/********************/
        childproc->p_vmmap=cmap;
       
        childproc->p_status = curproc->p_status;
	childproc->p_brk = curproc->p_brk;
	childproc->p_start_brk = curproc->p_start_brk;

        KASSERT(childproc->p_state == PROC_RUNNING);
        dbg(DBG_PRINT, "(GRADING3A 7.a)\n");
        KASSERT(childproc->p_pagedir != NULL);
        dbg(DBG_PRINT, "(GRADING3A 7.a)\n");
        
/*
        vmarea_t* temp_pvmarea=NULL;

        list_link_t *childbegin=childproc->p_vmmap->vmm_list.l_next;

        list_iterate_begin(&(curproc->p_vmmap->vmm_list),temp_pvmarea,vmarea_t,vma_plink)
        {
                if(temp_pvmarea->vma_flags&MAP_PRIVATE)
                {
                        mmobj_t *shadow_obj=shadow_create();
                        shadow_obj->mmo_shadowed=temp_pvmarea->vma_obj;
                        shadow_obj->mmo_un.mmo_bottom_obj=temp_pvmarea->vma_obj->mmo_un.mmo_bottom_obj;

                        vmarea_t* tpvmarea1=list_item(childbegin,vmarea_t,vma_plink);
                        mmobj_t *chshadow_obj=shadow_create();
                        chshadow_obj->mmo_shadowed=temp_pvmarea->vma_obj;
                        chshadow_obj->mmo_un.mmo_bottom_obj=temp_pvmarea->vma_obj->mmo_un.mmo_bottom_obj;
                        
                        temp_pvmarea->vma_obj->mmo_ops->ref(temp_pvmarea->vma_obj);

                        tpvmarea1->vma_obj=chshadow_obj;
                        temp_pvmarea->vma_obj=shadow_obj;
             
                }
                childbegin=childbegin->l_next;

        }list_iterate_end();
*/

        list_link_t* pindex=NULL;
        list_link_t* cindex=NULL;
        for (pindex = (curproc->p_vmmap->vmm_list.l_next),cindex= (childproc->p_vmmap->vmm_list.l_next);pindex !=&(curproc->p_vmmap->vmm_list);pindex=pindex->l_next,cindex=cindex->l_next)
        {
               
                vmarea_t* temp_pvmarea=list_item(pindex,vmarea_t,vma_plink);
                vmarea_t* tpvmarea1;
                 if(temp_pvmarea->vma_flags&MAP_PRIVATE)
                {
               
                        mmobj_t *shadow_obj=shadow_create();
                        shadow_obj->mmo_shadowed=temp_pvmarea->vma_obj;
                        shadow_obj->mmo_un.mmo_bottom_obj=temp_pvmarea->vma_obj->mmo_un.mmo_bottom_obj;
                        temp_pvmarea->vma_obj=shadow_obj;

                        tpvmarea1=list_item(cindex,vmarea_t,vma_plink);
                        mmobj_t *chshadow_obj=shadow_create();
                        chshadow_obj->mmo_shadowed=temp_pvmarea->vma_obj->mmo_shadowed;
                        chshadow_obj->mmo_un.mmo_bottom_obj=temp_pvmarea->vma_obj->mmo_un.mmo_bottom_obj;
                        chshadow_obj->mmo_shadowed->mmo_ops->ref(chshadow_obj->mmo_shadowed);
                        list_insert_tail(&(chshadow_obj->mmo_un.mmo_bottom_obj->mmo_un.mmo_vmas), &tpvmarea1->vma_olink);
                        tpvmarea1->vma_obj=chshadow_obj;
                }
                else{
                        tpvmarea1=list_item(cindex,vmarea_t,vma_plink);
                        tpvmarea1->vma_obj=temp_pvmarea->vma_obj;
                        tpvmarea1->vma_obj->mmo_ops->ref(tpvmarea1->vma_obj);
                        list_insert_tail(&(tpvmarea1->vma_obj->mmo_un.mmo_vmas), &tpvmarea1->vma_olink);
                }
                
                
        }


        pt_unmap_range(curproc->p_pagedir,USER_MEM_LOW,USER_MEM_HIGH);
        tlb_flush_all();

        kthread_t *chthread=kthread_clone(curthr);
        chthread->kt_proc=childproc;
        list_insert_tail(&(childproc->p_threads),&(chthread->kt_plink));

        (chthread->kt_ctx).c_pdptr=childproc->p_pagedir;
        (chthread->kt_ctx).c_eip=(uint32_t)(userland_entry);
        regs->r_eax = 0;
        (chthread->kt_ctx).c_esp=fork_setup_stack(regs, chthread->kt_kstack);
        /*(chthread->kt_ctx).c_ebp*/
        (chthread->kt_ctx).c_kstack=(uintptr_t)chthread->kt_kstack;
        (chthread->kt_ctx). c_kstacksz=DEFAULT_STACK_SIZE;
        KASSERT(chthread->kt_kstack != NULL);
        dbg(DBG_PRINT, "(GRADING3A 7.a)\n");
        /*********how to set return value*********/

        int i = 0;
	while (i<NFILES)
	{
		childproc->p_files[i] = curproc->p_files[i];
                if(childproc->p_files[i]!=NULL)
                {
                        fref(childproc->p_files[i]);
                }
                i++;
	}
/*      has been added in proc_create();
        childproc->p_cwd=curproc->p_cwd;
        vref(childproc->p_cwd);
*/
        sched_make_runnable(chthread);
        return childproc->p_pid;
}
示例#4
0
/*
 * This function implements the mmap(2) syscall, but only
 * supports the MAP_SHARED, MAP_PRIVATE, MAP_FIXED, and
 * MAP_ANON flags.
 *
 * Add a mapping to the current process's address space.
 * You need to do some error checking; see the ERRORS section
 * of the manpage for the problems you should anticipate.
 * After error checking most of the work of this function is
 * done by vmmap_map(), but remember to clear the TLB.
 */
int
do_mmap(void *addr, size_t len, int prot, int flags,
        int fd, off_t off, void **ret)
{
	  	dbg(DBG_PRINT,"go into do_mmap\n");
		file_t* file = NULL;

    	if(!PAGE_ALIGNED(off))
		{
			dbg(DBG_PRINT,"(GRADING3C)\n");
        	return -EINVAL;
		}

		if(len <= 0||len > 0xc0000000)
	    {
			dbg(DBG_PRINT,"(GRADING3C)\n");
	    	return -EINVAL;
	   	}

    	if (((uint32_t)addr < USER_MEM_LOW || (uint32_t)addr > USER_MEM_HIGH) && flags& MAP_FIXED)
		{      
			dbg(DBG_PRINT,"(GRADING3C)\n");  
			return -1;
		}

    if(!(flags & MAP_SHARED || flags & MAP_PRIVATE))
{			
	dbg(DBG_PRINT,"(GRADING3C)\n");
        return -EINVAL;
}
   	file = NULL;
    vnode_t *vn = NULL;
    int status = 0;
    uint32_t lopages = 0;
    size_t npages = (len - 1)/PAGE_SIZE  + 1;
    vmarea_t *newvma = NULL;
    if(flags & MAP_FIXED)
    {
			dbg(DBG_PRINT,"(GRADING3C)\n");
            lopages = ADDR_TO_PN( addr );
    }
    if(!(flags & MAP_ANON))
	{
			dbg(DBG_PRINT,"(GRADING3B)\n");
        if(fd < 0 || fd > NFILES)
		{
			dbg(DBG_PRINT,"(GRADING3C)\n");
            return -1;
        }
        file = fget(fd);
        if((prot & PROT_WRITE && MAP_SHARED & flags) && (file->f_mode == FMODE_READ))
		{
			dbg(DBG_PRINT,"(GRADING3C)\n");
            fput(file);
            return -1;
        }
        if(file == NULL) 
		{			
			dbg(DBG_PRINT,"(GRADING3C)\n");
			return -1;
		}
        vn = file->f_vnode;
    }




    status = vmmap_map(curproc->p_vmmap, vn, lopages, npages, prot, flags, off, VMMAP_DIR_HILO, &newvma);
    if(file != NULL) 
	{
		dbg(DBG_PRINT,"(GRADING3B)\n");
		fput(file);
	}
    if(newvma != NULL)
	{
			dbg(DBG_PRINT,"(GRADING3B)\n");
    *ret = PN_TO_ADDR(newvma->vma_start);
	}    
	if(status < 0)
	{
		dbg(DBG_PRINT,"(GRADING3C)\n");
		KASSERT(file == NULL);
        return status;
    }

    tlb_flush_all();
    KASSERT(curproc->p_pagedir != NULL);
    dbg(DBG_VM, "(GRADING3A 2.a)\n");
    return 0;

}
int send_mbox_callback(void *arg)
{
	struct WMD_DEV_CONTEXT *dev_ctxt = (struct WMD_DEV_CONTEXT *)arg;
	u32 temp;
	unsigned long flags;
	DEFINE_SPINLOCK(irq_lock);

	if (!dev_ctxt)
		return -EFAULT;

	if (dev_ctxt->dwBrdState == BRD_DSP_HIBERNATION ||
	    dev_ctxt->dwBrdState == BRD_HIBERNATION) {
		/* Restart the peripheral clocks */
		DSP_PeripheralClocks_Enable(dev_ctxt, NULL);

#ifdef CONFIG_BRIDGE_WDT3
		dsp_wdt_enable(true);
#endif

		spin_lock_irqsave(&irq_lock, flags);
		/* Enabling Dpll in lock mode*/
		temp = (u32) *((REG_UWORD32 *)
				((u32) (dev_ctxt->cmbase) + 0x34));
		temp = (temp & 0xFFFFFFFE) | 0x1;
		*((REG_UWORD32 *) ((u32) (dev_ctxt->cmbase) + 0x34)) =
			(u32) temp;
		temp = (u32) *((REG_UWORD32 *)
				((u32) (dev_ctxt->cmbase) + 0x4));
		temp = (temp & 0xFFFFF08) | 0x37;

		*((REG_UWORD32 *) ((u32) (dev_ctxt->cmbase) + 0x4)) =
			(u32) temp;
		/* Restore mailbox settings */
		omap_mbox_restore_ctx(dev_ctxt->mbox);

		/*
		  * Short wake up source is any read access to an MMU
		  * registers. Making a MMU flush or accessing any other MMU
		  * register before getting to this point will have the IVA in
		  * ON state or Retention if the DSP has moved to that state,
		  * having the Short Wakeup again is redundant and brings
		  * issues when accessing the MMU after the DSP has started
		  * its restore sequence. We will access only if the DSP
		  * is not in RET or ON.
		  */
		HW_PWRST_IVA2RegGet(dev_ctxt->prmbase, &temp);
		if (!(temp & HW_PWR_STATE_RET) && !(temp & HW_PWR_STATE_ON))
			/*
			  * Flush the TLBs, this will generate the
			  * shortwakeup.  Also wait for the DSP to restore.
			  */
                        tlb_flush_all(dev_ctxt->dwDSPMmuBase);

		udelay(10);
                spin_unlock_irqrestore(&irq_lock, flags);
                dev_ctxt->dwBrdState = BRD_RUNNING;
        } else if (dev_ctxt->dwBrdState == BRD_RETENTION) {
                /* Restart the peripheral clocks */
                DSP_PeripheralClocks_Enable(dev_ctxt, NULL);
                dev_ctxt->dwBrdState = BRD_RUNNING;
        }

	return 0;
}
示例#6
0
文件: elf32.c 项目: Aliced3645/os
static int _elf32_load(const char *filename, int fd, char *const argv[],
                       char *const envp[], uint32_t *eip, uint32_t *esp)
{
        int err = 0;
        Elf32_Ehdr header;
        Elf32_Ehdr interpheader;

        /* variables to clean up on failure */
        vmmap_t *map = NULL;
        file_t *file = NULL;
        char *pht = NULL;
        char *interpname = NULL;
        int interpfd = -1;
        file_t *interpfile = NULL;
        char *interppht = NULL;
        Elf32_auxv_t *auxv = NULL;
        char *argbuf = NULL;

        uintptr_t entry;

        file = fget(fd);
        KASSERT(NULL != file);

        /* Load and verify the ELF header */
        if (0 > (err = _elf32_load_ehdr(fd, &header, 0))) {
                goto done;
        }

        if (NULL == (map = vmmap_create())) {
                err = -ENOMEM;
                goto done;
        }

        size_t phtsize = header.e_phentsize * header.e_phnum;
        if (NULL == (pht = kmalloc(phtsize))) {
                err = -ENOMEM;
                goto done;
        }
        /* Read in the program header table */
        if (0 > (err = _elf32_load_phtable(fd, &header, pht, phtsize))) {
                goto done;
        }
        /* Load the segments in the program header table */
        if (0 > (err = _elf32_map_progsegs(file->f_vnode, map, &header, pht, 0))) {
                goto done;
        }

        Elf32_Phdr *phinterp = NULL;
        /* Check if program requires an interpreter */
        if (0 > (err = _elf32_find_phinterp(&header, pht, &phinterp))) {
                goto done;
        }

        /* Calculate program bounds for future reference */
        void *proglow;
        void *proghigh;
        _elf32_calc_progbounds(&header, pht, &proglow, &proghigh);

        entry = (uintptr_t) header.e_entry;

        /* if an interpreter was requested load it */
        if (NULL != phinterp) {
                /* read the file name of the interpreter from the binary */
                if (0 > (err = do_lseek(fd, phinterp->p_offset, SEEK_SET))) {
                        goto done;
                } else if (NULL == (interpname = kmalloc(phinterp->p_filesz))) {
                        err = -ENOMEM;
                        goto done;
                } else if (0 > (err = do_read(fd, interpname, phinterp->p_filesz))) {
                        goto done;
                }
                if (err != (int)phinterp->p_filesz) {
                        err = -ENOEXEC;
                        goto done;
                }

                /* open the interpreter */
                dbgq(DBG_ELF, "ELF Interpreter: %*s\n", phinterp->p_filesz, interpname);
                if (0 > (interpfd = do_open(interpname, O_RDONLY))) {
                        err = interpfd;
                        goto done;
                }
                kfree(interpname);
                interpname = NULL;

                interpfile = fget(interpfd);
                KASSERT(NULL != interpfile);

                /* Load and verify the interpreter ELF header */
                if (0 > (err = _elf32_load_ehdr(interpfd, &interpheader, 1))) {
                        goto done;
                }
                size_t interpphtsize = interpheader.e_phentsize * interpheader.e_phnum;
                if (NULL == (interppht = kmalloc(interpphtsize))) {
                        err = -ENOMEM;
                        goto done;
                }
                /* Read in the program header table */
                if (0 > (err = _elf32_load_phtable(interpfd, &interpheader, interppht, interpphtsize))) {
                        goto done;
                }

                /* Interpreter shouldn't itself need an interpreter */
                Elf32_Phdr *interpphinterp;
                if (0 > (err = _elf32_find_phinterp(&interpheader, interppht, &interpphinterp))) {
                        goto done;
                }
                if (NULL != interpphinterp) {
                        err = -EINVAL;
                        goto done;
                }

                /* Calculate the interpreter program size */
                void *interplow;
                void *interphigh;
                _elf32_calc_progbounds(&interpheader, interppht, &interplow, &interphigh);
                uint32_t interpnpages = ADDR_TO_PN(PAGE_ALIGN_UP(interphigh)) - ADDR_TO_PN(interplow);

                /* Find space for the interpreter */
                /* This is the first pn at which the interpreter will be mapped */
                uint32_t interppagebase = (uint32_t) vmmap_find_range(map, interpnpages, VMMAP_DIR_HILO);
                if ((uint32_t) - 1 == interppagebase) {
                        err = -ENOMEM;
                        goto done;
                }

                /* Base address at which the interpreter begins on that page */
                void *interpbase = (void *)((uintptr_t)PN_TO_ADDR(interppagebase) + PAGE_OFFSET(interplow));

                /* Offset from "expected base" in number of pages */
                int32_t interpoff = (int32_t) interppagebase - (int32_t) ADDR_TO_PN(interplow);

                entry = (uintptr_t) interpbase + ((uintptr_t) interpheader.e_entry - (uintptr_t) interplow);

                /* Load the interpreter program header and map in its segments */
                if (0 > (err = _elf32_map_progsegs(interpfile->f_vnode, map, &interpheader, interppht, interpoff))) {
                        goto done;
                }

                /* Build the ELF aux table */
                /* Need to hold AT_PHDR, AT_PHENT, AT_PHNUM, AT_ENTRY, AT_BASE,
                 * AT_PAGESZ, AT_NULL */
                if (NULL == (auxv = (Elf32_auxv_t *) kmalloc(7 * sizeof(Elf32_auxv_t)))) {
                        err = -ENOMEM;
                        goto done;
                }
                Elf32_auxv_t *auxvent = auxv;

                /* Add all the necessary entries */
                auxvent->a_type = AT_PHDR;
                auxvent->a_un.a_ptr = pht;
                auxvent++;

                auxvent->a_type = AT_PHENT;
                auxvent->a_un.a_val = header.e_phentsize;
                auxvent++;

                auxvent->a_type = AT_PHNUM;
                auxvent->a_un.a_val = header.e_phnum;
                auxvent++;

                auxvent->a_type = AT_ENTRY;
                auxvent->a_un.a_ptr = (void *) header.e_entry;
                auxvent++;

                auxvent->a_type = AT_BASE;
                auxvent->a_un.a_ptr = interpbase;
                auxvent++;

                auxvent->a_type = AT_PAGESZ;
                auxvent->a_un.a_val = PAGE_SIZE;
                auxvent++;

                auxvent->a_type = AT_NULL;

        } else {
                /* Just put AT_NULL (we don't really need this at all) */
                if (NULL == (auxv = (Elf32_auxv_t *) kmalloc(sizeof(Elf32_auxv_t)))) {
                        err = -ENOMEM;
                        goto done;
                }
                auxv->a_type = AT_NULL;
        }

        /* Allocate a stack. We put the stack immediately below the program text.
         * (in the Intel x86 ELF supplement pp 59 "example stack", that is where the
         * stack is located). I suppose we can add this "extra page for magic data" too */
        uint32_t stack_lopage = ADDR_TO_PN(proglow) - (DEFAULT_STACK_SIZE / PAGE_SIZE) - 1;
        err = vmmap_map(map, NULL, stack_lopage, (DEFAULT_STACK_SIZE / PAGE_SIZE) + 1,
                        PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, 0, 0, NULL);
        KASSERT(0 == err);
        dbg(DBG_ELF, "Mapped stack at low addr 0x%p, size %#x\n",
            PN_TO_ADDR(stack_lopage), DEFAULT_STACK_SIZE + PAGE_SIZE);


        /* Copy out arguments onto the user stack */
        int argc, envc, auxc;
        size_t argsize = _elf32_calc_argsize(argv, envp, auxv, phtsize, &argc, &envc, &auxc);
        /* Make sure it fits on the stack */
        if (argsize >= DEFAULT_STACK_SIZE) {
                err = -E2BIG;
                goto done;
        }
        /* Copy arguments into kernel buffer */
        if (NULL == (argbuf = (char *) kmalloc(argsize))) {
                err = -ENOMEM;
                goto done;
        }
        /* Calculate where in user space we start putting the args. */
        void *arglow = (void *)((uintptr_t)(((char *) proglow) - argsize) & ~PTR_MASK);
        /* Copy everything into the user address space, modifying addresses in
         * argv, envp, and auxv to be user addresses as we go. */
        _elf32_load_args(map, arglow, argsize, argbuf, argv, envp, auxv, argc, envc, auxc, phtsize);

        dbg(DBG_ELF, "Past the point of no return. Swapping to map at 0x%p, setting brk to 0x%p\n", map, proghigh);
        /* the final threshold / What warm unspoken secrets will we learn? / Beyond
         * the point of no return ... */

        /* Give the process the new mappings. */
        vmmap_t *tempmap = curproc->p_vmmap;
        curproc->p_vmmap = map;
        map = tempmap; /* So the old maps are cleaned up */
        curproc->p_vmmap->vmm_proc = curproc;
        map->vmm_proc = NULL;

        /* Flush the process pagetables and TLB */
        pt_unmap_range(curproc->p_pagedir, USER_MEM_LOW, USER_MEM_HIGH);
        tlb_flush_all();

        /* Set the process break and starting break (immediately after the mapped-in
         * text/data/bss from the executable) */
        curproc->p_brk = proghigh;
        curproc->p_start_brk = proghigh;

        strncpy(curproc->p_comm, filename, PROC_NAME_LEN);

        /* Tell the caller the correct stack pointer and instruction
         * pointer to begin execution in user space */
        *eip = (uint32_t) entry;
        *esp = ((uint32_t) arglow) - 4; /* Space on the user stack for the (garbage) return address */
        /* Note that the return address will be fixed by the userland entry code,
         * whether in static or dynamic */

        /* And we're done */
        err = 0;

done:
        if (NULL != map) {
                vmmap_destroy(map);
        }
        if (NULL != file) {
                fput(file);
        }
        if (NULL != pht) {
                kfree(pht);
        }
        if (NULL != interpname) {
                kfree(interpname);
        }
        if (0 <= interpfd) {
                do_close(interpfd);
        }
        if (NULL != interpfile) {
                fput(interpfile);
        }
        if (NULL != interppht) {
                kfree(interppht);
        }
        if (NULL != auxv) {
                kfree(auxv);
        }
        if (NULL != argbuf) {
                kfree(argbuf);
        }
        return err;
}