int32_t halt(uint8_t status) { // uint32_t flags; // cli_and_save(flags); pcb_t* parent_process = curr_process->parent_process; if(curr_process == curr_process->parent_process) { // We need to actually handle this case printf("YOU CAN CHECK OUT, BUT YOU CAN NEVER LEAVE...\n"); while(1); uint8_t fexec[33] = "shell"; curr_process->process_id = 0; execute(fexec); //sti(); return -1; } else { // saving return value retval = (uint32_t)status; //modify open_processes to indicate that current process is not running anymore open_processes ^= (MASK >> curr_process->process_id); //clear parent process' child flag parent_process->child_flag = 0; // restore TSS tss.esp0 = parent_process->k_sp; //tss.ss0 = curr_process->ss0; //restore paging set_PDBR(parent_process->PD_ptr); uint32_t p_sp = parent_process->k_sp; uint32_t p_bp = parent_process->k_bp; asm volatile("movl %0, %%esp"::"g"(p_sp):"memory"); asm volatile("movl %0, %%ebp"::"g"(p_bp):"memory"); uint32_t halting_task = (next_available - 1) % 7; task_queue[halting_task] = -1; next_available = halting_task; //context_switch(parent_process->process_id); curr_process = curr_process->parent_process; //go back to parent's instruction pointer asm volatile("jmp ret_halt"); } return 183; }
/* * PDE_t* task_mem_init(uint32_t PID) * Description: Initializes the PD for a new process * Inputs: PID - The process ID of the new process * Return Value: A pointer to the new page directory */ PDE_t* task_mem_init(uint32_t PID) { if(PID < 0 || PID > 6) return NULL; cur_PD = PD[PID]; map_4MB_page(PGRM_IMG, PGRM_PAGE[PID], 1, 1); //test_paging(); set_PDBR(cur_PD); return cur_PD; }
void context_switch(int new_pid) { if(new_pid == -1) { send_eoi(0); return; } uint32_t process_bp = _8MB - (_8KB)*(new_pid) - 4; pcb_t* new_process = (pcb_t *) (process_bp & 0xFFFFE000); set_PDBR(new_process->PD_ptr); tss.esp0 = new_process->k_sp; uint32_t p_sp = new_process->k_sp; uint32_t p_bp = new_process->k_bp; process_buf = new_process->file_fds[1].file_pos; process_id = new_pid; asm volatile("movl %%esp, %0":"=g"(curr_process->k_sp)); asm volatile("movl %%ebp, %0":"=g"(curr_process->k_bp)); curr_process = new_process; asm volatile("movl %0, %%esp"::"g"(p_sp):"memory"); asm volatile("movl %0, %%ebp"::"g"(p_bp):"memory"); // uint32_t process_bp = _8MB - (_8KB)*(new_pid) - 4; // pcb_t* new_process = (pcb_t *) (process_bp & 0xFFFFE000); // set_PDBR(curr_process->PD_ptr); // tss.esp0 = new_process->esp0; // tss.ss0 = new_process->ss0; send_eoi(0); // sti(); // return; }
/* * void init_PD() * Description: Sets all entries in the page directory * Inputs: none * Return Value: none */ void init_PD() { // Fill the page directory with blank entries PDE_default.present = 0; PDE_default.read_write = 0; PDE_default.user_super = 0; PDE_default.write_through = 0; PDE_default.cache_disabled = 0; PDE_default.accessed = 0; PDE_default.reserved = 0; PDE_default.page_size = 0; PDE_default.global = 0; PDE_default.avail = 0; PDE_default.page_table_base = 0; int i; for(i = 0; i < NUM_PDE; i++) { PD[0][i] = PDE_default; } // int i, j; // for(i = 0; i < NUM_PD; i++) // { // for(j = 0; j < NUM_PDE; j++) // { // PD[i][j] = PDE_default; // } // } cur_PD = PD[0]; // Set up video memory PDE int video_offset; video_offset = get_PDE_offset(VIDEO_MEM); PDE_t PDE_video; PDE_video = PDE_default; PDE_video.global = 1; PDE_video.read_write = 1; SET_PDE_4KB_PT(PDE_video, PT[0]); cur_PD[video_offset] = PDE_video; // Set up kernel memory PDE int kernel_offset; kernel_offset = get_PDE_offset(KERNEL_MEM); PDE_t PDE_kernel; PDE_kernel = PDE_default; PDE_kernel.global = 1; PDE_kernel.read_write = 1; SET_PDE_4MB_PAGE(PDE_kernel, KERNEL_MEM); cur_PD[kernel_offset] = PDE_kernel; // Pass the address of the page directory into the PBDR set_PDBR(cur_PD); // Copy all of PD[0] into all other PDs int j, k; for(j = 1; j < NUM_PD; j++) { for(k = 0; k < NUM_PDE; k++) { PD[j][k] = PD[0][k]; } } }
/*------------------------------------------------------------------------ * resched -- reschedule processor to highest priority ready process * * Notes: Upon entry, currpid gives current process id. * Proctab[currpid].pstate gives correct NEXT state for * current process if other than PRREADY. *------------------------------------------------------------------------ */ int resched() { STATWORD PS; register struct pentry *optr; /* pointer to old process entry */ register struct pentry *nptr; /* pointer to new process entry */ disable(PS); /* no switch needed if current process priority higher than next*/ if ( ( (optr= &proctab[currpid])->pstate == PRCURR) && (lastkey(rdytail)<optr->pprio)) { restore(PS); return(OK); } #ifdef STKCHK /* make sure current stack has room for ctsw */ asm("movl %esp, currSP"); if (currSP - optr->plimit < 48) { kprintf("Bad SP current process, pid=%d (%s), lim=0x%lx, currently 0x%lx\n", currpid, optr->pname, (unsigned long) optr->plimit, (unsigned long) currSP); panic("current process stack overflow"); } #endif /* force context switch */ if (optr->pstate == PRCURR) { optr->pstate = PRREADY; insert(currpid,rdyhead,optr->pprio); } /* remove highest priority process at end of ready list */ nptr = &proctab[ (currpid = getlast(rdytail)) ]; nptr->pstate = PRCURR; /* mark it currently running */ #ifdef notdef #ifdef STKCHK if ( *( (int *)nptr->pbase ) != MAGIC ) { kprintf("Bad magic pid=%d value=0x%lx, at 0x%lx\n", currpid, (unsigned long) *( (int *)nptr->pbase ), (unsigned long) nptr->pbase); panic("stack corrupted"); } /* * need ~16 longs of stack space below, so include that in check * below. */ if (nptr->pesp - nptr->plimit < 48) { kprintf("Bad SP pid=%d (%s), lim=0x%lx will be 0x%lx\n", currpid, nptr->pname, (unsigned long) nptr->plimit, (unsigned long) nptr->pesp); panic("stack overflow"); } #endif /* STKCHK */ #endif /* notdef */ #ifdef RTCLOCK preempt = QUANTUM; /* reset preemption counter */ #endif #ifdef DEBUG PrintSaved(nptr); #endif // When performing a context switch between processes we must also // switch between memory spaces. This is accomplished by adjusting // the PDBR register with every context switch. // // 5 - Context switch // - every process has separate page directory // - before ctxsw() load CR3 with the process' PDBR set_PDBR(VA2VPNO(nptr->pd)); #if DUSTYDEBUG kprintf("switching to process %d\n", (nptr - proctab)); #endif ctxsw(&optr->pesp, optr->pirmask, &nptr->pesp, nptr->pirmask); #ifdef DEBUG PrintSaved(nptr); #endif /* The OLD process returns here when resumed. */ restore(PS); return OK; }
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)); } }