void allocate_frame(int pid, int type, uint32 vpage)
{
	int i;
	for (i = 0; i < NFRAMES; i++)
	{
		if(invertpagetable[page_head].empty == TRUE)
		{
			invertpagetable[page_head].pid = pid;
			invertpagetable[page_head].type = type;
			invertpagetable[page_head].empty = FALSE;
			invertpagetable[page_head].vpage = vpage;
			return;
		}	
		page_head = (++page_head) % NFRAMES;		
	}
	kprintf ("Could not find any empty pages. Must evict\n");
	if (policy == FIFO)
	{
		kprintf("Eviction Policy: FIFO\n");
		uint32 evict_page = (page_head + 1) % NFRAMES;
		while(invertpagetable[page_head].type != FRAME_REG)
		{
			evict_page = (page_head + 1) % NFRAMES;
			if (evict_page == (page_head + 1) % NFRAMES)
			{
				kprintf ("All frames filled by directories or tables!\n");
			}
		}
		page_head = evict_page;
		
		int old_pid = invertpagetable[page_head].pid;
		int old_type = invertpagetable[page_head].type;
		int old_vpage = invertpagetable[page_head].vpage;

		int old_bs = bs_page(old_vpage);
		int old_pd = pd(old_vpage);
		int old_pt = pt(old_vpage);
		
		struct procent *old_prptr = &proctab[old_pid];
		pd_t *old_pd_t = old_prptr->prpagedir;
		pt_t *old_pt_t = (old_pd_t[old_pd].pd_base << 12);
		old_pt_t[old_pt].pt_pres = 0;
		char* addr = (char *)frame2addr(page_head);
		if(open_bs(old_prptr->prbs) == (uint32)-1 ||
		   write_bs(addr, old_prptr->prbs, old_bs)||
		   close_bs(old_prptr->prbs) == (uint32)-1)
		{
			kprintf("Backing store error during eviction!");
			return;
		}
		invertpagetable[page_head].pid = pid;
		invertpagetable[page_head].type = type;
		invertpagetable[page_head].empty = FALSE;
		invertpagetable[page_head].vpage = vpage;
	}

}
예제 #2
0
/*-------------------------------------------------------------------------
 * free_frm - free a frame 
 *-------------------------------------------------------------------------
 */
SYSCALL free_frm(int i)
{
	STATWORD ps;
	disable(ps);
	unsigned long v_addr;	
	unsigned int pt_offset;
	unsigned int pd_offset;
	unsigned long pdbr;
	pd_t *pd_entry; 
	pt_t *pt_entry;
	int bs_store;
	int page_num;
	if(frm_tab[i].fr_type == FR_PAGE)
	{
//		kprintf("Inside free frame starting \n");
		v_addr = frm_tab[i].fr_vpno;
		pdbr = proctab[frm_tab[i].fr_pid].pdbr;			
		pd_offset = v_addr>>10;
		pt_offset = v_addr & 0x000003FF;
		pd_entry = pdbr+(pd_offset*sizeof(pd_t));
		pt_entry = (pd_entry->pd_base*NBPG)+(pt_offset*sizeof(pt_t));
		bs_store = proctab[frm_tab[i].fr_pid].store;
		page_num = frm_tab[i].fr_vpno-proctab[frm_tab[i].fr_pid].vhpno;
//		kprintf("Before write bs bs_store %d and page_num %d\n", bs_store, page_num);
		write_bs((i+FRAME0)*NBPG, bs_store, page_num);
//		kprintf("After write bs\n");
		pt_entry->pt_pres = 0;
		pt_entry->pt_write = 0;
		pt_entry->pt_base = 0;
		frm_tab[i].cookie = 0;
  		frm_tab[i].fr_dirty = 0;
  		frm_tab[i].fr_loadtime = 0;
  		frm_tab[i].fr_pid = -1;
 		frm_tab[i].fr_refcnt = 0;
 		frm_tab[i].fr_status = FRM_UNMAPPED;
 		frm_tab[i].fr_type = FR_PAGE;
 		frm_tab[i].fr_vpno = BASE_VIRTUAL_PAGE;
 		frm_tab[i].next_frame = -1;
		frm_tab[pd_entry->pd_base-FRAME0].fr_refcnt--;
		if(frm_tab[pd_entry->pd_base-FRAME0].fr_refcnt == 0)
			{
			frm_tab[pd_entry->pd_base-FRAME0].cookie = 0;
			frm_tab[pd_entry->pd_base-FRAME0].fr_dirty = 0;
			frm_tab[pd_entry->pd_base-FRAME0].fr_loadtime = 0;
			frm_tab[pd_entry->pd_base-FRAME0].fr_pid = -1;
			frm_tab[pd_entry->pd_base-FRAME0].fr_refcnt = 0;
			frm_tab[pd_entry->pd_base-FRAME0].fr_status = FRM_UNMAPPED;
			frm_tab[pd_entry->pd_base-FRAME0].fr_type = FR_PAGE;
			frm_tab[pd_entry->pd_base-FRAME0].fr_vpno = BASE_VIRTUAL_PAGE;
			frm_tab[pd_entry->pd_base-FRAME0].next_frame = -1;
			pd_entry->pd_pres = 0;
			}
	}
예제 #3
0
파일: pfint.c 프로젝트: dichen001/CSC501
SYSCALL pfint()
{
  	unsigned long cr2,physical_addr;
  	virt_addr_t * vaddr;
    int vp,s,o,avail,*store,*pageth;
  	unsigned int p,q,pt;
    pd_t *pd;
    pt_t *new_pt;
    STATWORD ps;
	// Disable interrupts
    disable(ps);
    if(GDB)
      kprintf("\n*************pfint is running!************\n");
  // Get the faulted address. The processor loads the CR2 register
  // with the 32-bit address that generated the exception.
  /* 1. Get the faulted address. */
    cr2 = read_cr2();
    vaddr = (virt_addr_t *)(&cr2); 
    if(GDB)
      kprintf("&cr2=%x, cr2=%x, &vaddr=%x, vaddr=%x\n",&cr2,cr2,&vaddr,vaddr);
  /* 2. Let 'vp' be the virtual page number of the page containing of the faulted address */
    vp = a2pno(cr2);
    if(GDB)
      kprintf("vp=%d,\n",vp);
  /* 3. Let pd point to the current page directory. */
    pd = proctab[currpid].pdbr;
    if(GDB)
      kprintf("pd=%x,\n",pd);
  /* 4. Check that a is a legal address (i.e., it has been mapped). 
     If it is not, print an error message and kill the process. */  
    pageth = getmem( sizeof(int *) );
    store = getmem( sizeof(int *) );
    if( SYSERR == bsm_lookup(currpid, vp, store, pageth)){
      kprintf("ERROR: This virtual address hasn't been mapped!\n");
      kill(currpid);
    }
  /* 5. Let p be the upper ten bits of a. [p represents page dirctory offset] */
  /* 6. Let q be the bits [21:12] of a. [p represents page table offset.]
  /* 7.1 Let pt point to the pth page table.*/
    p = vaddr->pd_offset;
    q = vaddr->pt_offset;
    pt = vaddr->pg_offset;
    if(GDB)
      kprintf("p=%d,q=%d,pt=%d\n",p,q,pt);
  /* 7.2  If the pth page table does not exist obtain a frame for it and initialize it. */
    if(pd[p].pd_pres != 1){
      if(GDB)
        kprintf("**obtain a frame for the new page table. \n");
      avail = get_frm();  //get the id of a new frame from frm_tab[];
      if (avail == -1) {
            if(GDB)
              kprintf("Could not create page table!\n");
            restore(ps);
            return SYSERR;
      }
      //initialize frame[avail], update the process_id and frame_type of this frame.
      init_frm(avail, currpid, FR_TBL);
      frm_tab[avail].fr_upper_t = pa2frid((unsigned long) pd);
      if(GDB)
        kprintf("upper page table @frame[%d]  pd=%x, a2pno(pd)=%d\n",frm_tab[avail].fr_upper_t, pd, a2pno((unsigned long) pd));
      new_pt = frid2pa(avail);
      init_pt(new_pt);
      //update this page_table_entry in the page_directory.
      pd[p].pd_pres = 1;
      pd[p].pd_write = 1;
      pd[p].pd_user = 0; // not sure about the usage;
      pd[p].pd_pwt = 0;
      pd[p].pd_pcd = 0;
      pd[p].pd_acc = 0;
      pd[p].pd_mbz = 0;
      pd[p].pd_fmb = 0;
      pd[p].pd_global = 0;
      pd[p].pd_avail = 0; // not in use right now.
      pd[p].pd_base = a2pno((unsigned long) new_pt);  /* location of page table */
      if(GDB)
        kprintf("New page_table(%x)@frame[%d] updated in page_directory[%d]@(frame[%d])\n",
        new_pt, avail, p, frm_tab[avail].fr_upper_t);
      if(GDB)
        kprintf("q=%d, new_pt[q]=%x, new_pt=%x, pd[p].pd_base=%d\n",
        q, new_pt[q], new_pt, pd[p].pd_base);
    }
    //if the page table has already existed, just need to refcnt++;
    else
    {
      int avail = pd[p].pd_base -1024;
      frm_tab[avail].fr_refcnt++;
      if(GDB)
        kprintf("frm_tab[%d].fr_refcnt = %d, frame_type: %d\n",avail, frm_tab[avail].fr_refcnt, frm_tab[avail].fr_type);
    }
/* 8.1 Using the backing store map, find the store s and page offset o which correspond to vp. */
    //already saved in 'store' and 'pageth'
    s = *store;
    o = *pageth;
/* 8.2 In the inverted page table increment the reference count of the frame which holds pt. 
   This indicates that one more of pt's entries is marked "present." */
    avail = find_frm(currpid,vp);
    if (avail == -1)
    {
      if(GDB)
        kprintf("allocating a page for the page fault\n");

      avail = get_frm();
      if(avail == -1)
      {
        if(GDB)
          kprintf("ATTENTION! Frames full. ###Replacement NEEDED!###\n");
        int frame_number = proctab[currpid].nframes-1;
        int frame_id = proc_frames[currpid][0];
        //update_proc_frames(pid,frame_number);
        int i;
        for (i = 0; i+1 < frame_number; ++i)
        {
          proc_frames[currpid][i] = proc_frames[currpid][i+1];
        }
        proctab[currpid].nframes = frame_number;

        int pid = frm_tab[frame_id].fr_pid;
        int upper_id = frm_tab[frame_id].fr_upper_t;    
        vp = frm_tab[frame_id].fr_vpno;
        if(GDB)
          kprintf("currpid=%d, frame[%d].pid=%d .vpno=%d, upper_frame[%d].ref=%d\n",currpid,frame_id,pid,vp,upper_id,frm_tab[upper_id].fr_refcnt);
        p = vp>>10;
        q = vp &0x003ff;        
        new_pt = vp2pa(pd[p].pd_base);
        new_pt[q].pt_pres  = 0;
        new_pt[q].pt_write = 1;
        new_pt[q].pt_base  = 0;
        if(GDB)
          kprintf("pd_offset=%d, pt_offset=%d, pt_dirty=%d\n",p,q,new_pt[q].pt_dirty);
        if(new_pt[q].pt_dirty == 1)
        {
          //write back and 
          pageth = getmem( sizeof(int *) );
          store = getmem( sizeof(int *) );
          if( SYSERR == bsm_lookup(currpid, vp, store, pageth)){
            kprintf("ERROR: This virtual address hasn't been mapped!\n");
            kill(currpid);
          }
          if(GDB)
            kprintf("maping found: {pid: %d, vpno: %d, store: %d, pageth: %d}\n",currpid,vp,*store,*pageth);
          write_bs((char *)new_pt, *store, *pageth);
        }
        init_pt(new_pt);
        reset_frm(frame_id);

        frm_tab[upper_id].fr_refcnt -= 2; //it is 2, not 1.
        if(frm_tab[upper_id].fr_refcnt <= 0){
          //mark the appropriate entry in pd as being not present, and free pt.
        }

        //invalidate the TLB entry for the page vp using the invlpg instruction
        if(pid == currpid) {
          set_PDBR(currpid);
        }
      }
      else
      {
        init_frm(avail, currpid, FR_PAGE);
        frm_tab[avail].fr_upper_t = pd[p].pd_base-FRAME0;
        if(GDB)
          kprintf("upper page table @frame[%d]\n",frm_tab[avail].fr_upper_t);
        frm_tab[avail].fr_vpno = vp;
        

        int counter =  proctab[currpid].nframes;      
        proc_frames[currpid][counter] = frm_tab[avail].fr_id;
        proctab[currpid].nframes++;
        if(GDB)
          kprintf("proc_frames[%d][%d] = frame[%d]\n",currpid,counter,avail);


        // Add this frame to head of the frame list within the bs of this process
        //(frm_tab[avail].bs_next)->fr_vpno
        //, proctab[currpid].bsmap[s].frames->bs_next
        if(GDB)
          kprintf("&frm_tab[avail].bs_next = %x\n",frm_tab[avail].bs_next, &frm_tab[avail].bs_next);
        if(GDB)
          kprintf("proctab[%d].bsmap[%d].frames = %x, ->vpno=%d, ->bs_next=%x\n",currpid, s, proctab[currpid].bsmap[s].frames, proctab[currpid].bsmap[s].frames->fr_vpno, proctab[currpid].bsmap[s].frames->bs_next);
        frm_tab[avail].bs_next = getmem(sizeof(fr_map_t *));
        frm_tab[avail].bs_next =  proctab[currpid].bsmap[s].frames;
        proctab[currpid].bsmap[s].frames = &frm_tab[avail];
        fr_map_t *frame = proctab[currpid].bsmap[s].frames;
        int i = frame->fr_vpno;
        if(GDB)
          kprintf("i = %d\n",i);
        if(GDB)
          kprintf("~~~frame[%d] linked to frame[%d]\n", avail, frame->bs_next==NULL?-1:frame->bs_next->fr_id);
        if(GDB)
          kprintf("frame[%d].bs_next = %x, &**=%x\n",avail,frm_tab[avail].bs_next, &frm_tab[avail].bs_next);
        if(GDB)
          kprintf("proctab[%d].bsmap[%d].frames = %x, ->vpno=%d, ->bs_next=%x\n",currpid, s, proctab[currpid].bsmap[s].frames, proctab[currpid].bsmap[s].frames->fr_vpno, proctab[currpid].bsmap[s].frames->bs_next);

        
        if(GDB)
          kprintf("Mapping frame[%d](ppno[%d]) to {pid[%d], vpno[%d]} -> {bs[%d],offset:%d}\n",
          avail,frid2vpno(avail),currpid,vp,s,o);

        physical_addr = frid2pa(avail);
        read_bs(physical_addr,s,o);
        if(GDB)
          kprintf("copied from bs[%d]:offset[%d] to vp[%d]@(%x)\n",s,o,vp,vp2pa(vp));
      }
    }
예제 #4
0
int free_frame(frame_t * frame)
{
	intmask mask;
	mask = disable();
	//LOG("Freeing");
	//print_frame(frame);
	if(frame->id <5)
	{
		LOG(" WHAT THE F**K %d %d", frame->id, frame->type);
		restore(mask);
		return OK;
	}
	//kprintf("id %d type %d ", frame->id, frame->type);
	//print_fifo_list();
	//kprintf("\n");
	if(frame == NULL)
	{
		restore(mask);
		return SYSERR;
	}
	else if(!FRAMEID_IS_VALID(frame->id))
	{
		restore(mask);
		return SYSERR;
	}
	else if(frame->type == FREE)
	{
		restore(mask);
		return OK;
	}
	else if(frame->type == PAGE){

		//print_fifo_list();
		//LOG("Got here 0.5");
		//3. Using the inverted page table, get vp, the virtual page number of the page to be replaced.
		uint32 vp = frame->vp_no;
		//4. Let a be vp*4096 (the first virtual address on page vp).

		hook_pswap_out(vp, frame->id + FRAME0);
		uint32 a = vp*PAGE_SIZE;

		virtual_addr * virt = (virtual_addr *) &a;

		//5. Let p be the high 10 bits of a. Let q be bits [21:12] of a.
		uint32 p = virt->page_directory_offset;
		uint32 q = virt->page_table_offset;

		//6. Let pid be the process id of the process owning vp.
		pid32 pid = frame->pid;


		//7. Let pd point to the page directory of process pid.
		struct	procent	*prptr;		/* Ptr to process table entry	*/
		prptr = &proctab[pid];
		pd_t * pd = prptr->pagedir;

		if( pd == NULL)
		{
			LOG(" pd doesn't exist ");
			restore(mask);
			return SYSERR;
		}
		bool8 pt_pres = FALSE;
		pt_pres = (bool8) pd[p].pd_pres;

		bool8 pg_pres = FALSE;
		bool8 dirty = FALSE;
		if(pt_pres)
		{	//8. Let pt point to the pid's p_th page table.
			pt_t * pt = (pt_t *) ((pd[p].pd_base) * PAGE_SIZE);
			pg_pres = (bool8) pt[q].pt_pres;
			uint32 pg_base = (uint32) pt[q].pt_base;
			if(pg_pres){
				if((uint32)FRAMEID_TO_VPAGE(frame->id) == pg_base)
				{
					pg_pres = TRUE;
					dirty  = pt[q].pt_dirty;
				}
				else
				{
					pg_pres = FALSE;
				}
			}




		}
		if(pg_pres)
		{
			frame_t * pt_frame = &frames[(pd[p].pd_base) - FRAME0];
			pt_t * pt = (pt_t *) ((pd[p].pd_base) * PAGE_SIZE);
			//9. Mark the appropriate entry of pt as not present.
			pt[q].pt_pres = 0;
			if(pt_frame->type == VPTBL){
				decr_frame_refcount(pt_frame);
				if(pt_frame->refcount == 0){
					pd[p].pd_pres = 0;
					free_frame(pt_frame);

				}


				bzero((char *)&pt[q], sizeof(pt_t));
			}
			else if(pt_frame->type == GPTBL)
			{
			//	kprintf(" Uh  OH");
			}
			// If the reference count has reached zero, you should mark the appropriate entry in pd as "not present."
			// This conserves frames by keeping only page tables which are necessary.
			//LOG("Got here 1.5");

			//If the dirty bit for page vp was set in its page table, you must do the following:
			//a)	Using the backing store map, find the store and page offset within the store, given pid and a.
			//		If the lookup fails, something is wrong. Print an error message and kill the process with id pid.
			//b)	Write the page back to the backing store.

			//LOG("Got here 2");

			if(dirty){
				bsd_t bs_store_id;
				int bs_store_page_offset;
				if(SYSERR == bs_map_check(pid, vp, &bs_store_id, &bs_store_page_offset))
				{
						kprintf("FATAL :Can't find the bs_map");
						restore(mask);
						kill(currpid);
						return SYSERR;
				}
				//print_frame(frame);
				if(BACKSTORE_ID_IS_VALID(frame->backstore) && BACKSTORE_OFFSET_IS_VALID(frame->backstore_offset) && frame->backstore == bs_store_id && frame->backstore_offset == bs_store_page_offset)
				{
					//LOG("Frame %d was dirty", frame->id);
					open_bs(frame->backstore);
					write_bs(FRAMEID_TO_PHYSICALADDR(frame->id), frame->backstore, frame->backstore_offset);
					close_bs(frame->backstore);
				}
				//else
				//{
				//	print_frame(frame);
				//	kprintf("Fatal error: Cannot locate backstore for vpage %d to swap out page for pid %d ", vp, pid);
				//	kill(pid);
				//	initialize_frame(frame);
				//	restore(mask);
				//	return SYSERR;
				//}
			}

			else{
				//print_frame(frame);
			}
		}



		//LOG("Got here 1");
		//10. If the page being removed belongs to the current process,
		// invalidate the TLB entry for the page vp, using the invlpg instruction (see Intel Manual, volumes II and III for more details on this instruction).
		// 11. In the inverted page table, decrement the reference count of the frame occupied by pt.


		//LOG(" Free frame");
		//print_frame(frame);
		enable_paging();
		initialize_frame(frame);
		// Update page table entries associated with this frame
		// set the frame to be free
	}
	else if(frame->type == VPTBL)
	{
		evict_from_fifo_list(frame);
		hook_ptable_delete(frame->id + FRAME0);
		enable_paging();
		initialize_frame(frame);
	}
	else if(frame->type == DIR)
	{
		struct procent * prptrNULL = &proctab[NULLPROC];
		pd_t * null_pg_dir = prptrNULL->pagedir;
		struct	procent	*prptr;		/* Ptr to process table entry	*/
		prptr = &proctab[currpid];
		if(prptr->pagedir!= null_pg_dir)
		{
			evict_from_fifo_list(frame);
			prptr->pagedir = prptrNULL->pagedir;
			switch_page_directory(prptr->pagedir);
			enable_paging();
			initialize_frame(frame);

		}
	}
	restore(mask);
	return OK;

}