// // User-level fork with copy-on-write. // Set up our page fault handler appropriately. // Create a child. // Copy our address space and page fault handler setup to the child. // Then mark the child as runnable and return. // // Returns: child's envid to the parent, 0 to the child, < 0 on error. // It is also OK to panic on error. // // Hint: // Use vpd, vpt, and duppage. // Remember to fix "thisenv" in the child process. // Neither user exception stack should ever be marked copy-on-write, // so you must allocate a new page for the child's user exception stack. // envid_t fork(void) { // LAB 4: Your code here. //panic("fork not implemented"); extern void _pgfault_upcall(void); set_pgfault_handler(pgfault); envid_t id = sys_exofork(); int r; if (id < 0) panic("exofork: child"); if (id == 0) { thisenv = envs + ENVX(sys_getenvid()); return 0; } // cprintf("fork id: %x",id); if ((r=sys_page_alloc(id, (void*)(UXSTACKTOP-PGSIZE), PTE_U | PTE_W | PTE_P))<0) return r; int i; for (i=0;i<UTOP-PGSIZE;i+=PGSIZE) if ((vpd[PDX(i)] & PTE_P) && (vpt[PGNUM(i)] & PTE_P)) { // cprintf("i:%x ",i); if ((r=duppage(id,PGNUM(i)))<0) return r; } if ((r=sys_env_set_pgfault_upcall(id,(void*)_pgfault_upcall))<0) return r; if ((r=sys_env_set_status(id, ENV_RUNNABLE))<0) return r; return id; }
void umain(int argc, char **argv) { envid_t env; cprintf("Father:%04x", sys_getenvid()); a=1; if ((env = sfork()) == 0) { while (1) { cprintf("child:a=%d\n",a); sys_yield(); } exit(); } sys_yield(); sys_yield(); sys_yield(); sys_yield(); sys_yield(); sys_yield(); cprintf("Father:a changed\n"); a=2; sys_yield(); sys_yield(); sys_yield(); sys_yield(); sys_yield(); sys_yield(); cprintf("Killing the child\n"); sys_env_destroy(env); }
void umain(void) { envid_t ns_envid = sys_getenvid(); int i, r; binaryname = "testoutput"; output_envid = fork(); //cprintf("ns: %d, out:%d\n",ns_envid,output_envid); if (output_envid < 0) panic("error forking"); else if (output_envid == 0) { output(ns_envid); return; } for (i = 0; i < TESTOUTPUT_COUNT; i++) { if ((r = sys_page_alloc(0, pkt, PTE_P|PTE_U|PTE_W)) < 0) panic("sys_page_alloc: %e", r); pkt->jp_len = snprintf(pkt->jp_data, PGSIZE - sizeof(pkt->jp_len), "Packet %02d", i); cprintf("Transmitting packet %d\n", i); ipc_send(output_envid, NSREQ_OUTPUT, pkt, PTE_P|PTE_W|PTE_U); sys_page_unmap(0, pkt); } // Spin for a while, just in case IPC's or packets need to be flushed for (i = 0; i < TESTOUTPUT_COUNT*2; i++) sys_yield(); }
// Copy the current contents of the block out to disk. // Then clear the PTE_D bit using sys_page_map. // Hint: Use ide_write. // Hint: Use the PTE_USER constant when calling sys_page_map. void write_block(uint32_t blockno) { char *addr; if (!block_is_mapped(blockno)) panic("write unmapped block %08x", blockno); // Write the disk block and clear PTE_D. // LAB 5: Your code here. // We will use the VM hardware to keep track of whether a // disk block has been modified since it was last read from // or written to disk. To see whether a block needs writing, // we can just look to see if the PTE_D "dirty" bit is set // in the vpt entry. addr = diskaddr(blockno); if(!va_is_dirty(addr)) return; int error; int secno = blockno*BLKSECTS; error = ide_write(secno, addr, BLKSECTS); if(error<0) panic("write block error on writing"); int env_id = sys_getenvid(); error = sys_page_map(env_id, addr, env_id, addr, ((PTE_U|PTE_P|PTE_W) & ~PTE_D)); if(error<0) panic("write block error on clearing PTE_D"); // panic("write_block not implemented"); }
void libmain(int argc, char **argv) { // set env to point at our env structure in envs[]. // LAB 3: Your code here. envid_t pid; env = 0; pid = sys_getenvid(); env = (struct Env *)envs; env = env + ENVX(pid); // Debug info // cprintf("pid %u\n", pid); // cprintf("off %u\n", ENVX(pid)); LOG(DEBUG_LIBMAIN, "In libmain, about to start user program %x\n", pid); // save the name of the program so that panic() can use it if (argc > 0) binaryname = argv[0]; // call user main routine umain(argc, argv); // exit gracefully exit(); }
// // Set the page fault handler function. // If there isn't one yet, _pgfault_handler will be 0. // The first time we register a handler, we need to // allocate an exception stack (one page of memory with its top // at UXSTACKTOP), and tell the kernel to call the assembly-language // _pgfault_upcall routine when a page fault occurs. // void set_pgfault_handler(void (*handler)(struct UTrapframe *utf)) { int r; //cprintf("inside page fault handler, _pgfault_handler = %0x\n", _pgfault_handler); if (_pgfault_handler == 0) { // First time through! // LAB 4: Your code here. envid_t envid = sys_getenvid(); r = sys_page_alloc(envid, (void*) (UXSTACKTOP - PGSIZE), PTE_P|PTE_U|PTE_W); r = sys_page_alloc(envid, (void*) (UXSTACKTOP - 2*PGSIZE), PTE_P|PTE_U|PTE_W); if(r < 0) panic("page_alloc: %e", r); //cprintf("setting the upcall\n"); r = sys_env_set_pgfault_upcall(envid, _pgfault_upcall); //cprintf("set the upcall with result = %d\n", r); if(r < 0) panic("pgfault_upcall: %e", r); //panic("set_pgfault_handler not implemented"); } // Save handler pointer for assembly to call. _pgfault_handler = handler; }
// // User-level fork with copy-on-write. // Set up our page fault handler appropriately. // Create a child. // Copy our address space and page fault handler setup to the child. // Then mark the child as runnable and return. // // Returns: child's envid to the parent, 0 to the child, < 0 on error. // It is also OK to panic on error. // // Hint: // Use uvpd, uvpt, and duppage. // Remember to fix "thisenv" in the child process. // Neither user exception stack should ever be marked copy-on-write, // so you must allocate a new page for the child's user exception stack. // envid_t fork(void) { extern void _pgfault_upcall(); // LAB 4: Your code here. set_pgfault_handler(pgfault); envid_t envid = sys_exofork(); if (envid == 0) { thisenv = &envs[ENVX(sys_getenvid())]; return 0; } if (envid < 0) { panic("sys_exofork failed: %e", envid); } uint32_t addr; for (addr = 0; addr < USTACKTOP; addr += PGSIZE) { if ((uvpd[PDX(addr)] & PTE_P) && (uvpt[PGNUM(addr)] & PTE_P) && (uvpt[PGNUM(addr)] & PTE_U)) { duppage(envid, PGNUM(addr)); } } int alloc_err = sys_page_alloc(envid, (void *)(UXSTACKTOP-PGSIZE), PTE_U|PTE_W|PTE_P); if (alloc_err) { panic("sys_page_alloc failed with error: %e", alloc_err); } sys_env_set_pgfault_upcall(envid, _pgfault_upcall); int set_status_err = sys_env_set_status(envid, ENV_RUNNABLE); if (set_status_err) { panic("sys_env_set_status"); } return envid; }
// // Set the page fault handler function. // If there isn't one yet, _pgfault_handler will be 0. // The first time we register a handler, we need to // allocate an exception stack (one page of memory with its top // at UXSTACKTOP), and tell the kernel to call the assembly-language // _pgfault_upcall routine when a page fault occurs. // void set_pgfault_handler(void (*handler)(struct UTrapframe *utf)) { int r; int re; envid_t envid = sys_getenvid(); if (_pgfault_handler == 0) { // First time through! // LAB 4: Your code here. sys_env_set_pgfault_upcall(envid, _pgfault_upcall); re = sys_page_alloc(envid, (void *)(UXSTACKTOP - PGSIZE),PTE_U | PTE_P |PTE_W); if( re < 0){ cprintf("process %x,sys_page_alloc fail\n",envid); sys_env_destroy(envid); } //panic("set_pgfault_handler not implemented"); } // Save handler pointer for assembly to call. _pgfault_handler = handler; //cprintf("_pgfault_handler = %x\n",(uint32_t)_pgfault_handler); }
// // User-level fork with copy-on-write. // Set up our page fault handler appropriately. // Create a child. // Copy our address space and page fault handler setup to the child. // Then mark the child as runnable and return. // // Returns: child's envid to the parent, 0 to the child, < 0 on error. // It is also OK to panic on error. // // Hint: // Use uvpd, uvpt, and duppage. // Remember to fix "thisenv" in the child process. // Neither user exception stack should ever be marked copy-on-write, // so you must allocate a new page for the child's user exception stack. // envid_t fork(void) { // LAB 4: Your code here. set_pgfault_handler (pgfault); envid_t envid; uint32_t addr; int r; envid = sys_exofork(); if (envid < 0) panic("sys_exofork: %e", envid); // We’re the child if (envid == 0) { env = &envs[ENVX(sys_getenvid())]; return 0; } // We’re the parent. for (addr = UTEXT; addr < UXSTACKTOP - PGSIZE; addr += PGSIZE) { if ((vpd[VPD(addr)] & PTE_P) > 0 && (vpt[VPN(addr)] & PTE_P) > 0 && (vpt[ VPN(addr)] & PTE_U) > 0) duppage (envid, VPN(addr)); } if ((r = sys_page_alloc (envid, (void *)(UXSTACKTOP - PGSIZE), PTE_U|PTE_W|PTE_P)) < 0) panic ("fork: page allocation failed : %e", r); extern void _pgfault_upcall (void); sys_env_set_pgfault_upcall (envid, _pgfault_upcall); // Start the child environment running if ((r = sys_env_set_status(envid, ENV_RUNNABLE)) < 0) panic("fork: set child env status failed : %e", r); return envid; //panic("fork not implemented"); }
// Dispatches to the correct kernel function, passing the arguments. int64_t syscall(uint64_t syscallno, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. // panic("syscall not implemented"); switch (syscallno) { case SYS_cputs: sys_cputs((const char *)a1, (size_t)a2); return 0; case SYS_cgetc: return sys_cgetc(); case SYS_getenvid: return sys_getenvid(); case SYS_env_destroy: return sys_env_destroy(a1); case SYS_yield: sys_yield(); return 0; case SYS_page_alloc: return sys_page_alloc((envid_t)a1, (void *)a2,(int)a3); case SYS_page_map: return sys_page_map((envid_t)a1, (void *)a2, (envid_t)a3, (void *)a4, (int)a5); case SYS_page_unmap: return sys_page_unmap((envid_t)a1, (void *)a2); case SYS_exofork: return sys_exofork(); case SYS_env_set_status: return sys_env_set_status((envid_t)a1, a2); case SYS_env_set_pgfault_upcall: return sys_env_set_pgfault_upcall((envid_t)a1,(void *)a2); case SYS_ipc_try_send: return sys_ipc_try_send((envid_t)a1, (uint32_t)a2, (void *)a3, a4); case SYS_ipc_recv: return sys_ipc_recv((void *)a1); case SYS_env_set_trapframe: return sys_env_set_trapframe((envid_t)a1, (struct Trapframe *)a2); case SYS_time_msec: return sys_time_msec(); case SYS_packet_transmit: return sys_packet_transmit((char*)a1,(size_t)a2); case SYS_packet_receive: return sys_packet_receive((char *)a1); //lab 7 code from here case SYS_insmod: return sys_insmod((char *)a1, (char *)a2,(char *)a3); case SYS_rmmod: return sys_rmmod((char *)a1); case SYS_lsmod: return sys_lsmod(); case SYS_depmod: return sys_depmod((char *)a1); //lab7 code ends here default: return -E_NO_SYS; } }
// // User-level fork with copy-on-write. // Set up our page fault handler appropriately. // Create a child. // Copy our address space and page fault handler setup to the child. // Then mark the child as runnable and return. // // Returns: child's envid to the parent, 0 to the child, < 0 on error. // It is also OK to panic on error. // // Hint: // Use vpd, vpt, and duppage. // Remember to fix "thisenv" in the child process. // Neither user exception stack should ever be marked copy-on-write, // so you must allocate a new page for the child's user exception stack. // envid_t fork(void) { // LAB 4: Your code here. envid_t envid; uint64_t addr; uint32_t err; extern unsigned char end[]; int r; set_pgfault_handler(pgfault); envid = sys_exofork(); if (envid < 0) panic("sys_exofork: %e", envid); if (envid == 0) { // We're the child. // The copied value of the global variable 'thisenv' // is no longer valid (it refers to the parent!). // Fix it and return 0. thisenv = &envs[ENVX(sys_getenvid())]; return 0; } //Allocate exception stack for the child if ((err = sys_page_alloc(envid, (void *) (UXSTACKTOP - PGSIZE), PTE_P|PTE_U|PTE_W)) < 0) panic("Error in sys_page_alloc: %e", err); // We're the parent. // Map our entire address space into the child. for (addr = UTEXT; addr < USTACKTOP-PGSIZE; addr += PGSIZE) { if((vpml4e[VPML4E(addr)] & PTE_P) && (vpde[VPDPE(addr)] & PTE_P) && (vpd[VPD(addr)] & PTE_P) && (vpt[VPN(addr)] & PTE_P)) { duppage(envid, VPN(addr)); } } //Allocate a new stack for the child and copy the contents of parent on to it. addr = USTACKTOP-PGSIZE; if ((r = sys_page_alloc(0, (void *)PFTEMP, PTE_P|PTE_U|PTE_W)) < 0) panic("sys_page_alloc failed: %e\n", r); memcpy(PFTEMP, (void *) ROUNDDOWN(addr, PGSIZE), PGSIZE); void *vaTemp = (void *) ROUNDDOWN(addr, PGSIZE); if ((r = sys_page_map(0, (void *)PFTEMP, envid, vaTemp, PTE_P|PTE_U|PTE_W)) < 0) panic("sys_page_map failed: %e\n", r); if ((r = sys_page_unmap(0, (void *)PFTEMP)) < 0) panic("sys_page_unmap failed: %e\n", r); //Set child's page fault handler if ((err = sys_env_set_pgfault_upcall(envid, _pgfault_upcall) < 0)) panic("Error in sys_env_set_pgfault_upcall: %e",err); //Set the child ready to run if ((err = sys_env_set_status(envid, ENV_RUNNABLE)) < 0) panic("sys_env_set_status: %e", err); return envid; panic("fork not implemented"); }
void _main(void) { char arr[PAGE_SIZE*10]; uint32 kilo = 1024; int envID = sys_getenvid(); // cprintf("envID = %d\n",envID); volatile struct Env* myEnv; myEnv = &(envs[envID]); int freePages = sys_calculate_free_frames(); int usedDiskPages = sys_pf_calculate_allocated_pages(); int i ; for (i = 0 ; i < PAGE_SIZE*10 ; i+=PAGE_SIZE/2) arr[i] = -1 ; cprintf("checking REPLACEMENT fault handling of STACK pages... \n"); { for (i = 0 ; i < PAGE_SIZE*10 ; i+=PAGE_SIZE/2) if( arr[i] != -1) panic("modified stack page(s) not restored correctly"); if( (sys_pf_calculate_allocated_pages() - usedDiskPages) != 9) panic("Unexpected extra/less pages have been added to page file"); if( (freePages - (sys_calculate_free_frames() + sys_calculate_modified_frames())) != 0 ) panic("Extra memory are wrongly allocated... It's REplacement: expected that no extra frames are allocated"); } cprintf("Congratulations: stack pages created, modified and read successfully!\n\n"); return; }
// Copy the mappings for shared pages into the child address space. static int copy_shared_pages(envid_t child) { // LAB 5: Your code here. int i,j,ret; uintptr_t addr; envid_t curr_envid = sys_getenvid(); for(i=0;i<PDX(UTOP);i++) { if(uvpd[i] & PTE_P && i != PDX(UVPT)) { addr = i << PDXSHIFT; for(j=0;j<NPTENTRIES;j++) { addr = (i<<PDXSHIFT)+(j<<PGSHIFT); if((uvpt[addr>>PGSHIFT] & PTE_P) && (uvpt[addr>>PGSHIFT] & PTE_SHARE)) { ret = sys_page_map(curr_envid, (void *)addr, child,(void *)addr,PTE_AVAIL|PTE_P|PTE_U|PTE_W); if(ret) panic("sys_page_map: %e", ret); //cprintf("addr %x is shared\n",addr); } } } }
// Dispatches to the correct kernel function, passing the arguments. int32_t syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. // // TBD: gain 10+ percent of performance improvement // by using goto-label-array. switch(syscallno) { case SYS_cputs: sys_cputs((char *) a1, (size_t) a2); break; case SYS_cgetc: return sys_cgetc(); case SYS_getenvid: return sys_getenvid(); case SYS_env_destroy: sys_env_destroy(a1); break; case SYS_exofork: return sys_exofork(); case SYS_env_set_status: return sys_env_set_status(a1, a2); default: cprintf("Error syscall(%u)\n", syscallno); panic("syscall not implemented"); return -E_INVAL; } return 0; }
// Dispatches to the correct kernel function, passing the arguments. int32_t syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. /*stone's solution for lab3-B*/ int32_t ret = -E_INVAL; switch (syscallno){ case SYS_cputs: sys_cputs((char*)a1, a2); ret = 0; break; case SYS_cgetc: ret = sys_cgetc(); break; case SYS_getenvid: ret = sys_getenvid(); break; case SYS_env_destroy: ret = sys_env_destroy(a1); break; case SYS_map_kernel_page: ret = sys_map_kernel_page((void*)a1, (void*)a2); break; case SYS_sbrk: ret = sys_sbrk(a1); break; default: break; } return ret; //panic("syscall not implemented"); }
void umain(int argc, char **argv) { int i, j; int seen; envid_t parent = sys_getenvid(); // Fork several environments for (i = 0; i < 20; i++) if (fork() == 0) break; if (i == 20) { sys_yield(); return; } // Wait for the parent to finish forking while (envs[ENVX(parent)].env_status != ENV_FREE) asm volatile("pause"); // Check that one environment doesn't run on two CPUs at once for (i = 0; i < 10; i++) { sys_yield(); for (j = 0; j < 10000; j++) counter++; } if (counter != 10*10000) panic("ran on two CPUs at once (counter is %d)", counter); // Check that we see environments running on different CPUs cprintf("[%08x] stresssched on CPU %d\n", thisenv->env_id, thisenv->env_cpunum); }
// // Set the page fault handler function. // If there isn't one yet, _pgfault_handler will be 0. // The first time we register a handler, we need to // allocate an exception stack (one page of memory with its top // at UXSTACKTOP), and tell the kernel to call the assembly-language // _pgfault_upcall routine when a page fault occurs. // void set_pgfault_handler(void (*handler)(struct UTrapframe *utf)) { int r; if (_pgfault_handler == 0) { // First time through! // code for lab 4 -M.G // panic("set_pgfault_handler not implemented"); envid_t cur_envid = sys_getenvid(); uintptr_t ux_stack_top = UXSTACKTOP - PGSIZE; if (sys_page_alloc(cur_envid, (void *)ux_stack_top, PTE_P | PTE_U | PTE_W) < 0) { panic("ERROR: Cannot allocate memory for exception stack!!"); } if (sys_env_set_pgfault_upcall(cur_envid, _pgfault_upcall) < 0) { panic("ERROR: Cannot set pagefault handler!!"); } } // Save handler pointer for assembly to call. _pgfault_handler = handler; }
// // User-level fork with copy-on-write. // Set up our page fault handler appropriately. // Create a child. // Copy our address space and page fault handler setup to the child. // Then mark the child as runnable and return. // // Returns: child's envid to the parent, 0 to the child, < 0 on error. // It is also OK to panic on error. // // Hint: // Use uvpd, uvpt, and duppage. // Remember to fix "thisenv" in the child process. // Neither user exception stack should ever be marked copy-on-write, // so you must allocate a new page for the child's user exception stack. // envid_t fork(void) { // LAB 4: Your code here. set_pgfault_handler(pgfault); int r, childid; childid = sys_exofork(); if (childid <0) panic("exofork error in fork()!\n"); else if (childid ==0) { thisenv = &envs[ENVX(sys_getenvid())]; return 0; } else { int addr; for (addr = UTEXT; addr<UXSTACKTOP-PGSIZE; addr+=PGSIZE) { int pn = PGNUM(addr); if (((uvpd[PDX(addr)] & PTE_P) >0) && ((uvpt[pn] & PTE_P) >0) && ((uvpt[pn] & PTE_U) > 0)) duppage(childid, pn); } extern void _pgfault_upcall(); sys_page_alloc(childid, (void*) (UXSTACKTOP - PGSIZE), PTE_U|PTE_W|PTE_P); sys_env_set_pgfault_upcall(childid, _pgfault_upcall); sys_env_set_status(childid, ENV_RUNNABLE); return childid; } }
void _main(void) { int envID = sys_getenvid(); // cprintf("envID = %d\n",envID); volatile struct Env* myEnv; myEnv = &(envs[envID]); //("STEP 0: checking Initial WS entries ...\n"); { if( ROUNDDOWN(myEnv->__uptr_pws[0].virtual_address,PAGE_SIZE) != 0x200000) panic("INITIAL PAGE WS entry checking failed! Review size of the WS..!!"); if( ROUNDDOWN(myEnv->__uptr_pws[1].virtual_address,PAGE_SIZE) != 0x201000) panic("INITIAL PAGE WS entry checking failed! Review size of the WS..!!"); if( ROUNDDOWN(myEnv->__uptr_pws[2].virtual_address,PAGE_SIZE) != 0x202000) panic("INITIAL PAGE WS entry checking failed! Review size of the WS..!!"); if( ROUNDDOWN(myEnv->__uptr_pws[3].virtual_address,PAGE_SIZE) != 0x203000) panic("INITIAL PAGE WS entry checking failed! Review size of the WS..!!"); if( ROUNDDOWN(myEnv->__uptr_pws[4].virtual_address,PAGE_SIZE) != 0x204000) panic("INITIAL PAGE WS entry checking failed! Review size of the WS..!!"); if( ROUNDDOWN(myEnv->__uptr_pws[5].virtual_address,PAGE_SIZE) != 0x205000) panic("INITIAL PAGE WS entry checking failed! Review size of the WS..!!"); if( ROUNDDOWN(myEnv->__uptr_pws[6].virtual_address,PAGE_SIZE) != 0x800000) panic("INITIAL PAGE WS entry checking failed! Review size of the WS..!!"); if( ROUNDDOWN(myEnv->__uptr_pws[7].virtual_address,PAGE_SIZE) != 0x801000) panic("INITIAL PAGE WS entry checking failed! Review size of the WS..!!"); if( ROUNDDOWN(myEnv->__uptr_pws[8].virtual_address,PAGE_SIZE) != 0xeebfd000) panic("INITIAL PAGE WS entry checking failed! Review size of the WS..!!"); if( myEnv->page_last_WS_index != 0) panic("INITIAL PAGE WS last index checking failed! Review size of the WS..!!"); } int freePages = sys_calculate_free_frames(); int usedDiskPages = sys_pf_calculate_allocated_pages(); //Reading (Not Modified) char garbage1 = arr[PAGE_SIZE*11-1]; char garbage2 = arr[PAGE_SIZE*12-1]; //Writing (Modified) int i; for (i = 0 ; i < PAGE_SIZE*10 ; i+=PAGE_SIZE/2) { arr[i] = -1 ; *ptr = *ptr2 ; ptr++ ; ptr2++ ; } //=================== //cprintf("Checking PAGE FIFO algorithm... \n"); { if( ROUNDDOWN(myEnv->__uptr_pws[0].virtual_address,PAGE_SIZE) != 0x801000) panic("Page FIFO algo failed.. trace it by printing WS before and after page fault"); if( ROUNDDOWN(myEnv->__uptr_pws[1].virtual_address,PAGE_SIZE) != 0xeebfd000) panic("Page FIFO algo failed.. trace it by printing WS before and after page fault"); if( ROUNDDOWN(myEnv->__uptr_pws[2].virtual_address,PAGE_SIZE) != 0x809000) panic("Page FIFO algo failed.. trace it by printing WS before and after page fault"); if( ROUNDDOWN(myEnv->__uptr_pws[3].virtual_address,PAGE_SIZE) != 0x803000) panic("Page FIFO algo failed.. trace it by printing WS before and after page fault"); if( ROUNDDOWN(myEnv->__uptr_pws[4].virtual_address,PAGE_SIZE) != 0x804000) panic("Page FIFO algo failed.. trace it by printing WS before and after page fault"); if( ROUNDDOWN(myEnv->__uptr_pws[5].virtual_address,PAGE_SIZE) != 0x80a000) panic("Page FIFO algo failed.. trace it by printing WS before and after page fault"); if( ROUNDDOWN(myEnv->__uptr_pws[6].virtual_address,PAGE_SIZE) != 0x80b000) panic("Page FIFO algo failed.. trace it by printing WS before and after page fault"); if( ROUNDDOWN(myEnv->__uptr_pws[7].virtual_address,PAGE_SIZE) != 0x80c000) panic("Page FIFO algo failed.. trace it by printing WS before and after page fault"); if( ROUNDDOWN(myEnv->__uptr_pws[8].virtual_address,PAGE_SIZE) != 0x800000) panic("Page FIFO algo failed.. trace it by printing WS before and after page fault"); if(myEnv->page_last_WS_index != 2) panic("wrong PAGE WS pointer location"); } cprintf("Congratulations!! test PAGE replacement [FIFO Alg.] is completed successfully.\n"); return; }
// Dispatches to the correct kernel function, passing the arguments. int32_t syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. curenv->env_syscalls++; switch(syscallno){ case SYS_cputs: sys_cputs((char *)a1, (size_t)a2);break; case SYS_cgetc: sys_cgetc();break; case SYS_getenvid: return sys_getenvid(); case SYS_env_destroy: return sys_env_destroy((envid_t)a1); case SYS_dump_env: sys_dump_env();break; case SYS_page_alloc: return sys_page_alloc((envid_t)a1, (void *)a2, (int)a3); case SYS_page_map: { return sys_page_map((envid_t)a1, (void *)a2, (envid_t)a3, (void *)a4, (int)a5); } case SYS_page_unmap: return sys_page_unmap((envid_t)a1, (void *)a2); case SYS_exofork: return sys_exofork(); case SYS_env_set_status: return sys_env_set_status((envid_t)a1,(int)a2); case SYS_env_set_trapframe: return sys_env_set_trapframe((envid_t)a1, (struct Trapframe *)a2); case SYS_env_set_pgfault_upcall: return sys_env_set_pgfault_upcall((envid_t)a1, (void *)a2); case SYS_yield: sys_yield();break;//new add syscall for lab4; case SYS_ipc_try_send: return sys_ipc_try_send((envid_t)a1, (uint32_t)a2, (void *)a3, (unsigned)a4); case SYS_ipc_recv: return sys_ipc_recv((void *)a1); case SYS_ide_read: sys_ide_read((uint32_t)a1, (void *)a2, (size_t)a3); break; case SYS_ide_write: sys_ide_write((uint32_t)a1, (void *)a2, (size_t)a3); break; case SYS_time_msec: return sys_time_msec(); case NSYSCALLS: break; default: return -E_INVAL; } return 0; //panic("syscall not implemented"); }
void umain(int argc, char **argv) { uint32_t i=0; for(i=0;i<3;i++) cprintf("[%8x] Priority Middle is Running!\n",sys_getenvid()); return; }
void forktree(const char *cur) { cprintf("%04x: I am '%s'\n", sys_getenvid(), cur); forkchild(cur, '0'); forkchild(cur, '1'); }
// // User-level fork with copy-on-write. // Set up our page fault handler appropriately. // Create a child. // Copy our address space and page fault handler setup to the child. // Then mark the child as runnable and return. // // Returns: child's envid to the parent, 0 to the child, < 0 on error. // It is also OK to panic on error. // // Hint: // Use vpd, vpt, and duppage. // Remember to fix "thisenv" in the child process. // Neither user exception stack should ever be marked copy-on-write, // so you must allocate a new page for the child's user exception stack. // envid_t fork(void) { // LAB 4: Your code here. int r; envid_t envid; set_pgfault_handler(pgfault); if((envid = sys_exofork())<0) panic("sys_exofork error: %e\n",envid); if(envid == 0){ thisenv = &envs[ENVX(sys_getenvid())]; return 0; } uint32_t vaddr; extern unsigned char end[]; for (vaddr = 0 ; vaddr < UTOP; vaddr += PGSIZE ){ //Check sequentially if ((vpml4e[VPML4E(vaddr)] & PTE_P ) && (vpde[VPDPE(vaddr)] & PTE_P ) && (vpd[VPD(vaddr)] & PTE_P ) && (vpt[VPN(vaddr)] & PTE_P)){ //Order is imp... if ((vaddr != (UXSTACKTOP - PGSIZE)) && (vaddr != (USTACKTOP - PGSIZE))){ duppage(envid, (uint64_t)vaddr / PGSIZE); } } } if ((r = sys_page_alloc(envid,(void*)(USTACKTOP - PGSIZE), PTE_U | PTE_W | PTE_P ))<0){ panic("error from sys_page_alloc: %e\n", r); } else { if ((r = sys_page_alloc(0, PFTEMP, PTE_U|PTE_W|PTE_P)) < 0) panic("error from sys_page_alloc: %e", r); memmove(PFTEMP, (void *)(USTACKTOP - PGSIZE), PGSIZE); if ((r = sys_page_map(0,PFTEMP, envid, (void *)(USTACKTOP - PGSIZE) , PTE_U|PTE_W|PTE_P)) < 0) panic("error from sys_page_map: %e", r); } if((r = sys_page_alloc(envid,(void*)(UXSTACKTOP - PGSIZE), PTE_U | PTE_W | PTE_P ))<0) panic("error from sys_page_alloc : %e\n",r); if((r=sys_env_set_pgfault_upcall(envid, thisenv->env_pgfault_upcall))!=0) panic("error from sys_env_set_pgfault_upcall : %e\n",r); if((r = sys_env_set_status(envid, ENV_RUNNABLE))<0) panic("error from sys_env_set_status : %e\n",r); return envid; }
void _main(void) { int envID = sys_getenvid(); volatile struct Env* myEnv; myEnv = &(envs[envID]); int Mega = 1024*1024; int kilo = 1024; char minByte = 1<<7; char maxByte = 0x7F; short minShort = 1<<15 ; short maxShort = 0x7FFF; int minInt = 1<<31 ; int maxInt = 0x7FFFFFFF; void* ptr_allocations[20] = {0}; { ptr_allocations[0] = malloc(2*Mega-kilo); char *byteArr = (char *) ptr_allocations[0]; int lastIndexOfByte = (2*Mega-kilo)/sizeof(char) - 1; byteArr[0] = minByte ; byteArr[lastIndexOfByte] = maxByte ; ptr_allocations[1] = malloc(2*Mega-kilo); short *shortArr = (short *) ptr_allocations[1]; int lastIndexOfShort = (2*Mega-kilo)/sizeof(short) - 1; shortArr[0] = minShort; shortArr[lastIndexOfShort] = maxShort; ptr_allocations[2] = malloc(2*kilo); int *intArr = (int *) ptr_allocations[2]; int lastIndexOfInt = (2*kilo)/sizeof(int) - 1; intArr[0] = minInt; intArr[lastIndexOfInt] = maxInt; ptr_allocations[3] = malloc(7*kilo); struct MyStruct *structArr = (struct MyStruct *) ptr_allocations[3]; int lastIndexOfStruct = (7*kilo)/sizeof(struct MyStruct) - 1; structArr[0].a = minByte; structArr[0].b = minShort; structArr[0].c = minInt; structArr[lastIndexOfStruct].a = maxByte; structArr[lastIndexOfStruct].b = maxShort; structArr[lastIndexOfStruct].c = maxInt; //Check that the values are successfully stored if (byteArr[0] != minByte || byteArr[lastIndexOfByte] != maxByte) panic("Wrong allocation: stored values are wrongly changed!"); if (shortArr[0] != minShort || shortArr[lastIndexOfShort] != maxShort) panic("Wrong allocation: stored values are wrongly changed!"); if (intArr[0] != minInt || intArr[lastIndexOfInt] != maxInt) panic("Wrong allocation: stored values are wrongly changed!"); if (structArr[0].a != minByte || structArr[lastIndexOfStruct].a != maxByte) panic("Wrong allocation: stored values are wrongly changed!"); if (structArr[0].b != minShort || structArr[lastIndexOfStruct].b != maxShort) panic("Wrong allocation: stored values are wrongly changed!"); if (structArr[0].c != minInt || structArr[lastIndexOfStruct].c != maxInt) panic("Wrong allocation: stored values are wrongly changed!"); } cprintf("Congratulations!! test malloc (2) completed successfully.\n"); return; }
// // Custom page fault handler - if faulting page is copy-on-write, // map in our own private writable copy. // static void pgfault(struct UTrapframe *utf) { void *addr = (void *) utf->utf_fault_va; uint32_t err = utf->utf_err; int r; // Check that the faulting access was (1) a write, and (2) to a // copy-on-write page. If not, panic. // Hint: // Use the read-only page table mappings at vpt // (see <inc/memlayout.h>). // LAB 4: Your code here. // seanyliu if (!(err & FEC_WR) || !(vpt[VPN(addr)] & PTE_COW)) { panic("pgfault, err != FEC_WR or not copy-on-write page"); } // Allocate a new page, map it at a temporary location (PFTEMP), // copy the data from the old page to the new page, then move the new // page to the old page's address. // Hint: // You should make three system calls. // No need to explicitly delete the old page's mapping. // LAB 4: Your code here. // seanyliu addr = ROUNDDOWN(addr, PGSIZE); // Allocate a new page, map it at a temporary location (PFTEMP), if ((r = sys_page_alloc(sys_getenvid(), (void *)PFTEMP, PTE_U | PTE_W | PTE_P)) < 0) { panic("pgfault: sys_page_alloc %d", r); } // copy the data from the old page to the new page memmove(PFTEMP, addr, PGSIZE); // move the new page to the old page's address. if ((r = sys_page_map(sys_getenvid(), PFTEMP, sys_getenvid(), addr, PTE_U | PTE_W | PTE_P)) < 0) { panic("pgfault: sys_page_map %d", r); } if ((r = sys_page_unmap(sys_getenvid(), PFTEMP)) < 0) { panic("pgfault: sys_page_unmap %d", r); } //panic("pgfault not implemented"); }
// // Set the page fault handler function. // If there isn't one yet, _pgfault_handler will be 0. // The first time we register a handler, we need to // allocate an exception stack (one page of memory with its top // at UXSTACKTOP), and tell the kernel to call the assembly-language // _pgfault_upcall routine when a page fault occurs. // void set_pgfault_handler(void (*handler)(struct UTrapframe *utf)) { int r; if (_pgfault_handler == 0) { // First time through! // LAB 4: Your code here. if ((r = sys_page_alloc(sys_getenvid(), (void*)(UXSTACKTOP-PGSIZE), PTE_P|PTE_U|PTE_W)) < 0) panic("error sys_page_alloc: %e\n",r); if ((r = sys_env_set_pgfault_upcall(sys_getenvid(), _pgfault_upcall)) < 0) panic("error sys_env_set_pgfault_upcall: %e\n",r); } // Save handler pointer for assembly to call. _pgfault_handler = handler; }
// Dispatches to the correct kernel function, passing the arguments. int32_t syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. int32_t ret = -E_INVAL; switch(syscallno) { case SYS_cputs: sys_cputs((char *)a1, a2); break; case SYS_cgetc: ret = sys_cgetc(); break; case SYS_getenvid: ret = sys_getenvid(); break; case SYS_env_destroy: ret = sys_env_destroy(a1); break; case SYS_yield: sys_yield(); ret = 0; break; case SYS_map_kernel_page: ret = sys_map_kernel_page((void *)a1, (void *)a2); break; case SYS_sbrk: ret = sys_sbrk(a1); break; case SYS_exofork: ret = sys_exofork(); break; case SYS_env_set_status: ret = sys_env_set_status(a1,a2); break; case SYS_page_alloc: ret = sys_page_alloc(a1,(void*)a2,a3); break; case SYS_page_map: ret = sys_page_map(a1,(void*)a2,a3,(void*)a4,a5); break; case SYS_page_unmap: ret = sys_page_unmap(a1,(void*)a2); break; case SYS_env_set_pgfault_upcall: ret = sys_env_set_pgfault_upcall(a1,(void*)a2); break; case SYS_ipc_try_send: ret = sys_ipc_try_send(a1,a2,(void*)a3,a4); break; case SYS_ipc_recv: ret = sys_ipc_recv((void*)a1); } return ret; // panic("syscall not implemented"); }
// Dispatches to the correct kernel function, passing the arguments. int32_t syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. /* lj */ int ret = 0; switch(syscallno) { case SYS_cputs: sys_cputs((const char *)a1, a2); break; case SYS_cgetc: ret = sys_cgetc(); break; case SYS_getenvid: ret = sys_getenvid(); break; case SYS_env_destroy: ret = sys_env_destroy(a1); break; case SYS_yield: sys_yield(); break; case SYS_exofork: ret = sys_exofork(); break; case SYS_env_set_status: ret = sys_env_set_status((envid_t)a1, a2); break; case SYS_page_alloc: ret = sys_page_alloc((envid_t)a1, (void *)a2, a3); break; case SYS_page_map: ret = sys_page_map((envid_t)a1, (void *)a2, (envid_t)a3, (void *)a4, a5); break; case SYS_page_unmap: ret = sys_page_unmap((envid_t)a1, (void *)a2); break; case SYS_env_set_pgfault_upcall: ret = sys_env_set_pgfault_upcall((envid_t)a1, (void *)a2); break; case SYS_ipc_try_send: ret = sys_ipc_try_send((envid_t)a1, a2, (void *)a3, a4); break; case SYS_ipc_recv: ret = sys_ipc_recv((void *)a1); break; default: ret = -E_INVAL; break; } //panic("syscall not implemented"); //cprintf("%d return to user %d\n", syscallno, ret); return ret; }
void handler(struct UTrapframe *utf) { cprintf("\n IN FAULT DIE HANDLER \n"); void *addr = (void*)utf->utf_fault_va; uint32_t err = utf->utf_err; cprintf("i faulted at va %x, err %x\n", addr, err & 7); sys_env_destroy(sys_getenvid()); }
void umain(int argc, char **argv) { sys_env_set_priority(0, PRIORITY_SUPER); int i; int n = 3; for (i = 0; i < n; i++) { cprintf("[%08x] Super Priority Process is Running\n", sys_getenvid()); } return; }