diff --git a/lab/.dir-locals.el b/lab/.dir-locals.el new file mode 100644 index 0000000..1b46b0b --- /dev/null +++ b/lab/.dir-locals.el @@ -0,0 +1,12 @@ +((nil + (indent-tabs-mode . t) + (tab-width . 8)) + (c-mode + (c-file-style . "bsd") + (c-basic-offset . 8)) + (shell-mode + (sh-basic-offset . 8) + (sh-indentation . 8)) + (python-mode + (indent-tabs-mode . nil)) + ) diff --git a/lab/.gdbinit.tmpl b/lab/.gdbinit.tmpl new file mode 100644 index 0000000..234bb85 --- /dev/null +++ b/lab/.gdbinit.tmpl @@ -0,0 +1,30 @@ +set $lastcs = -1 + +define hook-stop + # There doesn't seem to be a good way to detect if we're in 16- or + # 32-bit mode, but we always run with CS == 8 in 32-bit mode. + if $cs == 8 || $cs == 27 + if $lastcs != 8 && $lastcs != 27 + set architecture i386 + end + x/i $pc + else + if $lastcs == -1 || $lastcs == 8 || $lastcs == 27 + set architecture i8086 + end + # Translate the segment:offset into a physical address + printf "[%4x:%4x] ", $cs, $eip + x/i $cs*16+$eip + end + set $lastcs = $cs +end + +echo + target remote localhost:1234\n +target remote localhost:1234 + +# If this fails, it's probably because your GDB doesn't support ELF. +# Look at the tools page at +# http://pdos.csail.mit.edu/6.828/2009/tools.html +# for instructions on building GDB with ELF support. +echo + symbol-file obj/kern/kernel\n +symbol-file obj/kern/kernel diff --git a/lab/.gitignore b/lab/.gitignore new file mode 100644 index 0000000..85c53b8 --- /dev/null +++ b/lab/.gitignore @@ -0,0 +1,18 @@ +/obj +/jos.in +/jos.log +/jos.out +/jos.out.* +/jos.cmd +/.gdbinit +/wget.log +/qemu.pcap +/qemu.pcap.* +/qemu.out +/qemu.log +/gradelib.pyc +/lab*-handin.tar.gz +/lab?/ +/sol?/ +/myapi.key +/.suf diff --git a/lab/GNUmakefile b/lab/GNUmakefile index c7e8242..2b85d1d 100644 --- a/lab/GNUmakefile +++ b/lab/GNUmakefile @@ -141,6 +141,7 @@ include boot/Makefrag include kern/Makefrag include lib/Makefrag include user/Makefrag +include fs/Makefrag CPUS ?= 1 @@ -149,6 +150,8 @@ QEMUOPTS = -drive file=$(OBJDIR)/kern/kernel.img,index=0,media=disk,format=raw - QEMUOPTS += $(shell if $(QEMU) -nographic -help | grep -q '^-D '; then echo '-D qemu.log'; fi) IMAGES = $(OBJDIR)/kern/kernel.img QEMUOPTS += -smp $(CPUS) +QEMUOPTS += -drive file=$(OBJDIR)/fs/fs.img,index=1,media=disk,format=raw +IMAGES += $(OBJDIR)/fs/fs.img QEMUOPTS += $(QEMUEXTRA) .gdbinit: .gdbinit.tmpl diff --git a/lab/LAB4.si4project/Backup/dumbfork(162).c b/lab/LAB4.si4project/Backup/dumbfork(162).c deleted file mode 100644 index e5e433c..0000000 --- a/lab/LAB4.si4project/Backup/dumbfork(162).c +++ /dev/null @@ -1,80 +0,0 @@ -// Ping-pong a counter between two processes. -// Only need to start one of these -- splits into two, crudely. - -#include -#include - -envid_t dumbfork(void); - -void -umain(int argc, char **argv) -{ - envid_t who; - int i; - - // fork a child process - who = dumbfork(); - - // print a message and yield to the other a few times - for (i = 0; i < (who ? 10 : 20); i++) { - cprintf("%d: I am the %s!\n", i, who ? "parent" : "child"); - sys_yield(); - } -} - -void -duppage(envid_t dstenv, void *addr) -{ - int r; - - // This is NOT what you should do in your fork. - if ((r = sys_page_alloc(dstenv, addr, PTE_P|PTE_U|PTE_W)) < 0) - panic("sys_page_alloc: %e", r); - if ((r = sys_page_map(dstenv, addr, 0, UTEMP, PTE_P|PTE_U|PTE_W)) < 0) - panic("sys_page_map: %e", r); - memmove(UTEMP, addr, PGSIZE); - if ((r = sys_page_unmap(0, UTEMP)) < 0) - panic("sys_page_unmap: %e", r); -} - -envid_t -dumbfork(void) -{ - envid_t envid; - uint8_t *addr; - int r; - extern unsigned char end[]; - - // Allocate a new child environment. - // The kernel will initialize it with a copy of our register state, - // so that the child will appear to have called sys_exofork() too - - // except that in the child, this "fake" call to sys_exofork() - // will return 0 instead of the envid of the child. - 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; - } - - // We're the parent. - // Eagerly copy our entire address space into the child. - // This is NOT what you should do in your fork implementation. - for (addr = (uint8_t*) UTEXT; addr < end; addr += PGSIZE) - duppage(envid, addr); - - // Also copy the stack we are currently running on. - duppage(envid, ROUNDDOWN(&addr, PGSIZE)); - - // Start the child environment running - if ((r = sys_env_set_status(envid, ENV_RUNNABLE)) < 0) - panic("sys_env_set_status: %e", r); - - return envid; -} - diff --git a/lab/LAB4.si4project/Backup/dumbfork(7443).c b/lab/LAB4.si4project/Backup/dumbfork(7443).c deleted file mode 100644 index e5e433c..0000000 --- a/lab/LAB4.si4project/Backup/dumbfork(7443).c +++ /dev/null @@ -1,80 +0,0 @@ -// Ping-pong a counter between two processes. -// Only need to start one of these -- splits into two, crudely. - -#include -#include - -envid_t dumbfork(void); - -void -umain(int argc, char **argv) -{ - envid_t who; - int i; - - // fork a child process - who = dumbfork(); - - // print a message and yield to the other a few times - for (i = 0; i < (who ? 10 : 20); i++) { - cprintf("%d: I am the %s!\n", i, who ? "parent" : "child"); - sys_yield(); - } -} - -void -duppage(envid_t dstenv, void *addr) -{ - int r; - - // This is NOT what you should do in your fork. - if ((r = sys_page_alloc(dstenv, addr, PTE_P|PTE_U|PTE_W)) < 0) - panic("sys_page_alloc: %e", r); - if ((r = sys_page_map(dstenv, addr, 0, UTEMP, PTE_P|PTE_U|PTE_W)) < 0) - panic("sys_page_map: %e", r); - memmove(UTEMP, addr, PGSIZE); - if ((r = sys_page_unmap(0, UTEMP)) < 0) - panic("sys_page_unmap: %e", r); -} - -envid_t -dumbfork(void) -{ - envid_t envid; - uint8_t *addr; - int r; - extern unsigned char end[]; - - // Allocate a new child environment. - // The kernel will initialize it with a copy of our register state, - // so that the child will appear to have called sys_exofork() too - - // except that in the child, this "fake" call to sys_exofork() - // will return 0 instead of the envid of the child. - 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; - } - - // We're the parent. - // Eagerly copy our entire address space into the child. - // This is NOT what you should do in your fork implementation. - for (addr = (uint8_t*) UTEXT; addr < end; addr += PGSIZE) - duppage(envid, addr); - - // Also copy the stack we are currently running on. - duppage(envid, ROUNDDOWN(&addr, PGSIZE)); - - // Start the child environment running - if ((r = sys_env_set_status(envid, ENV_RUNNABLE)) < 0) - panic("sys_env_set_status: %e", r); - - return envid; -} - diff --git a/lab/LAB4.si4project/Backup/dumbfork(8040).c b/lab/LAB4.si4project/Backup/dumbfork(8040).c deleted file mode 100644 index 281f4bf..0000000 --- a/lab/LAB4.si4project/Backup/dumbfork(8040).c +++ /dev/null @@ -1,89 +0,0 @@ -// Ping-pong a counter between two processes. -// Only need to start one of these -- splits into two, crudely. - -#include -#include - -envid_t dumbfork(void); - -void -umain(int argc, char **argv) -{ - envid_t who; - int i; - - // fork a child process - who = dumbfork(); - - // print a message and yield to the other a few times - for (i = 0; i < (who ? 10 : 20); i++) { - cprintf("%d: I am the %s!\n", i, who ? "parent" : "child"); - sys_yield(); - } -} - -void -duppage(envid_t dstenv, void *addr) -{ - int r; - - // This is NOT what you should do in your fork. - if ((r = sys_page_alloc(dstenv, addr, PTE_P|PTE_U|PTE_W)) < 0) - panic("sys_page_alloc: %e", r); - // dstenv 的 addr 映射到 envs[0]的UTEMP, - if ((r = sys_page_map(dstenv, addr, 0, UTEMP, PTE_P|PTE_U|PTE_W)) < 0) - panic("sys_page_map: %e", r); - - memmove(UTEMP, addr, PGSIZE); - if ((r = sys_page_unmap(0, UTEMP)) < 0) - panic("sys_page_unmap: %e", r); -} - -envid_t -dumbfork(void) -{ - envid_t envid; - uint8_t *addr; - int r; - extern unsigned char end[]; - - // Allocate a new child environment. - // The kernel will initialize it with a copy of our register state, - // so that the child will appear to have called sys_exofork() too - - // except that in the child, this "fake" call to sys_exofork() - // will return 0 instead of the envid of the child. - envid = sys_exofork(); - cprintf("envid: %d\n",envid); - 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. - // "child, sysgetenvid() : 1 - // cprintf("child, sysgetenvid() :%d\n", ENVX(sys_getenvid())); - thisenv = &envs[ENVX(sys_getenvid())]; - return 0; - } - - // We're the parent. - // Eagerly copy our entire address space into the child. - // This is NOT what you should do in your fork implementation. - for (addr = (uint8_t*) UTEXT; addr < end; addr += PGSIZE) { - // copying addr :00800000 - // copying addr :00801000 - // copying addr :00802000 - cprintf("copying addr :%08x\n", (uint32_t)addr); - duppage(envid, addr); - } - // Also copy the stack we are currently running on. - duppage(envid, ROUNDDOWN(&addr, PGSIZE)); - - // Start the child environment running - if ((r = sys_env_set_status(envid, ENV_RUNNABLE)) < 0) - panic("sys_env_set_status: %e", r); - - return envid; -} - diff --git a/lab/LAB4.si4project/Backup/entry(6508).S b/lab/LAB4.si4project/Backup/entry(6508).S deleted file mode 100644 index 222d16c..0000000 --- a/lab/LAB4.si4project/Backup/entry(6508).S +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -.data -// Define the global symbols 'envs', 'pages', 'uvpt', and 'uvpd' -// so that they can be used in C as if they were ordinary global arrays. - .globl envs - .set envs, UENVS - .globl pages - .set pages, UPAGES - .globl uvpt - .set uvpt, UVPT - .globl uvpd - .set uvpd, (UVPT+(UVPT>>12)*4) - - -// Entrypoint - this is where the kernel (or our parent environment) -// starts us running when we are initially loaded into a new environment. -.text -.globl _start -_start: - // See if we were started with arguments on the stack - cmpl $USTACKTOP, %esp - jne args_exist - - // If not, push dummy argc/argv arguments. - // This happens when we are loaded by the kernel, - // because the kernel does not know about passing arguments. - pushl $0 - pushl $0 - -args_exist: - call libmain -1: jmp 1b - diff --git a/lab/LAB4.si4project/Backup/env(4388).h b/lab/LAB4.si4project/Backup/env(4388).h deleted file mode 100644 index b04f1a3..0000000 --- a/lab/LAB4.si4project/Backup/env(4388).h +++ /dev/null @@ -1,70 +0,0 @@ -/* See COPYRIGHT for copyright information. */ - -#ifndef JOS_INC_ENV_H -#define JOS_INC_ENV_H - -#include -#include -#include - -typedef int32_t envid_t; - -// An environment ID 'envid_t' has three parts: -// -// +1+---------------21-----------------+--------10--------+ -// |0| Uniqueifier | Environment | -// | | | Index | -// +------------------------------------+------------------+ -// \--- ENVX(eid) --/ -// -// The environment index ENVX(eid) equals the environment's index in the -// 'envs[]' array. The uniqueifier distinguishes environments that were -// created at different times, but share the same environment index. -// -// All real environments are greater than 0 (so the sign bit is zero). -// envid_ts less than 0 signify errors. The envid_t == 0 is special, and -// stands for the current environment. - -#define LOG2NENV 10 -#define NENV (1 << LOG2NENV) -#define ENVX(envid) ((envid) & (NENV - 1)) - -// Values of env_status in struct Env -enum { - ENV_FREE = 0, - ENV_DYING, - ENV_RUNNABLE, - ENV_RUNNING, - ENV_NOT_RUNNABLE -}; - -// Special environment types -enum EnvType { - ENV_TYPE_USER = 0, -}; - -struct Env { - struct Trapframe env_tf; // Saved registers - struct Env *env_link; // Next free Env - envid_t env_id; // Unique environment identifier - envid_t env_parent_id; // env_id of this env's parent - enum EnvType env_type; // Indicates special system environments - unsigned env_status; // Status of the environment - uint32_t env_runs; // Number of times environment has run - int env_cpunum; // The CPU that the env is running on - - // Address space - pde_t *env_pgdir; // Kernel virtual address of page dir - - // Exception handling - void *env_pgfault_upcall; // Page fault upcall entry point - - // Lab 4 IPC - bool env_ipc_recving; // Env is blocked receiving - void *env_ipc_dstva; // VA at which to map received page - uint32_t env_ipc_value; // Data value sent to us - envid_t env_ipc_from; // envid of the sender - int env_ipc_perm; // Perm of page mapping received -}; - -#endif // !JOS_INC_ENV_H diff --git a/lab/LAB4.si4project/Backup/fork(3728).c b/lab/LAB4.si4project/Backup/fork(3728).c deleted file mode 100644 index 61264da..0000000 --- a/lab/LAB4.si4project/Backup/fork(3728).c +++ /dev/null @@ -1,90 +0,0 @@ -// implement fork from user space - -#include -#include - -// PTE_COW marks copy-on-write page table entries. -// It is one of the bits explicitly allocated to user processes (PTE_AVAIL). -#define PTE_COW 0x800 - -// -// 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 uvpt - // (see ). - - // LAB 4: Your code here. - - // 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. - - // LAB 4: Your code here. - - panic("pgfault not implemented"); -} - -// -// Map our virtual page pn (address pn*PGSIZE) into the target envid -// at the same virtual address. If the page is writable or copy-on-write, -// the new mapping must be created copy-on-write, and then our mapping must be -// marked copy-on-write as well. (Exercise: Why do we need to mark ours -// copy-on-write again if it was already copy-on-write at the beginning of -// this function?) -// -// Returns: 0 on success, < 0 on error. -// It is also OK to panic on error. -// -static int -duppage(envid_t envid, unsigned pn) -{ - int r; - - // LAB 4: Your code here. - panic("duppage not implemented"); - return 0; -} - -// -// 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. - panic("fork not implemented"); -} - -// Challenge! -int -sfork(void) -{ - panic("sfork not implemented"); - return -E_INVAL; -} diff --git a/lab/LAB4.si4project/Backup/ipc(963).c b/lab/LAB4.si4project/Backup/ipc(963).c deleted file mode 100644 index 2e222b9..0000000 --- a/lab/LAB4.si4project/Backup/ipc(963).c +++ /dev/null @@ -1,56 +0,0 @@ -// User-level IPC library routines - -#include - -// Receive a value via IPC and return it. -// If 'pg' is nonnull, then any page sent by the sender will be mapped at -// that address. -// If 'from_env_store' is nonnull, then store the IPC sender's envid in -// *from_env_store. -// If 'perm_store' is nonnull, then store the IPC sender's page permission -// in *perm_store (this is nonzero iff a page was successfully -// transferred to 'pg'). -// If the system call fails, then store 0 in *fromenv and *perm (if -// they're nonnull) and return the error. -// Otherwise, return the value sent by the sender -// -// Hint: -// Use 'thisenv' to discover the value and who sent it. -// If 'pg' is null, pass sys_ipc_recv a value that it will understand -// as meaning "no page". (Zero is not the right value, since that's -// a perfectly valid place to map a page.) -int32_t -ipc_recv(envid_t *from_env_store, void *pg, int *perm_store) -{ - // LAB 4: Your code here. - panic("ipc_recv not implemented"); - return 0; -} - -// Send 'val' (and 'pg' with 'perm', if 'pg' is nonnull) to 'toenv'. -// This function keeps trying until it succeeds. -// It should panic() on any error other than -E_IPC_NOT_RECV. -// -// Hint: -// Use sys_yield() to be CPU-friendly. -// If 'pg' is null, pass sys_ipc_try_send a value that it will understand -// as meaning "no page". (Zero is not the right value.) -void -ipc_send(envid_t to_env, uint32_t val, void *pg, int perm) -{ - // LAB 4: Your code here. - panic("ipc_send not implemented"); -} - -// Find the first environment of the given type. We'll use this to -// find special environments. -// Returns 0 if no such environment exists. -envid_t -ipc_find_env(enum EnvType type) -{ - int i; - for (i = 0; i < NENV; i++) - if (envs[i].env_type == type) - return envs[i].env_id; - return 0; -} diff --git a/lab/LAB4.si4project/Backup/pfentry(173).S b/lab/LAB4.si4project/Backup/pfentry(173).S deleted file mode 100644 index f40aeeb..0000000 --- a/lab/LAB4.si4project/Backup/pfentry(173).S +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include - -// Page fault upcall entrypoint. - -// This is where we ask the kernel to redirect us to whenever we cause -// a page fault in user space (see the call to sys_set_pgfault_handler -// in pgfault.c). -// -// When a page fault actually occurs, the kernel switches our ESP to -// point to the user exception stack if we're not already on the user -// exception stack, and then it pushes a UTrapframe onto our user -// exception stack: -// -// trap-time esp -// trap-time eflags -// trap-time eip -// utf_regs.reg_eax -// ... -// utf_regs.reg_esi -// utf_regs.reg_edi -// utf_err (error code) -// utf_fault_va <-- %esp -// -// If this is a recursive fault, the kernel will reserve for us a -// blank word above the trap-time esp for scratch work when we unwind -// the recursive call. -// -// We then have call up to the appropriate page fault handler in C -// code, pointed to by the global variable '_pgfault_handler'. - -.text -.globl _pgfault_upcall -_pgfault_upcall: - // Call the C page fault handler. - pushl %esp // function argument: pointer to UTF - movl _pgfault_handler, %eax - call *%eax - addl $4, %esp // pop function argument - - // Now the C page fault handler has returned and you must return - // to the trap time state. - // Push trap-time %eip onto the trap-time stack. - // - // Explanation: - // We must prepare the trap-time stack for our eventual return to - // re-execute the instruction that faulted. - // Unfortunately, we can't return directly from the exception stack: - // We can't call 'jmp', since that requires that we load the address - // into a register, and all registers must have their trap-time - // values after the return. - // We can't call 'ret' from the exception stack either, since if we - // did, %esp would have the wrong value. - // So instead, we push the trap-time %eip onto the *trap-time* stack! - // Below we'll switch to that stack and call 'ret', which will - // restore %eip to its pre-fault value. - // - // In the case of a recursive fault on the exception stack, - // note that the word we're pushing now will fit in the - // blank word that the kernel reserved for us. - // - // Throughout the remaining code, think carefully about what - // registers are available for intermediate calculations. You - // may find that you have to rearrange your code in non-obvious - // ways as registers become unavailable as scratch space. - // - // LAB 4: Your code here. - - // Restore the trap-time registers. After you do this, you - // can no longer modify any general-purpose registers. - // LAB 4: Your code here. - - // Restore eflags from the stack. After you do this, you can - // no longer use arithmetic operations or anything else that - // modifies eflags. - // LAB 4: Your code here. - - // Switch back to the adjusted trap-time stack. - // LAB 4: Your code here. - - // Return to re-execute the instruction that faulted. - // LAB 4: Your code here. diff --git a/lab/LAB4.si4project/Backup/pgfault(4647).c b/lab/LAB4.si4project/Backup/pgfault(4647).c deleted file mode 100644 index a975518..0000000 --- a/lab/LAB4.si4project/Backup/pgfault(4647).c +++ /dev/null @@ -1,37 +0,0 @@ -// User-level page fault handler support. -// Rather than register the C page fault handler directly with the -// kernel as the page fault handler, we register the assembly language -// wrapper in pfentry.S, which in turns calls the registered C -// function. - -#include - - -// Assembly language pgfault entrypoint defined in lib/pfentry.S. -extern void _pgfault_upcall(void); - -// Pointer to currently installed C-language pgfault handler. -void (*_pgfault_handler)(struct UTrapframe *utf); - -// -// 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. - panic("set_pgfault_handler not implemented"); - } - - // Save handler pointer for assembly to call. - _pgfault_handler = handler; -} diff --git a/lab/LAB4.si4project/Backup/picirq(7101).c b/lab/LAB4.si4project/Backup/picirq(7101).c deleted file mode 100644 index 8cb3e62..0000000 --- a/lab/LAB4.si4project/Backup/picirq(7101).c +++ /dev/null @@ -1,86 +0,0 @@ -/* See COPYRIGHT for copyright information. */ - -#include -#include - -#include - - -// Current IRQ mask. -// Initial IRQ mask has interrupt 2 enabled (for slave 8259A). -uint16_t irq_mask_8259A = 0xFFFF & ~(1<> 8)); - cprintf("enabled interrupts:"); - for (i = 0; i < 16; i++) - if (~mask & (1< -#include -#include -#include -#include - -#include -#include -#include -#include - -// These variables are set by i386_detect_memory() -size_t npages; // Amount of physical memory (in pages) -static size_t npages_basemem; // Amount of base memory (in pages) - -// These variables are set in mem_init() -pde_t *kern_pgdir; // Kernel's initial page directory -struct PageInfo *pages; // Physical page state array -static struct PageInfo *page_free_list; // Free list of physical pages - - -// -------------------------------------------------------------- -// Detect machine's physical memory setup. -// -------------------------------------------------------------- - -static int -nvram_read(int r) -{ - return mc146818_read(r) | (mc146818_read(r + 1) << 8); -} - -static void -i386_detect_memory(void) -{ - size_t basemem, extmem, ext16mem, totalmem; - - // Use CMOS calls to measure available base & extended memory. - // (CMOS calls return results in kilobytes.) - basemem = nvram_read(NVRAM_BASELO); - extmem = nvram_read(NVRAM_EXTLO); - ext16mem = nvram_read(NVRAM_EXT16LO) * 64; - - // Calculate the number of physical pages available in both base - // and extended memory. - if (ext16mem) - totalmem = 16 * 1024 + ext16mem; - else if (extmem) - totalmem = 1 * 1024 + extmem; - else - totalmem = basemem; - - npages = totalmem / (PGSIZE / 1024); - npages_basemem = basemem / (PGSIZE / 1024); - - cprintf("Physical memory: %uK available, base = %uK, extended = %uK\n", - totalmem, basemem, totalmem - basemem); -} - - -// -------------------------------------------------------------- -// Set up memory mappings above UTOP. -// -------------------------------------------------------------- - -static void mem_init_mp(void); -static void boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm); -static void check_page_free_list(bool only_low_memory); -static void check_page_alloc(void); -static void check_kern_pgdir(void); -static physaddr_t check_va2pa(pde_t *pgdir, uintptr_t va); -static void check_page(void); -static void check_page_installed_pgdir(void); - -// This simple physical memory allocator is used only while JOS is setting -// up its virtual memory system. page_alloc() is the real allocator. -// -// If n>0, allocates enough pages of contiguous physical memory to hold 'n' -// bytes. Doesn't initialize the memory. Returns a kernel virtual address. -// -// If n==0, returns the address of the next free page without allocating -// anything. -// -// If we're out of memory, boot_alloc should panic. -// This function may ONLY be used during initialization, -// before the page_free_list list has been set up. -static void * -boot_alloc(uint32_t n) -{ - static char *nextfree; // virtual address of next byte of free memory - char *result; - - // Initialize nextfree if this is the first time. - // 'end' is a magic symbol automatically generated by the linker, - // which points to the end of the kernel's bss segment: - // the first virtual address that the linker did *not* assign - // to any kernel code or global variables. - if (!nextfree) { - extern char end[]; - nextfree = ROUNDUP((char *) end, PGSIZE); - } - - // Allocate a chunk large enough to hold 'n' bytes, then update - // nextfree. Make sure nextfree is kept aligned - // to a multiple of PGSIZE. - // - // LAB 2: Your code here. - result = nextfree; - nextfree = ROUNDUP(nextfree+n, PGSIZE); - - return result; -} - -// Set up a two-level page table: -// kern_pgdir is its linear (virtual) address of the root -// -// This function only sets up the kernel part of the address space -// (ie. addresses >= UTOP). The user part of the address space -// will be set up later. -// -// From UTOP to ULIM, the user is allowed to read but not write. -// Above ULIM the user cannot read or write. -void -mem_init(void) -{ - uint32_t cr0; - size_t n; - - // Find out how much memory the machine has (npages & npages_basemem). - i386_detect_memory(); - - // Remove this line when you're ready to test this function. - //panic("mem_init: This function is not finished\n"); - - ////////////////////////////////////////////////////////////////////// - // create initial page directory. - kern_pgdir = (pde_t *) boot_alloc(PGSIZE); - memset(kern_pgdir, 0, PGSIZE); - - ////////////////////////////////////////////////////////////////////// - // Recursively insert PD in itself as a page table, to form - // a virtual page table at virtual address UVPT. - // (For now, you don't have understand the greater purpose of the - // following line.) - - // Permissions: kernel R, user R - kern_pgdir[PDX(UVPT)] = PADDR(kern_pgdir) | PTE_U | PTE_P; - - ////////////////////////////////////////////////////////////////////// - // Allocate an array of npages 'struct PageInfo's and store it in 'pages'. - // The kernel uses this array to keep track of physical pages: for - // each physical page, there is a corresponding struct PageInfo in this - // array. 'npages' is the number of physical pages in memory. Use memset - // to initialize all fields of each struct PageInfo to 0. - // Your code goes here: - pages = (struct PageInfo*)boot_alloc(sizeof(struct PageInfo)*npages); - memset(pages, 0, sizeof(struct PageInfo)*npages); - - ////////////////////////////////////////////////////////////////////// - // Make 'envs' point to an array of size 'NENV' of 'struct Env'. - // LAB 3: Your code here. - envs = (struct Env*)boot_alloc(sizeof(struct Env)*NENV); - memset(envs, 0, sizeof(struct Env)*NENV); - ////////////////////////////////////////////////////////////////////// - // Now that we've allocated the initial kernel data structures, we set - // up the list of free physical pages. Once we've done so, all further - // memory management will go through the page_* functions. In - // particular, we can now map memory using boot_map_region - // or page_insert - page_init(); - - check_page_free_list(1); - check_page_alloc(); - check_page(); - - ////////////////////////////////////////////////////////////////////// - // Now we set up virtual memory - - ////////////////////////////////////////////////////////////////////// - // Map 'pages' read-only by the user at linear address UPAGES - // Permissions: - // - the new image at UPAGES -- kernel R, user R - // (ie. perm = PTE_U | PTE_P) - // - pages itself -- kernel RW, user NONE - // Your code goes here: - // 要求把pages结构体所在的页面和虚拟地址UPAGES相互映射。 - // 这里只要计算出pages结构体的大小,就可以进行映射了。 - // 说实话,之前注释有点没看懂。以为要实现虚存对pages指向的物理页的映射 - boot_map_region(kern_pgdir, - UPAGES, - ROUNDUP((sizeof(struct PageInfo)*npages), PGSIZE), - PADDR(pages), - PTE_U ); - ////////////////////////////////////////////////////////////////////// - // Map the 'envs' array read-only by the user at linear address UENVS - // (ie. perm = PTE_U | PTE_P). - // Permissions: - // - the new image at UENVS -- kernel R, user R - // - envs itself -- kernel RW, user NONE - // LAB 3: Your code here. - boot_map_region(kern_pgdir, - UENVS, - ROUNDUP((sizeof(struct Env)*NENV), PGSIZE), - PADDR(envs), - PTE_U); - ////////////////////////////////////////////////////////////////////// - // Use the physical memory that 'bootstack' refers to as the kernel - // stack. The kernel stack grows down from virtual address KSTACKTOP. - // We consider the entire range from [KSTACKTOP-PTSIZE, KSTACKTOP) - // to be the kernel stack, but break this into two pieces: - // * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory - // * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed; so if - // the kernel overflows its stack, it will fault rather than - // overwrite memory. Known as a "guard page". - // Permissions: kernel RW, user NONE - // Your code goes here: - // extern char bootstacktop[], bootstack[]; - boot_map_region(kern_pgdir, - KSTACKTOP-KSTKSIZE, - KSTKSIZE, - PADDR(bootstack), - PTE_W ); - ////////////////////////////////////////////////////////////////////// - // Map all of physical memory at KERNBASE. - // Ie. the VA range [KERNBASE, 2^32) should map to - // the PA range [0, 2^32 - KERNBASE) - // We might not have 2^32 - KERNBASE bytes of physical memory, but - // we just set up the mapping anyway. - // Permissions: kernel RW, user NONE - // Your code goes here: - uint32_t kern_size = ROUNDUP((0xFFFFFFFF-KERNBASE), PGSIZE); - // cprintf("size: %d pages:%d\n", kern_size, kern_size/PGSIZE); - boot_map_region(kern_pgdir, - (uintptr_t) KERNBASE, - kern_size, - (physaddr_t)0, - PTE_W ); - - // Initialize the SMP-related parts of the memory map - // 这部分与上面的stack映射有点重复吧。 - mem_init_mp(); - - - // Check that the initial page directory has been set up correctly. - check_kern_pgdir(); - - // Switch from the minimal entry page directory to the full kern_pgdir - // page table we just created. Our instruction pointer should be - // somewhere between KERNBASE and KERNBASE+4MB right now, which is - // mapped the same way by both page tables. - // - // If the machine reboots at this point, you've probably set up your - // kern_pgdir wrong. - lcr3(PADDR(kern_pgdir)); - - check_page_free_list(0); - - // entry.S set the really important flags in cr0 (including enabling - // paging). Here we configure the rest of the flags that we care about. - cr0 = rcr0(); - cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_MP; - cr0 &= ~(CR0_TS|CR0_EM); - lcr0(cr0); - - // Some more checks, only possible after kern_pgdir is installed. - check_page_installed_pgdir(); -} - -// Modify mappings in kern_pgdir to support SMP -// - Map the per-CPU stacks in the region [KSTACKTOP-PTSIZE, KSTACKTOP) -// -static void -mem_init_mp(void) -{ - // Map per-CPU stacks starting at KSTACKTOP, for up to 'NCPU' CPUs. - // - // For CPU i, use the physical memory that 'percpu_kstacks[i]' refers - // to as its kernel stack. CPU i's kernel stack grows down from virtual - // address kstacktop_i = KSTACKTOP - i * (KSTKSIZE + KSTKGAP), and is - // divided into two pieces, just like the single stack you set up in - // mem_init: - // * [kstacktop_i - KSTKSIZE, kstacktop_i) - // -- backed by physical memory - // * [kstacktop_i - (KSTKSIZE + KSTKGAP), kstacktop_i - KSTKSIZE) - // -- not backed; so if the kernel overflows its stack, - // it will fault rather than overwrite another CPU's stack. - // Known as a "guard page". - // Permissions: kernel RW, user NONE - // - // LAB 4: Your code here: - size_t i; - size_t kstacktop_i; - for(i = 0; i < NCPU; i++) { - kstacktop_i = KSTACKTOP - i * (KSTKSIZE + KSTKGAP); - boot_map_region(kern_pgdir, - kstacktop_i - KSTKSIZE, - KSTKSIZE, - PADDR(&percpu_kstacks[i]), - PTE_W ); - - } -} - -// -------------------------------------------------------------- -// Tracking of physical pages. -// The 'pages' array has one 'struct PageInfo' entry per physical page. -// Pages are reference counted, and free pages are kept on a linked list. -// -------------------------------------------------------------- - -// -// Initialize page structure and memory free list. -// After this is done, NEVER use boot_alloc again. ONLY use the page -// allocator functions below to allocate and deallocate physical -// memory via the page_free_list. -// -void -page_init(void) -{ - // LAB 4: - // Change your code to mark the physical page at MPENTRY_PADDR - // as in use - - // The example code here marks all physical pages as free. - // However this is not truly the case. What memory is free? - // 1) Mark physical page 0 as in use. - // This way we preserve the real-mode IDT and BIOS structures - // in case we ever need them. (Currently we don't, but...) - // 2) The rest of base memory, [PGSIZE, npages_basemem * PGSIZE) - // is free. - // 3) Then comes the IO hole [IOPHYSMEM, EXTPHYSMEM), which must - // never be allocated. - // 4) Then extended memory [EXTPHYSMEM, ...). - // Some of it is in use, some is free. Where is the kernel - // in physical memory? Which pages are already in use for - // page tables and other data structures? - // - // Change the code to reflect this. - // NB: DO NOT actually touch the physical memory corresponding to - // free pages! - - // 1.mark page 0 as in use - // 这样我们就可以保留实模式IDT和BIOS结构,以备不时之需。 - pages[0].pp_ref = 1; - - // 2. - size_t i; - for (i = 1; i < MPENTRY_PADDR/PGSIZE; i++) { - pages[i].pp_ref = 0; - pages[i].pp_link = page_free_list; - page_free_list = &pages[i]; - } - // cprintf("npage_basemem: %d\n", npages_basemem); npage_basemem:160 - // boot APs entry code - extern unsigned char mpentry_start[], mpentry_end[]; - size_t size = mpentry_end - mpentry_start; - size = ROUNDUP(size, PGSIZE); - for(;i<(MPENTRY_PADDR+size)/PGSIZE; i++) { - pages[i].pp_ref = 1; - } - - for (; i < npages_basemem; i++) { - pages[i].pp_ref = 0; - pages[i].pp_link = page_free_list; - page_free_list = &pages[i]; - } - - // 3.[IOPHYSMEM, EXTPHYSMEM) - // mark I/O hole - for (;ipp_link; - pp->pp_link = NULL; - - //page2kva 返回值 KernelBase + 物理页号<pp_ref reaches 0.) -// -void -page_free(struct PageInfo *pp) -{ - // Fill this function in - // Hint: You may want to panic if pp->pp_ref is nonzero or - // pp->pp_link is not NULL. - if(pp->pp_link || pp->pp_ref) { - panic("pp->pp_ref is nonzero or pp->pp_link is not NULL\n"); - } - pp->pp_link = page_free_list; - page_free_list = pp; -} - -// -// Decrement the reference count on a page, -// freeing it if there are no more refs. -// -void -page_decref(struct PageInfo* pp) -{ - if (--pp->pp_ref == 0) - page_free(pp); -} - -// Given 'pgdir', a pointer to a page directory, pgdir_walk returns -// a pointer to the page table entry (PTE) for linear address 'va'. -// This requires walking the two-level page table structure. -// -// The relevant page table page might not exist yet. -// If this is true, and create == false, then pgdir_walk returns NULL. -// Otherwise, pgdir_walk allocates a new page table page with page_alloc. -// - If the allocation fails, pgdir_walk returns NULL. -// - Otherwise, the new page's reference count is incremented, -// the page is cleared, -// and pgdir_walk returns a pointer into the new page table page. -// -// Hint 1: you can turn a PageInfo * into the physical address of the -// page it refers to with page2pa() from kern/pmap.h. -// -// Hint 2: the x86 MMU checks permission bits in both the page directory -// and the page table, so it's safe to leave permissions in the page -// directory more permissive than strictly necessary. -// -// Hint 3: look at inc/mmu.h for useful macros that manipulate page -// table and page directory entries. -// -pte_t * -pgdir_walk(pde_t *pgdir, const void *va, int create) -{ - // Fill this function in - uint32_t pdx = PDX(va); // 页目录项索引 - uint32_t ptx = PTX(va); // 页表项索引 - pte_t *pde; // 页目录项指针 - pte_t *pte; // 页表项指针 - struct PageInfo *pp; - - pde = &pgdir[pdx]; //获取页目录项 - - if (*pde & PTE_P) { - // 二级页表有效 - // PTE_ADDR得到物理地址,KADDR转为虚拟地址 - pte = (KADDR(PTE_ADDR(*pde))); - } - else { - - // 二级页表不存在, - if (!create) { - return NULL; - } - // 获取一页的内存,创建一个新的页表,来存放页表项 - if(!(pp = page_alloc(ALLOC_ZERO))) { - return NULL; - } - pte = (pte_t *)page2kva(pp); - pp->pp_ref++; - *pde = PADDR(pte) | (PTE_P | PTE_W | PTE_U); // 设置页目录项 - } - // 返回页表项的虚拟地址 - return &pte[ptx]; -} - -// -// Map [va, va+size) of virtual address space to physical [pa, pa+size) -// in the page table rooted at pgdir. Size is a multiple of PGSIZE, and -// va and pa are both page-aligned. -// Use permission bits perm|PTE_P for the entries. -// -// This function is only intended to set up the ``static'' mappings -// above UTOP. As such, it should *not* change the pp_ref field on the -// mapped pages. -// -// Hint: the TA solution uses pgdir_walk -static void -boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm) -{ - size_t pgs = size / PGSIZE; - if (size % PGSIZE != 0) { - pgs++; - } //计算总共有多少页 - for (int i = 0; i < pgs; i++) { - // 其实可以使用page_insert实现 - pte_t *pte = pgdir_walk(pgdir, (void *)va, 1);//获取va对应的PTE的地址 - if (pte == NULL) { - panic("boot_map_region(): out of memory\n"); - } - *pte = pa | PTE_P | perm; //修改va对应的PTE的值 - pa += PGSIZE; //更新pa和va,进行下一轮循环 - va += PGSIZE; - } -} - - -// -// Map the physical page 'pp' at virtual address 'va'. -// The permissions (the low 12 bits) of the page table entry -// should be set to 'perm|PTE_P'. -// -// Requirements -// - If there is already a page mapped at 'va', it should be page_remove()d. -// - If necessary, on demand, a page table should be allocated and inserted -// into 'pgdir'. // create -// - pp->pp_ref should be incremented if the insertion succeeds. -// - The TLB must be invalidated if a page was formerly present at 'va'. -// -// Corner-case hint: Make sure to consider what happens when the same -// pp is re-inserted at the same virtual address in the same pgdir. -// However, try not to distinguish this case in your code, as this -// frequently leads to subtle bugs; there's an elegant way to handle -// everything in one code path. -// -// RETURNS: -// 0 on success -// -E_NO_MEM, if page table couldn't be allocated -// -// Hint: The TA solution is implemented using pgdir_walk, page_remove, -// and page2pa. -// -int -page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm) -{ - // Fill this function in - pte_t *pte = pgdir_walk(pgdir, va, 1); - - if (!pte) { - - return -E_NO_MEM; - } - - if (*pte & PTE_P) { - if (PTE_ADDR(*pte) == page2pa(pp)) { - - // 插入的是同一个页面,只需要修改权限等即可 - pp->pp_ref--; - } - else { - - page_remove(pgdir, va); - } - - } - - pp->pp_ref++; - *pte = page2pa(pp)| perm | PTE_P; - - return 0; -} - -// -// Return the page mapped at virtual address 'va'. -// If pte_store is not zero, then we store in it the address -// of the pte for this page. This is used by page_remove and -// can be used to verify page permissions for syscall arguments, -// but should not be used by most callers. -// -// Return NULL if there is no page mapped at va. -// -// Hint: the TA solution uses pgdir_walk and pa2page. -// -struct PageInfo * -page_lookup(pde_t *pgdir, void *va, pte_t **pte_store) -{ - // Fill this function in - pte_t *pte = pgdir_walk(pgdir, va, 0); - if (!pte) { - - return NULL; - } - if (pte_store) { - *pte_store = pte; // 通过指针的指针返回指针给调用者 - } - - // 难道不用考虑页表项是否存在 - - if (*pte & PTE_P) { - - return (pa2page(PTE_ADDR(*pte))); - } - - return NULL; - - //return pa2page(PTE_ADDR(*pte)); -} - -// -// Unmaps the physical page at virtual address 'va'. -// If there is no physical page at that address, silently does nothing. -// -// Details: -// - The ref count on the physical page should decrement. -// - The physical page should be freed if the refcount reaches 0. -// - The pg table entry corresponding to 'va' should be set to 0. -// (if such a PTE exists) -// - The TLB must be invalidated if you remove an entry from -// the page table. -// -// Hint: The TA solution is implemented using page_lookup, -// tlb_invalidate, and page_decref. -// - -void -page_remove(pde_t *pgdir, void *va) -{ - // Fill this function in - // 二级指针有点晕 - pte_t *pte; - pte_t **pte_store = &pte; - - struct PageInfo *pi = page_lookup(pgdir, va, pte_store); - if (!pi) { - return ; - } - - page_decref(pi); // 减引用 - - **pte_store = 0; // 取消映射 - tlb_invalidate(pgdir, va); - - -} - -// -// Invalidate a TLB entry, but only if the page tables being -// edited are the ones currently in use by the processor. -// -void -tlb_invalidate(pde_t *pgdir, void *va) -{ - // Flush the entry only if we're modifying the current address space. - if (!curenv || curenv->env_pgdir == pgdir) - invlpg(va); -} - -// -// Reserve size bytes in the MMIO region and map [pa,pa+size) at this -// location. Return the base of the reserved region. size does *not* -// have to be multiple of PGSIZE. -// -void * -mmio_map_region(physaddr_t pa, size_t size) -{ - // Where to start the next region. Initially, this is the - // beginning of the MMIO region. Because this is static, its - // value will be preserved between calls to mmio_map_region - // (just like nextfree in boot_alloc). - static uintptr_t base = MMIOBASE; - - // Reserve size bytes of virtual memory starting at base and - // map physical pages [pa,pa+size) to virtual addresses - // [base,base+size). Since this is device memory and not - // regular DRAM, you'll have to tell the CPU that it isn't - // safe to cache access to this memory. Luckily, the page - // tables provide bits for this purpose; simply create the - // mapping with PTE_PCD|PTE_PWT (cache-disable and - // write-through) in addition to PTE_W. (If you're interested - // in more details on this, see section 10.5 of IA32 volume - // 3A.) - // - // Be sure to round size up to a multiple of PGSIZE and to - // handle if this reservation would overflow MMIOLIM (it's - // okay to simply panic if this happens). - // - // Hint: The staff solution uses boot_map_region. - // - // Your code here: - // ret -> MMIOBASE 暂存 - void *ret = (void *)base; - size = ROUNDUP(size, PGSIZE); - if (base + size > MMIOLIM || base + size < base) { - panic("mmio_map_region reservation overflow\n"); - } - - boot_map_region(kern_pgdir, base, size, pa, PTE_W|PTE_PCD|PTE_PWT); - // 为什么需要加以下操作? base 为static! - base += size; - return ret; -} - -static uintptr_t user_mem_check_addr; - -// -// Check that an environment is allowed to access the range of memory -// [va, va+len) with permissions 'perm | PTE_P'. -// Normally 'perm' will contain PTE_U at least, but this is not required. -// 'va' and 'len' need not be page-aligned; you must test every page that -// contains any of that range. You will test either 'len/PGSIZE', -// 'len/PGSIZE + 1', or 'len/PGSIZE + 2' pages. -// -// A user program can access a virtual address if (1) the address is below -// ULIM, and (2) the page table gives it permission. These are exactly -// the tests you should implement here. -// -// If there is an error, set the 'user_mem_check_addr' variable to the first -// erroneous virtual address. -// -// Returns 0 if the user program can access this range of addresses, -// and -E_FAULT otherwise. -// -/* -int -user_mem_check(struct Env *env, const void *va, size_t len, int perm) -{ - // LAB 3: Your code here. - - size_t vae = ROUNDUP((size_t)(va+len), PGSIZE); - size_t vas = ROUNDDOWN((size_t)va, PGSIZE); - - - pte_t * pte; - - for (; vas < vae; vas += PGSIZE ) { - pte = pgdir_walk(env->env_pgdir, (void *)vas, 0); - if(!( vas < ULIM && pte==NULL && (*pte & perm))) { - if (vas < (size_t)va) - { - user_mem_check_addr = (uintptr_t)va; - } - else - { - user_mem_check_addr = (uintptr_t)vas; - } - return -E_FAULT; - } - } - return 0; -} -*/ -int -user_mem_check(struct Env *env, const void *va, size_t len, int perm) -{ - // LAB 3: Your code here. - uint32_t start = (uint32_t)ROUNDDOWN((char *)va, PGSIZE); - uint32_t end = (uint32_t)ROUNDUP((char *)va+len, PGSIZE); - for(; start < end; start += PGSIZE) { - pte_t *pte = pgdir_walk(env->env_pgdir, (void*)start, 0); - if((start >= ULIM) || (pte == NULL) || !(*pte & PTE_P) || ((*pte & perm) != perm)) { - user_mem_check_addr = (start < (uint32_t)va ? (uint32_t)va : start); - return -E_FAULT; - } - } - return 0; -} - - -// -// Checks that environment 'env' is allowed to access the range -// of memory [va, va+len) with permissions 'perm | PTE_U | PTE_P'. -// If it can, then the function simply returns. -// If it cannot, 'env' is destroyed and, if env is the current -// environment, this function will not return. -// -void -user_mem_assert(struct Env *env, const void *va, size_t len, int perm) -{ - if (user_mem_check(env, va, len, perm | PTE_U) < 0) { - cprintf("[%08x] user_mem_check assertion failure for " - "va %08x\n", env->env_id, user_mem_check_addr); - env_destroy(env); // may not return - } -} - - -// -------------------------------------------------------------- -// Checking functions. -// -------------------------------------------------------------- - -// -// Check that the pages on the page_free_list are reasonable. -// -static void -check_page_free_list(bool only_low_memory) -{ - struct PageInfo *pp; - unsigned pdx_limit = only_low_memory ? 1 : NPDENTRIES; - int nfree_basemem = 0, nfree_extmem = 0; - char *first_free_page; - - if (!page_free_list) - panic("'page_free_list' is a null pointer!"); - - if (only_low_memory) { - // Move pages with lower addresses first in the free - // list, since entry_pgdir does not map all pages. - struct PageInfo *pp1, *pp2; - struct PageInfo **tp[2] = { &pp1, &pp2 }; - for (pp = page_free_list; pp; pp = pp->pp_link) { - int pagetype = PDX(page2pa(pp)) >= pdx_limit; - *tp[pagetype] = pp; - tp[pagetype] = &pp->pp_link; - } - *tp[1] = 0; - *tp[0] = pp2; - page_free_list = pp1; - } - - // if there's a page that shouldn't be on the free list, - // try to make sure it eventually causes trouble. - for (pp = page_free_list; pp; pp = pp->pp_link) - if (PDX(page2pa(pp)) < pdx_limit) - memset(page2kva(pp), 0x97, 128); - - first_free_page = (char *) boot_alloc(0); - for (pp = page_free_list; pp; pp = pp->pp_link) { - // check that we didn't corrupt the free list itself - assert(pp >= pages); - assert(pp < pages + npages); - assert(((char *) pp - (char *) pages) % sizeof(*pp) == 0); - - // check a few pages that shouldn't be on the free list - assert(page2pa(pp) != 0); - assert(page2pa(pp) != IOPHYSMEM); - assert(page2pa(pp) != EXTPHYSMEM - PGSIZE); - assert(page2pa(pp) != EXTPHYSMEM); - assert(page2pa(pp) < EXTPHYSMEM || (char *) page2kva(pp) >= first_free_page); - // (new test for lab 4) - assert(page2pa(pp) != MPENTRY_PADDR); - - if (page2pa(pp) < EXTPHYSMEM) - ++nfree_basemem; - else - ++nfree_extmem; - } - - assert(nfree_basemem > 0); - assert(nfree_extmem > 0); - - cprintf("check_page_free_list() succeeded!\n"); -} - -// -// Check the physical page allocator (page_alloc(), page_free(), -// and page_init()). -// -static void -check_page_alloc(void) -{ - struct PageInfo *pp, *pp0, *pp1, *pp2; - int nfree; - struct PageInfo *fl; - char *c; - int i; - - if (!pages) - panic("'pages' is a null pointer!"); - - // check number of free pages - for (pp = page_free_list, nfree = 0; pp; pp = pp->pp_link) - ++nfree; - - // should be able to allocate three pages - pp0 = pp1 = pp2 = 0; - assert((pp0 = page_alloc(0))); - assert((pp1 = page_alloc(0))); - assert((pp2 = page_alloc(0))); - - assert(pp0); - assert(pp1 && pp1 != pp0); - assert(pp2 && pp2 != pp1 && pp2 != pp0); - assert(page2pa(pp0) < npages*PGSIZE); - assert(page2pa(pp1) < npages*PGSIZE); - assert(page2pa(pp2) < npages*PGSIZE); - - // temporarily steal the rest of the free pages - fl = page_free_list; - page_free_list = 0; - - // should be no free memory - assert(!page_alloc(0)); - - // free and re-allocate? - page_free(pp0); - page_free(pp1); - page_free(pp2); - pp0 = pp1 = pp2 = 0; - assert((pp0 = page_alloc(0))); - assert((pp1 = page_alloc(0))); - assert((pp2 = page_alloc(0))); - assert(pp0); - assert(pp1 && pp1 != pp0); - assert(pp2 && pp2 != pp1 && pp2 != pp0); - assert(!page_alloc(0)); - - // test flags - memset(page2kva(pp0), 1, PGSIZE); - page_free(pp0); - assert((pp = page_alloc(ALLOC_ZERO))); - assert(pp && pp0 == pp); - c = page2kva(pp); - for (i = 0; i < PGSIZE; i++) - assert(c[i] == 0); - - // give free list back - page_free_list = fl; - - // free the pages we took - page_free(pp0); - page_free(pp1); - page_free(pp2); - - // number of free pages should be the same - for (pp = page_free_list; pp; pp = pp->pp_link) - --nfree; - assert(nfree == 0); - - cprintf("check_page_alloc() succeeded!\n"); -} - -// -// Checks that the kernel part of virtual address space -// has been set up roughly correctly (by mem_init()). -// -// This function doesn't test every corner case, -// but it is a pretty good sanity check. -// - -static void -check_kern_pgdir(void) -{ - uint32_t i, n; - pde_t *pgdir; - - pgdir = kern_pgdir; - - // check pages array - n = ROUNDUP(npages*sizeof(struct PageInfo), PGSIZE); - for (i = 0; i < n; i += PGSIZE) - assert(check_va2pa(pgdir, UPAGES + i) == PADDR(pages) + i); - - // check envs array (new test for lab 3) - n = ROUNDUP(NENV*sizeof(struct Env), PGSIZE); - for (i = 0; i < n; i += PGSIZE) - assert(check_va2pa(pgdir, UENVS + i) == PADDR(envs) + i); - - // check phys mem - for (i = 0; i < npages * PGSIZE; i += PGSIZE) - assert(check_va2pa(pgdir, KERNBASE + i) == i); - - // check kernel stack - // (updated in lab 4 to check per-CPU kernel stacks) - for (n = 0; n < NCPU; n++) { - uint32_t base = KSTACKTOP - (KSTKSIZE + KSTKGAP) * (n + 1); - for (i = 0; i < KSTKSIZE; i += PGSIZE) - assert(check_va2pa(pgdir, base + KSTKGAP + i) - == PADDR(percpu_kstacks[n]) + i); - for (i = 0; i < KSTKGAP; i += PGSIZE) - assert(check_va2pa(pgdir, base + i) == ~0); - } - - // check PDE permissions - for (i = 0; i < NPDENTRIES; i++) { - switch (i) { - case PDX(UVPT): - case PDX(KSTACKTOP-1): - case PDX(UPAGES): - case PDX(UENVS): - case PDX(MMIOBASE): - assert(pgdir[i] & PTE_P); - break; - default: - if (i >= PDX(KERNBASE)) { - assert(pgdir[i] & PTE_P); - assert(pgdir[i] & PTE_W); - } else - assert(pgdir[i] == 0); - break; - } - } - cprintf("check_kern_pgdir() succeeded!\n"); -} - -// This function returns the physical address of the page containing 'va', -// defined by the page directory 'pgdir'. The hardware normally performs -// this functionality for us! We define our own version to help check -// the check_kern_pgdir() function; it shouldn't be used elsewhere. - -static physaddr_t -check_va2pa(pde_t *pgdir, uintptr_t va) -{ - pte_t *p; - - pgdir = &pgdir[PDX(va)]; - if (!(*pgdir & PTE_P)) - return ~0; - p = (pte_t*) KADDR(PTE_ADDR(*pgdir)); - if (!(p[PTX(va)] & PTE_P)) - return ~0; - return PTE_ADDR(p[PTX(va)]); -} - - -// check page_insert, page_remove, &c -static void -check_page(void) -{ - struct PageInfo *pp, *pp0, *pp1, *pp2; - struct PageInfo *fl; - pte_t *ptep, *ptep1; - void *va; - uintptr_t mm1, mm2; - int i; - extern pde_t entry_pgdir[]; - - // should be able to allocate three pages - pp0 = pp1 = pp2 = 0; - assert((pp0 = page_alloc(0))); - assert((pp1 = page_alloc(0))); - assert((pp2 = page_alloc(0))); - - assert(pp0); - assert(pp1 && pp1 != pp0); - assert(pp2 && pp2 != pp1 && pp2 != pp0); - - // temporarily steal the rest of the free pages - fl = page_free_list; - page_free_list = 0; - - // should be no free memory - assert(!page_alloc(0)); - - // there is no page allocated at address 0 - assert(page_lookup(kern_pgdir, (void *) 0x0, &ptep) == NULL); - - // there is no free memory, so we can't allocate a page table - assert(page_insert(kern_pgdir, pp1, 0x0, PTE_W) < 0); - - // free pp0 and try again: pp0 should be used for page table - page_free(pp0); - assert(page_insert(kern_pgdir, pp1, 0x0, PTE_W) == 0); - assert(PTE_ADDR(kern_pgdir[0]) == page2pa(pp0)); - assert(check_va2pa(kern_pgdir, 0x0) == page2pa(pp1)); - assert(pp1->pp_ref == 1); - assert(pp0->pp_ref == 1); - - // should be able to map pp2 at PGSIZE because pp0 is already allocated for page table - assert(page_insert(kern_pgdir, pp2, (void*) PGSIZE, PTE_W) == 0); - assert(check_va2pa(kern_pgdir, PGSIZE) == page2pa(pp2)); - assert(pp2->pp_ref == 1); - - // should be no free memory - assert(!page_alloc(0)); - - // should be able to map pp2 at PGSIZE because it's already there - assert(page_insert(kern_pgdir, pp2, (void*) PGSIZE, PTE_W) == 0); - assert(check_va2pa(kern_pgdir, PGSIZE) == page2pa(pp2)); - assert(pp2->pp_ref == 1); - - // pp2 should NOT be on the free list - // could happen in ref counts are handled sloppily in page_insert - assert(!page_alloc(0)); - - // check that pgdir_walk returns a pointer to the pte - ptep = (pte_t *) KADDR(PTE_ADDR(kern_pgdir[PDX(PGSIZE)])); - assert(pgdir_walk(kern_pgdir, (void*)PGSIZE, 0) == ptep+PTX(PGSIZE)); - - // should be able to change permissions too. - assert(page_insert(kern_pgdir, pp2, (void*) PGSIZE, PTE_W|PTE_U) == 0); - assert(check_va2pa(kern_pgdir, PGSIZE) == page2pa(pp2)); - assert(pp2->pp_ref == 1); - assert(*pgdir_walk(kern_pgdir, (void*) PGSIZE, 0) & PTE_U); - assert(kern_pgdir[0] & PTE_U); - - // should be able to remap with fewer permissions - assert(page_insert(kern_pgdir, pp2, (void*) PGSIZE, PTE_W) == 0); - assert(*pgdir_walk(kern_pgdir, (void*) PGSIZE, 0) & PTE_W); - assert(!(*pgdir_walk(kern_pgdir, (void*) PGSIZE, 0) & PTE_U)); - - // should not be able to map at PTSIZE because need free page for page table - assert(page_insert(kern_pgdir, pp0, (void*) PTSIZE, PTE_W) < 0); - - // insert pp1 at PGSIZE (replacing pp2) - assert(page_insert(kern_pgdir, pp1, (void*) PGSIZE, PTE_W) == 0); - assert(!(*pgdir_walk(kern_pgdir, (void*) PGSIZE, 0) & PTE_U)); - - // should have pp1 at both 0 and PGSIZE, pp2 nowhere, ... - assert(check_va2pa(kern_pgdir, 0) == page2pa(pp1)); - assert(check_va2pa(kern_pgdir, PGSIZE) == page2pa(pp1)); - // ... and ref counts should reflect this - assert(pp1->pp_ref == 2); - assert(pp2->pp_ref == 0); - - // pp2 should be returned by page_alloc - assert((pp = page_alloc(0)) && pp == pp2); - - // unmapping pp1 at 0 should keep pp1 at PGSIZE - page_remove(kern_pgdir, 0x0); - assert(check_va2pa(kern_pgdir, 0x0) == ~0); - assert(check_va2pa(kern_pgdir, PGSIZE) == page2pa(pp1)); - assert(pp1->pp_ref == 1); - assert(pp2->pp_ref == 0); - - // test re-inserting pp1 at PGSIZE - assert(page_insert(kern_pgdir, pp1, (void*) PGSIZE, 0) == 0); - assert(pp1->pp_ref); - assert(pp1->pp_link == NULL); - - // unmapping pp1 at PGSIZE should free it - page_remove(kern_pgdir, (void*) PGSIZE); - assert(check_va2pa(kern_pgdir, 0x0) == ~0); - assert(check_va2pa(kern_pgdir, PGSIZE) == ~0); - assert(pp1->pp_ref == 0); - assert(pp2->pp_ref == 0); - - // so it should be returned by page_alloc - assert((pp = page_alloc(0)) && pp == pp1); - - // should be no free memory - assert(!page_alloc(0)); - - // forcibly take pp0 back - assert(PTE_ADDR(kern_pgdir[0]) == page2pa(pp0)); - kern_pgdir[0] = 0; - assert(pp0->pp_ref == 1); - pp0->pp_ref = 0; - - // check pointer arithmetic in pgdir_walk - page_free(pp0); - va = (void*)(PGSIZE * NPDENTRIES + PGSIZE); - ptep = pgdir_walk(kern_pgdir, va, 1); - ptep1 = (pte_t *) KADDR(PTE_ADDR(kern_pgdir[PDX(va)])); - assert(ptep == ptep1 + PTX(va)); - kern_pgdir[PDX(va)] = 0; - pp0->pp_ref = 0; - - // check that new page tables get cleared - memset(page2kva(pp0), 0xFF, PGSIZE); - page_free(pp0); - pgdir_walk(kern_pgdir, 0x0, 1); - ptep = (pte_t *) page2kva(pp0); - for(i=0; ipp_ref = 0; - - // give free list back - page_free_list = fl; - - // free the pages we took - page_free(pp0); - page_free(pp1); - page_free(pp2); - - // test mmio_map_region - mm1 = (uintptr_t) mmio_map_region(0, 4097); - mm2 = (uintptr_t) mmio_map_region(0, 4096); - // check that they're in the right region - assert(mm1 >= MMIOBASE && mm1 + 8192 < MMIOLIM); - assert(mm2 >= MMIOBASE && mm2 + 8192 < MMIOLIM); - // check that they're page-aligned - assert(mm1 % PGSIZE == 0 && mm2 % PGSIZE == 0); - // check that they don't overlap - assert(mm1 + 8192 <= mm2); - // check page mappings - assert(check_va2pa(kern_pgdir, mm1) == 0); - assert(check_va2pa(kern_pgdir, mm1+PGSIZE) == PGSIZE); - assert(check_va2pa(kern_pgdir, mm2) == 0); - assert(check_va2pa(kern_pgdir, mm2+PGSIZE) == ~0); - // check permissions - assert(*pgdir_walk(kern_pgdir, (void*) mm1, 0) & (PTE_W|PTE_PWT|PTE_PCD)); - assert(!(*pgdir_walk(kern_pgdir, (void*) mm1, 0) & PTE_U)); - // clear the mappings - *pgdir_walk(kern_pgdir, (void*) mm1, 0) = 0; - *pgdir_walk(kern_pgdir, (void*) mm1 + PGSIZE, 0) = 0; - *pgdir_walk(kern_pgdir, (void*) mm2, 0) = 0; - - cprintf("check_page() succeeded!\n"); -} - -// check page_insert, page_remove, &c, with an installed kern_pgdir -static void -check_page_installed_pgdir(void) -{ - struct PageInfo *pp, *pp0, *pp1, *pp2; - struct PageInfo *fl; - pte_t *ptep, *ptep1; - uintptr_t va; - int i; - - // check that we can read and write installed pages - pp1 = pp2 = 0; - assert((pp0 = page_alloc(0))); - assert((pp1 = page_alloc(0))); - assert((pp2 = page_alloc(0))); - page_free(pp0); - memset(page2kva(pp1), 1, PGSIZE); - memset(page2kva(pp2), 2, PGSIZE); - page_insert(kern_pgdir, pp1, (void*) PGSIZE, PTE_W); - assert(pp1->pp_ref == 1); - assert(*(uint32_t *)PGSIZE == 0x01010101U); - page_insert(kern_pgdir, pp2, (void*) PGSIZE, PTE_W); - assert(*(uint32_t *)PGSIZE == 0x02020202U); - assert(pp2->pp_ref == 1); - assert(pp1->pp_ref == 0); - *(uint32_t *)PGSIZE = 0x03030303U; - assert(*(uint32_t *)page2kva(pp2) == 0x03030303U); - page_remove(kern_pgdir, (void*) PGSIZE); - assert(pp2->pp_ref == 0); - - // forcibly take pp0 back - assert(PTE_ADDR(kern_pgdir[0]) == page2pa(pp0)); - kern_pgdir[0] = 0; - assert(pp0->pp_ref == 1); - pp0->pp_ref = 0; - - // free the pages we took - page_free(pp0); - - cprintf("check_page_installed_pgdir() succeeded!\n"); -} diff --git a/lab/LAB4.si4project/Backup/sched(4329).c b/lab/LAB4.si4project/Backup/sched(4329).c deleted file mode 100644 index f595bb1..0000000 --- a/lab/LAB4.si4project/Backup/sched(4329).c +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void sched_halt(void); - -// Choose a user environment to run and run it. -void -sched_yield(void) -{ - struct Env *idle; - - // Implement simple round-robin scheduling. - // - // Search through 'envs' for an ENV_RUNNABLE environment in - // circular fashion starting just after the env this CPU was - // last running. Switch to the first such environment found. - // - // If no envs are runnable, but the environment previously - // running on this CPU is still ENV_RUNNING, it's okay to - // choose that environment. - // - // Never choose an environment that's currently running on - // another CPU (env_status == ENV_RUNNING). If there are - // no runnable environments, simply drop through to the code - // below to halt the cpu. - - // LAB 4: Your code here. - - // sched_halt never returns - sched_halt(); -} - -// Halt this CPU when there is nothing to do. Wait until the -// timer interrupt wakes it up. This function never returns. -// -void -sched_halt(void) -{ - int i; - - // For debugging and testing purposes, if there are no runnable - // environments in the system, then drop into the kernel monitor. - for (i = 0; i < NENV; i++) { - if ((envs[i].env_status == ENV_RUNNABLE || - envs[i].env_status == ENV_RUNNING || - envs[i].env_status == ENV_DYING)) - break; - } - if (i == NENV) { - cprintf("No runnable environments in the system!\n"); - while (1) - monitor(NULL); - } - - // Mark that no environment is running on this CPU - curenv = NULL; - lcr3(PADDR(kern_pgdir)); - - // Mark that this CPU is in the HALT state, so that when - // timer interupts come in, we know we should re-acquire the - // big kernel lock - xchg(&thiscpu->cpu_status, CPU_HALTED); - - // Release the big kernel lock as if we were "leaving" the kernel - unlock_kernel(); - - // Reset stack pointer, enable interrupts and then halt. - asm volatile ( - "movl $0, %%ebp\n" - "movl %0, %%esp\n" - "pushl $0\n" - "pushl $0\n" - // Uncomment the following line after completing exercise 13 - //"sti\n" - "1:\n" - "hlt\n" - "jmp 1b\n" - : : "a" (thiscpu->cpu_ts.ts_esp0)); -} - diff --git a/lab/LAB4.si4project/Backup/sched(5719).c b/lab/LAB4.si4project/Backup/sched(5719).c deleted file mode 100644 index 04e9617..0000000 --- a/lab/LAB4.si4project/Backup/sched(5719).c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void sched_halt(void); - -// Choose a user environment to run and run it. -void -sched_yield(void) -{ - struct Env *idle; - - // Implement simple round-robin scheduling. - // - // Search through 'envs' for an ENV_RUNNABLE environment in - // circular fashion starting just after the env this CPU was - // last running. Switch to the first such environment found. - // - // If no envs are runnable, but the environment previously - // running on this CPU is still ENV_RUNNING, it's okay to - // choose that environment. - // - // Never choose an environment that's currently running on - // another CPU (env_status == ENV_RUNNING). If there are - // no runnable environments, simply drop through to the code - // below to halt the cpu. - - // LAB 4: Your code here. - - idle = curenv; - int start_envid = idle ? ENVX(idle->env_id)+1 : 0; - - for (int i = 0; i < NENV; i++) { - int j = (start_envid + i) % NENV; - if (envs[j].env_status == ENV_RUNNABLE) { - env_run(&envs[j]); - } - } - - if (idle && idle->env_status == ENV_RUNNING) { - env_run(idle); - } - - // sched_halt never returns - sched_halt(); - -} - -// Halt this CPU when there is nothing to do. Wait until the -// timer interrupt wakes it up. This function never returns. -// -void -sched_halt(void) -{ - int i; - - // For debugging and testing purposes, if there are no runnable - // environments in the system, then drop into the kernel monitor. - for (i = 0; i < NENV; i++) { - if ((envs[i].env_status == ENV_RUNNABLE || - envs[i].env_status == ENV_RUNNING || - envs[i].env_status == ENV_DYING)) - break; - } - if (i == NENV) { - cprintf("No runnable environments in the system!\n"); - while (1) - monitor(NULL); - } - - // Mark that no environment is running on this CPU - curenv = NULL; - lcr3(PADDR(kern_pgdir)); - - // Mark that this CPU is in the HALT state, so that when - // timer interupts come in, we know we should re-acquire the - // big kernel lock - xchg(&thiscpu->cpu_status, CPU_HALTED); - - // Release the big kernel lock as if we were "leaving" the kernel - unlock_kernel(); - - // Reset stack pointer, enable interrupts and then halt. - asm volatile ( - "movl $0, %%ebp\n" - "movl %0, %%esp\n" - "pushl $0\n" - "pushl $0\n" - // Uncomment the following line after completing exercise 13 - //"sti\n" - "1:\n" - "hlt\n" - "jmp 1b\n" - : : "a" (thiscpu->cpu_ts.ts_esp0)); -} - diff --git a/lab/LAB4.si4project/Backup/sched(6307).c b/lab/LAB4.si4project/Backup/sched(6307).c deleted file mode 100644 index 04e9617..0000000 --- a/lab/LAB4.si4project/Backup/sched(6307).c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void sched_halt(void); - -// Choose a user environment to run and run it. -void -sched_yield(void) -{ - struct Env *idle; - - // Implement simple round-robin scheduling. - // - // Search through 'envs' for an ENV_RUNNABLE environment in - // circular fashion starting just after the env this CPU was - // last running. Switch to the first such environment found. - // - // If no envs are runnable, but the environment previously - // running on this CPU is still ENV_RUNNING, it's okay to - // choose that environment. - // - // Never choose an environment that's currently running on - // another CPU (env_status == ENV_RUNNING). If there are - // no runnable environments, simply drop through to the code - // below to halt the cpu. - - // LAB 4: Your code here. - - idle = curenv; - int start_envid = idle ? ENVX(idle->env_id)+1 : 0; - - for (int i = 0; i < NENV; i++) { - int j = (start_envid + i) % NENV; - if (envs[j].env_status == ENV_RUNNABLE) { - env_run(&envs[j]); - } - } - - if (idle && idle->env_status == ENV_RUNNING) { - env_run(idle); - } - - // sched_halt never returns - sched_halt(); - -} - -// Halt this CPU when there is nothing to do. Wait until the -// timer interrupt wakes it up. This function never returns. -// -void -sched_halt(void) -{ - int i; - - // For debugging and testing purposes, if there are no runnable - // environments in the system, then drop into the kernel monitor. - for (i = 0; i < NENV; i++) { - if ((envs[i].env_status == ENV_RUNNABLE || - envs[i].env_status == ENV_RUNNING || - envs[i].env_status == ENV_DYING)) - break; - } - if (i == NENV) { - cprintf("No runnable environments in the system!\n"); - while (1) - monitor(NULL); - } - - // Mark that no environment is running on this CPU - curenv = NULL; - lcr3(PADDR(kern_pgdir)); - - // Mark that this CPU is in the HALT state, so that when - // timer interupts come in, we know we should re-acquire the - // big kernel lock - xchg(&thiscpu->cpu_status, CPU_HALTED); - - // Release the big kernel lock as if we were "leaving" the kernel - unlock_kernel(); - - // Reset stack pointer, enable interrupts and then halt. - asm volatile ( - "movl $0, %%ebp\n" - "movl %0, %%esp\n" - "pushl $0\n" - "pushl $0\n" - // Uncomment the following line after completing exercise 13 - //"sti\n" - "1:\n" - "hlt\n" - "jmp 1b\n" - : : "a" (thiscpu->cpu_ts.ts_esp0)); -} - diff --git a/lab/LAB4.si4project/Backup/syscall(1135).c b/lab/LAB4.si4project/Backup/syscall(1135).c deleted file mode 100644 index 055deef..0000000 --- a/lab/LAB4.si4project/Backup/syscall(1135).c +++ /dev/null @@ -1,378 +0,0 @@ -/* See COPYRIGHT for copyright information. */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -// Print a string to the system console. -// The string is exactly 'len' characters long. -// Destroys the environment on memory errors. -static void -sys_cputs(const char *s, size_t len) -{ - // Check that the user has permission to read memory [s, s+len). - // Destroy the environment if not. - - // LAB 3: Your code here. - user_mem_assert(curenv, (const void *) s, len, 0); - // Print the string supplied by the user. - cprintf("%.*s", len, s); -} - -// Read a character from the system console without blocking. -// Returns the character, or 0 if there is no input waiting. -static int -sys_cgetc(void) -{ - return cons_getc(); -} - -// Returns the current environment's envid. -static envid_t -sys_getenvid(void) -{ - return curenv->env_id; -} - -// Destroy a given environment (possibly the currently running environment). -// -// Returns 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -static int -sys_env_destroy(envid_t envid) -{ - int r; - struct Env *e; - - if ((r = envid2env(envid, &e, 1)) < 0) - return r; - if (e == curenv) - cprintf("[%08x] exiting gracefully\n", curenv->env_id); - else - cprintf("[%08x] destroying %08x\n", curenv->env_id, e->env_id); - env_destroy(e); - return 0; -} - -// Deschedule current environment and pick a different one to run. -static void -sys_yield(void) -{ - sched_yield(); -} - - -// Allocate a new environment. -// Returns envid of new environment, or < 0 on error. Errors are: -// -E_NO_FREE_ENV if no free environment is available. -// -E_NO_MEM on memory exhaustion. -static envid_t -sys_exofork(void) -{ - // Create the new environment with env_alloc(), from kern/env.c. - // It should be left as env_alloc created it, except that - // status is set to ENV_NOT_RUNNABLE, and the register set is copied - // from the current environment -- but tweaked so sys_exofork - // will appear to return 0. - // LAB 4: Your code here. - struct Env *newenv; - int32_t ret; - if ((ret = env_alloc(&newenv, sys_getenvid())) < 0) { - // 两个函数的返回值是一样的 - return ret; - } - newenv->env_status = ENV_NOT_RUNNABLE; - newenv->env_tf = curenv->env_tf; - // newenv的返回值为0, 实现子进程返回0值 - newenv->env_tf.tf_regs.reg_eax = 0; - // 返回值存放在eax中 - return newenv->env_id; - - // panic("sys_exofork not implemented"); -} - -// Set envid's env_status to status, which must be ENV_RUNNABLE -// or ENV_NOT_RUNNABLE. -// -// Returns 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -// -E_INVAL if status is not a valid status for an environment. -static int -sys_env_set_status(envid_t envid, int status) -{ - // Hint: Use the 'envid2env' function from kern/env.c to translate an - // envid to a struct Env. - // You should set envid2env's third argument to 1, which will - // check whether the current environment has permission to set - // envid's status. - - // LAB 4: Your code here. - struct Env *e; - if (envid2env(envid, &e, 1)) return -E_BAD_ENV; - - if (status != ENV_NOT_RUNNABLE && status != ENV_RUNNABLE) - return -E_INVAL; - - e->env_status = status; - return 0; -} - -// Set the page fault upcall for 'envid' by modifying the corresponding struct -// Env's 'env_pgfault_upcall' field. When 'envid' causes a page fault, the -// kernel will push a fault record onto the exception stack, then branch to -// 'func'. -// -// Returns 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -static int -sys_env_set_pgfault_upcall(envid_t envid, void *func) -{ - // LAB 4: Your code here. - - - panic("sys_env_set_pgfault_upcall not implemented"); -} - -// Allocate a page of memory and map it at 'va' with permission -// 'perm' in the address space of 'envid'. -// The page's contents are set to 0. -// If a page is already mapped at 'va', that page is unmapped as a -// side effect. -// -// perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set, -// but no other bits may be set. See PTE_SYSCALL in inc/mmu.h. -// -// Return 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -// -E_INVAL if va >= UTOP, or va is not page-aligned. -// -E_INVAL if perm is inappropriate (see above). -// -E_NO_MEM if there's no memory to allocate the new page, -// or to allocate any necessary page tables. -static int -sys_page_alloc(envid_t envid, void *va, int perm) -{ - // Hint: This function is a wrapper around page_alloc() and - // page_insert() from kern/pmap.c. - // Most of the new code you write should be to check the - // parameters for correctness. - // If page_insert() fails, remember to free the page you - // allocated! - - // LAB 4: Your code here. - int ret = 0; - struct Env *env; - - if ((ret = envid2env(envid, &env, 1)) < 0) - return -E_BAD_ENV; - - if((uintptr_t)va >= UTOP || PGOFF(va)) - return -E_INVAL; - if ((perm & PTE_U) == 0 || (perm & PTE_P) == 0) - return -E_INVAL; - if (perm & ~PTE_SYSCALL) - return -E_INVAL; - - struct PageInfo *pp = page_alloc(ALLOC_ZERO); - if(!pp) - return -E_NO_MEM; - - if (page_insert(env->env_pgdir, pp, va, perm) < 0) - return -E_NO_MEM; - - return 0; - // panic("sys_page_alloc not implemented"); -} - -// Map the page of memory at 'srcva' in srcenvid's address space -// at 'dstva' in dstenvid's address space with permission 'perm'. -// Perm has the same restrictions as in sys_page_alloc, except -// that it also must not grant write access to a read-only -// page. -// -// Return 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist, -// or the caller doesn't have permission to change one of them. -// -E_INVAL if srcva >= UTOP or srcva is not page-aligned, -// or dstva >= UTOP or dstva is not page-aligned. -// -E_INVAL is srcva is not mapped in srcenvid's address space. -// -E_INVAL if perm is inappropriate (see sys_page_alloc). -// -E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's -// address space. -// -E_NO_MEM if there's no memory to allocate any necessary page tables. -static int -sys_page_map(envid_t srcenvid, void *srcva, - envid_t dstenvid, void *dstva, int perm) -{ - // Hint: This function is a wrapper around page_lookup() and - // page_insert() from kern/pmap.c. - // Again, most of the new code you write should be to check the - // parameters for correctness. - // Use the third argument to page_lookup() to - // check the current permissions on the page. - - // LAB 4: Your code here. - int ret = 0; - struct Env *srcenv, *dstenv; - struct PageInfo *srcpp, *dstpp; - pte_t *pte; - if ((envid2env(srcenvid, &srcenv, 1) < 0 )|| ( envid2env(dstenvid, &dstenv, 1) < 0)) - return -E_BAD_ENV; - if ((uintptr_t)srcva >= UTOP || PGOFF(srcva) || (uintptr_t)dstva >= UTOP || PGOFF(dstva)) - return -E_INVAL; - if ( (perm & PTE_U) == 0 || (perm & PTE_P) == 0 || (perm & ~PTE_SYSCALL)) - return -E_INVAL; - if (!(srcpp = page_lookup(srcenv->env_pgdir, srcva, &pte))) - return -E_INVAL; - if ((perm & PTE_W) && ((*pte & PTE_W) == 0)) - return -E_INVAL; - if (page_insert(dstenv->env_pgdir, srcpp, dstva, perm) < 0) - return -E_NO_MEM; - - return 0; - // panic("sys_page_map not implemented"); -} - -// Unmap the page of memory at 'va' in the address space of 'envid'. -// If no page is mapped, the function silently succeeds. -// -// Return 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -// -E_INVAL if va >= UTOP, or va is not page-aligned. -static int -sys_page_unmap(envid_t envid, void *va) -{ - // Hint: This function is a wrapper around page_remove(). - - // LAB 4: Your code here. - int ret = 0; - struct Env *env; - - if ((ret = envid2env(envid, &env, 1)) < 0) - return -E_BAD_ENV; - if ((uintptr_t)va >= UTOP || PGOFF(va)) - return -E_INVAL; - page_remove(env->env_pgdir, va); - return 0; - // panic("sys_page_unmap not implemented"); -} - -// Try to send 'value' to the target env 'envid'. -// If srcva < UTOP, then also send page currently mapped at 'srcva', -// so that receiver gets a duplicate mapping of the same page. -// -// The send fails with a return value of -E_IPC_NOT_RECV if the -// target is not blocked, waiting for an IPC. -// -// The send also can fail for the other reasons listed below. -// -// Otherwise, the send succeeds, and the target's ipc fields are -// updated as follows: -// env_ipc_recving is set to 0 to block future sends; -// env_ipc_from is set to the sending envid; -// env_ipc_value is set to the 'value' parameter; -// env_ipc_perm is set to 'perm' if a page was transferred, 0 otherwise. -// The target environment is marked runnable again, returning 0 -// from the paused sys_ipc_recv system call. (Hint: does the -// sys_ipc_recv function ever actually return?) -// -// If the sender wants to send a page but the receiver isn't asking for one, -// then no page mapping is transferred, but no error occurs. -// The ipc only happens when no errors occur. -// -// Returns 0 on success, < 0 on error. -// Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist. -// (No need to check permissions.) -// -E_IPC_NOT_RECV if envid is not currently blocked in sys_ipc_recv, -// or another environment managed to send first. -// -E_INVAL if srcva < UTOP but srcva is not page-aligned. -// -E_INVAL if srcva < UTOP and perm is inappropriate -// (see sys_page_alloc). -// -E_INVAL if srcva < UTOP but srcva is not mapped in the caller's -// address space. -// -E_INVAL if (perm & PTE_W), but srcva is read-only in the -// current environment's address space. -// -E_NO_MEM if there's not enough memory to map srcva in envid's -// address space. -static int -sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm) -{ - // LAB 4: Your code here. - panic("sys_ipc_try_send not implemented"); -} - -// Block until a value is ready. Record that you want to receive -// using the env_ipc_recving and env_ipc_dstva fields of struct Env, -// mark yourself not runnable, and then give up the CPU. -// -// If 'dstva' is < UTOP, then you are willing to receive a page of data. -// 'dstva' is the virtual address at which the sent page should be mapped. -// -// This function only returns on error, but the system call will eventually -// return 0 on success. -// Return < 0 on error. Errors are: -// -E_INVAL if dstva < UTOP but dstva is not page-aligned. -static int -sys_ipc_recv(void *dstva) -{ - // LAB 4: Your code here. - panic("sys_ipc_recv not implemented"); - 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. - switch (syscallno) { - case SYS_cputs: - sys_cputs((const char*)a1, a2); - break; - case SYS_cgetc: - return sys_cgetc(); - case SYS_getenvid: - ret = sys_getenvid(); - break; - case SYS_env_destroy: - return sys_env_destroy(a1); - case SYS_yield: - sys_yield(); - 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 NSYSCALLS: - return -E_INVAL; - - default: - return -E_INVAL; - } -} - diff --git a/lab/LAB4.si4project/Backup/syscall(2799).c b/lab/LAB4.si4project/Backup/syscall(2799).c deleted file mode 100644 index 406b1df..0000000 --- a/lab/LAB4.si4project/Backup/syscall(2799).c +++ /dev/null @@ -1,301 +0,0 @@ -/* See COPYRIGHT for copyright information. */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -// Print a string to the system console. -// The string is exactly 'len' characters long. -// Destroys the environment on memory errors. -static void -sys_cputs(const char *s, size_t len) -{ - // Check that the user has permission to read memory [s, s+len). - // Destroy the environment if not. - - // LAB 3: Your code here. - user_mem_assert(curenv, (const void *) s, len, 0); - // Print the string supplied by the user. - cprintf("%.*s", len, s); -} - -// Read a character from the system console without blocking. -// Returns the character, or 0 if there is no input waiting. -static int -sys_cgetc(void) -{ - return cons_getc(); -} - -// Returns the current environment's envid. -static envid_t -sys_getenvid(void) -{ - return curenv->env_id; -} - -// Destroy a given environment (possibly the currently running environment). -// -// Returns 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -static int -sys_env_destroy(envid_t envid) -{ - int r; - struct Env *e; - - if ((r = envid2env(envid, &e, 1)) < 0) - return r; - if (e == curenv) - cprintf("[%08x] exiting gracefully\n", curenv->env_id); - else - cprintf("[%08x] destroying %08x\n", curenv->env_id, e->env_id); - env_destroy(e); - return 0; -} - -// Deschedule current environment and pick a different one to run. -static void -sys_yield(void) -{ - sched_yield(); -} - -// Allocate a new environment. -// Returns envid of new environment, or < 0 on error. Errors are: -// -E_NO_FREE_ENV if no free environment is available. -// -E_NO_MEM on memory exhaustion. -static envid_t -sys_exofork(void) -{ - // Create the new environment with env_alloc(), from kern/env.c. - // It should be left as env_alloc created it, except that - // status is set to ENV_NOT_RUNNABLE, and the register set is copied - // from the current environment -- but tweaked so sys_exofork - // will appear to return 0. - - // LAB 4: Your code here. - panic("sys_exofork not implemented"); -} - -// Set envid's env_status to status, which must be ENV_RUNNABLE -// or ENV_NOT_RUNNABLE. -// -// Returns 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -// -E_INVAL if status is not a valid status for an environment. -static int -sys_env_set_status(envid_t envid, int status) -{ - // Hint: Use the 'envid2env' function from kern/env.c to translate an - // envid to a struct Env. - // You should set envid2env's third argument to 1, which will - // check whether the current environment has permission to set - // envid's status. - - // LAB 4: Your code here. - panic("sys_env_set_status not implemented"); -} - -// Set the page fault upcall for 'envid' by modifying the corresponding struct -// Env's 'env_pgfault_upcall' field. When 'envid' causes a page fault, the -// kernel will push a fault record onto the exception stack, then branch to -// 'func'. -// -// Returns 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -static int -sys_env_set_pgfault_upcall(envid_t envid, void *func) -{ - // LAB 4: Your code here. - panic("sys_env_set_pgfault_upcall not implemented"); -} - -// Allocate a page of memory and map it at 'va' with permission -// 'perm' in the address space of 'envid'. -// The page's contents are set to 0. -// If a page is already mapped at 'va', that page is unmapped as a -// side effect. -// -// perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set, -// but no other bits may be set. See PTE_SYSCALL in inc/mmu.h. -// -// Return 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -// -E_INVAL if va >= UTOP, or va is not page-aligned. -// -E_INVAL if perm is inappropriate (see above). -// -E_NO_MEM if there's no memory to allocate the new page, -// or to allocate any necessary page tables. -static int -sys_page_alloc(envid_t envid, void *va, int perm) -{ - // Hint: This function is a wrapper around page_alloc() and - // page_insert() from kern/pmap.c. - // Most of the new code you write should be to check the - // parameters for correctness. - // If page_insert() fails, remember to free the page you - // allocated! - - // LAB 4: Your code here. - panic("sys_page_alloc not implemented"); -} - -// Map the page of memory at 'srcva' in srcenvid's address space -// at 'dstva' in dstenvid's address space with permission 'perm'. -// Perm has the same restrictions as in sys_page_alloc, except -// that it also must not grant write access to a read-only -// page. -// -// Return 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist, -// or the caller doesn't have permission to change one of them. -// -E_INVAL if srcva >= UTOP or srcva is not page-aligned, -// or dstva >= UTOP or dstva is not page-aligned. -// -E_INVAL is srcva is not mapped in srcenvid's address space. -// -E_INVAL if perm is inappropriate (see sys_page_alloc). -// -E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's -// address space. -// -E_NO_MEM if there's no memory to allocate any necessary page tables. -static int -sys_page_map(envid_t srcenvid, void *srcva, - envid_t dstenvid, void *dstva, int perm) -{ - // Hint: This function is a wrapper around page_lookup() and - // page_insert() from kern/pmap.c. - // Again, most of the new code you write should be to check the - // parameters for correctness. - // Use the third argument to page_lookup() to - // check the current permissions on the page. - - // LAB 4: Your code here. - panic("sys_page_map not implemented"); -} - -// Unmap the page of memory at 'va' in the address space of 'envid'. -// If no page is mapped, the function silently succeeds. -// -// Return 0 on success, < 0 on error. Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist, -// or the caller doesn't have permission to change envid. -// -E_INVAL if va >= UTOP, or va is not page-aligned. -static int -sys_page_unmap(envid_t envid, void *va) -{ - // Hint: This function is a wrapper around page_remove(). - - // LAB 4: Your code here. - panic("sys_page_unmap not implemented"); -} - -// Try to send 'value' to the target env 'envid'. -// If srcva < UTOP, then also send page currently mapped at 'srcva', -// so that receiver gets a duplicate mapping of the same page. -// -// The send fails with a return value of -E_IPC_NOT_RECV if the -// target is not blocked, waiting for an IPC. -// -// The send also can fail for the other reasons listed below. -// -// Otherwise, the send succeeds, and the target's ipc fields are -// updated as follows: -// env_ipc_recving is set to 0 to block future sends; -// env_ipc_from is set to the sending envid; -// env_ipc_value is set to the 'value' parameter; -// env_ipc_perm is set to 'perm' if a page was transferred, 0 otherwise. -// The target environment is marked runnable again, returning 0 -// from the paused sys_ipc_recv system call. (Hint: does the -// sys_ipc_recv function ever actually return?) -// -// If the sender wants to send a page but the receiver isn't asking for one, -// then no page mapping is transferred, but no error occurs. -// The ipc only happens when no errors occur. -// -// Returns 0 on success, < 0 on error. -// Errors are: -// -E_BAD_ENV if environment envid doesn't currently exist. -// (No need to check permissions.) -// -E_IPC_NOT_RECV if envid is not currently blocked in sys_ipc_recv, -// or another environment managed to send first. -// -E_INVAL if srcva < UTOP but srcva is not page-aligned. -// -E_INVAL if srcva < UTOP and perm is inappropriate -// (see sys_page_alloc). -// -E_INVAL if srcva < UTOP but srcva is not mapped in the caller's -// address space. -// -E_INVAL if (perm & PTE_W), but srcva is read-only in the -// current environment's address space. -// -E_NO_MEM if there's not enough memory to map srcva in envid's -// address space. -static int -sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm) -{ - // LAB 4: Your code here. - panic("sys_ipc_try_send not implemented"); -} - -// Block until a value is ready. Record that you want to receive -// using the env_ipc_recving and env_ipc_dstva fields of struct Env, -// mark yourself not runnable, and then give up the CPU. -// -// If 'dstva' is < UTOP, then you are willing to receive a page of data. -// 'dstva' is the virtual address at which the sent page should be mapped. -// -// This function only returns on error, but the system call will eventually -// return 0 on success. -// Return < 0 on error. Errors are: -// -E_INVAL if dstva < UTOP but dstva is not page-aligned. -static int -sys_ipc_recv(void *dstva) -{ - // LAB 4: Your code here. - panic("sys_ipc_recv not implemented"); - 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. - - - // panic("syscall not implemented"); - - 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: - sys_env_destroy(a1); - break; - case NSYSCALLS: - return -E_INVAL; - - default: - return -E_INVAL; - } - - return ret; -} - diff --git a/lab/LAB4.si4project/Backup/syscall(5045).h b/lab/LAB4.si4project/Backup/syscall(5045).h deleted file mode 100644 index 71b3512..0000000 --- a/lab/LAB4.si4project/Backup/syscall(5045).h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef JOS_INC_SYSCALL_H -#define JOS_INC_SYSCALL_H - -/* system call numbers */ -enum { - SYS_cputs = 0, - SYS_cgetc, - SYS_getenvid, - SYS_env_destroy, - SYS_page_alloc, - SYS_page_map, - SYS_page_unmap, - SYS_exofork, - SYS_env_set_status, - SYS_env_set_pgfault_upcall, - SYS_yield, - SYS_ipc_try_send, - SYS_ipc_recv, - NSYSCALLS -}; - -#endif /* !JOS_INC_SYSCALL_H */ diff --git a/lab/LAB4.si4project/Backup/trapentry(2731).S b/lab/LAB4.si4project/Backup/trapentry(2731).S deleted file mode 100644 index 7487913..0000000 --- a/lab/LAB4.si4project/Backup/trapentry(2731).S +++ /dev/null @@ -1,100 +0,0 @@ -/* See COPYRIGHT for copyright information. */ - -#include -#include -#include - -#include - - -################################################################### -# exceptions/interrupts -################################################################### - -/* TRAPHANDLER defines a globally-visible function for handling a trap. - * It pushes a trap number onto the stack, then jumps to _alltraps. - * Use TRAPHANDLER for traps where the CPU automatically pushes an error code. - * - * You shouldn't call a TRAPHANDLER function from C, but you may - * need to _declare_ one in C (for instance, to get a function pointer - * during IDT setup). You can declare the function with - * void NAME(); - * where NAME is the argument passed to TRAPHANDLER. - */ -#define TRAPHANDLER(name, num) \ - .globl name; /* define global symbol for 'name' */ \ - .type name, @function; /* symbol type is function */ \ - .align 2; /* align function definition */ \ - name: /* function starts here */ \ - pushl $(num); \ - jmp _alltraps - -/* Use TRAPHANDLER_NOEC for traps where the CPU doesn't push an error code. - * It pushes a 0 in place of the error code, so the trap frame has the same - * format in either case. - - * tarp handler no error code - */ - -#define TRAPHANDLER_NOEC(name, num) \ - .globl name; \ - .type name, @function; \ - .align 2; \ - name: \ - pushl $0; \ - pushl $(num); \ - jmp _alltraps - -.text - -/* - * 我们知道哪些trap是有错误代码的? https://wiki.osdev.org/Exceptions - * Lab 3: Your code here for generating entry points for the different traps. - */ -TRAPHANDLER_NOEC(divide_handler, T_DIVIDE); -TRAPHANDLER_NOEC(debug_handler, T_DEBUG); -TRAPHANDLER_NOEC(nmi_handler, T_NMI); -TRAPHANDLER_NOEC(brkpt_handler, T_BRKPT); -TRAPHANDLER_NOEC(oflow_handler, T_OFLOW); -TRAPHANDLER_NOEC(bound_handler, T_BOUND); -TRAPHANDLER_NOEC(illop_handler, T_ILLOP); -TRAPHANDLER_NOEC(device_handler, T_DEVICE); -TRAPHANDLER(dblflt_handler, T_DBLFLT); -TRAPHANDLER(tss_handler, T_TSS); -TRAPHANDLER(segnp_handler, T_SEGNP); -TRAPHANDLER(stack_handler, T_STACK); -TRAPHANDLER(gpflt_handler, T_GPFLT); -TRAPHANDLER(pgflt_handler, T_PGFLT); -TRAPHANDLER_NOEC(fperr_handler, T_FPERR); -TRAPHANDLER(align_handler, T_ALIGN); -TRAPHANDLER_NOEC(mchk_handler, T_MCHK); -TRAPHANDLER_NOEC(simderr_handler, T_SIMDERR); -TRAPHANDLER_NOEC(syscall_handler, T_SYSCALL); - -/* -Your _alltraps should: - 1. push values to make the stack look like a struct Trapframe - 2. load GD_KD into %ds and %es - 3. pushl %esp to pass a pointer to the Trapframe as an argument to trap() - 4. call trap (can trap ever return?) -*/ - -/* - * Lab 3: Your code here for _alltraps - *what is padding ? 填充 pushl %ds;小端模式,是指数据的高字节保存在内存的高地址中 - */ -.globl _alltraps -_alltraps: - - pushl %ds; - pushl %es; - pushal; - - movw $GD_KD, %ax; - movw %ax, %ds; - movw %ax, %es; - - /*push esp, trap 能自己读esp, 我有点觉得是赋值*/ - pushl %esp; - call trap - \ No newline at end of file diff --git a/lab/LAB4.si4project/Backup/trapentry(7165).S b/lab/LAB4.si4project/Backup/trapentry(7165).S deleted file mode 100644 index 7487913..0000000 --- a/lab/LAB4.si4project/Backup/trapentry(7165).S +++ /dev/null @@ -1,100 +0,0 @@ -/* See COPYRIGHT for copyright information. */ - -#include -#include -#include - -#include - - -################################################################### -# exceptions/interrupts -################################################################### - -/* TRAPHANDLER defines a globally-visible function for handling a trap. - * It pushes a trap number onto the stack, then jumps to _alltraps. - * Use TRAPHANDLER for traps where the CPU automatically pushes an error code. - * - * You shouldn't call a TRAPHANDLER function from C, but you may - * need to _declare_ one in C (for instance, to get a function pointer - * during IDT setup). You can declare the function with - * void NAME(); - * where NAME is the argument passed to TRAPHANDLER. - */ -#define TRAPHANDLER(name, num) \ - .globl name; /* define global symbol for 'name' */ \ - .type name, @function; /* symbol type is function */ \ - .align 2; /* align function definition */ \ - name: /* function starts here */ \ - pushl $(num); \ - jmp _alltraps - -/* Use TRAPHANDLER_NOEC for traps where the CPU doesn't push an error code. - * It pushes a 0 in place of the error code, so the trap frame has the same - * format in either case. - - * tarp handler no error code - */ - -#define TRAPHANDLER_NOEC(name, num) \ - .globl name; \ - .type name, @function; \ - .align 2; \ - name: \ - pushl $0; \ - pushl $(num); \ - jmp _alltraps - -.text - -/* - * 我们知道哪些trap是有错误代码的? https://wiki.osdev.org/Exceptions - * Lab 3: Your code here for generating entry points for the different traps. - */ -TRAPHANDLER_NOEC(divide_handler, T_DIVIDE); -TRAPHANDLER_NOEC(debug_handler, T_DEBUG); -TRAPHANDLER_NOEC(nmi_handler, T_NMI); -TRAPHANDLER_NOEC(brkpt_handler, T_BRKPT); -TRAPHANDLER_NOEC(oflow_handler, T_OFLOW); -TRAPHANDLER_NOEC(bound_handler, T_BOUND); -TRAPHANDLER_NOEC(illop_handler, T_ILLOP); -TRAPHANDLER_NOEC(device_handler, T_DEVICE); -TRAPHANDLER(dblflt_handler, T_DBLFLT); -TRAPHANDLER(tss_handler, T_TSS); -TRAPHANDLER(segnp_handler, T_SEGNP); -TRAPHANDLER(stack_handler, T_STACK); -TRAPHANDLER(gpflt_handler, T_GPFLT); -TRAPHANDLER(pgflt_handler, T_PGFLT); -TRAPHANDLER_NOEC(fperr_handler, T_FPERR); -TRAPHANDLER(align_handler, T_ALIGN); -TRAPHANDLER_NOEC(mchk_handler, T_MCHK); -TRAPHANDLER_NOEC(simderr_handler, T_SIMDERR); -TRAPHANDLER_NOEC(syscall_handler, T_SYSCALL); - -/* -Your _alltraps should: - 1. push values to make the stack look like a struct Trapframe - 2. load GD_KD into %ds and %es - 3. pushl %esp to pass a pointer to the Trapframe as an argument to trap() - 4. call trap (can trap ever return?) -*/ - -/* - * Lab 3: Your code here for _alltraps - *what is padding ? 填充 pushl %ds;小端模式,是指数据的高字节保存在内存的高地址中 - */ -.globl _alltraps -_alltraps: - - pushl %ds; - pushl %es; - pushal; - - movw $GD_KD, %ax; - movw %ax, %ds; - movw %ax, %es; - - /*push esp, trap 能自己读esp, 我有点觉得是赋值*/ - pushl %esp; - call trap - \ No newline at end of file diff --git a/lab/LAB4.si4project/LAB4.SearchResults b/lab/LAB4.si4project/LAB4.SearchResults deleted file mode 100644 index d4dfec4..0000000 --- a/lab/LAB4.si4project/LAB4.SearchResults +++ /dev/null @@ -1,4 +0,0 @@ ----- sched_halt Matches (3 in 1 files) ---- -sched.c (kern) line 8 : void sched_halt(void); -sched_yield in sched.c (kern) : sched_halt(); -sched.c (kern) line 56 : sched_halt(void) diff --git a/lab/LAB4.si4project/LAB4.sip_sym b/lab/LAB4.si4project/LAB4.sip_sym deleted file mode 100644 index 7d59ad9..0000000 Binary files a/lab/LAB4.si4project/LAB4.sip_sym and /dev/null differ diff --git a/lab/LAB4.si4project/LAB4.sip_xab b/lab/LAB4.si4project/LAB4.sip_xab deleted file mode 100644 index c021212..0000000 Binary files a/lab/LAB4.si4project/LAB4.sip_xab and /dev/null differ diff --git a/lab/LAB4.si4project/LAB4.sip_xad b/lab/LAB4.si4project/LAB4.sip_xad deleted file mode 100644 index 408fcf3..0000000 Binary files a/lab/LAB4.si4project/LAB4.sip_xad and /dev/null differ diff --git a/lab/LAB4.si4project/LAB4.sip_xm b/lab/LAB4.si4project/LAB4.sip_xm deleted file mode 100644 index 2b014e0..0000000 Binary files a/lab/LAB4.si4project/LAB4.sip_xm and /dev/null differ diff --git a/lab/LAB4.si4project/LAB4.sip_xsb b/lab/LAB4.si4project/LAB4.sip_xsb deleted file mode 100644 index def0f34..0000000 Binary files a/lab/LAB4.si4project/LAB4.sip_xsb and /dev/null differ diff --git a/lab/LAB4.si4project/LAB4.sip_xsd b/lab/LAB4.si4project/LAB4.sip_xsd deleted file mode 100644 index 1ae7230..0000000 Binary files a/lab/LAB4.si4project/LAB4.sip_xsd and /dev/null differ diff --git a/lab/LAB4.si4project/LAB4.siwork b/lab/LAB4.si4project/LAB4.siwork deleted file mode 100644 index 9e1dd08..0000000 Binary files a/lab/LAB4.si4project/LAB4.siwork and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/boot_main.c.sisc b/lab/LAB4.si4project/cache/parse/boot_main.c.sisc deleted file mode 100644 index b538876..0000000 Binary files a/lab/LAB4.si4project/cache/parse/boot_main.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/gradelib.py.sisc b/lab/LAB4.si4project/cache/parse/gradelib.py.sisc deleted file mode 100644 index 0d64c45..0000000 Binary files a/lab/LAB4.si4project/cache/parse/gradelib.py.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_assert.h.sisc b/lab/LAB4.si4project/cache/parse/inc_assert.h.sisc deleted file mode 100644 index 4d48776..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_assert.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_env.h.sisc b/lab/LAB4.si4project/cache/parse/inc_env.h.sisc deleted file mode 100644 index 0ecbd52..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_env.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_error.h.sisc b/lab/LAB4.si4project/cache/parse/inc_error.h.sisc deleted file mode 100644 index ebc864d..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_error.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_lib.h.sisc b/lab/LAB4.si4project/cache/parse/inc_lib.h.sisc deleted file mode 100644 index 314f201..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_lib.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_mmu.h.sisc b/lab/LAB4.si4project/cache/parse/inc_mmu.h.sisc deleted file mode 100644 index b0c1e71..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_mmu.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_stdarg.h.sisc b/lab/LAB4.si4project/cache/parse/inc_stdarg.h.sisc deleted file mode 100644 index a96ff79..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_stdarg.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_stdio.h.sisc b/lab/LAB4.si4project/cache/parse/inc_stdio.h.sisc deleted file mode 100644 index 0e4d523..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_stdio.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_string.h.sisc b/lab/LAB4.si4project/cache/parse/inc_string.h.sisc deleted file mode 100644 index c54d79f..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_string.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_syscall.h.sisc b/lab/LAB4.si4project/cache/parse/inc_syscall.h.sisc deleted file mode 100644 index 7410a23..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_syscall.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_types.h.sisc b/lab/LAB4.si4project/cache/parse/inc_types.h.sisc deleted file mode 100644 index 9048bad..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_types.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/inc_x86.h.sisc b/lab/LAB4.si4project/cache/parse/inc_x86.h.sisc deleted file mode 100644 index cdd006c..0000000 Binary files a/lab/LAB4.si4project/cache/parse/inc_x86.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_console.c.sisc b/lab/LAB4.si4project/cache/parse/kern_console.c.sisc deleted file mode 100644 index e08be43..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_console.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_console.h.sisc b/lab/LAB4.si4project/cache/parse/kern_console.h.sisc deleted file mode 100644 index f4df42f..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_console.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_cpu.h.sisc b/lab/LAB4.si4project/cache/parse/kern_cpu.h.sisc deleted file mode 100644 index bb59bbb..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_cpu.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_env.c.sisc b/lab/LAB4.si4project/cache/parse/kern_env.c.sisc deleted file mode 100644 index b245379..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_env.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_env.h.sisc b/lab/LAB4.si4project/cache/parse/kern_env.h.sisc deleted file mode 100644 index 6fd7040..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_env.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_init.c.sisc b/lab/LAB4.si4project/cache/parse/kern_init.c.sisc deleted file mode 100644 index 558f838..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_init.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_kclock.c.sisc b/lab/LAB4.si4project/cache/parse/kern_kclock.c.sisc deleted file mode 100644 index 5f1618d..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_kclock.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_kclock.h.sisc b/lab/LAB4.si4project/cache/parse/kern_kclock.h.sisc deleted file mode 100644 index a4a04b4..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_kclock.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_kdebug.h.sisc b/lab/LAB4.si4project/cache/parse/kern_kdebug.h.sisc deleted file mode 100644 index ea89564..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_kdebug.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_lapic.c.sisc b/lab/LAB4.si4project/cache/parse/kern_lapic.c.sisc deleted file mode 100644 index e3d2e33..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_lapic.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_monitor.c.sisc b/lab/LAB4.si4project/cache/parse/kern_monitor.c.sisc deleted file mode 100644 index c65b70b..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_monitor.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_monitor.h.sisc b/lab/LAB4.si4project/cache/parse/kern_monitor.h.sisc deleted file mode 100644 index 504848e..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_monitor.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_mpconfig.c.sisc b/lab/LAB4.si4project/cache/parse/kern_mpconfig.c.sisc deleted file mode 100644 index 65c70d5..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_mpconfig.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_picirq.c.sisc b/lab/LAB4.si4project/cache/parse/kern_picirq.c.sisc deleted file mode 100644 index 9c8a44c..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_picirq.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_picirq.h.sisc b/lab/LAB4.si4project/cache/parse/kern_picirq.h.sisc deleted file mode 100644 index b6c1a4c..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_picirq.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_pmap.c.sisc b/lab/LAB4.si4project/cache/parse/kern_pmap.c.sisc deleted file mode 100644 index 9948953..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_pmap.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_pmap.h.sisc b/lab/LAB4.si4project/cache/parse/kern_pmap.h.sisc deleted file mode 100644 index eaa9109..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_pmap.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_printf.c.sisc b/lab/LAB4.si4project/cache/parse/kern_printf.c.sisc deleted file mode 100644 index fda30fe..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_printf.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_sched.c.sisc b/lab/LAB4.si4project/cache/parse/kern_sched.c.sisc deleted file mode 100644 index d0f5a44..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_sched.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_sched.h.sisc b/lab/LAB4.si4project/cache/parse/kern_sched.h.sisc deleted file mode 100644 index fd9e774..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_sched.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_spinlock.c.sisc b/lab/LAB4.si4project/cache/parse/kern_spinlock.c.sisc deleted file mode 100644 index 71d85a8..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_spinlock.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_spinlock.h.sisc b/lab/LAB4.si4project/cache/parse/kern_spinlock.h.sisc deleted file mode 100644 index 3fbd34d..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_spinlock.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_syscall.c.sisc b/lab/LAB4.si4project/cache/parse/kern_syscall.c.sisc deleted file mode 100644 index eaaf1cd..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_syscall.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_syscall.h.sisc b/lab/LAB4.si4project/cache/parse/kern_syscall.h.sisc deleted file mode 100644 index 184330c..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_syscall.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_trap.c.sisc b/lab/LAB4.si4project/cache/parse/kern_trap.c.sisc deleted file mode 100644 index 3c3fc32..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_trap.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/kern_trap.h.sisc b/lab/LAB4.si4project/cache/parse/kern_trap.h.sisc deleted file mode 100644 index 74bd5a4..0000000 Binary files a/lab/LAB4.si4project/cache/parse/kern_trap.h.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_console.c.sisc b/lab/LAB4.si4project/cache/parse/lib_console.c.sisc deleted file mode 100644 index 4e0d806..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_console.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_exit.c.sisc b/lab/LAB4.si4project/cache/parse/lib_exit.c.sisc deleted file mode 100644 index 6bf2a4c..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_exit.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_fork.c.sisc b/lab/LAB4.si4project/cache/parse/lib_fork.c.sisc deleted file mode 100644 index b16393e..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_fork.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_ipc.c.sisc b/lab/LAB4.si4project/cache/parse/lib_ipc.c.sisc deleted file mode 100644 index fe1ff75..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_ipc.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_panic.c.sisc b/lab/LAB4.si4project/cache/parse/lib_panic.c.sisc deleted file mode 100644 index a5ec958..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_panic.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_pgfault.c.sisc b/lab/LAB4.si4project/cache/parse/lib_pgfault.c.sisc deleted file mode 100644 index 75639df..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_pgfault.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_printf.c.sisc b/lab/LAB4.si4project/cache/parse/lib_printf.c.sisc deleted file mode 100644 index 64eaab5..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_printf.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_printfmt.c.sisc b/lab/LAB4.si4project/cache/parse/lib_printfmt.c.sisc deleted file mode 100644 index 61a63cf..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_printfmt.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_readline.c.sisc b/lab/LAB4.si4project/cache/parse/lib_readline.c.sisc deleted file mode 100644 index 7d024d0..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_readline.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_string.c.sisc b/lab/LAB4.si4project/cache/parse/lib_string.c.sisc deleted file mode 100644 index 71b687f..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_string.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/lib_syscall.c.sisc b/lab/LAB4.si4project/cache/parse/lib_syscall.c.sisc deleted file mode 100644 index 120c2f9..0000000 Binary files a/lab/LAB4.si4project/cache/parse/lib_syscall.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_badsegment.c.sisc b/lab/LAB4.si4project/cache/parse/user_badsegment.c.sisc deleted file mode 100644 index dea973b..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_badsegment.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_breakpoint.c.sisc b/lab/LAB4.si4project/cache/parse/user_breakpoint.c.sisc deleted file mode 100644 index 5d1acfc..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_breakpoint.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_buggyhello.c.sisc b/lab/LAB4.si4project/cache/parse/user_buggyhello.c.sisc deleted file mode 100644 index b7c8e68..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_buggyhello.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_buggyhello2.c.sisc b/lab/LAB4.si4project/cache/parse/user_buggyhello2.c.sisc deleted file mode 100644 index be83d74..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_buggyhello2.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_divzero.c.sisc b/lab/LAB4.si4project/cache/parse/user_divzero.c.sisc deleted file mode 100644 index 23debe4..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_divzero.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_dumbfork.c.sisc b/lab/LAB4.si4project/cache/parse/user_dumbfork.c.sisc deleted file mode 100644 index 922a43b..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_dumbfork.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_evilhello.c.sisc b/lab/LAB4.si4project/cache/parse/user_evilhello.c.sisc deleted file mode 100644 index 893f330..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_evilhello.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_fairness.c.sisc b/lab/LAB4.si4project/cache/parse/user_fairness.c.sisc deleted file mode 100644 index a7556fc..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_fairness.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultalloc.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultalloc.c.sisc deleted file mode 100644 index b377b33..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultalloc.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultallocbad.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultallocbad.c.sisc deleted file mode 100644 index f1d041b..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultallocbad.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultbadhandler.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultbadhandler.c.sisc deleted file mode 100644 index 725d33c..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultbadhandler.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultdie.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultdie.c.sisc deleted file mode 100644 index c33871d..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultdie.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultevilhandler.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultevilhandler.c.sisc deleted file mode 100644 index 0fc8efc..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultevilhandler.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultnostack.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultnostack.c.sisc deleted file mode 100644 index d3c4a51..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultnostack.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultread.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultread.c.sisc deleted file mode 100644 index adb06bc..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultread.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultreadkernel.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultreadkernel.c.sisc deleted file mode 100644 index 0ba502a..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultreadkernel.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultregs.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultregs.c.sisc deleted file mode 100644 index a248b5a..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultregs.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultwrite.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultwrite.c.sisc deleted file mode 100644 index cbf5c38..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultwrite.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_faultwritekernel.c.sisc b/lab/LAB4.si4project/cache/parse/user_faultwritekernel.c.sisc deleted file mode 100644 index 89b7ff2..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_faultwritekernel.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_forktree.c.sisc b/lab/LAB4.si4project/cache/parse/user_forktree.c.sisc deleted file mode 100644 index 8984602..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_forktree.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_hello.c.sisc b/lab/LAB4.si4project/cache/parse/user_hello.c.sisc deleted file mode 100644 index 6601029..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_hello.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_idle.c.sisc b/lab/LAB4.si4project/cache/parse/user_idle.c.sisc deleted file mode 100644 index b9ba423..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_idle.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_pingpong.c.sisc b/lab/LAB4.si4project/cache/parse/user_pingpong.c.sisc deleted file mode 100644 index 01ae47d..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_pingpong.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_pingpongs.c.sisc b/lab/LAB4.si4project/cache/parse/user_pingpongs.c.sisc deleted file mode 100644 index 3fc4c1e..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_pingpongs.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_primes.c.sisc b/lab/LAB4.si4project/cache/parse/user_primes.c.sisc deleted file mode 100644 index 2a8d8b9..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_primes.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_sendpage.c.sisc b/lab/LAB4.si4project/cache/parse/user_sendpage.c.sisc deleted file mode 100644 index 02cf01a..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_sendpage.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_softint.c.sisc b/lab/LAB4.si4project/cache/parse/user_softint.c.sisc deleted file mode 100644 index 35fccfb..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_softint.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_spin.c.sisc b/lab/LAB4.si4project/cache/parse/user_spin.c.sisc deleted file mode 100644 index 4ef7835..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_spin.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_stresssched.c.sisc b/lab/LAB4.si4project/cache/parse/user_stresssched.c.sisc deleted file mode 100644 index 3001b8d..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_stresssched.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_testbss.c.sisc b/lab/LAB4.si4project/cache/parse/user_testbss.c.sisc deleted file mode 100644 index d8e5700..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_testbss.c.sisc and /dev/null differ diff --git a/lab/LAB4.si4project/cache/parse/user_yield.c.sisc b/lab/LAB4.si4project/cache/parse/user_yield.c.sisc deleted file mode 100644 index 8e99b55..0000000 Binary files a/lab/LAB4.si4project/cache/parse/user_yield.c.sisc and /dev/null differ diff --git a/lab/Untitled Project.si4project/Backup/bc(1629).c b/lab/Untitled Project.si4project/Backup/bc(1629).c new file mode 100644 index 0000000..e3922c4 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/bc(1629).c @@ -0,0 +1,151 @@ + +#include "fs.h" + +// Return the virtual address of this disk block. +void* +diskaddr(uint32_t blockno) +{ + if (blockno == 0 || (super && blockno >= super->s_nblocks)) + panic("bad block number %08x in diskaddr", blockno); + return (char*) (DISKMAP + blockno * BLKSIZE); +} + +// Is this virtual address mapped? +bool +va_is_mapped(void *va) +{ + return (uvpd[PDX(va)] & PTE_P) && (uvpt[PGNUM(va)] & PTE_P); +} + +// Is this virtual address dirty? +bool +va_is_dirty(void *va) +{ + return (uvpt[PGNUM(va)] & PTE_D) != 0; +} + +// Fault any disk block that is read in to memory by +// loading it from disk. +static void +bc_pgfault(struct UTrapframe *utf) +{ + void *addr = (void *) utf->utf_fault_va; + uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; + int r; + + // Check that the fault was within the block cache region + if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) + panic("page fault in FS: eip %08x, va %08x, err %04x", + utf->utf_eip, addr, utf->utf_err); + + // Sanity check the block number. + if (super && blockno >= super->s_nblocks) + panic("reading non-existent block %08x\n", blockno); + + // Allocate a page in the disk map region, read the contents + // of the block from the disk into that page. + // Hint: first round addr to page boundary. fs/ide.c has code to read + // the disk. + // + // LAB 5: you code here: + + // Clear the dirty bit for the disk block page since we just read the + // block from disk + if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0) + panic("in bc_pgfault, sys_page_map: %e", r); + + // Check that the block we read was allocated. (exercise for + // the reader: why do we do this *after* reading the block + // in?) + if (bitmap && block_is_free(blockno)) + panic("reading free block %08x\n", blockno); +} + +// Flush the contents of the block containing VA out to disk if +// necessary, then clear the PTE_D bit using sys_page_map. +// If the block is not in the block cache or is not dirty, does +// nothing. +// Hint: Use va_is_mapped, va_is_dirty, and ide_write. +// Hint: Use the PTE_SYSCALL constant when calling sys_page_map. +// Hint: Don't forget to round addr down. +void +flush_block(void *addr) +{ + uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; + + if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) + panic("flush_block of bad va %08x", addr); + + // LAB 5: Your code here. + panic("flush_block not implemented"); +} + +// Test that the block cache works, by smashing the superblock and +// reading it back. +static void +check_bc(void) +{ + struct Super backup; + + // back up super block + memmove(&backup, diskaddr(1), sizeof backup); + + // smash it + strcpy(diskaddr(1), "OOPS!\n"); + flush_block(diskaddr(1)); + assert(va_is_mapped(diskaddr(1))); + assert(!va_is_dirty(diskaddr(1))); + + // clear it out + sys_page_unmap(0, diskaddr(1)); + assert(!va_is_mapped(diskaddr(1))); + + // read it back in + assert(strcmp(diskaddr(1), "OOPS!\n") == 0); + + // fix it + memmove(diskaddr(1), &backup, sizeof backup); + flush_block(diskaddr(1)); + + // Now repeat the same experiment, but pass an unaligned address to + // flush_block. + + // back up super block + memmove(&backup, diskaddr(1), sizeof backup); + + // smash it + strcpy(diskaddr(1), "OOPS!\n"); + + // Pass an unaligned address to flush_block. + flush_block(diskaddr(1) + 20); + assert(va_is_mapped(diskaddr(1))); + + // Skip the !va_is_dirty() check because it makes the bug somewhat + // obscure and hence harder to debug. + //assert(!va_is_dirty(diskaddr(1))); + + // clear it out + sys_page_unmap(0, diskaddr(1)); + assert(!va_is_mapped(diskaddr(1))); + + // read it back in + assert(strcmp(diskaddr(1), "OOPS!\n") == 0); + + // fix it + memmove(diskaddr(1), &backup, sizeof backup); + flush_block(diskaddr(1)); + + cprintf("block cache is good\n"); +} + +void +bc_init(void) +{ + struct Super super; + set_pgfault_handler(bc_pgfault); + check_bc(); + + // cache the super block by reading it once + memmove(&super, diskaddr(1), sizeof super); +} + diff --git a/lab/Untitled Project.si4project/Backup/bc(3621).c b/lab/Untitled Project.si4project/Backup/bc(3621).c new file mode 100644 index 0000000..dd5f20d --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/bc(3621).c @@ -0,0 +1,169 @@ + +#include "fs.h" + +// Return the virtual address of this disk block. +void* +diskaddr(uint32_t blockno) +{ + if (blockno == 0 || (super && blockno >= super->s_nblocks)) + panic("bad block number %08x in diskaddr", blockno); + return (char*) (DISKMAP + blockno * BLKSIZE); +} + +// Is this virtual address mapped? +bool +va_is_mapped(void *va) +{ + return (uvpd[PDX(va)] & PTE_P) && (uvpt[PGNUM(va)] & PTE_P); +} + +// Is this virtual address dirty? +bool +va_is_dirty(void *va) +{ + return (uvpt[PGNUM(va)] & PTE_D) != 0; +} + +// Fault any disk block that is read in to memory by +// loading it from disk. +static void +bc_pgfault(struct UTrapframe *utf) +{ + void *addr = (void *) utf->utf_fault_va; + uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; + int r; + + // Check that the fault was within the block cache region + if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) + panic("page fault in FS: eip %08x, va %08x, err %04x", + utf->utf_eip, addr, utf->utf_err); + + // Sanity check the block number. + if (super && blockno >= super->s_nblocks) + panic("reading non-existent block %08x\n", blockno); + + // Allocate a page in the disk map region, read the contents + // of the block from the disk into that page. + // Hint: first round addr to page boundary. fs/ide.c has code to read + // the disk. + // + // LAB 5: you code here: + // envid 传入 0? 在最初的哪个进程下 alloc 一个page ? + addr =(void *) ROUNDDOWN(addr, PGSIZE); + if ( (r = sys_page_alloc(0, addr, PTE_P |PTE_W|PTE_U)) < 0) { + panic("in bc_pgfault, sys_page_alloc: %e", r); + } + // size_t secno = (addr - DISKMAP) / BLKSIZE; + if ( (r = ide_read(blockno*BLKSECTS, addr, BLKSECTS)) < 0) { + panic("in bc_pgfault, ide_read: %e",r); + } + + // Clear the dirty bit for the disk block page since we just read the + // block from disk + // 只是为了修改标志位 + if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0) + panic("in bc_pgfault, sys_page_map: %e", r); + + // Check that the block we read was allocated. (exercise for + // the reader: why do we do this *after* reading the block + // in?) + if (bitmap && block_is_free(blockno)) + panic("reading free block %08x\n", blockno); +} + +// Flush the contents of the block containing VA out to disk if +// necessary, then clear the PTE_D bit using sys_page_map. +// If the block is not in the block cache or is not dirty, does +// nothing. +// Hint: Use va_is_mapped, va_is_dirty, and ide_write. +// Hint: Use the PTE_SYSCALL constant when calling sys_page_map. +// Hint: Don't forget to round addr down. +void +flush_block(void *addr) +{ + uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; + + if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) + panic("flush_block of bad va %08x", addr); + int r; + // LAB 5: Your code here. + addr = (void *)ROUNDDOWN(addr, PGSIZE); + if (va_is_mapped(addr) && va_is_dirty(addr)) { + + ide_write(blockno*BLKSECTS, addr , BLKSECTS); + if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0) + panic("in flush_block, sys_page_map: %e", r); + } + + // panic("flush_block not implemented"); +} + +// Test that the block cache works, by smashing the superblock and +// reading it back. +static void +check_bc(void) +{ + struct Super backup; + + // back up super block + memmove(&backup, diskaddr(1), sizeof backup); + + // smash it + strcpy(diskaddr(1), "OOPS!\n"); + flush_block(diskaddr(1)); + assert(va_is_mapped(diskaddr(1))); + assert(!va_is_dirty(diskaddr(1))); + + // clear it out + sys_page_unmap(0, diskaddr(1)); + assert(!va_is_mapped(diskaddr(1))); + + // read it back in + assert(strcmp(diskaddr(1), "OOPS!\n") == 0); + + // fix it + memmove(diskaddr(1), &backup, sizeof backup); + flush_block(diskaddr(1)); + + // Now repeat the same experiment, but pass an unaligned address to + // flush_block. + + // back up super block + memmove(&backup, diskaddr(1), sizeof backup); + + // smash it + strcpy(diskaddr(1), "OOPS!\n"); + + // Pass an unaligned address to flush_block. + flush_block(diskaddr(1) + 20); + assert(va_is_mapped(diskaddr(1))); + + // Skip the !va_is_dirty() check because it makes the bug somewhat + // obscure and hence harder to debug. + //assert(!va_is_dirty(diskaddr(1))); + + // clear it out + sys_page_unmap(0, diskaddr(1)); + assert(!va_is_mapped(diskaddr(1))); + + // read it back in + assert(strcmp(diskaddr(1), "OOPS!\n") == 0); + + // fix it + memmove(diskaddr(1), &backup, sizeof backup); + flush_block(diskaddr(1)); + + cprintf("block cache is good\n"); +} + +void +bc_init(void) +{ + struct Super super; + set_pgfault_handler(bc_pgfault); + check_bc(); + + // cache the super block by reading it once + memmove(&super, diskaddr(1), sizeof super); +} + diff --git a/lab/LAB4.si4project/Backup/env(572).c b/lab/Untitled Project.si4project/Backup/env(3753).c similarity index 98% rename from lab/LAB4.si4project/Backup/env(572).c rename to lab/Untitled Project.si4project/Backup/env(3753).c index 7396b21..03d9a34 100644 --- a/lab/LAB4.si4project/Backup/env(572).c +++ b/lab/Untitled Project.si4project/Backup/env(3753).c @@ -263,7 +263,7 @@ env_alloc(struct Env **newenv_store, envid_t parent_id) // Enable interrupts while in user mode. // LAB 4: Your code here. - + e->env_tf.tf_eflags |= FL_IF; // Clear the page fault handler until user installs one. e->env_pgfault_upcall = 0; @@ -274,7 +274,7 @@ env_alloc(struct Env **newenv_store, envid_t parent_id) env_free_list = e->env_link; *newenv_store = e; - cprintf("[%08x] new env %08x\n", curenv ? curenv->env_id : 0, e->env_id); + // cprintf("[%08x] new env %08x\n", curenv ? curenv->env_id : 0, e->env_id); return 0; } @@ -415,6 +415,11 @@ void env_create(uint8_t *binary, enum EnvType type) { // LAB 3: Your code here. +<<<<<<< HEAD + + // If this is the file server (type == ENV_TYPE_FS) give it I/O privileges. + // LAB 5: Your code here. +======= struct Env *newenv; int ret = 0; if ((ret = env_alloc(&newenv, 0)) < 0) { @@ -423,6 +428,7 @@ env_create(uint8_t *binary, enum EnvType type) newenv->env_type = type; load_icode(newenv, binary); +>>>>>>> lab4 } // @@ -442,7 +448,7 @@ env_free(struct Env *e) lcr3(PADDR(kern_pgdir)); // Note the environment's demise. - cprintf("[%08x] free env %08x\n", curenv ? curenv->env_id : 0, e->env_id); + // cprintf("[%08x] free env %08x\n", curenv ? curenv->env_id : 0, e->env_id); // Flush all mapped pages in the user portion of the address space static_assert(UTOP % PTSIZE == 0); diff --git a/lab/LAB4.si4project/Backup/env(1818).c b/lab/Untitled Project.si4project/Backup/env(840).c similarity index 97% rename from lab/LAB4.si4project/Backup/env(1818).c rename to lab/Untitled Project.si4project/Backup/env(840).c index 746327b..2f03e35 100644 --- a/lab/LAB4.si4project/Backup/env(1818).c +++ b/lab/Untitled Project.si4project/Backup/env(840).c @@ -263,7 +263,7 @@ env_alloc(struct Env **newenv_store, envid_t parent_id) // Enable interrupts while in user mode. // LAB 4: Your code here. - + e->env_tf.tf_eflags |= FL_IF; // Clear the page fault handler until user installs one. e->env_pgfault_upcall = 0; @@ -274,7 +274,7 @@ env_alloc(struct Env **newenv_store, envid_t parent_id) env_free_list = e->env_link; *newenv_store = e; - cprintf("[%08x] new env %08x\n", curenv ? curenv->env_id : 0, e->env_id); + cprintf(".%08x. new env %08x\n", curenv ? curenv->env_id : 0, e->env_id); return 0; } @@ -415,14 +415,19 @@ void env_create(uint8_t *binary, enum EnvType type) { // LAB 3: Your code here. + struct Env *newenv; int ret = 0; if ((ret = env_alloc(&newenv, 0)) < 0) { panic("env_create: %e\n", ret); } newenv->env_type = type; + if (type == ENV_TYPE_FS) { + newenv->env_tf.tf_eflags |= FL_IOPL_MASK; + } load_icode(newenv, binary); - + // If this is the file server (type == ENV_TYPE_FS) give it I/O privileges. + // LAB 5: Your code here. } // @@ -442,7 +447,7 @@ env_free(struct Env *e) lcr3(PADDR(kern_pgdir)); // Note the environment's demise. - cprintf("[%08x] free env %08x\n", curenv ? curenv->env_id : 0, e->env_id); + cprintf(".%08x. free env %08x\n", curenv ? curenv->env_id : 0, e->env_id); // Flush all mapped pages in the user portion of the address space static_assert(UTOP % PTSIZE == 0); @@ -560,10 +565,13 @@ env_run(struct Env *e) curenv->env_status = ENV_RUNNING; curenv->env_runs++; lcr3(PADDR(curenv->env_pgdir)); - // 将当前进程的trapframe通过弹栈的形式,切换当前的运行环境 + + unlock_kernel(); + // iret退出内核, 回到用户环境执行, + // 在load_icode() 中 env_tf保存了可执行文件的eip等信息 env_pop_tf(&(curenv->env_tf)); - unlock_kernel(); + // panic("env_run not yet implemented"); } diff --git a/lab/Untitled Project.si4project/Backup/exit(6898).c b/lab/Untitled Project.si4project/Backup/exit(6898).c new file mode 100644 index 0000000..cee3336 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/exit(6898).c @@ -0,0 +1,10 @@ + +#include + +void +exit(void) +{ + close_all(); + sys_env_destroy(0); +} + diff --git a/lab/Untitled Project.si4project/Backup/faultio(2032).c b/lab/Untitled Project.si4project/Backup/faultio(2032).c new file mode 100644 index 0000000..4308a65 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/faultio(2032).c @@ -0,0 +1,22 @@ +// test user-level fault handler -- alloc pages to fix faults + +#include +#include + +void +umain(int argc, char **argv) +{ + int x, r; + int nsecs = 1; + int secno = 0; + int diskno = 1; + + if (read_eflags() & FL_IOPL_3) + cprintf("eflags wrong\n"); + + // this outb to select disk 1 should result in a general protection + // fault, because user-level code shouldn't be able to use the io space. + outb(0x1F6, 0xE0 | (1<<4)); + + cprintf("%s: made it here --- bug\n"); +} diff --git a/lab/Untitled Project.si4project/Backup/file(8133).c b/lab/Untitled Project.si4project/Backup/file(8133).c new file mode 100644 index 0000000..39025b2 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/file(8133).c @@ -0,0 +1,180 @@ +#include +#include +#include + +#define debug 0 + +union Fsipc fsipcbuf __attribute__((aligned(PGSIZE))); + +// Send an inter-environment request to the file server, and wait for +// a reply. The request body should be in fsipcbuf, and parts of the +// response may be written back to fsipcbuf. +// type: request code, passed as the simple integer IPC value. +// dstva: virtual address at which to receive reply page, 0 if none. +// Returns result from the file server. +static int +fsipc(unsigned type, void *dstva) +{ + static envid_t fsenv; + if (fsenv == 0) + fsenv = ipc_find_env(ENV_TYPE_FS); + + static_assert(sizeof(fsipcbuf) == PGSIZE); + + if (debug) + cprintf("[%08x] fsipc %d %08x\n", thisenv->env_id, type, *(uint32_t *)&fsipcbuf); + + ipc_send(fsenv, type, &fsipcbuf, PTE_P | PTE_W | PTE_U); + return ipc_recv(NULL, dstva, NULL); +} + +static int devfile_flush(struct Fd *fd); +static ssize_t devfile_read(struct Fd *fd, void *buf, size_t n); +static ssize_t devfile_write(struct Fd *fd, const void *buf, size_t n); +static int devfile_stat(struct Fd *fd, struct Stat *stat); +static int devfile_trunc(struct Fd *fd, off_t newsize); + +struct Dev devfile = +{ + .dev_id = 'f', + .dev_name = "file", + .dev_read = devfile_read, + .dev_close = devfile_flush, + .dev_stat = devfile_stat, + .dev_write = devfile_write, + .dev_trunc = devfile_trunc +}; + +// Open a file (or directory). +// +// Returns: +// The file descriptor index on success +// -E_BAD_PATH if the path is too long (>= MAXPATHLEN) +// < 0 for other errors. +int +open(const char *path, int mode) +{ + // Find an unused file descriptor page using fd_alloc. + // Then send a file-open request to the file server. + // Include 'path' and 'omode' in request, + // and map the returned file descriptor page + // at the appropriate fd address. + // FSREQ_OPEN returns 0 on success, < 0 on failure. + // + // (fd_alloc does not allocate a page, it just returns an + // unused fd address. Do you need to allocate a page?) + // + // Return the file descriptor index. + // If any step after fd_alloc fails, use fd_close to free the + // file descriptor. + + int r; + struct Fd *fd; + + if (strlen(path) >= MAXPATHLEN) + return -E_BAD_PATH; + + if ((r = fd_alloc(&fd)) < 0) + return r; + + strcpy(fsipcbuf.open.req_path, path); + fsipcbuf.open.req_omode = mode; + + if ((r = fsipc(FSREQ_OPEN, fd)) < 0) { + fd_close(fd, 0); + return r; + } + + return fd2num(fd); +} + +// Flush the file descriptor. After this the fileid is invalid. +// +// This function is called by fd_close. fd_close will take care of +// unmapping the FD page from this environment. Since the server uses +// the reference counts on the FD pages to detect which files are +// open, unmapping it is enough to free up server-side resources. +// Other than that, we just have to make sure our changes are flushed +// to disk. +static int +devfile_flush(struct Fd *fd) +{ + fsipcbuf.flush.req_fileid = fd->fd_file.id; + return fsipc(FSREQ_FLUSH, NULL); +} + +// Read at most 'n' bytes from 'fd' at the current position into 'buf'. +// +// Returns: +// The number of bytes successfully read. +// < 0 on error. +static ssize_t +devfile_read(struct Fd *fd, void *buf, size_t n) +{ + // Make an FSREQ_READ request to the file system server after + // filling fsipcbuf.read with the request arguments. The + // bytes read will be written back to fsipcbuf by the file + // system server. + int r; + + fsipcbuf.read.req_fileid = fd->fd_file.id; + fsipcbuf.read.req_n = n; + if ((r = fsipc(FSREQ_READ, NULL)) < 0) + return r; + assert(r <= n); + assert(r <= PGSIZE); + memmove(buf, fsipcbuf.readRet.ret_buf, r); + return r; +} + + +// Write at most 'n' bytes from 'buf' to 'fd' at the current seek position. +// +// Returns: +// The number of bytes successfully written. +// < 0 on error. +static ssize_t +devfile_write(struct Fd *fd, const void *buf, size_t n) +{ + // Make an FSREQ_WRITE request to the file system server. Be + // careful: fsipcbuf.write.req_buf is only so large, but + // remember that write is always allowed to write *fewer* + // bytes than requested. + // LAB 5: Your code here + panic("devfile_write not implemented"); +} + +static int +devfile_stat(struct Fd *fd, struct Stat *st) +{ + int r; + + fsipcbuf.stat.req_fileid = fd->fd_file.id; + if ((r = fsipc(FSREQ_STAT, NULL)) < 0) + return r; + strcpy(st->st_name, fsipcbuf.statRet.ret_name); + st->st_size = fsipcbuf.statRet.ret_size; + st->st_isdir = fsipcbuf.statRet.ret_isdir; + return 0; +} + +// Truncate or extend an open file to 'size' bytes +static int +devfile_trunc(struct Fd *fd, off_t newsize) +{ + fsipcbuf.set_size.req_fileid = fd->fd_file.id; + fsipcbuf.set_size.req_size = newsize; + return fsipc(FSREQ_SET_SIZE, NULL); +} + + +// Synchronize disk with buffer cache +int +sync(void) +{ + // Ask the file server to update the disk + // by writing any dirty blocks in the buffer cache. + + return fsipc(FSREQ_SYNC, NULL); +} + diff --git a/lab/Untitled Project.si4project/Backup/fork(6291).c b/lab/Untitled Project.si4project/Backup/fork(6291).c new file mode 100644 index 0000000..644e0c9 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/fork(6291).c @@ -0,0 +1,167 @@ +// implement fork from user space + +#include +#include + +// PTE_COW marks copy-on-write page table entries. +// It is one of the bits explicitly allocated to user processes (PTE_AVAIL). +#define PTE_COW 0x800 + +// +// 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 uvpt + // (see ). + + // LAB 4: Your code here. + if (! ( (err & FEC_WR) && (uvpd[PDX(addr)] & PTE_P) && (uvpt[PGNUM(addr)] & PTE_P) && (uvpt[PGNUM(addr)] & PTE_COW))) + panic("Neither the fault is a write nor COW page. \n"); + // 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. + + // LAB 4: Your code here. + envid_t envid = sys_getenvid(); + // cprintf("pgfault: envid: %d\n", ENVX(envid)); + // 临时页暂存 + if ((r = sys_page_alloc(envid, (void *)PFTEMP, PTE_P| PTE_W|PTE_U)) < 0) + panic("pgfault: page allocation fault:%e\n", r); + addr = ROUNDDOWN(addr, PGSIZE); + memcpy((void *) PFTEMP, (const void *) addr, PGSIZE); + if ((r = sys_page_map(envid, (void *) PFTEMP, envid, addr , PTE_P|PTE_W|PTE_U)) < 0 ) + panic("pgfault: page map failed %e\n", r); + + if ((r = sys_page_unmap(envid, (void *) PFTEMP)) < 0) + panic("pgfault: page unmap failed %e\n", r); + + + + // panic("pgfault not implemented"); +} + +// +// Map our virtual page pn (address pn*PGSIZE) into the target envid +// at the same virtual address. If the page is writable or copy-on-write, +// the new mapping must be created copy-on-write, and then our mapping must be +// marked copy-on-write as well. (Exercise: Why do we need to mark ours +// copy-on-write again if it was already copy-on-write at the beginning of +// this function?) +// +// Returns: 0 on success, < 0 on error. +// It is also OK to panic on error. +// + +static int +duppage(envid_t envid, unsigned pn) +{ + + // LAB 4: Your code here. + pte_t *pte; + int ret; + // 用户空间的地址较低 + uint32_t va = pn * PGSIZE; + + + if ( (uvpt[pn] & PTE_W) || (uvpt[pn] & PTE_COW)) { + + // 子进程标记 + if ((ret = sys_page_map(thisenv->env_id, (void *) va, envid, (void *) va, PTE_P|PTE_U|PTE_COW)) < 0) + return ret; + // 父进程标记 + if ((ret = sys_page_map(thisenv->env_id, (void *)va, thisenv->env_id, (void *)va, PTE_P|PTE_U|PTE_COW)) < 0) + return ret; + } + else { + // 简单映射 + if((ret = sys_page_map(thisenv->env_id, (void *) va, envid, (void * )va, PTE_P|PTE_U)) <0 ) + return ret; + } + + return 0; + // panic("duppage not implemented"); +} + + +// +// 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. + envid_t envid; + int r; + size_t i, j, pn; + // Set up our page fault handler + set_pgfault_handler(pgfault); + + envid = sys_exofork(); + + if (envid < 0) { + panic("sys_exofork failed: %e", envid); + } + + if (envid == 0) { + // child + thisenv = &envs[ENVX(sys_getenvid())]; + return 0; + } + // here is parent ! + // Copy our address space and page fault handler setup to the child. + + for (pn = PGNUM(UTEXT); pn < PGNUM(USTACKTOP); pn++) { + if ( (uvpd[pn >> 10] & PTE_P) && (uvpt[pn] & PTE_P)) { + // 页表 + if ( (r = duppage(envid, pn)) < 0) + return r; + + } + } + // alloc a page and map child exception stack + if ((r = sys_page_alloc(envid, (void *)(UXSTACKTOP-PGSIZE), PTE_U | PTE_P | PTE_W)) < 0) + return r; + extern void _pgfault_upcall(void); + if ((r = sys_env_set_pgfault_upcall(envid, _pgfault_upcall)) < 0) + return r; + + // Start the child environment running + if ((r = sys_env_set_status(envid, ENV_RUNNABLE)) < 0) + panic("sys_env_set_status: %e", r); + + return envid; + // panic("fork not implemented"); +} + +// Challenge! +int +sfork(void) +{ + panic("sfork not implemented"); + return -E_INVAL; +} diff --git a/lab/Untitled Project.si4project/Backup/fs(6931).c b/lab/Untitled Project.si4project/Backup/fs(6931).c new file mode 100644 index 0000000..45ecaf8 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/fs(6931).c @@ -0,0 +1,456 @@ +#include +#include + +#include "fs.h" + +// -------------------------------------------------------------- +// Super block +// -------------------------------------------------------------- + +// Validate the file system super-block. +void +check_super(void) +{ + if (super->s_magic != FS_MAGIC) + panic("bad file system magic number"); + + if (super->s_nblocks > DISKSIZE/BLKSIZE) + panic("file system is too large"); + + cprintf("superblock is good\n"); +} + +// -------------------------------------------------------------- +// Free block bitmap +// -------------------------------------------------------------- + +// Check to see if the block bitmap indicates that block 'blockno' is free. +// Return 1 if the block is free, 0 if not. +bool +block_is_free(uint32_t blockno) +{ + if (super == 0 || blockno >= super->s_nblocks) + return 0; + if (bitmap[blockno / 32] & (1 << (blockno % 32))) + return 1; + return 0; +} + +// Mark a block free in the bitmap +void +free_block(uint32_t blockno) +{ + // Blockno zero is the null pointer of block numbers. + if (blockno == 0) + panic("attempt to free zero block"); + bitmap[blockno/32] |= 1<<(blockno%32); +} + +// Search the bitmap for a free block and allocate it. When you +// allocate a block, immediately flush the changed bitmap block +// to disk. +// +// Return block number allocated on success, +// -E_NO_DISK if we are out of blocks. +// +// Hint: use free_block as an example for manipulating the bitmap. +int +alloc_block(void) +{ + // The bitmap consists of one or more blocks. A single bitmap block + // contains the in-use bits for BLKBITSIZE blocks. There are + // super->s_nblocks blocks in the disk altogether. + + // LAB 5: Your code here. + panic("alloc_block not implemented"); + return -E_NO_DISK; +} + +// Validate the file system bitmap. +// +// Check that all reserved blocks -- 0, 1, and the bitmap blocks themselves -- +// are all marked as in-use. +void +check_bitmap(void) +{ + uint32_t i; + + // Make sure all bitmap blocks are marked in-use + for (i = 0; i * BLKBITSIZE < super->s_nblocks; i++) + assert(!block_is_free(2+i)); + + // Make sure the reserved and root blocks are marked in-use. + assert(!block_is_free(0)); + assert(!block_is_free(1)); + + cprintf("bitmap is good\n"); +} + +// -------------------------------------------------------------- +// File system structures +// -------------------------------------------------------------- + + + +// Initialize the file system +void +fs_init(void) +{ + static_assert(sizeof(struct File) == 256); + + // Find a JOS disk. Use the second IDE disk (number 1) if available + if (ide_probe_disk1()) + ide_set_disk(1); + else + ide_set_disk(0); + bc_init(); + + // Set "super" to point to the super block. + super = diskaddr(1); + check_super(); + + // Set "bitmap" to the beginning of the first bitmap block. + bitmap = diskaddr(2); + check_bitmap(); + +} + +// Find the disk block number slot for the 'filebno'th block in file 'f'. +// Set '*ppdiskbno' to point to that slot. +// The slot will be one of the f->f_direct[] entries, +// or an entry in the indirect block. +// When 'alloc' is set, this function will allocate an indirect block +// if necessary. +// +// Returns: +// 0 on success (but note that *ppdiskbno might equal 0). +// -E_NOT_FOUND if the function needed to allocate an indirect block, but +// alloc was 0. +// -E_NO_DISK if there's no space on the disk for an indirect block. +// -E_INVAL if filebno is out of range (it's >= NDIRECT + NINDIRECT). +// +// Analogy: This is like pgdir_walk for files. +// Hint: Don't forget to clear any block you allocate. +static int +file_block_walk(struct File *f, uint32_t filebno, uint32_t **ppdiskbno, bool alloc) +{ + // LAB 5: Your code here. + panic("file_block_walk not implemented"); +} + +// Set *blk to the address in memory where the filebno'th +// block of file 'f' would be mapped. +// +// Returns 0 on success, < 0 on error. Errors are: +// -E_NO_DISK if a block needed to be allocated but the disk is full. +// -E_INVAL if filebno is out of range. +// +// Hint: Use file_block_walk and alloc_block. +int +file_get_block(struct File *f, uint32_t filebno, char **blk) +{ + // LAB 5: Your code here. + panic("file_get_block not implemented"); +} + +// Try to find a file named "name" in dir. If so, set *file to it. +// +// Returns 0 and sets *file on success, < 0 on error. Errors are: +// -E_NOT_FOUND if the file is not found +static int +dir_lookup(struct File *dir, const char *name, struct File **file) +{ + int r; + uint32_t i, j, nblock; + char *blk; + struct File *f; + + // Search dir for name. + // We maintain the invariant that the size of a directory-file + // is always a multiple of the file system's block size. + assert((dir->f_size % BLKSIZE) == 0); + nblock = dir->f_size / BLKSIZE; + for (i = 0; i < nblock; i++) { + if ((r = file_get_block(dir, i, &blk)) < 0) + return r; + f = (struct File*) blk; + for (j = 0; j < BLKFILES; j++) + if (strcmp(f[j].f_name, name) == 0) { + *file = &f[j]; + return 0; + } + } + return -E_NOT_FOUND; +} + +// Set *file to point at a free File structure in dir. The caller is +// responsible for filling in the File fields. +static int +dir_alloc_file(struct File *dir, struct File **file) +{ + int r; + uint32_t nblock, i, j; + char *blk; + struct File *f; + + assert((dir->f_size % BLKSIZE) == 0); + nblock = dir->f_size / BLKSIZE; + for (i = 0; i < nblock; i++) { + if ((r = file_get_block(dir, i, &blk)) < 0) + return r; + f = (struct File*) blk; + for (j = 0; j < BLKFILES; j++) + if (f[j].f_name[0] == '\0') { + *file = &f[j]; + return 0; + } + } + dir->f_size += BLKSIZE; + if ((r = file_get_block(dir, i, &blk)) < 0) + return r; + f = (struct File*) blk; + *file = &f[0]; + return 0; +} + +// Skip over slashes. +static const char* +skip_slash(const char *p) +{ + while (*p == '/') + p++; + return p; +} + +// Evaluate a path name, starting at the root. +// On success, set *pf to the file we found +// and set *pdir to the directory the file is in. +// If we cannot find the file but find the directory +// it should be in, set *pdir and copy the final path +// element into lastelem. +static int +walk_path(const char *path, struct File **pdir, struct File **pf, char *lastelem) +{ + const char *p; + char name[MAXNAMELEN]; + struct File *dir, *f; + int r; + + // if (*path != '/') + // return -E_BAD_PATH; + path = skip_slash(path); + f = &super->s_root; + dir = 0; + name[0] = 0; + + if (pdir) + *pdir = 0; + *pf = 0; + while (*path != '\0') { + dir = f; + p = path; + while (*path != '/' && *path != '\0') + path++; + if (path - p >= MAXNAMELEN) + return -E_BAD_PATH; + memmove(name, p, path - p); + name[path - p] = '\0'; + path = skip_slash(path); + + if (dir->f_type != FTYPE_DIR) + return -E_NOT_FOUND; + + if ((r = dir_lookup(dir, name, &f)) < 0) { + if (r == -E_NOT_FOUND && *path == '\0') { + if (pdir) + *pdir = dir; + if (lastelem) + strcpy(lastelem, name); + *pf = 0; + } + return r; + } + } + + if (pdir) + *pdir = dir; + *pf = f; + return 0; +} + +// -------------------------------------------------------------- +// File operations +// -------------------------------------------------------------- + +// Create "path". On success set *pf to point at the file and return 0. +// On error return < 0. +int +file_create(const char *path, struct File **pf) +{ + char name[MAXNAMELEN]; + int r; + struct File *dir, *f; + + if ((r = walk_path(path, &dir, &f, name)) == 0) + return -E_FILE_EXISTS; + if (r != -E_NOT_FOUND || dir == 0) + return r; + if ((r = dir_alloc_file(dir, &f)) < 0) + return r; + + strcpy(f->f_name, name); + *pf = f; + file_flush(dir); + return 0; +} + +// Open "path". On success set *pf to point at the file and return 0. +// On error return < 0. +int +file_open(const char *path, struct File **pf) +{ + return walk_path(path, 0, pf, 0); +} + +// Read count bytes from f into buf, starting from seek position +// offset. This meant to mimic the standard pread function. +// Returns the number of bytes read, < 0 on error. +ssize_t +file_read(struct File *f, void *buf, size_t count, off_t offset) +{ + int r, bn; + off_t pos; + char *blk; + + if (offset >= f->f_size) + return 0; + + count = MIN(count, f->f_size - offset); + + for (pos = offset; pos < offset + count; ) { + if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0) + return r; + bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos); + memmove(buf, blk + pos % BLKSIZE, bn); + pos += bn; + buf += bn; + } + + return count; +} + + +// Write count bytes from buf into f, starting at seek position +// offset. This is meant to mimic the standard pwrite function. +// Extends the file if necessary. +// Returns the number of bytes written, < 0 on error. +int +file_write(struct File *f, const void *buf, size_t count, off_t offset) +{ + int r, bn; + off_t pos; + char *blk; + + // Extend file if necessary + if (offset + count > f->f_size) + if ((r = file_set_size(f, offset + count)) < 0) + return r; + + for (pos = offset; pos < offset + count; ) { + if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0) + return r; + bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos); + memmove(blk + pos % BLKSIZE, buf, bn); + pos += bn; + buf += bn; + } + + return count; +} + +// Remove a block from file f. If it's not there, just silently succeed. +// Returns 0 on success, < 0 on error. +static int +file_free_block(struct File *f, uint32_t filebno) +{ + int r; + uint32_t *ptr; + + if ((r = file_block_walk(f, filebno, &ptr, 0)) < 0) + return r; + if (*ptr) { + free_block(*ptr); + *ptr = 0; + } + return 0; +} + +// Remove any blocks currently used by file 'f', +// but not necessary for a file of size 'newsize'. +// For both the old and new sizes, figure out the number of blocks required, +// and then clear the blocks from new_nblocks to old_nblocks. +// If the new_nblocks is no more than NDIRECT, and the indirect block has +// been allocated (f->f_indirect != 0), then free the indirect block too. +// (Remember to clear the f->f_indirect pointer so you'll know +// whether it's valid!) +// Do not change f->f_size. +static void +file_truncate_blocks(struct File *f, off_t newsize) +{ + int r; + uint32_t bno, old_nblocks, new_nblocks; + + old_nblocks = (f->f_size + BLKSIZE - 1) / BLKSIZE; + new_nblocks = (newsize + BLKSIZE - 1) / BLKSIZE; + for (bno = new_nblocks; bno < old_nblocks; bno++) + if ((r = file_free_block(f, bno)) < 0) + cprintf("warning: file_free_block: %e", r); + + if (new_nblocks <= NDIRECT && f->f_indirect) { + free_block(f->f_indirect); + f->f_indirect = 0; + } +} + +// Set the size of file f, truncating or extending as necessary. +int +file_set_size(struct File *f, off_t newsize) +{ + if (f->f_size > newsize) + file_truncate_blocks(f, newsize); + f->f_size = newsize; + flush_block(f); + return 0; +} + +// Flush the contents and metadata of file f out to disk. +// Loop over all the blocks in file. +// Translate the file block number into a disk block number +// and then check whether that disk block is dirty. If so, write it out. +void +file_flush(struct File *f) +{ + int i; + uint32_t *pdiskbno; + + for (i = 0; i < (f->f_size + BLKSIZE - 1) / BLKSIZE; i++) { + if (file_block_walk(f, i, &pdiskbno, 0) < 0 || + pdiskbno == NULL || *pdiskbno == 0) + continue; + flush_block(diskaddr(*pdiskbno)); + } + flush_block(f); + if (f->f_indirect) + flush_block(diskaddr(f->f_indirect)); +} + + +// Sync the entire file system. A big hammer. +void +fs_sync(void) +{ + int i; + for (i = 1; i < super->s_nblocks; i++) + flush_block(diskaddr(i)); +} + diff --git a/lab/Untitled Project.si4project/Backup/fs(7516).c b/lab/Untitled Project.si4project/Backup/fs(7516).c new file mode 100644 index 0000000..0b9b76e --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/fs(7516).c @@ -0,0 +1,515 @@ +#include +#include + +#include "fs.h" + +// -------------------------------------------------------------- +// Super block +// -------------------------------------------------------------- + +// Validate the file system super-block. +void +check_super(void) +{ + if (super->s_magic != FS_MAGIC) + panic("bad file system magic number"); + + if (super->s_nblocks > DISKSIZE/BLKSIZE) + panic("file system is too large"); + + cprintf("superblock is good\n"); +} + +// -------------------------------------------------------------- +// Free block bitmap +// -------------------------------------------------------------- + +// Check to see if the block bitmap indicates that block 'blockno' is free. +// Return 1 if the block is free, 0 if not. +bool +block_is_free(uint32_t blockno) +{ + if (super == 0 || blockno >= super->s_nblocks) + return 0; + if (bitmap[blockno / 32] & (1 << (blockno % 32))) + return 1; + return 0; +} + +// Mark a block free in the bitmap +void +free_block(uint32_t blockno) +{ + // Blockno zero is the null pointer of block numbers. + // 0 块启动块 + if (blockno == 0) + panic("attempt to free zero block"); + bitmap[blockno/32] |= 1<<(blockno%32); +} + +// Search the bitmap for a free block and allocate it. When you +// allocate a block, immediately flush the changed bitmap block +// to disk. +// +// Return block number allocated on success, +// -E_NO_DISK if we are out of blocks. +// +// Hint: use free_block as an example for manipulating the bitmap. +int +alloc_block(void) +{ + // The bitmap consists of one or more blocks. A single bitmap block + // contains the in-use bits for BLKBITSIZE blocks. There are + // super->s_nblocks blocks in the disk altogether. + + // LAB 5: Your code here. + size_t i; + for(i=1; i < super->s_nblocks; i++) { + if (block_is_free(i)) { + bitmap[i/32] &= ~(1<<(i%32)); + flush_block(&bitmap[i/32]); + return i; + } + } + // panic("alloc_block not implemented"); + return -E_NO_DISK; +} + +// Validate the file system bitmap. +// +// Check that all reserved blocks -- 0, 1, and the bitmap blocks themselves -- +// are all marked as in-use. +void +check_bitmap(void) +{ + uint32_t i; + + // Make sure all bitmap blocks are marked in-use + for (i = 0; i * BLKBITSIZE < super->s_nblocks; i++) + assert(!block_is_free(2+i)); + + // Make sure the reserved and root blocks are marked in-use. + assert(!block_is_free(0)); + assert(!block_is_free(1)); + + cprintf("bitmap is good\n"); +} + +// -------------------------------------------------------------- +// File system structures +// -------------------------------------------------------------- + + + +// Initialize the file system +void +fs_init(void) +{ + static_assert(sizeof(struct File) == 256); + + // Find a JOS disk. Use the second IDE disk (number 1) if available + if (ide_probe_disk1()) + ide_set_disk(1); + else + ide_set_disk(0); + bc_init(); + + // Set "super" to point to the super block. + super = diskaddr(1); + check_super(); + + // Set "bitmap" to the beginning of the first bitmap block. + bitmap = diskaddr(2); + check_bitmap(); + +} + +// Find the disk block number slot for the 'filebno'th block in file 'f'. +// Set '*ppdiskbno' to point to that slot. +// The slot will be one of the f->f_direct[] entries, +// or an entry in the indirect block. +// When 'alloc' is set, this function will allocate an indirect block +// if necessary. +// +// Returns: +// 0 on success (but note that *ppdiskbno might equal 0). +// -E_NOT_FOUND if the function needed to allocate an indirect block, but +// alloc was 0. +// -E_NO_DISK if there's no space on the disk for an indirect block. +// -E_INVAL if filebno is out of range (it's >= NDIRECT + NINDIRECT). +// +// Analogy: This is like pgdir_walk for files. +// Hint: Don't forget to clear any block you allocate. +static int +file_block_walk(struct File *f, uint32_t filebno, uint32_t **ppdiskbno, bool alloc) +{ + // LAB 5: Your code here. + // ppdiskbno 块指针 + if (filebno < NDIRECT) { + // but note that *ppdiskbno might equal 0 + if(ppdiskbno) + *ppdiskbno = &(f->f_direct[filebno]); + + return 0; + } + + if (filebno >= (NDIRECT + NINDIRECT)) + return -E_INVAL; + + filebno -= NDIRECT; + // indirect 还未分配 + if (!f->f_indirect) { + if (alloc == 0) + return -E_NOT_FOUND; + // 分配一个 indirect block + uint32_t blockno; + if ( (blockno = alloc_block()) < 0) + return blockno; + // f_indirect 直接记录块号,而不是记地址 + // f->f_indirect = (uint32_t)diskaddr(blockno); + f->f_indirect = blockno; + memset(diskaddr(blockno), 0, BLKSIZE); + flush_block(diskaddr(blockno)); + } + if (ppdiskbno) + *ppdiskbno = (uint32_t *)diskaddr(f->f_indirect) + filebno; + return 0; + // panic("file_block_walk not implemented"); +} + +// Set *blk to the address in memory where the filebno'th +// block of file 'f' would be mapped. +// +// Returns 0 on success, < 0 on error. Errors are: +// -E_NO_DISK if a block needed to be allocated but the disk is full. +// -E_INVAL if filebno is out of range. +// +// Hint: Use file_block_walk and alloc_block. +int +file_get_block(struct File *f, uint32_t filebno, char **blk) +{ + // LAB 5: Your code here. + uint32_t *pdiskbno; + int r; + if ( (r = file_block_walk(f, filebno, &pdiskbno, 1))< 0) + return r; + + if(*pdiskbno == 0) { + // 文件块还未分配 + if ( (r = alloc_block()) < 0) + return r; + *pdiskbno = r; + memset(diskaddr(r), 0, BLKSIZE); + flush_block(diskaddr(r)); + } + + // 最终指向块 + *blk = diskaddr(*pdiskbno); + return 0; + //panic("file_get_block not implemented"); +} + +// Try to find a file named "name" in dir. If so, set *file to it. +// +// Returns 0 and sets *file on success, < 0 on error. Errors are: +// -E_NOT_FOUND if the file is not found +static int +dir_lookup(struct File *dir, const char *name, struct File **file) +{ + int r; + uint32_t i, j, nblock; + char *blk; + struct File *f; + + // Search dir for name. + // We maintain the invariant that the size of a directory-file + // is always a multiple of the file system's block size. + // 目录size 必须为 文件系统块size的倍数。 + assert((dir->f_size % BLKSIZE) == 0); + nblock = dir->f_size / BLKSIZE; + for (i = 0; i < nblock; i++) { + if ((r = file_get_block(dir, i, &blk)) < 0) + return r; + f = (struct File*) blk; + for (j = 0; j < BLKFILES; j++) + // 不会出现子目录与文件同名吗? + if (strcmp(f[j].f_name, name) == 0) { + *file = &f[j]; + return 0; + } + } + return -E_NOT_FOUND; +} + +// Set *file to point at a free File structure in dir. The caller is +// responsible for filling in the File fields. +static int +dir_alloc_file(struct File *dir, struct File **file) +{ + int r; + uint32_t nblock, i, j; + char *blk; + struct File *f; + + assert((dir->f_size % BLKSIZE) == 0); + nblock = dir->f_size / BLKSIZE; + for (i = 0; i < nblock; i++) { + if ((r = file_get_block(dir, i, &blk)) < 0) + return r; + f = (struct File*) blk; + for (j = 0; j < BLKFILES; j++) + if (f[j].f_name[0] == '\0') { + *file = &f[j]; + return 0; + } + } + // 目录里没有空项,增添一个块 + dir->f_size += BLKSIZE; + if ((r = file_get_block(dir, i, &blk)) < 0) + return r; + f = (struct File*) blk; + *file = &f[0]; + return 0; +} + +// Skip over slashes. +static const char* +skip_slash(const char *p) +{ + while (*p == '/') + p++; + return p; +} + +// Evaluate a path name, starting at the root. +// On success, set *pf to the file we found +// and set *pdir to the directory the file is in. +// If we cannot find the file but find the directory +// it should be in, set *pdir and copy the final path +// element into lastelem. +static int +walk_path(const char *path, struct File **pdir, struct File **pf, char *lastelem) +{ + const char *p; + char name[MAXNAMELEN]; + struct File *dir, *f; + int r; + + // if (*path != '/') + // return -E_BAD_PATH; + path = skip_slash(path); + f = &super->s_root; + dir = 0; + name[0] = 0; + + if (pdir) + *pdir = 0; + *pf = 0; + while (*path != '\0') { + dir = f; + p = path; + while (*path != '/' && *path != '\0') + path++; + if (path - p >= MAXNAMELEN) + return -E_BAD_PATH; + memmove(name, p, path - p); + name[path - p] = '\0'; + path = skip_slash(path); + + if (dir->f_type != FTYPE_DIR) + return -E_NOT_FOUND; + + if ((r = dir_lookup(dir, name, &f)) < 0) { + if (r == -E_NOT_FOUND && *path == '\0') { + if (pdir) + *pdir = dir; + if (lastelem) + strcpy(lastelem, name); + *pf = 0; + } + return r; + } + } + + if (pdir) + *pdir = dir; + *pf = f; + return 0; +} + +// -------------------------------------------------------------- +// File operations +// -------------------------------------------------------------- + +// Create "path". On success set *pf to point at the file and return 0. +// On error return < 0. +int +file_create(const char *path, struct File **pf) +{ + char name[MAXNAMELEN]; + int r; + struct File *dir, *f; + + if ((r = walk_path(path, &dir, &f, name)) == 0) + return -E_FILE_EXISTS; + if (r != -E_NOT_FOUND || dir == 0) + return r; + if ((r = dir_alloc_file(dir, &f)) < 0) + return r; + + strcpy(f->f_name, name); + *pf = f; + file_flush(dir); + return 0; +} + +// Open "path". On success set *pf to point at the file and return 0. +// On error return < 0. +int +file_open(const char *path, struct File **pf) +{ + return walk_path(path, 0, pf, 0); +} + +// Read count bytes from f into buf, starting from seek position +// offset. This meant to mimic the standard pread function. +// Returns the number of bytes read, < 0 on error. +ssize_t +file_read(struct File *f, void *buf, size_t count, off_t offset) +{ + int r, bn; + off_t pos; + char *blk; + + if (offset >= f->f_size) + return 0; + + count = MIN(count, f->f_size - offset); + + for (pos = offset; pos < offset + count; ) { + if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0) + return r; + bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos); + memmove(buf, blk + pos % BLKSIZE, bn); + pos += bn; + buf += bn; + } + + return count; +} + + +// Write count bytes from buf into f, starting at seek position +// offset. This is meant to mimic the standard pwrite function. +// Extends the file if necessary. +// Returns the number of bytes written, < 0 on error. +int +file_write(struct File *f, const void *buf, size_t count, off_t offset) +{ + int r, bn; + off_t pos; + char *blk; + + // Extend file if necessary + if (offset + count > f->f_size) + if ((r = file_set_size(f, offset + count)) < 0) + return r; + + for (pos = offset; pos < offset + count; ) { + if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0) + return r; + bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos); + memmove(blk + pos % BLKSIZE, buf, bn); + pos += bn; + buf += bn; + } + + return count; +} + +// Remove a block from file f. If it's not there, just silently succeed. +// Returns 0 on success, < 0 on error. +static int +file_free_block(struct File *f, uint32_t filebno) +{ + int r; + uint32_t *ptr; + + if ((r = file_block_walk(f, filebno, &ptr, 0)) < 0) + return r; + if (*ptr) { + free_block(*ptr); + *ptr = 0; + } + return 0; +} + +// Remove any blocks currently used by file 'f', +// but not necessary for a file of size 'newsize'. +// For both the old and new sizes, figure out the number of blocks required, +// and then clear the blocks from new_nblocks to old_nblocks. +// If the new_nblocks is no more than NDIRECT, and the indirect block has +// been allocated (f->f_indirect != 0), then free the indirect block too. +// (Remember to clear the f->f_indirect pointer so you'll know +// whether it's valid!) +// Do not change f->f_size. +static void +file_truncate_blocks(struct File *f, off_t newsize) +{ + int r; + uint32_t bno, old_nblocks, new_nblocks; + + old_nblocks = (f->f_size + BLKSIZE - 1) / BLKSIZE; + new_nblocks = (newsize + BLKSIZE - 1) / BLKSIZE; + for (bno = new_nblocks; bno < old_nblocks; bno++) + if ((r = file_free_block(f, bno)) < 0) + cprintf("warning: file_free_block: %e", r); + + if (new_nblocks <= NDIRECT && f->f_indirect) { + free_block(f->f_indirect); + f->f_indirect = 0; + } +} + +// Set the size of file f, truncating or extending as necessary. +int +file_set_size(struct File *f, off_t newsize) +{ + if (f->f_size > newsize) + file_truncate_blocks(f, newsize); + f->f_size = newsize; + flush_block(f); + return 0; +} + +// Flush the contents and metadata of file f out to disk. +// Loop over all the blocks in file. +// Translate the file block number into a disk block number +// and then check whether that disk block is dirty. If so, write it out. +void +file_flush(struct File *f) +{ + int i; + uint32_t *pdiskbno; + + for (i = 0; i < (f->f_size + BLKSIZE - 1) / BLKSIZE; i++) { + if (file_block_walk(f, i, &pdiskbno, 0) < 0 || + pdiskbno == NULL || *pdiskbno == 0) + continue; + flush_block(diskaddr(*pdiskbno)); + } + flush_block(f); + if (f->f_indirect) + flush_block(diskaddr(f->f_indirect)); +} + + +// Sync the entire file system. A big hammer. +void +fs_sync(void) +{ + int i; + for (i = 1; i < super->s_nblocks; i++) + flush_block(diskaddr(i)); +} + diff --git a/lab/Untitled Project.si4project/Backup/init(5052).c b/lab/Untitled Project.si4project/Backup/init(5052).c new file mode 100644 index 0000000..0ca8221 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/init(5052).c @@ -0,0 +1,180 @@ +/* See COPYRIGHT for copyright information. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void boot_aps(void); + + +void +i386_init(void) +{ + // Initialize the console. + // Can't call cprintf until after we do this! + cons_init(); + + cprintf("6828 decimal is %o octal!\n", 6828); + + // Lab 2 memory management initialization functions + mem_init(); + + // Lab 3 user environment initialization functions + env_init(); + trap_init(); + + // Lab 4 multiprocessor initialization functions + mp_init(); + lapic_init(); + + // Lab 4 multitasking initialization functions + pic_init(); + + // Acquire the big kernel lock before waking up APs + // Your code here: + lock_kernel(); + // Starting non-boot CPUs + boot_aps(); + + // Start fs. + ENV_CREATE(fs_fs, ENV_TYPE_FS); + +#if defined(TEST) + // Don't touch -- used by grading script! + ENV_CREATE(TEST, ENV_TYPE_USER); +#else + // Touch all you want. +<<<<<<< HEAD + ENV_CREATE(user_icode, ENV_TYPE_USER); +======= + //ENV_CREATE(user_primes, ENV_TYPE_USER); + ENV_CREATE(user_yield, ENV_TYPE_USER); + ENV_CREATE(user_yield, ENV_TYPE_USER); + ENV_CREATE(user_yield, ENV_TYPE_USER); + ENV_CREATE(user_yield, ENV_TYPE_USER); + + +>>>>>>> lab4 +#endif // TEST* + + // Should not be necessary - drains keyboard because interrupt has given up. + kbd_intr(); + + // Schedule and run the first user environment! + sched_yield(); +} + +// While boot_aps is booting a given CPU, it communicates the per-core +// stack pointer that should be loaded by mpentry.S to that CPU in +// this variable. +void *mpentry_kstack; + +// Start the non-boot (AP) processors. +static void +boot_aps(void) +{ + extern unsigned char mpentry_start[], mpentry_end[]; + void *code; + struct CpuInfo *c; + + // Write entry code to unused memory at MPENTRY_PADDR + code = KADDR(MPENTRY_PADDR); + memmove(code, mpentry_start, mpentry_end - mpentry_start); + + // Boot each AP one at a time + for (c = cpus; c < cpus + ncpu; c++) { + if (c == cpus + cpunum()) // We've started already. + continue; + + // Tell mpentry.S what stack to use + mpentry_kstack = percpu_kstacks[c - cpus] + KSTKSIZE; + // Start the CPU at mpentry_start + lapic_startap(c->cpu_id, PADDR(code)); + // Wait for the CPU to finish some basic setup in mp_main() + while(c->cpu_status != CPU_STARTED) + ; + } +} + +// Setup code for APs +void +mp_main(void) +{ + // We are in high EIP now, safe to switch to kern_pgdir + lcr3(PADDR(kern_pgdir)); + cprintf("SMP: CPU %d starting\n", cpunum()); + + lapic_init(); + env_init_percpu(); + trap_init_percpu(); + xchg(&thiscpu->cpu_status, CPU_STARTED); // tell boot_aps() we're up + + // Now that we have finished some basic setup, call sched_yield() + // to start running processes on this CPU. But make sure that + // only one CPU can enter the scheduler at a time! + // + // Your code here: + lock_kernel(); + + sched_yield(); + // Remove this after you finish Exercise 6 + for (;;); +} + +/* + * Variable panicstr contains argument to first call to panic; used as flag + * to indicate that the kernel has already called panic. + */ +const char *panicstr; + +/* + * Panic is called on unresolvable fatal errors. + * It prints "panic: mesg", and then enters the kernel monitor. + */ +void +_panic(const char *file, int line, const char *fmt,...) +{ + va_list ap; + + if (panicstr) + goto dead; + panicstr = fmt; + + // Be extra sure that the machine is in as reasonable state + asm volatile("cli; cld"); + + va_start(ap, fmt); + cprintf("kernel panic on CPU %d at %s:%d: ", cpunum(), file, line); + vcprintf(fmt, ap); + cprintf("\n"); + va_end(ap); + +dead: + /* break into the kernel monitor */ + while (1) + monitor(NULL); +} + +/* like panic, but don't */ +void +_warn(const char *file, int line, const char *fmt,...) +{ + va_list ap; + + va_start(ap, fmt); + cprintf("kernel warning at %s:%d: ", file, line); + vcprintf(fmt, ap); + cprintf("\n"); + va_end(ap); +} diff --git a/lab/Untitled Project.si4project/Backup/init(7465).c b/lab/Untitled Project.si4project/Backup/init(7465).c new file mode 100644 index 0000000..afe4745 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/init(7465).c @@ -0,0 +1,174 @@ +/* See COPYRIGHT for copyright information. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void boot_aps(void); + + +void +i386_init(void) +{ + // Initialize the console. + // Can't call cprintf until after we do this! + cons_init(); + + cprintf("6828 decimal is %o octal!\n", 6828); + + // Lab 2 memory management initialization functions + mem_init(); + + // Lab 3 user environment initialization functions + env_init(); + trap_init(); + + // Lab 4 multiprocessor initialization functions + mp_init(); + lapic_init(); + + // Lab 4 multitasking initialization functions + pic_init(); + + // Acquire the big kernel lock before waking up APs + // Your code here: + lock_kernel(); + // Starting non-boot CPUs + boot_aps(); + + // Start fs. + ENV_CREATE(fs_fs, ENV_TYPE_FS); + +#if defined(TEST) + // Don't touch -- used by grading script! + ENV_CREATE(TEST, ENV_TYPE_USER); +#else + // Touch all you want. + ENV_CREATE(user_yield, ENV_TYPE_USER); + ENV_CREATE(user_yield, ENV_TYPE_USER); + ENV_CREATE(user_yield, ENV_TYPE_USER); + ENV_CREATE(user_yield, ENV_TYPE_USER); + +#endif // TEST* + + // Should not be necessary - drains keyboard because interrupt has given up. + kbd_intr(); + + // Schedule and run the first user environment! + sched_yield(); +} + +// While boot_aps is booting a given CPU, it communicates the per-core +// stack pointer that should be loaded by mpentry.S to that CPU in +// this variable. +void *mpentry_kstack; + +// Start the non-boot (AP) processors. +static void +boot_aps(void) +{ + extern unsigned char mpentry_start[], mpentry_end[]; + void *code; + struct CpuInfo *c; + + // Write entry code to unused memory at MPENTRY_PADDR + code = KADDR(MPENTRY_PADDR); + memmove(code, mpentry_start, mpentry_end - mpentry_start); + + // Boot each AP one at a time + for (c = cpus; c < cpus + ncpu; c++) { + if (c == cpus + cpunum()) // We've started already. + continue; + + // Tell mpentry.S what stack to use + mpentry_kstack = percpu_kstacks[c - cpus] + KSTKSIZE; + // Start the CPU at mpentry_start + lapic_startap(c->cpu_id, PADDR(code)); + // Wait for the CPU to finish some basic setup in mp_main() + while(c->cpu_status != CPU_STARTED) + ; + } +} + +// Setup code for APs +void +mp_main(void) +{ + // We are in high EIP now, safe to switch to kern_pgdir + lcr3(PADDR(kern_pgdir)); + cprintf("SMP: CPU %d starting\n", cpunum()); + + lapic_init(); + env_init_percpu(); + trap_init_percpu(); + xchg(&thiscpu->cpu_status, CPU_STARTED); // tell boot_aps() we're up + + // Now that we have finished some basic setup, call sched_yield() + // to start running processes on this CPU. But make sure that + // only one CPU can enter the scheduler at a time! + // + // Your code here: + lock_kernel(); + + sched_yield(); + // Remove this after you finish Exercise 6 + for (;;); +} + +/* + * Variable panicstr contains argument to first call to panic; used as flag + * to indicate that the kernel has already called panic. + */ +const char *panicstr; + +/* + * Panic is called on unresolvable fatal errors. + * It prints "panic: mesg", and then enters the kernel monitor. + */ +void +_panic(const char *file, int line, const char *fmt,...) +{ + va_list ap; + + if (panicstr) + goto dead; + panicstr = fmt; + + // Be extra sure that the machine is in as reasonable state + asm volatile("cli; cld"); + + va_start(ap, fmt); + cprintf("kernel panic on CPU %d at %s:%d: ", cpunum(), file, line); + vcprintf(fmt, ap); + cprintf("\n"); + va_end(ap); + +dead: + /* break into the kernel monitor */ + while (1) + monitor(NULL); +} + +/* like panic, but don't */ +void +_warn(const char *file, int line, const char *fmt,...) +{ + va_list ap; + + va_start(ap, fmt); + cprintf("kernel warning at %s:%d: ", file, line); + vcprintf(fmt, ap); + cprintf("\n"); + va_end(ap); +} diff --git a/lab/Untitled Project.si4project/Backup/serv(2429).c b/lab/Untitled Project.si4project/Backup/serv(2429).c new file mode 100644 index 0000000..76c1d99 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/serv(2429).c @@ -0,0 +1,345 @@ +/* + * File system server main loop - + * serves IPC requests from other environments. + */ + +#include +#include + +#include "fs.h" + + +#define debug 0 + +// The file system server maintains three structures +// for each open file. +// +// 1. The on-disk 'struct File' is mapped into the part of memory +// that maps the disk. This memory is kept private to the file +// server. +// 2. Each open file has a 'struct Fd' as well, which sort of +// corresponds to a Unix file descriptor. This 'struct Fd' is kept +// on *its own page* in memory, and it is shared with any +// environments that have the file open. +// 3. 'struct OpenFile' links these other two structures, and is kept +// private to the file server. The server maintains an array of +// all open files, indexed by "file ID". (There can be at most +// MAXOPEN files open concurrently.) The client uses file IDs to +// communicate with the server. File IDs are a lot like +// environment IDs in the kernel. Use openfile_lookup to translate +// file IDs to struct OpenFile. + +struct OpenFile { + uint32_t o_fileid; // file id + struct File *o_file; // mapped descriptor for open file + int o_mode; // open mode + struct Fd *o_fd; // Fd page +}; + +// Max number of open files in the file system at once +#define MAXOPEN 1024 +#define FILEVA 0xD0000000 + +// initialize to force into data section +struct OpenFile opentab[MAXOPEN] = { + { 0, 0, 1, 0 } +}; + +// Virtual address at which to receive page mappings containing client requests. +union Fsipc *fsreq = (union Fsipc *)0x0ffff000; + +void +serve_init(void) +{ + int i; + uintptr_t va = FILEVA; + for (i = 0; i < MAXOPEN; i++) { + opentab[i].o_fileid = i; + opentab[i].o_fd = (struct Fd*) va; + va += PGSIZE; + } +} + +// Allocate an open file. +int +openfile_alloc(struct OpenFile **o) +{ + int i, r; + + // Find an available open-file table entry + for (i = 0; i < MAXOPEN; i++) { + switch (pageref(opentab[i].o_fd)) { + case 0: + if ((r = sys_page_alloc(0, opentab[i].o_fd, PTE_P|PTE_U|PTE_W)) < 0) + return r; + /* fall through */ + case 1: + opentab[i].o_fileid += MAXOPEN; + *o = &opentab[i]; + memset(opentab[i].o_fd, 0, PGSIZE); + return (*o)->o_fileid; + } + } + return -E_MAX_OPEN; +} + +// Look up an open file for envid. +int +openfile_lookup(envid_t envid, uint32_t fileid, struct OpenFile **po) +{ + struct OpenFile *o; + + o = &opentab[fileid % MAXOPEN]; + if (pageref(o->o_fd) <= 1 || o->o_fileid != fileid) + return -E_INVAL; + *po = o; + return 0; +} + +// Open req->req_path in mode req->req_omode, storing the Fd page and +// permissions to return to the calling environment in *pg_store and +// *perm_store respectively. +int +serve_open(envid_t envid, struct Fsreq_open *req, + void **pg_store, int *perm_store) +{ + char path[MAXPATHLEN]; + struct File *f; + int fileid; + int r; + struct OpenFile *o; + + if (debug) + cprintf("serve_open %08x %s 0x%x\n", envid, req->req_path, req->req_omode); + + // Copy in the path, making sure it's null-terminated + memmove(path, req->req_path, MAXPATHLEN); + path[MAXPATHLEN-1] = 0; + + // Find an open file ID + if ((r = openfile_alloc(&o)) < 0) { + if (debug) + cprintf("openfile_alloc failed: %e", r); + return r; + } + fileid = r; + + // Open the file + if (req->req_omode & O_CREAT) { + if ((r = file_create(path, &f)) < 0) { + if (!(req->req_omode & O_EXCL) && r == -E_FILE_EXISTS) + goto try_open; + if (debug) + cprintf("file_create failed: %e", r); + return r; + } + } else { +try_open: + if ((r = file_open(path, &f)) < 0) { + if (debug) + cprintf("file_open failed: %e", r); + return r; + } + } + + // Truncate + if (req->req_omode & O_TRUNC) { + if ((r = file_set_size(f, 0)) < 0) { + if (debug) + cprintf("file_set_size failed: %e", r); + return r; + } + } + if ((r = file_open(path, &f)) < 0) { + if (debug) + cprintf("file_open failed: %e", r); + return r; + } + + // Save the file pointer + o->o_file = f; + + // Fill out the Fd structure + o->o_fd->fd_file.id = o->o_fileid; + o->o_fd->fd_omode = req->req_omode & O_ACCMODE; + o->o_fd->fd_dev_id = devfile.dev_id; + o->o_mode = req->req_omode; + + if (debug) + cprintf("sending success, page %08x\n", (uintptr_t) o->o_fd); + + // Share the FD page with the caller by setting *pg_store, + // store its permission in *perm_store + *pg_store = o->o_fd; + *perm_store = PTE_P|PTE_U|PTE_W|PTE_SHARE; + + return 0; +} + +// Set the size of req->req_fileid to req->req_size bytes, truncating +// or extending the file as necessary. +int +serve_set_size(envid_t envid, struct Fsreq_set_size *req) +{ + struct OpenFile *o; + int r; + + if (debug) + cprintf("serve_set_size %08x %08x %08x\n", envid, req->req_fileid, req->req_size); + + // Every file system IPC call has the same general structure. + // Here's how it goes. + + // First, use openfile_lookup to find the relevant open file. + // On failure, return the error code to the client with ipc_send. + if ((r = openfile_lookup(envid, req->req_fileid, &o)) < 0) + return r; + + // Second, call the relevant file system function (from fs/fs.c). + // On failure, return the error code to the client. + return file_set_size(o->o_file, req->req_size); +} + +// Read at most ipc->read.req_n bytes from the current seek position +// in ipc->read.req_fileid. Return the bytes read from the file to +// the caller in ipc->readRet, then update the seek position. Returns +// the number of bytes successfully read, or < 0 on error. +int +serve_read(envid_t envid, union Fsipc *ipc) +{ + struct Fsreq_read *req = &ipc->read; + struct Fsret_read *ret = &ipc->readRet; + + if (debug) + cprintf("serve_read %08x %08x %08x\n", envid, req->req_fileid, req->req_n); + + // Lab 5: Your code here: + return 0; +} + + +// Write req->req_n bytes from req->req_buf to req_fileid, starting at +// the current seek position, and update the seek position +// accordingly. Extend the file if necessary. Returns the number of +// bytes written, or < 0 on error. +int +serve_write(envid_t envid, struct Fsreq_write *req) +{ + if (debug) + cprintf("serve_write %08x %08x %08x\n", envid, req->req_fileid, req->req_n); + + // LAB 5: Your code here. + panic("serve_write not implemented"); +} + +// Stat ipc->stat.req_fileid. Return the file's struct Stat to the +// caller in ipc->statRet. +int +serve_stat(envid_t envid, union Fsipc *ipc) +{ + struct Fsreq_stat *req = &ipc->stat; + struct Fsret_stat *ret = &ipc->statRet; + struct OpenFile *o; + int r; + + if (debug) + cprintf("serve_stat %08x %08x\n", envid, req->req_fileid); + + if ((r = openfile_lookup(envid, req->req_fileid, &o)) < 0) + return r; + + strcpy(ret->ret_name, o->o_file->f_name); + ret->ret_size = o->o_file->f_size; + ret->ret_isdir = (o->o_file->f_type == FTYPE_DIR); + return 0; +} + +// Flush all data and metadata of req->req_fileid to disk. +int +serve_flush(envid_t envid, struct Fsreq_flush *req) +{ + struct OpenFile *o; + int r; + + if (debug) + cprintf("serve_flush %08x %08x\n", envid, req->req_fileid); + + if ((r = openfile_lookup(envid, req->req_fileid, &o)) < 0) + return r; + file_flush(o->o_file); + return 0; +} + + +int +serve_sync(envid_t envid, union Fsipc *req) +{ + fs_sync(); + return 0; +} + +typedef int (*fshandler)(envid_t envid, union Fsipc *req); + +fshandler handlers[] = { + // Open is handled specially because it passes pages + /* [FSREQ_OPEN] = (fshandler)serve_open, */ + [FSREQ_READ] = serve_read, + [FSREQ_STAT] = serve_stat, + [FSREQ_FLUSH] = (fshandler)serve_flush, + [FSREQ_WRITE] = (fshandler)serve_write, + [FSREQ_SET_SIZE] = (fshandler)serve_set_size, + [FSREQ_SYNC] = serve_sync +}; + +void +serve(void) +{ + uint32_t req, whom; + int perm, r; + void *pg; + + while (1) { + perm = 0; + req = ipc_recv((int32_t *) &whom, fsreq, &perm); + if (debug) + cprintf("fs req %d from %08x [page %08x: %s]\n", + req, whom, uvpt[PGNUM(fsreq)], fsreq); + + // All requests must contain an argument page + if (!(perm & PTE_P)) { + cprintf("Invalid request from %08x: no argument page\n", + whom); + continue; // just leave it hanging... + } + + pg = NULL; + if (req == FSREQ_OPEN) { + r = serve_open(whom, (struct Fsreq_open*)fsreq, &pg, &perm); + } else if (req < ARRAY_SIZE(handlers) && handlers[req]) { + r = handlers[req](whom, fsreq); + } else { + cprintf("Invalid request code %d from %08x\n", req, whom); + r = -E_INVAL; + } + ipc_send(whom, r, pg, perm); + sys_page_unmap(0, fsreq); + } +} + +void +umain(int argc, char **argv) +{ + static_assert(sizeof(struct File) == 256); + binaryname = "fs"; + cprintf("FS is running\n"); + + // Check that we are able to do I/O + outw(0x8A00, 0x8A00); + cprintf("FS can do I/O\n"); + + serve_init(); + fs_init(); + fs_test(); + serve(); +} + diff --git a/lab/Untitled Project.si4project/Backup/sh(7186).c b/lab/Untitled Project.si4project/Backup/sh(7186).c new file mode 100644 index 0000000..26f501a --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/sh(7186).c @@ -0,0 +1,322 @@ +#include + +#define BUFSIZ 1024 /* Find the buffer overrun bug! */ +int debug = 0; + + +// gettoken(s, 0) prepares gettoken for subsequent calls and returns 0. +// gettoken(0, token) parses a shell token from the previously set string, +// null-terminates that token, stores the token pointer in '*token', +// and returns a token ID (0, '<', '>', '|', or 'w'). +// Subsequent calls to 'gettoken(0, token)' will return subsequent +// tokens from the string. +int gettoken(char *s, char **token); + + +// Parse a shell command from string 's' and execute it. +// Do not return until the shell command is finished. +// runcmd() is called in a forked child, +// so it's OK to manipulate file descriptor state. +#define MAXARGS 16 +void +runcmd(char* s) +{ + char *argv[MAXARGS], *t, argv0buf[BUFSIZ]; + int argc, c, i, r, p[2], fd, pipe_child; + + pipe_child = 0; + gettoken(s, 0); + +again: + argc = 0; + while (1) { + switch ((c = gettoken(0, &t))) { + + case 'w': // Add an argument + if (argc == MAXARGS) { + cprintf("too many arguments\n"); + exit(); + } + argv[argc++] = t; + break; + + case '<': // Input redirection + // Grab the filename from the argument list + if (gettoken(0, &t) != 'w') { + cprintf("syntax error: < not followed by word\n"); + exit(); + } + // Open 't' for reading as file descriptor 0 + // (which environments use as standard input). + // We can't open a file onto a particular descriptor, + // so open the file as 'fd', + // then check whether 'fd' is 0. + // If not, dup 'fd' onto file descriptor 0, + // then close the original 'fd'. + + // LAB 5: Your code here. + panic("< redirection not implemented"); + break; + + case '>': // Output redirection + // Grab the filename from the argument list + if (gettoken(0, &t) != 'w') { + cprintf("syntax error: > not followed by word\n"); + exit(); + } + if ((fd = open(t, O_WRONLY|O_CREAT|O_TRUNC)) < 0) { + cprintf("open %s for write: %e", t, fd); + exit(); + } + if (fd != 1) { + dup(fd, 1); + close(fd); + } + break; + + case '|': // Pipe + if ((r = pipe(p)) < 0) { + cprintf("pipe: %e", r); + exit(); + } + if (debug) + cprintf("PIPE: %d %d\n", p[0], p[1]); + if ((r = fork()) < 0) { + cprintf("fork: %e", r); + exit(); + } + if (r == 0) { + if (p[0] != 0) { + dup(p[0], 0); + close(p[0]); + } + close(p[1]); + goto again; + } else { + pipe_child = r; + if (p[1] != 1) { + dup(p[1], 1); + close(p[1]); + } + close(p[0]); + goto runit; + } + panic("| not implemented"); + break; + + case 0: // String is complete + // Run the current command! + goto runit; + + default: + panic("bad return %d from gettoken", c); + break; + + } + } + +runit: + // Return immediately if command line was empty. + if(argc == 0) { + if (debug) + cprintf("EMPTY COMMAND\n"); + return; + } + + // Clean up command line. + // Read all commands from the filesystem: add an initial '/' to + // the command name. + // This essentially acts like 'PATH=/'. + if (argv[0][0] != '/') { + argv0buf[0] = '/'; + strcpy(argv0buf + 1, argv[0]); + argv[0] = argv0buf; + } + argv[argc] = 0; + + // Print the command. + if (debug) { + cprintf("[%08x] SPAWN:", thisenv->env_id); + for (i = 0; argv[i]; i++) + cprintf(" %s", argv[i]); + cprintf("\n"); + } + + // Spawn the command! + if ((r = spawn(argv[0], (const char**) argv)) < 0) + cprintf("spawn %s: %e\n", argv[0], r); + + // In the parent, close all file descriptors and wait for the + // spawned command to exit. + close_all(); + if (r >= 0) { + if (debug) + cprintf("[%08x] WAIT %s %08x\n", thisenv->env_id, argv[0], r); + wait(r); + if (debug) + cprintf("[%08x] wait finished\n", thisenv->env_id); + } + + // If we were the left-hand part of a pipe, + // wait for the right-hand part to finish. + if (pipe_child) { + if (debug) + cprintf("[%08x] WAIT pipe_child %08x\n", thisenv->env_id, pipe_child); + wait(pipe_child); + if (debug) + cprintf("[%08x] wait finished\n", thisenv->env_id); + } + + // Done! + exit(); +} + + +// Get the next token from string s. +// Set *p1 to the beginning of the token and *p2 just past the token. +// Returns +// 0 for end-of-string; +// < for <; +// > for >; +// | for |; +// w for a word. +// +// Eventually (once we parse the space where the \0 will go), +// words get nul-terminated. +#define WHITESPACE " \t\r\n" +#define SYMBOLS "<|>&;()" + +int +_gettoken(char *s, char **p1, char **p2) +{ + int t; + + if (s == 0) { + if (debug > 1) + cprintf("GETTOKEN NULL\n"); + return 0; + } + + if (debug > 1) + cprintf("GETTOKEN: %s\n", s); + + *p1 = 0; + *p2 = 0; + + while (strchr(WHITESPACE, *s)) + *s++ = 0; + if (*s == 0) { + if (debug > 1) + cprintf("EOL\n"); + return 0; + } + if (strchr(SYMBOLS, *s)) { + t = *s; + *p1 = s; + *s++ = 0; + *p2 = s; + if (debug > 1) + cprintf("TOK %c\n", t); + return t; + } + *p1 = s; + while (*s && !strchr(WHITESPACE SYMBOLS, *s)) + s++; + *p2 = s; + if (debug > 1) { + t = **p2; + **p2 = 0; + cprintf("WORD: %s\n", *p1); + **p2 = t; + } + return 'w'; +} + +int +gettoken(char *s, char **p1) +{ + static int c, nc; + static char* np1, *np2; + + if (s) { + nc = _gettoken(s, &np1, &np2); + return 0; + } + c = nc; + *p1 = np1; + nc = _gettoken(np2, &np1, &np2); + return c; +} + + +void +usage(void) +{ + cprintf("usage: sh [-dix] [command-file]\n"); + exit(); +} + +void +umain(int argc, char **argv) +{ + int r, interactive, echocmds; + struct Argstate args; + + interactive = '?'; + echocmds = 0; + argstart(&argc, argv, &args); + while ((r = argnext(&args)) >= 0) + switch (r) { + case 'd': + debug++; + break; + case 'i': + interactive = 1; + break; + case 'x': + echocmds = 1; + break; + default: + usage(); + } + + if (argc > 2) + usage(); + if (argc == 2) { + close(0); + if ((r = open(argv[1], O_RDONLY)) < 0) + panic("open %s: %e", argv[1], r); + assert(r == 0); + } + if (interactive == '?') + interactive = iscons(0); + + while (1) { + char *buf; + + buf = readline(interactive ? "$ " : NULL); + if (buf == NULL) { + if (debug) + cprintf("EXITING\n"); + exit(); // end of file + } + if (debug) + cprintf("LINE: %s\n", buf); + if (buf[0] == '#') + continue; + if (echocmds) + printf("# %s\n", buf); + if (debug) + cprintf("BEFORE FORK\n"); + if ((r = fork()) < 0) + panic("fork: %e", r); + if (debug) + cprintf("FORK: %d\n", r); + if (r == 0) { + runcmd(buf); + exit(); + } else + wait(r); + } +} + diff --git a/lab/Untitled Project.si4project/Backup/spawn(5260).c b/lab/Untitled Project.si4project/Backup/spawn(5260).c new file mode 100644 index 0000000..9d0eb07 --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/spawn(5260).c @@ -0,0 +1,307 @@ +#include +#include + +#define UTEMP2USTACK(addr) ((void*) (addr) + (USTACKTOP - PGSIZE) - UTEMP) +#define UTEMP2 (UTEMP + PGSIZE) +#define UTEMP3 (UTEMP2 + PGSIZE) + +// Helper functions for spawn. +static int init_stack(envid_t child, const char **argv, uintptr_t *init_esp); +static int map_segment(envid_t child, uintptr_t va, size_t memsz, + int fd, size_t filesz, off_t fileoffset, int perm); +static int copy_shared_pages(envid_t child); + +// Spawn a child process from a program image loaded from the file system. +// prog: the pathname of the program to run. +// argv: pointer to null-terminated array of pointers to strings, +// which will be passed to the child as its command-line arguments. +// Returns child envid on success, < 0 on failure. +int +spawn(const char *prog, const char **argv) +{ + unsigned char elf_buf[512]; + struct Trapframe child_tf; + envid_t child; + + int fd, i, r; + struct Elf *elf; + struct Proghdr *ph; + int perm; + + // This code follows this procedure: + // + // - Open the program file. + // + // - Read the ELF header, as you have before, and sanity check its + // magic number. (Check out your load_icode!) + // + // - Use sys_exofork() to create a new environment. + // + // - Set child_tf to an initial struct Trapframe for the child. + // + // - Call the init_stack() function above to set up + // the initial stack page for the child environment. + // + // - Map all of the program's segments that are of p_type + // ELF_PROG_LOAD into the new environment's address space. + // Use the p_flags field in the Proghdr for each segment + // to determine how to map the segment: + // + // * If the ELF flags do not include ELF_PROG_FLAG_WRITE, + // then the segment contains text and read-only data. + // Use read_map() to read the contents of this segment, + // and map the pages it returns directly into the child + // so that multiple instances of the same program + // will share the same copy of the program text. + // Be sure to map the program text read-only in the child. + // Read_map is like read but returns a pointer to the data in + // *blk rather than copying the data into another buffer. + // + // * If the ELF segment flags DO include ELF_PROG_FLAG_WRITE, + // then the segment contains read/write data and bss. + // As with load_icode() in Lab 3, such an ELF segment + // occupies p_memsz bytes in memory, but only the FIRST + // p_filesz bytes of the segment are actually loaded + // from the executable file - you must clear the rest to zero. + // For each page to be mapped for a read/write segment, + // allocate a page in the parent temporarily at UTEMP, + // read() the appropriate portion of the file into that page + // and/or use memset() to zero non-loaded portions. + // (You can avoid calling memset(), if you like, if + // page_alloc() returns zeroed pages already.) + // Then insert the page mapping into the child. + // Look at init_stack() for inspiration. + // Be sure you understand why you can't use read_map() here. + // + // Note: None of the segment addresses or lengths above + // are guaranteed to be page-aligned, so you must deal with + // these non-page-aligned values appropriately. + // The ELF linker does, however, guarantee that no two segments + // will overlap on the same page; and it guarantees that + // PGOFF(ph->p_offset) == PGOFF(ph->p_va). + // + // - Call sys_env_set_trapframe(child, &child_tf) to set up the + // correct initial eip and esp values in the child. + // + // - Start the child process running with sys_env_set_status(). + + if ((r = open(prog, O_RDONLY)) < 0) + return r; + fd = r; + + // Read elf header + elf = (struct Elf*) elf_buf; + if (readn(fd, elf_buf, sizeof(elf_buf)) != sizeof(elf_buf) + || elf->e_magic != ELF_MAGIC) { + close(fd); + cprintf("elf magic %08x want %08x\n", elf->e_magic, ELF_MAGIC); + return -E_NOT_EXEC; + } + + // Create new child environment + if ((r = sys_exofork()) < 0) + return r; + child = r; + + // Set up trap frame, including initial stack. + child_tf = envs[ENVX(child)].env_tf; + child_tf.tf_eip = elf->e_entry; + + if ((r = init_stack(child, argv, &child_tf.tf_esp)) < 0) + return r; + + // Set up program segments as defined in ELF header. + ph = (struct Proghdr*) (elf_buf + elf->e_phoff); + for (i = 0; i < elf->e_phnum; i++, ph++) { + if (ph->p_type != ELF_PROG_LOAD) + continue; + perm = PTE_P | PTE_U; + if (ph->p_flags & ELF_PROG_FLAG_WRITE) + perm |= PTE_W; + if ((r = map_segment(child, ph->p_va, ph->p_memsz, + fd, ph->p_filesz, ph->p_offset, perm)) < 0) + goto error; + } + close(fd); + fd = -1; + + // Copy shared library state. + if ((r = copy_shared_pages(child)) < 0) + panic("copy_shared_pages: %e", r); + + child_tf.tf_eflags |= FL_IOPL_3; // devious: see user/faultio.c + if ((r = sys_env_set_trapframe(child, &child_tf)) < 0) + panic("sys_env_set_trapframe: %e", r); + + if ((r = sys_env_set_status(child, ENV_RUNNABLE)) < 0) + panic("sys_env_set_status: %e", r); + + return child; + +error: + sys_env_destroy(child); + close(fd); + return r; +} + +// Spawn, taking command-line arguments array directly on the stack. +// NOTE: Must have a sentinal of NULL at the end of the args +// (none of the args may be NULL). +int +spawnl(const char *prog, const char *arg0, ...) +{ + // We calculate argc by advancing the args until we hit NULL. + // The contract of the function guarantees that the last + // argument will always be NULL, and that none of the other + // arguments will be NULL. + int argc=0; + va_list vl; + va_start(vl, arg0); + while(va_arg(vl, void *) != NULL) + argc++; + va_end(vl); + + // Now that we have the size of the args, do a second pass + // and store the values in a VLA, which has the format of argv + const char *argv[argc+2]; + argv[0] = arg0; + argv[argc+1] = NULL; + + va_start(vl, arg0); + unsigned i; + for(i=0;i= filesz) { + // allocate a blank page + if ((r = sys_page_alloc(child, (void*) (va + i), perm)) < 0) + return r; + } else { + // from file + if ((r = sys_page_alloc(0, UTEMP, PTE_P|PTE_U|PTE_W)) < 0) + return r; + if ((r = seek(fd, fileoffset + i)) < 0) + return r; + if ((r = readn(fd, UTEMP, MIN(PGSIZE, filesz-i))) < 0) + return r; + if ((r = sys_page_map(0, UTEMP, child, (void*) (va + i), perm)) < 0) + panic("spawn: sys_page_map data: %e", r); + sys_page_unmap(0, UTEMP); + } + } + return 0; +} + +// Copy the mappings for shared pages into the child address space. +static int +copy_shared_pages(envid_t child) +{ + // LAB 5: Your code here. + return 0; +} + diff --git a/lab/LAB4.si4project/Backup/syscall(1286).c b/lab/Untitled Project.si4project/Backup/syscall(7911).c similarity index 84% rename from lab/LAB4.si4project/Backup/syscall(1286).c rename to lab/Untitled Project.si4project/Backup/syscall(7911).c index 6ee15ee..cf2eb2f 100644 --- a/lab/LAB4.si4project/Backup/syscall(1286).c +++ b/lab/Untitled Project.si4project/Backup/syscall(7911).c @@ -55,10 +55,6 @@ sys_env_destroy(envid_t envid) if ((r = envid2env(envid, &e, 1)) < 0) return r; - if (e == curenv) - cprintf("[%08x] exiting gracefully\n", curenv->env_id); - else - cprintf("[%08x] destroying %08x\n", curenv->env_id, e->env_id); env_destroy(e); return 0; } @@ -94,6 +90,7 @@ sys_exofork(void) newenv->env_tf = curenv->env_tf; // newenv的返回值为0, 实现子进程返回0值 newenv->env_tf.tf_regs.reg_eax = 0; + // 返回值存放在eax中 return newenv->env_id; @@ -127,6 +124,22 @@ sys_env_set_status(envid_t envid, int status) return 0; } +// Set envid's trap frame to 'tf'. +// tf is modified to make sure that user environments always run at code +// protection level 3 (CPL 3), interrupts enabled, and IOPL of 0. +// +// Returns 0 on success, < 0 on error. Errors are: +// -E_BAD_ENV if environment envid doesn't currently exist, +// or the caller doesn't have permission to change envid. +static int +sys_env_set_trapframe(envid_t envid, struct Trapframe *tf) +{ + // LAB 5: Your code here. + // Remember to check whether the user has supplied us with a good + // address! + panic("sys_env_set_trapframe not implemented"); +} + // Set the page fault upcall for 'envid' by modifying the corresponding struct // Env's 'env_pgfault_upcall' field. When 'envid' causes a page fault, the // kernel will push a fault record onto the exception stack, then branch to @@ -142,7 +155,7 @@ sys_env_set_pgfault_upcall(envid_t envid, void *func) struct Env *e; if (envid2env(envid, &e, 1)) return -E_BAD_ENV; - + // cprintf("set pgfault upcall\n"); e->env_pgfault_upcall = func; return 0; // panic("sys_env_set_pgfault_upcall not implemented"); @@ -311,13 +324,61 @@ sys_page_unmap(envid_t envid, void *va) // current environment's address space. // -E_NO_MEM if there's not enough memory to map srcva in envid's // address space. + static int sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm) { // LAB 4: Your code here. - panic("sys_ipc_try_send not implemented"); + struct Env *dstenv; + pte_t *pte; + struct PageInfo *pp; + int r; + if ( (r = envid2env( envid, &dstenv, 0)) < 0) + return r; + + // 不处于等待接收状态, 或有进程已经请求发送数据 + if ( (dstenv->env_ipc_recving != true) || dstenv->env_ipc_from != 0) + return -E_IPC_NOT_RECV; + + if ((uint32_t)srcva < UTOP) { + if ( PGOFF(srcva)) + return -E_INVAL; + if ( !(perm & PTE_P ) || !(perm & PTE_U) ) + return -E_INVAL; + if (perm & (~ PTE_SYSCALL)) + return -E_INVAL; + + + if ((pp = page_lookup(curenv->env_pgdir, srcva, &pte)) == NULL ) + return -E_INVAL; + + + if ((perm & PTE_W) && !(*pte & PTE_W) ) + return -E_INVAL; + + // 接收进程愿意接收一个页 + if (dstenv->env_ipc_dstva) { + // 开始映射 + if( (r = page_insert(dstenv->env_pgdir, pp, dstenv->env_ipc_dstva, perm)) < 0) + return r; + dstenv->env_ipc_perm = perm; + } + + } + + + dstenv->env_ipc_from = curenv->env_id; + dstenv->env_ipc_recving = false; + dstenv->env_ipc_value = value; + dstenv->env_status = ENV_RUNNABLE; + // 返回值 + dstenv->env_tf.tf_regs.reg_eax = 0; + return 0; + + //panic("sys_ipc_try_send not implemented"); } + // Block until a value is ready. Record that you want to receive // using the env_ipc_recving and env_ipc_dstva fields of struct Env, // mark yourself not runnable, and then give up the CPU. @@ -333,7 +394,18 @@ static int sys_ipc_recv(void *dstva) { // LAB 4: Your code here. - panic("sys_ipc_recv not implemented"); + if ((uint32_t) dstva < UTOP ) { + if (PGOFF(dstva)) + return -E_INVAL; + + } + // 大于小于都可以赋值为desva。 + curenv->env_ipc_dstva = dstva; + curenv->env_status = ENV_NOT_RUNNABLE; + curenv->env_ipc_recving = true; + curenv->env_ipc_from = 0; + sched_yield(); + // panic("sys_ipc_recv not implemented"); return 0; } @@ -372,6 +444,10 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, case SYS_env_set_status: return sys_env_set_status((envid_t) a1, (int) a2); + case SYS_ipc_recv: + return sys_ipc_recv( (void *) a1); + case SYS_ipc_try_send: + return sys_ipc_try_send((envid_t) a1, (uint32_t) a2, (void *) a3, (int) a4); case NSYSCALLS: return -E_INVAL; diff --git a/lab/LAB4.si4project/Backup/syscall(7459).c b/lab/Untitled Project.si4project/Backup/syscall(8111).c similarity index 84% rename from lab/LAB4.si4project/Backup/syscall(7459).c rename to lab/Untitled Project.si4project/Backup/syscall(8111).c index 4b2925a..d28128c 100644 --- a/lab/LAB4.si4project/Backup/syscall(7459).c +++ b/lab/Untitled Project.si4project/Backup/syscall(8111).c @@ -55,6 +55,7 @@ sys_env_destroy(envid_t envid) if ((r = envid2env(envid, &e, 1)) < 0) return r; + if (e == curenv) cprintf("[%08x] exiting gracefully\n", curenv->env_id); else @@ -128,6 +129,22 @@ sys_env_set_status(envid_t envid, int status) return 0; } +// Set envid's trap frame to 'tf'. +// tf is modified to make sure that user environments always run at code +// protection level 3 (CPL 3), interrupts enabled, and IOPL of 0. +// +// Returns 0 on success, < 0 on error. Errors are: +// -E_BAD_ENV if environment envid doesn't currently exist, +// or the caller doesn't have permission to change envid. +static int +sys_env_set_trapframe(envid_t envid, struct Trapframe *tf) +{ + // LAB 5: Your code here. + // Remember to check whether the user has supplied us with a good + // address! + panic("sys_env_set_trapframe not implemented"); +} + // Set the page fault upcall for 'envid' by modifying the corresponding struct // Env's 'env_pgfault_upcall' field. When 'envid' causes a page fault, the // kernel will push a fault record onto the exception stack, then branch to @@ -312,13 +329,61 @@ sys_page_unmap(envid_t envid, void *va) // current environment's address space. // -E_NO_MEM if there's not enough memory to map srcva in envid's // address space. + static int sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm) { // LAB 4: Your code here. - panic("sys_ipc_try_send not implemented"); + struct Env *dstenv; + pte_t *pte; + struct PageInfo *pp; + int r; + if ( (r = envid2env( envid, &dstenv, 0)) < 0) + return r; + + // 不处于等待接收状态, 或有进程已经请求发送数据 + if ( (dstenv->env_ipc_recving != true) || dstenv->env_ipc_from != 0) + return -E_IPC_NOT_RECV; + + if ((uint32_t)srcva < UTOP) { + if ( PGOFF(srcva)) + return -E_INVAL; + if ( !(perm & PTE_P ) || !(perm & PTE_U) ) + return -E_INVAL; + if (perm & (~ PTE_SYSCALL)) + return -E_INVAL; + + + if ((pp = page_lookup(curenv->env_pgdir, srcva, &pte)) == NULL ) + return -E_INVAL; + + + if ((perm & PTE_W) && !(*pte & PTE_W) ) + return -E_INVAL; + + // 接收进程愿意接收一个页 + if (dstenv->env_ipc_dstva) { + // 开始映射 + if( (r = page_insert(dstenv->env_pgdir, pp, dstenv->env_ipc_dstva, perm)) < 0) + return r; + dstenv->env_ipc_perm = perm; + } + + } + + + dstenv->env_ipc_from = curenv->env_id; + dstenv->env_ipc_recving = false; + dstenv->env_ipc_value = value; + dstenv->env_status = ENV_RUNNABLE; + // 返回值 + dstenv->env_tf.tf_regs.reg_eax = 0; + return 0; + + //panic("sys_ipc_try_send not implemented"); } + // Block until a value is ready. Record that you want to receive // using the env_ipc_recving and env_ipc_dstva fields of struct Env, // mark yourself not runnable, and then give up the CPU. @@ -334,7 +399,18 @@ static int sys_ipc_recv(void *dstva) { // LAB 4: Your code here. - panic("sys_ipc_recv not implemented"); + if ((uint32_t) dstva < UTOP ) { + if (PGOFF(dstva)) + return -E_INVAL; + + } + // 大于小于都可以赋值为desva。 + curenv->env_ipc_dstva = dstva; + curenv->env_status = ENV_NOT_RUNNABLE; + curenv->env_ipc_recving = true; + curenv->env_ipc_from = 0; + sched_yield(); + // panic("sys_ipc_recv not implemented"); return 0; } @@ -373,6 +449,10 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, case SYS_env_set_status: return sys_env_set_status((envid_t) a1, (int) a2); + case SYS_ipc_recv: + return sys_ipc_recv( (void *) a1); + case SYS_ipc_try_send: + return sys_ipc_try_send((envid_t) a1, (uint32_t) a2, (void *) a3, (int) a4); case NSYSCALLS: return -E_INVAL; diff --git a/lab/LAB4.si4project/Backup/trap(6309).c b/lab/Untitled Project.si4project/Backup/trap(3657).c similarity index 85% rename from lab/LAB4.si4project/Backup/trap(6309).c rename to lab/Untitled Project.si4project/Backup/trap(3657).c index e814e98..c36b562 100644 --- a/lab/LAB4.si4project/Backup/trap(6309).c +++ b/lab/Untitled Project.si4project/Backup/trap(3657).c @@ -92,7 +92,14 @@ trap_init(void) void simderr_handler(); void syscall_handler(); void dblflt_handler(); + void timer_handler(); + void kbd_handler(); + void serial_handler(); + void spurious_handler(); + void ide_handler(); + void error_handler(); + // LAB 3: Your code here. // GD_KT 全局描述符, kernel text SETGATE(idt[T_DIVIDE], 0, GD_KT, divide_handler, 0); @@ -114,6 +121,13 @@ trap_init(void) SETGATE(idt[T_MCHK], 0, GD_KT, mchk_handler, 0); SETGATE(idt[T_SIMDERR], 0, GD_KT, simderr_handler, 0); SETGATE(idt[T_SYSCALL], 0, GD_KT, syscall_handler, 3); + // IRQ + SETGATE(idt[IRQ_OFFSET + IRQ_TIMER], 0, GD_KT, timer_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_KBD], 0, GD_KT, kbd_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SERIAL], 0, GD_KT, serial_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SPURIOUS], 0, GD_KT, spurious_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_IDE], 0, GD_KT, ide_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_ERROR], 0, GD_KT, error_handler, 3); // Per-CPU setup trap_init_percpu(); @@ -229,6 +243,12 @@ trap_dispatch(struct Trapframe *tf) tf->tf_regs.reg_edi, tf->tf_regs.reg_esi); break; + case (IRQ_OFFSET + IRQ_TIMER): + // 回应8259A 接收中断。 + lapic_eoi(); + sched_yield(); + break; + default: // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); @@ -246,6 +266,10 @@ trap_dispatch(struct Trapframe *tf) // interrupt using lapic_eoi() before calling the scheduler! // LAB 4: Your code here. +<<<<<<< HEAD + // Handle keyboard and serial interrupts. + // LAB 5: Your code here. + // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); if (tf->tf_cs == GD_KT) @@ -253,9 +277,10 @@ trap_dispatch(struct Trapframe *tf) else { env_destroy(curenv); return; - } +======= +>>>>>>> lab4 } void @@ -371,14 +396,41 @@ page_fault_handler(struct Trapframe *tf) // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. + struct UTrapframe *utf; + // cprintf("I'M in page_fault_handler [%08x] user fault va %08x \n",curenv->env_id, fault_va); + if (curenv->env_pgfault_upcall) { + + if (tf->tf_esp >= UXSTACKTOP-PGSIZE && tf->tf_esp < UXSTACKTOP) { + // 异常模式下陷入 + utf = (struct UTrapframe *)(tf->tf_esp - sizeof(struct UTrapframe) - 4); - - // user_mem_assert(curenv, (const void *) fault_va, PGSIZE, 0); - - // Destroy the environment that caused the fault. - cprintf("[%08x] user fault va %08x ip %08x\n", - curenv->env_id, fault_va, tf->tf_eip); - print_trapframe(tf); - env_destroy(curenv); + } + else { + // 非异常模式下陷入 + utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe)); + } + // 检查异常栈是否溢出 + user_mem_assert(curenv, (const void *) utf, sizeof(struct UTrapframe), PTE_P|PTE_W); + + utf->utf_fault_va = fault_va; + utf->utf_err = tf->tf_trapno; + utf->utf_regs = tf->tf_regs; + utf->utf_eflags = tf->tf_eflags; + // 保存陷入时现场,用于返回 + utf->utf_eip = tf->tf_eip; + utf->utf_esp = tf->tf_esp; + // 再次转向执行 + curenv->env_tf.tf_eip = (uint32_t) curenv->env_pgfault_upcall; + // 异常栈 + curenv->env_tf.tf_esp = (uint32_t) utf; + env_run(curenv); + } + else { + // Destroy the environment that caused the fault. + cprintf("[%08x] user fault va %08x ip %08x\n", + curenv->env_id, fault_va, tf->tf_eip); + print_trapframe(tf); + env_destroy(curenv); + } } diff --git a/lab/LAB4.si4project/Backup/trap(2812).c b/lab/Untitled Project.si4project/Backup/trap(5971).c similarity index 83% rename from lab/LAB4.si4project/Backup/trap(2812).c rename to lab/Untitled Project.si4project/Backup/trap(5971).c index d9a201f..96bf71c 100644 --- a/lab/LAB4.si4project/Backup/trap(2812).c +++ b/lab/Untitled Project.si4project/Backup/trap(5971).c @@ -92,7 +92,14 @@ trap_init(void) void simderr_handler(); void syscall_handler(); void dblflt_handler(); + void timer_handler(); + void kbd_handler(); + void serial_handler(); + void spurious_handler(); + void ide_handler(); + void error_handler(); + // LAB 3: Your code here. // GD_KT 全局描述符, kernel text SETGATE(idt[T_DIVIDE], 0, GD_KT, divide_handler, 0); @@ -114,6 +121,13 @@ trap_init(void) SETGATE(idt[T_MCHK], 0, GD_KT, mchk_handler, 0); SETGATE(idt[T_SIMDERR], 0, GD_KT, simderr_handler, 0); SETGATE(idt[T_SYSCALL], 0, GD_KT, syscall_handler, 3); + // IRQ + SETGATE(idt[IRQ_OFFSET + IRQ_TIMER], 0, GD_KT, timer_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_KBD], 0, GD_KT, kbd_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SERIAL], 0, GD_KT, serial_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SPURIOUS], 0, GD_KT, spurious_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_IDE], 0, GD_KT, ide_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_ERROR], 0, GD_KT, error_handler, 3); // Per-CPU setup trap_init_percpu(); @@ -229,6 +243,24 @@ trap_dispatch(struct Trapframe *tf) tf->tf_regs.reg_edi, tf->tf_regs.reg_esi); break; + // Handle clock interrupts. Don't forget to acknowledge the + // interrupt using lapic_eoi() before calling the scheduler! + // LAB 4: Your code here. + case (IRQ_OFFSET + IRQ_TIMER): + // 回应8259A 接收中断。 + lapic_eoi(); + sched_yield(); + break; + + case (IRQ_OFFSET + IRQ_KBD): + lapic_eoi(); + kbd_intr(); + break; + case (IRQ_OFFSET + IRQ_SERIAL): + lapic_eoi(); + serial_intr(); + break; + default: // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); @@ -242,11 +274,7 @@ trap_dispatch(struct Trapframe *tf) } - // Handle clock interrupts. Don't forget to acknowledge the - // interrupt using lapic_eoi() before calling the scheduler! - // LAB 4: Your code here. - } void @@ -362,14 +390,41 @@ page_fault_handler(struct Trapframe *tf) // (the 'tf' variable points at 'curenv->env_tf'). // LAB 4: Your code here. + struct UTrapframe *utf; + // cprintf("I'M in page_fault_handler [%08x] user fault va %08x \n",curenv->env_id, fault_va); + if (curenv->env_pgfault_upcall) { + + if (tf->tf_esp >= UXSTACKTOP-PGSIZE && tf->tf_esp < UXSTACKTOP) { + // 异常模式下陷入 + utf = (struct UTrapframe *)(tf->tf_esp - sizeof(struct UTrapframe) - 4); - - // user_mem_assert(curenv, (const void *) fault_va, PGSIZE, 0); - - // Destroy the environment that caused the fault. - cprintf("[%08x] user fault va %08x ip %08x\n", - curenv->env_id, fault_va, tf->tf_eip); - print_trapframe(tf); - env_destroy(curenv); + } + else { + // 非异常模式下陷入 + utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe)); + } + // 检查异常栈是否溢出 + user_mem_assert(curenv, (const void *) utf, sizeof(struct UTrapframe), PTE_P|PTE_W); + + utf->utf_fault_va = fault_va; + utf->utf_err = tf->tf_trapno; + utf->utf_regs = tf->tf_regs; + utf->utf_eflags = tf->tf_eflags; + // 保存陷入时现场,用于返回 + utf->utf_eip = tf->tf_eip; + utf->utf_esp = tf->tf_esp; + // 再次转向执行 + curenv->env_tf.tf_eip = (uint32_t) curenv->env_pgfault_upcall; + // 异常栈 + curenv->env_tf.tf_esp = (uint32_t) utf; + env_run(curenv); + } + else { + // Destroy the environment that caused the fault. + cprintf("[%08x] user fault va %08x ip %08x\n", + curenv->env_id, fault_va, tf->tf_eip); + print_trapframe(tf); + env_destroy(curenv); + } } diff --git a/lab/LAB4.si4project/Backup/trap(1475).c b/lab/Untitled Project.si4project/Backup/trap(6591).c similarity index 94% rename from lab/LAB4.si4project/Backup/trap(1475).c rename to lab/Untitled Project.si4project/Backup/trap(6591).c index b80f42b..b4153b6 100644 --- a/lab/LAB4.si4project/Backup/trap(1475).c +++ b/lab/Untitled Project.si4project/Backup/trap(6591).c @@ -92,7 +92,14 @@ trap_init(void) void simderr_handler(); void syscall_handler(); void dblflt_handler(); + void timer_handler(); + void kbd_handler(); + void serial_handler(); + void spurious_handler(); + void ide_handler(); + void error_handler(); + // LAB 3: Your code here. // GD_KT 全局描述符, kernel text SETGATE(idt[T_DIVIDE], 0, GD_KT, divide_handler, 0); @@ -114,6 +121,13 @@ trap_init(void) SETGATE(idt[T_MCHK], 0, GD_KT, mchk_handler, 0); SETGATE(idt[T_SIMDERR], 0, GD_KT, simderr_handler, 0); SETGATE(idt[T_SYSCALL], 0, GD_KT, syscall_handler, 3); + // IRQ + SETGATE(idt[IRQ_OFFSET + IRQ_TIMER], 0, GD_KT, timer_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_KBD], 0, GD_KT, kbd_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SERIAL], 0, GD_KT, serial_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SPURIOUS], 0, GD_KT, spurious_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_IDE], 0, GD_KT, ide_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_ERROR], 0, GD_KT, error_handler, 3); // Per-CPU setup trap_init_percpu(); @@ -229,6 +243,12 @@ trap_dispatch(struct Trapframe *tf) tf->tf_regs.reg_edi, tf->tf_regs.reg_esi); break; + case (IRQ_OFFSET + IRQ_TIMER): + // 回应8259A 接收中断。 + lapic_eoi(); + sched_yield(); + break; + default: // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); diff --git a/lab/LAB4.si4project/Backup/trap(359).c b/lab/Untitled Project.si4project/Backup/trap(6593).c similarity index 89% rename from lab/LAB4.si4project/Backup/trap(359).c rename to lab/Untitled Project.si4project/Backup/trap(6593).c index 2621500..141c7df 100644 --- a/lab/LAB4.si4project/Backup/trap(359).c +++ b/lab/Untitled Project.si4project/Backup/trap(6593).c @@ -92,7 +92,14 @@ trap_init(void) void simderr_handler(); void syscall_handler(); void dblflt_handler(); + void timer_handler(); + void kbd_handler(); + void serial_handler(); + void spurious_handler(); + void ide_handler(); + void error_handler(); + // LAB 3: Your code here. // GD_KT 全局描述符, kernel text SETGATE(idt[T_DIVIDE], 0, GD_KT, divide_handler, 0); @@ -114,6 +121,13 @@ trap_init(void) SETGATE(idt[T_MCHK], 0, GD_KT, mchk_handler, 0); SETGATE(idt[T_SIMDERR], 0, GD_KT, simderr_handler, 0); SETGATE(idt[T_SYSCALL], 0, GD_KT, syscall_handler, 3); + // IRQ + SETGATE(idt[IRQ_OFFSET + IRQ_TIMER], 0, GD_KT, timer_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_KBD], 0, GD_KT, kbd_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SERIAL], 0, GD_KT, serial_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SPURIOUS], 0, GD_KT, spurious_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_IDE], 0, GD_KT, ide_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_ERROR], 0, GD_KT, error_handler, 3); // Per-CPU setup trap_init_percpu(); @@ -229,6 +243,15 @@ trap_dispatch(struct Trapframe *tf) tf->tf_regs.reg_edi, tf->tf_regs.reg_esi); break; + // Handle clock interrupts. Don't forget to acknowledge the + // interrupt using lapic_eoi() before calling the scheduler! + // LAB 4: Your code here. + case (IRQ_OFFSET + IRQ_TIMER): + // 回应8259A 接收中断。 + lapic_eoi(); + sched_yield(); + break; + default: // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); @@ -242,11 +265,7 @@ trap_dispatch(struct Trapframe *tf) } - // Handle clock interrupts. Don't forget to acknowledge the - // interrupt using lapic_eoi() before calling the scheduler! - // LAB 4: Your code here. - } void @@ -363,7 +382,7 @@ page_fault_handler(struct Trapframe *tf) // LAB 4: Your code here. struct UTrapframe *utf; - + // cprintf("I'M in page_fault_handler [%08x] user fault va %08x \n",curenv->env_id, fault_va); if (curenv->env_pgfault_upcall) { if (tf->tf_esp >= UXSTACKTOP-PGSIZE && tf->tf_esp < UXSTACKTOP) { @@ -373,29 +392,30 @@ page_fault_handler(struct Trapframe *tf) } else { // 非异常模式下陷入 - utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe) - 4); + utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe)); } // 检查异常栈是否溢出 - user_mem_assert(curenv, (const void *) utf, sizeof(struct UTrapframe), PTE_U|PTE_W); + user_mem_assert(curenv, (const void *) utf, sizeof(struct UTrapframe), PTE_P|PTE_W); utf->utf_fault_va = fault_va; utf->utf_err = tf->tf_trapno; utf->utf_regs = tf->tf_regs; utf->utf_eflags = tf->tf_eflags; - // 保存上次陷入时现场,用于返回 + // 保存陷入时现场,用于返回 utf->utf_eip = tf->tf_eip; utf->utf_esp = tf->tf_esp; // 再次转向执行 - tf->tf_eip = (uint32_t) curenv->env_pgfault_upcall; - tf->tf_esp = (uint32_t) utf; + curenv->env_tf.tf_eip = (uint32_t) curenv->env_pgfault_upcall; + // 异常栈 + curenv->env_tf.tf_esp = (uint32_t) utf; env_run(curenv); } - - - // Destroy the environment that caused the fault. - cprintf("[%08x] user fault va %08x ip %08x\n", - curenv->env_id, fault_va, tf->tf_eip); - print_trapframe(tf); - env_destroy(curenv); + else { + // Destroy the environment that caused the fault. + cprintf("[%08x] user fault va %08x ip %08x\n", + curenv->env_id, fault_va, tf->tf_eip); + print_trapframe(tf); + env_destroy(curenv); + } } diff --git a/lab/Untitled Project.si4project/Backup/trap(7420).c b/lab/Untitled Project.si4project/Backup/trap(7420).c new file mode 100644 index 0000000..96bf71c --- /dev/null +++ b/lab/Untitled Project.si4project/Backup/trap(7420).c @@ -0,0 +1,430 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct Taskstate ts; + +/* For debugging, so print_trapframe can distinguish between printing + * a saved trapframe and printing the current trapframe and print some + * additional information in the latter case. + */ +static struct Trapframe *last_tf; + +/* Interrupt descriptor table. (Must be built at run time because + * shifted function addresses can't be represented in relocation records.) + */ +struct Gatedesc idt[256] = { { 0 } }; +struct Pseudodesc idt_pd = { + sizeof(idt) - 1, (uint32_t) idt +}; + + +static const char *trapname(int trapno) +{ + static const char * const excnames[] = { + "Divide error", + "Debug", + "Non-Maskable Interrupt", + "Breakpoint", + "Overflow", + "BOUND Range Exceeded", + "Invalid Opcode", + "Device Not Available", + "Double Fault", + "Coprocessor Segment Overrun", + "Invalid TSS", + "Segment Not Present", + "Stack Fault", + "General Protection", + "Page Fault", + "(unknown trap)", + "x87 FPU Floating-Point Error", + "Alignment Check", + "Machine-Check", + "SIMD Floating-Point Exception" + }; + + if (trapno < ARRAY_SIZE(excnames)) + return excnames[trapno]; + if (trapno == T_SYSCALL) + return "System call"; + if (trapno >= IRQ_OFFSET && trapno < IRQ_OFFSET + 16) + return "Hardware Interrupt"; + return "(unknown trap)"; +} + +// You will also need to modify trap_init() to initialize the idt to +// point to each of these entry points defined in trapentry.S; +// the SETGATE macro will be helpful here +void +trap_init(void) +{ + + extern struct Segdesc gdt[]; + void divide_handler(); + void debug_handler(); + void nmi_handler(); + void brkpt_handler(); + void oflow_handler(); + void bound_handler(); + void device_handler(); + void illop_handler(); + void tss_handler(); + void segnp_handler(); + void stack_handler(); + void gpflt_handler(); + void pgflt_handler(); + void fperr_handler(); + void align_handler(); + void mchk_handler(); + void simderr_handler(); + void syscall_handler(); + void dblflt_handler(); + void timer_handler(); + void kbd_handler(); + void serial_handler(); + void spurious_handler(); + void ide_handler(); + void error_handler(); + + + // LAB 3: Your code here. + // GD_KT 全局描述符, kernel text + SETGATE(idt[T_DIVIDE], 0, GD_KT, divide_handler, 0); + SETGATE(idt[T_DEBUG], 0, GD_KT, debug_handler, 0); + SETGATE(idt[T_NMI], 0, GD_KT, nmi_handler, 0); + SETGATE(idt[T_BRKPT], 0, GD_KT, brkpt_handler, 3); + SETGATE(idt[T_OFLOW], 0, GD_KT, oflow_handler, 0); + SETGATE(idt[T_BOUND], 0, GD_KT, bound_handler, 0); + SETGATE(idt[T_DEVICE], 0, GD_KT, device_handler, 0); + SETGATE(idt[T_ILLOP], 0, GD_KT, illop_handler, 0); + SETGATE(idt[T_DBLFLT], 0, GD_KT, dblflt_handler, 0); + SETGATE(idt[T_TSS], 0, GD_KT, tss_handler, 0); + SETGATE(idt[T_SEGNP], 0, GD_KT, segnp_handler, 0); + SETGATE(idt[T_STACK], 0, GD_KT, stack_handler, 0); + SETGATE(idt[T_GPFLT], 0, GD_KT, gpflt_handler, 0); + SETGATE(idt[T_PGFLT], 0, GD_KT, pgflt_handler, 0); + SETGATE(idt[T_FPERR], 0, GD_KT, fperr_handler, 0); + SETGATE(idt[T_ALIGN], 0, GD_KT, align_handler, 0); + SETGATE(idt[T_MCHK], 0, GD_KT, mchk_handler, 0); + SETGATE(idt[T_SIMDERR], 0, GD_KT, simderr_handler, 0); + SETGATE(idt[T_SYSCALL], 0, GD_KT, syscall_handler, 3); + // IRQ + SETGATE(idt[IRQ_OFFSET + IRQ_TIMER], 0, GD_KT, timer_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_KBD], 0, GD_KT, kbd_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SERIAL], 0, GD_KT, serial_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_SPURIOUS], 0, GD_KT, spurious_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_IDE], 0, GD_KT, ide_handler, 3); + SETGATE(idt[IRQ_OFFSET + IRQ_ERROR], 0, GD_KT, error_handler, 3); + + // Per-CPU setup + trap_init_percpu(); +} + +// Initialize and load the per-CPU TSS and IDT +void +trap_init_percpu(void) +{ + // The example code here sets up the Task State Segment (TSS) and + // the TSS descriptor for CPU 0. But it is incorrect if we are + // running on other CPUs because each CPU has its own kernel stack. + // Fix the code so that it works for all CPUs. + // + // Hints: + // - The macro "thiscpu" always refers to the current CPU's + // struct CpuInfo; + // - The ID of the current CPU is given by cpunum() or + // thiscpu->cpu_id; + // - Use "thiscpu->cpu_ts" as the TSS for the current CPU, + // rather than the global "ts" variable; + // - Use gdt[(GD_TSS0 >> 3) + i] for CPU i's TSS descriptor; + // - You mapped the per-CPU kernel stacks in mem_init_mp() + // - Initialize cpu_ts.ts_iomb to prevent unauthorized environments + // from doing IO (0 is not the correct value!) + // + // ltr sets a 'busy' flag in the TSS selector, so if you + // accidentally load the same TSS on more than one CPU, you'll + // get a triple fault. If you set up an individual CPU's TSS + // wrong, you may not get a fault until you try to return from + // user space on that CPU. + // + // LAB 4: Your code here: + thiscpu->cpu_ts.ts_esp0 = KSTACKTOP - cpunum() * (KSTKGAP + KSTKSIZE); + thiscpu->cpu_ts.ts_ss0 = GD_KD; + + // Initialize the TSS slot of the gdt. + gdt[(GD_TSS0 >> 3) + cpunum()] = SEG16(STS_T32A, (uint32_t) (&thiscpu->cpu_ts), sizeof(struct Taskstate) - 1, 0); + gdt[(GD_TSS0 >> 3) + cpunum()].sd_s = 0; + + // Load the TSS selector (like other segment selectors, the + // bottom three bits are special; we leave them 0) + ltr(GD_TSS0 + sizeof(struct Segdesc) * cpunum()); + + // Load the IDT + lidt(&idt_pd); +} + +void +print_trapframe(struct Trapframe *tf) +{ + cprintf("TRAP frame at %p from CPU %d\n", tf, cpunum()); + print_regs(&tf->tf_regs); + cprintf(" es 0x----%04x\n", tf->tf_es); + cprintf(" ds 0x----%04x\n", tf->tf_ds); + cprintf(" trap 0x%08x %s\n", tf->tf_trapno, trapname(tf->tf_trapno)); + // If this trap was a page fault that just happened + // (so %cr2 is meaningful), print the faulting linear address. + if (tf == last_tf && tf->tf_trapno == T_PGFLT) + cprintf(" cr2 0x%08x\n", rcr2()); + cprintf(" err 0x%08x", tf->tf_err); + // For page faults, print decoded fault error code: + // U/K=fault occurred in user/kernel mode + // W/R=a write/read caused the fault + // PR=a protection violation caused the fault (NP=page not present). + if (tf->tf_trapno == T_PGFLT) + cprintf(" [%s, %s, %s]\n", + tf->tf_err & 4 ? "user" : "kernel", + tf->tf_err & 2 ? "write" : "read", + tf->tf_err & 1 ? "protection" : "not-present"); + else + cprintf("\n"); + cprintf(" eip 0x%08x\n", tf->tf_eip); + cprintf(" cs 0x----%04x\n", tf->tf_cs); + cprintf(" flag 0x%08x\n", tf->tf_eflags); + if ((tf->tf_cs & 3) != 0) { + cprintf(" esp 0x%08x\n", tf->tf_esp); + cprintf(" ss 0x----%04x\n", tf->tf_ss); + } +} + +void +print_regs(struct PushRegs *regs) +{ + cprintf(" edi 0x%08x\n", regs->reg_edi); + cprintf(" esi 0x%08x\n", regs->reg_esi); + cprintf(" ebp 0x%08x\n", regs->reg_ebp); + cprintf(" oesp 0x%08x\n", regs->reg_oesp); + cprintf(" ebx 0x%08x\n", regs->reg_ebx); + cprintf(" edx 0x%08x\n", regs->reg_edx); + cprintf(" ecx 0x%08x\n", regs->reg_ecx); + cprintf(" eax 0x%08x\n", regs->reg_eax); +} + +static void +trap_dispatch(struct Trapframe *tf) +{ + // Handle processor exceptions. + // LAB 3: Your code here. + switch(tf->tf_trapno) { + case T_PGFLT: + page_fault_handler(tf); + break; + case T_BRKPT: + monitor(tf); + break; + case T_SYSCALL: + + tf->tf_regs.reg_eax = syscall(tf->tf_regs.reg_eax, + tf->tf_regs.reg_edx, + tf->tf_regs.reg_ecx, + tf->tf_regs.reg_ebx, + tf->tf_regs.reg_edi, + tf->tf_regs.reg_esi); + break; + // Handle clock interrupts. Don't forget to acknowledge the + // interrupt using lapic_eoi() before calling the scheduler! + // LAB 4: Your code here. + case (IRQ_OFFSET + IRQ_TIMER): + // 回应8259A 接收中断。 + lapic_eoi(); + sched_yield(); + break; + + case (IRQ_OFFSET + IRQ_KBD): + lapic_eoi(); + kbd_intr(); + break; + case (IRQ_OFFSET + IRQ_SERIAL): + lapic_eoi(); + serial_intr(); + break; + + default: + // Unexpected trap: The user process or the kernel has a bug. + print_trapframe(tf); + if (tf->tf_cs == GD_KT) + panic("unhandled trap in kernel"); + else { + env_destroy(curenv); + return; + } + break; + + } + + +} + +void +trap(struct Trapframe *tf) +{ + // The environment may have set DF and some versions + // of GCC rely on DF being clear + asm volatile("cld" ::: "cc"); + + // Halt the CPU if some other CPU has called panic() + extern char *panicstr; + if (panicstr) + asm volatile("hlt"); + + // Re-acqurie the big kernel lock if we were halted in + // sched_yield() + if (xchg(&thiscpu->cpu_status, CPU_STARTED) == CPU_HALTED) + lock_kernel(); + // Check that interrupts are disabled. If this assertion + // fails, DO NOT be tempted to fix it by inserting a "cli" in + // the interrupt path. + assert(!(read_eflags() & FL_IF)); + + if ((tf->tf_cs & 3) == 3) { + // Trapped from user mode. + // Acquire the big kernel lock before doing any + // serious kernel work. + // LAB 4: Your code here. + lock_kernel(); + assert(curenv); + + // Garbage collect if current enviroment is a zombie + if (curenv->env_status == ENV_DYING) { + env_free(curenv); + curenv = NULL; + sched_yield(); + } + + // Copy trap frame (which is currently on the stack) + // into 'curenv->env_tf', so that running the environment + // will restart at the trap point. + curenv->env_tf = *tf; + // The trapframe on the stack should be ignored from here on. + tf = &curenv->env_tf; + } + + // Record that tf is the last real trapframe so + // print_trapframe can print some additional information. + last_tf = tf; + + // Dispatch based on what type of trap occurred + trap_dispatch(tf); + + // If we made it to this point, then no other environment was + // scheduled, so we should return to the current environment + // if doing so makes sense. + if (curenv && curenv->env_status == ENV_RUNNING) + env_run(curenv); + else + sched_yield(); +} + + +void +page_fault_handler(struct Trapframe *tf) +{ + uint32_t fault_va; + + // Read processor's CR2 register to find the faulting address + fault_va = rcr2(); + + // Handle kernel-mode page faults. + + // LAB 3: Your code here. + + // 怎么判断是内核模式, CPL位 + + if(tf->tf_cs && 3 == 0) { + panic("page_fault in kernel mode, fault address %d\n", fault_va); + } + + // We've already handled kernel-mode exceptions, so if we get here, + // the page fault happened in user mode. + + + // Call the environment's page fault upcall, if one exists. Set up a + // page fault stack frame on the user exception stack (below + // UXSTACKTOP), then branch to curenv->env_pgfault_upcall. + // + // The page fault upcall might cause another page fault, in which case + // we branch to the page fault upcall recursively, pushing another + // page fault stack frame on top of the user exception stack. + // + // It is convenient for our code which returns from a page fault + // (lib/pfentry.S) to have one word of scratch space at the top of the + // trap-time stack; it allows us to more easily restore the eip/esp. In + // the non-recursive case, we don't have to worry about this because + // the top of the regular user stack is free. In the recursive case, + // this means we have to leave an extra word between the current top of + // the exception stack and the new stack frame because the exception + // stack _is_ the trap-time stack. + // + // If there's no page fault upcall, the environment didn't allocate a + // page for its exception stack or can't write to it, or the exception + // stack overflows, then destroy the environment that caused the fault. + // Note that the grade script assumes you will first check for the page + // fault upcall and print the "user fault va" message below if there is + // none. The remaining three checks can be combined into a single test. + // + // Hints: + // user_mem_assert() and env_run() are useful here. + // To change what the user environment runs, modify 'curenv->env_tf' + // (the 'tf' variable points at 'curenv->env_tf'). + + // LAB 4: Your code here. + struct UTrapframe *utf; + // cprintf("I'M in page_fault_handler [%08x] user fault va %08x \n",curenv->env_id, fault_va); + if (curenv->env_pgfault_upcall) { + + if (tf->tf_esp >= UXSTACKTOP-PGSIZE && tf->tf_esp < UXSTACKTOP) { + // 异常模式下陷入 + utf = (struct UTrapframe *)(tf->tf_esp - sizeof(struct UTrapframe) - 4); + + } + else { + // 非异常模式下陷入 + utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe)); + } + // 检查异常栈是否溢出 + user_mem_assert(curenv, (const void *) utf, sizeof(struct UTrapframe), PTE_P|PTE_W); + + utf->utf_fault_va = fault_va; + utf->utf_err = tf->tf_trapno; + utf->utf_regs = tf->tf_regs; + utf->utf_eflags = tf->tf_eflags; + // 保存陷入时现场,用于返回 + utf->utf_eip = tf->tf_eip; + utf->utf_esp = tf->tf_esp; + // 再次转向执行 + curenv->env_tf.tf_eip = (uint32_t) curenv->env_pgfault_upcall; + // 异常栈 + curenv->env_tf.tf_esp = (uint32_t) utf; + env_run(curenv); + } + else { + // Destroy the environment that caused the fault. + cprintf("[%08x] user fault va %08x ip %08x\n", + curenv->env_id, fault_va, tf->tf_eip); + print_trapframe(tf); + env_destroy(curenv); + } +} + diff --git a/lab/Untitled Project.si4project/Untitled Project.SearchResults b/lab/Untitled Project.si4project/Untitled Project.SearchResults new file mode 100644 index 0000000..943d2e3 --- /dev/null +++ b/lab/Untitled Project.si4project/Untitled Project.SearchResults @@ -0,0 +1,3 @@ +---- IOPL Matches (2 in 2 files) ---- +env_create in env.c (kern) : newenv->env_tf.tf_eflags |= IOPL +syscall.c (kern) line 134 : // protection level 3 (CPL 3), interrupts enabled, and IOPL of 0. diff --git a/lab/LAB4.si4project/LAB4.bookmarks.xml b/lab/Untitled Project.si4project/Untitled Project.bookmarks.xml similarity index 100% rename from lab/LAB4.si4project/LAB4.bookmarks.xml rename to lab/Untitled Project.si4project/Untitled Project.bookmarks.xml diff --git a/lab/Untitled Project.si4project/Untitled Project.sip_sym b/lab/Untitled Project.si4project/Untitled Project.sip_sym new file mode 100644 index 0000000..ca00bff Binary files /dev/null and b/lab/Untitled Project.si4project/Untitled Project.sip_sym differ diff --git a/lab/Untitled Project.si4project/Untitled Project.sip_xab b/lab/Untitled Project.si4project/Untitled Project.sip_xab new file mode 100644 index 0000000..df7c68a Binary files /dev/null and b/lab/Untitled Project.si4project/Untitled Project.sip_xab differ diff --git a/lab/Untitled Project.si4project/Untitled Project.sip_xad b/lab/Untitled Project.si4project/Untitled Project.sip_xad new file mode 100644 index 0000000..c715f24 Binary files /dev/null and b/lab/Untitled Project.si4project/Untitled Project.sip_xad differ diff --git a/lab/LAB4.si4project/LAB4.sip_xc b/lab/Untitled Project.si4project/Untitled Project.sip_xc similarity index 64% rename from lab/LAB4.si4project/LAB4.sip_xc rename to lab/Untitled Project.si4project/Untitled Project.sip_xc index 1656324..95bb266 100644 Binary files a/lab/LAB4.si4project/LAB4.sip_xc and b/lab/Untitled Project.si4project/Untitled Project.sip_xc differ diff --git a/lab/LAB4.si4project/LAB4.sip_xf b/lab/Untitled Project.si4project/Untitled Project.sip_xf similarity index 59% rename from lab/LAB4.si4project/LAB4.sip_xf rename to lab/Untitled Project.si4project/Untitled Project.sip_xf index 09e8462..ed8959b 100644 Binary files a/lab/LAB4.si4project/LAB4.sip_xf and b/lab/Untitled Project.si4project/Untitled Project.sip_xf differ diff --git a/lab/Untitled Project.si4project/Untitled Project.sip_xm b/lab/Untitled Project.si4project/Untitled Project.sip_xm new file mode 100644 index 0000000..72739ae Binary files /dev/null and b/lab/Untitled Project.si4project/Untitled Project.sip_xm differ diff --git a/lab/LAB4.si4project/LAB4.sip_xr b/lab/Untitled Project.si4project/Untitled Project.sip_xr similarity index 61% rename from lab/LAB4.si4project/LAB4.sip_xr rename to lab/Untitled Project.si4project/Untitled Project.sip_xr index 0eb429b..2458b6b 100644 Binary files a/lab/LAB4.si4project/LAB4.sip_xr and b/lab/Untitled Project.si4project/Untitled Project.sip_xr differ diff --git a/lab/Untitled Project.si4project/Untitled Project.sip_xsb b/lab/Untitled Project.si4project/Untitled Project.sip_xsb new file mode 100644 index 0000000..7f3daf7 Binary files /dev/null and b/lab/Untitled Project.si4project/Untitled Project.sip_xsb differ diff --git a/lab/Untitled Project.si4project/Untitled Project.sip_xsd b/lab/Untitled Project.si4project/Untitled Project.sip_xsd new file mode 100644 index 0000000..c349472 Binary files /dev/null and b/lab/Untitled Project.si4project/Untitled Project.sip_xsd differ diff --git a/lab/LAB4.si4project/LAB4.siproj b/lab/Untitled Project.si4project/Untitled Project.siproj similarity index 53% rename from lab/LAB4.si4project/LAB4.siproj rename to lab/Untitled Project.si4project/Untitled Project.siproj index 89a2a82..0e7a9af 100644 Binary files a/lab/LAB4.si4project/LAB4.siproj and b/lab/Untitled Project.si4project/Untitled Project.siproj differ diff --git a/lab/LAB4.si4project/LAB4.siproj_settings.xml b/lab/Untitled Project.si4project/Untitled Project.siproj_settings.xml similarity index 100% rename from lab/LAB4.si4project/LAB4.siproj_settings.xml rename to lab/Untitled Project.si4project/Untitled Project.siproj_settings.xml diff --git a/lab/Untitled Project.si4project/Untitled Project.siwork b/lab/Untitled Project.si4project/Untitled Project.siwork new file mode 100644 index 0000000..031bc25 Binary files /dev/null and b/lab/Untitled Project.si4project/Untitled Project.siwork differ diff --git a/lab/LAB4.si4project/LAB4.snippets.xml b/lab/Untitled Project.si4project/Untitled Project.snippets.xml similarity index 100% rename from lab/LAB4.si4project/LAB4.snippets.xml rename to lab/Untitled Project.si4project/Untitled Project.snippets.xml diff --git a/lab/Untitled Project.si4project/cache/parse/boot_main.c.sisc b/lab/Untitled Project.si4project/cache/parse/boot_main.c.sisc new file mode 100644 index 0000000..adb2cb0 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/boot_main.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/fs_bc.c.sisc b/lab/Untitled Project.si4project/cache/parse/fs_bc.c.sisc new file mode 100644 index 0000000..03549f8 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/fs_bc.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/fs_fs.c.sisc b/lab/Untitled Project.si4project/cache/parse/fs_fs.c.sisc new file mode 100644 index 0000000..74ab517 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/fs_fs.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/fs_fs.h.sisc b/lab/Untitled Project.si4project/cache/parse/fs_fs.h.sisc new file mode 100644 index 0000000..6d7d533 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/fs_fs.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/fs_fsformat.c.sisc b/lab/Untitled Project.si4project/cache/parse/fs_fsformat.c.sisc new file mode 100644 index 0000000..65fd089 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/fs_fsformat.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/fs_ide.c.sisc b/lab/Untitled Project.si4project/cache/parse/fs_ide.c.sisc new file mode 100644 index 0000000..3be2f5c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/fs_ide.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/fs_serv.c.sisc b/lab/Untitled Project.si4project/cache/parse/fs_serv.c.sisc new file mode 100644 index 0000000..9331896 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/fs_serv.c.sisc differ diff --git a/lab/LAB4.si4project/cache/parse/fs_test.c.sisc b/lab/Untitled Project.si4project/cache/parse/fs_test.c.sisc similarity index 51% rename from lab/LAB4.si4project/cache/parse/fs_test.c.sisc rename to lab/Untitled Project.si4project/cache/parse/fs_test.c.sisc index bb1775d..a55672a 100644 Binary files a/lab/LAB4.si4project/cache/parse/fs_test.c.sisc and b/lab/Untitled Project.si4project/cache/parse/fs_test.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/gradelib.py.sisc b/lab/Untitled Project.si4project/cache/parse/gradelib.py.sisc new file mode 100644 index 0000000..b312ced Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/gradelib.py.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_args.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_args.h.sisc new file mode 100644 index 0000000..d5e27c4 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_args.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_assert.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_assert.h.sisc new file mode 100644 index 0000000..e476f77 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_assert.h.sisc differ diff --git a/lab/LAB4.si4project/cache/parse/inc_elf.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_elf.h.sisc similarity index 68% rename from lab/LAB4.si4project/cache/parse/inc_elf.h.sisc rename to lab/Untitled Project.si4project/cache/parse/inc_elf.h.sisc index 57c8451..e9bd9df 100644 Binary files a/lab/LAB4.si4project/cache/parse/inc_elf.h.sisc and b/lab/Untitled Project.si4project/cache/parse/inc_elf.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_env.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_env.h.sisc new file mode 100644 index 0000000..81a6f46 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_env.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_error.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_error.h.sisc new file mode 100644 index 0000000..3c00ea9 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_error.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_fd.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_fd.h.sisc new file mode 100644 index 0000000..239d385 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_fd.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_fs.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_fs.h.sisc new file mode 100644 index 0000000..b77a438 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_fs.h.sisc differ diff --git a/lab/LAB4.si4project/cache/parse/inc_kbdreg.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_kbdreg.h.sisc similarity index 94% rename from lab/LAB4.si4project/cache/parse/inc_kbdreg.h.sisc rename to lab/Untitled Project.si4project/cache/parse/inc_kbdreg.h.sisc index 7df5bb3..eb7b8fe 100644 Binary files a/lab/LAB4.si4project/cache/parse/inc_kbdreg.h.sisc and b/lab/Untitled Project.si4project/cache/parse/inc_kbdreg.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_lib.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_lib.h.sisc new file mode 100644 index 0000000..0c041b5 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_lib.h.sisc differ diff --git a/lab/LAB4.si4project/cache/parse/inc_memlayout.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_memlayout.h.sisc similarity index 68% rename from lab/LAB4.si4project/cache/parse/inc_memlayout.h.sisc rename to lab/Untitled Project.si4project/cache/parse/inc_memlayout.h.sisc index bcc4294..49ccd6a 100644 Binary files a/lab/LAB4.si4project/cache/parse/inc_memlayout.h.sisc and b/lab/Untitled Project.si4project/cache/parse/inc_memlayout.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_mmu.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_mmu.h.sisc new file mode 100644 index 0000000..f643bad Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_mmu.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_partition.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_partition.h.sisc new file mode 100644 index 0000000..68e1064 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_partition.h.sisc differ diff --git a/lab/LAB4.si4project/cache/parse/inc_stab.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_stab.h.sisc similarity index 84% rename from lab/LAB4.si4project/cache/parse/inc_stab.h.sisc rename to lab/Untitled Project.si4project/cache/parse/inc_stab.h.sisc index 16ba2ad..e073ebf 100644 Binary files a/lab/LAB4.si4project/cache/parse/inc_stab.h.sisc and b/lab/Untitled Project.si4project/cache/parse/inc_stab.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_stdarg.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_stdarg.h.sisc new file mode 100644 index 0000000..74e580e Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_stdarg.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_stdio.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_stdio.h.sisc new file mode 100644 index 0000000..217976c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_stdio.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_string.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_string.h.sisc new file mode 100644 index 0000000..1adf4a3 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_string.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_syscall.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_syscall.h.sisc new file mode 100644 index 0000000..7ac2227 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_syscall.h.sisc differ diff --git a/lab/LAB4.si4project/cache/parse/inc_trap.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_trap.h.sisc similarity index 82% rename from lab/LAB4.si4project/cache/parse/inc_trap.h.sisc rename to lab/Untitled Project.si4project/cache/parse/inc_trap.h.sisc index a6b4471..44e262a 100644 Binary files a/lab/LAB4.si4project/cache/parse/inc_trap.h.sisc and b/lab/Untitled Project.si4project/cache/parse/inc_trap.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_types.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_types.h.sisc new file mode 100644 index 0000000..32be6e8 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_types.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/inc_x86.h.sisc b/lab/Untitled Project.si4project/cache/parse/inc_x86.h.sisc new file mode 100644 index 0000000..8b8cbd9 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/inc_x86.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_console.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_console.c.sisc new file mode 100644 index 0000000..755a4ea Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_console.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_console.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_console.h.sisc new file mode 100644 index 0000000..66b4fc0 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_console.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_cpu.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_cpu.h.sisc new file mode 100644 index 0000000..c5a4b5a Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_cpu.h.sisc differ diff --git a/lab/LAB4.si4project/cache/parse/kern_entrypgdir.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_entrypgdir.c.sisc similarity index 84% rename from lab/LAB4.si4project/cache/parse/kern_entrypgdir.c.sisc rename to lab/Untitled Project.si4project/cache/parse/kern_entrypgdir.c.sisc index ad405fe..1d79897 100644 Binary files a/lab/LAB4.si4project/cache/parse/kern_entrypgdir.c.sisc and b/lab/Untitled Project.si4project/cache/parse/kern_entrypgdir.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_env.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_env.c.sisc new file mode 100644 index 0000000..7ac8f79 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_env.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_env.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_env.h.sisc new file mode 100644 index 0000000..7714a1c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_env.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_init.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_init.c.sisc new file mode 100644 index 0000000..c6b6372 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_init.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_kclock.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_kclock.c.sisc new file mode 100644 index 0000000..78e9d70 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_kclock.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_kclock.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_kclock.h.sisc new file mode 100644 index 0000000..719cf48 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_kclock.h.sisc differ diff --git a/lab/LAB4.si4project/cache/parse/kern_kdebug.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_kdebug.c.sisc similarity index 66% rename from lab/LAB4.si4project/cache/parse/kern_kdebug.c.sisc rename to lab/Untitled Project.si4project/cache/parse/kern_kdebug.c.sisc index 283db2c..aa08d6c 100644 Binary files a/lab/LAB4.si4project/cache/parse/kern_kdebug.c.sisc and b/lab/Untitled Project.si4project/cache/parse/kern_kdebug.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_kdebug.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_kdebug.h.sisc new file mode 100644 index 0000000..22df6e1 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_kdebug.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_lapic.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_lapic.c.sisc new file mode 100644 index 0000000..03cd588 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_lapic.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_monitor.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_monitor.c.sisc new file mode 100644 index 0000000..ad45c6a Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_monitor.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_monitor.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_monitor.h.sisc new file mode 100644 index 0000000..b332160 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_monitor.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_mpconfig.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_mpconfig.c.sisc new file mode 100644 index 0000000..f4a9898 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_mpconfig.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_picirq.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_picirq.c.sisc new file mode 100644 index 0000000..4c3854e Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_picirq.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_picirq.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_picirq.h.sisc new file mode 100644 index 0000000..7d6921a Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_picirq.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_pmap.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_pmap.c.sisc new file mode 100644 index 0000000..b9e30b0 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_pmap.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_pmap.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_pmap.h.sisc new file mode 100644 index 0000000..0ca201a Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_pmap.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_printf.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_printf.c.sisc new file mode 100644 index 0000000..64df07c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_printf.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_sched.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_sched.c.sisc new file mode 100644 index 0000000..6f6c8a5 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_sched.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_sched.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_sched.h.sisc new file mode 100644 index 0000000..ae66252 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_sched.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_spinlock.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_spinlock.c.sisc new file mode 100644 index 0000000..1b4d1a6 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_spinlock.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_spinlock.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_spinlock.h.sisc new file mode 100644 index 0000000..a3a4091 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_spinlock.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_syscall.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_syscall.c.sisc new file mode 100644 index 0000000..082d85c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_syscall.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_syscall.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_syscall.h.sisc new file mode 100644 index 0000000..2a31ccd Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_syscall.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_trap.c.sisc b/lab/Untitled Project.si4project/cache/parse/kern_trap.c.sisc new file mode 100644 index 0000000..efe689c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_trap.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/kern_trap.h.sisc b/lab/Untitled Project.si4project/cache/parse/kern_trap.h.sisc new file mode 100644 index 0000000..6bab04e Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/kern_trap.h.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_args.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_args.c.sisc new file mode 100644 index 0000000..8d7c5b9 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_args.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_console.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_console.c.sisc new file mode 100644 index 0000000..75c60fd Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_console.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_exit.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_exit.c.sisc new file mode 100644 index 0000000..3bd1ca9 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_exit.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_fd.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_fd.c.sisc new file mode 100644 index 0000000..e967475 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_fd.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_file.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_file.c.sisc new file mode 100644 index 0000000..e456fcf Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_file.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_fork.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_fork.c.sisc new file mode 100644 index 0000000..22decab Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_fork.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_fprintf.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_fprintf.c.sisc new file mode 100644 index 0000000..660f056 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_fprintf.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_ipc.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_ipc.c.sisc new file mode 100644 index 0000000..dc1616c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_ipc.c.sisc differ diff --git a/lab/LAB4.si4project/cache/parse/lib_libmain.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_libmain.c.sisc similarity index 62% rename from lab/LAB4.si4project/cache/parse/lib_libmain.c.sisc rename to lab/Untitled Project.si4project/cache/parse/lib_libmain.c.sisc index 29cc64f..2a65a9b 100644 Binary files a/lab/LAB4.si4project/cache/parse/lib_libmain.c.sisc and b/lab/Untitled Project.si4project/cache/parse/lib_libmain.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_pageref.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_pageref.c.sisc new file mode 100644 index 0000000..aab01c0 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_pageref.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_panic.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_panic.c.sisc new file mode 100644 index 0000000..19d74f4 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_panic.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_pgfault.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_pgfault.c.sisc new file mode 100644 index 0000000..0a8818c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_pgfault.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_pipe.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_pipe.c.sisc new file mode 100644 index 0000000..7edbeaf Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_pipe.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_printf.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_printf.c.sisc new file mode 100644 index 0000000..4b39f2e Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_printf.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_printfmt.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_printfmt.c.sisc new file mode 100644 index 0000000..16a168c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_printfmt.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_readline.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_readline.c.sisc new file mode 100644 index 0000000..ebf9a2c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_readline.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_spawn.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_spawn.c.sisc new file mode 100644 index 0000000..28bf33c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_spawn.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_string.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_string.c.sisc new file mode 100644 index 0000000..fa9ecef Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_string.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_syscall.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_syscall.c.sisc new file mode 100644 index 0000000..8ec2319 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_syscall.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/lib_wait.c.sisc b/lab/Untitled Project.si4project/cache/parse/lib_wait.c.sisc new file mode 100644 index 0000000..ba91a7d Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/lib_wait.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_badsegment.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_badsegment.c.sisc new file mode 100644 index 0000000..5c81a0e Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_badsegment.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_breakpoint.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_breakpoint.c.sisc new file mode 100644 index 0000000..0022198 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_breakpoint.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_buggyhello.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_buggyhello.c.sisc new file mode 100644 index 0000000..c51629f Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_buggyhello.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_buggyhello2.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_buggyhello2.c.sisc new file mode 100644 index 0000000..bb9466b Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_buggyhello2.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_cat.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_cat.c.sisc new file mode 100644 index 0000000..f6a3355 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_cat.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_divzero.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_divzero.c.sisc new file mode 100644 index 0000000..3ca2c41 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_divzero.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_dumbfork.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_dumbfork.c.sisc new file mode 100644 index 0000000..f388f08 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_dumbfork.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_echo.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_echo.c.sisc new file mode 100644 index 0000000..6903dfc Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_echo.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_evilhello.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_evilhello.c.sisc new file mode 100644 index 0000000..c887123 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_evilhello.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_fairness.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_fairness.c.sisc new file mode 100644 index 0000000..5cf4bb4 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_fairness.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultalloc.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultalloc.c.sisc new file mode 100644 index 0000000..cdfbfd9 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultalloc.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultallocbad.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultallocbad.c.sisc new file mode 100644 index 0000000..5abe41e Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultallocbad.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultbadhandler.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultbadhandler.c.sisc new file mode 100644 index 0000000..ae7d619 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultbadhandler.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultdie.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultdie.c.sisc new file mode 100644 index 0000000..4ac0a5e Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultdie.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultevilhandler.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultevilhandler.c.sisc new file mode 100644 index 0000000..93ae4bb Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultevilhandler.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultio.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultio.c.sisc new file mode 100644 index 0000000..6b2090f Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultio.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultnostack.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultnostack.c.sisc new file mode 100644 index 0000000..d5df1b4 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultnostack.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultread.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultread.c.sisc new file mode 100644 index 0000000..3e03b6b Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultread.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultreadkernel.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultreadkernel.c.sisc new file mode 100644 index 0000000..8f0a2c3 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultreadkernel.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultregs.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultregs.c.sisc new file mode 100644 index 0000000..3cd4cee Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultregs.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultwrite.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultwrite.c.sisc new file mode 100644 index 0000000..296313b Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultwrite.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_faultwritekernel.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_faultwritekernel.c.sisc new file mode 100644 index 0000000..5f80201 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_faultwritekernel.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_forktree.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_forktree.c.sisc new file mode 100644 index 0000000..4b48576 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_forktree.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_hello.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_hello.c.sisc new file mode 100644 index 0000000..29c682b Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_hello.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_icode.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_icode.c.sisc new file mode 100644 index 0000000..1965434 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_icode.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_idle.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_idle.c.sisc new file mode 100644 index 0000000..2ebf9f2 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_idle.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_init.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_init.c.sisc new file mode 100644 index 0000000..6fbac5b Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_init.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_initsh.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_initsh.c.sisc new file mode 100644 index 0000000..74f0f8d Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_initsh.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_ls.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_ls.c.sisc new file mode 100644 index 0000000..6b8a8ff Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_ls.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_lsfd.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_lsfd.c.sisc new file mode 100644 index 0000000..bb7d6cc Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_lsfd.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_num.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_num.c.sisc new file mode 100644 index 0000000..4654316 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_num.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_pingpong.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_pingpong.c.sisc new file mode 100644 index 0000000..e9cdd97 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_pingpong.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_pingpongs.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_pingpongs.c.sisc new file mode 100644 index 0000000..607c83a Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_pingpongs.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_primes.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_primes.c.sisc new file mode 100644 index 0000000..984f426 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_primes.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_primespipe.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_primespipe.c.sisc new file mode 100644 index 0000000..bdffcd6 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_primespipe.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_sendpage.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_sendpage.c.sisc new file mode 100644 index 0000000..3caaa5b Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_sendpage.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_sh.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_sh.c.sisc new file mode 100644 index 0000000..4dfc58d Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_sh.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_softint.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_softint.c.sisc new file mode 100644 index 0000000..fbf40ef Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_softint.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_spawnfaultio.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_spawnfaultio.c.sisc new file mode 100644 index 0000000..3738b18 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_spawnfaultio.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_spawnhello.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_spawnhello.c.sisc new file mode 100644 index 0000000..bbca73f Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_spawnhello.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_spawninit.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_spawninit.c.sisc new file mode 100644 index 0000000..beed4da Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_spawninit.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_spin.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_spin.c.sisc new file mode 100644 index 0000000..6ca4f6d Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_spin.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_stresssched.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_stresssched.c.sisc new file mode 100644 index 0000000..cc21a74 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_stresssched.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testbss.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testbss.c.sisc new file mode 100644 index 0000000..cacc47a Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testbss.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testfdsharing.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testfdsharing.c.sisc new file mode 100644 index 0000000..a95f96c Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testfdsharing.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testfile.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testfile.c.sisc new file mode 100644 index 0000000..ce9ff14 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testfile.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testkbd.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testkbd.c.sisc new file mode 100644 index 0000000..eeee61b Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testkbd.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testmalloc.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testmalloc.c.sisc new file mode 100644 index 0000000..e1c7a03 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testmalloc.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testpipe.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testpipe.c.sisc new file mode 100644 index 0000000..6a0d8c8 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testpipe.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testpiperace.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testpiperace.c.sisc new file mode 100644 index 0000000..9c8b126 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testpiperace.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testpiperace2.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testpiperace2.c.sisc new file mode 100644 index 0000000..2567df4 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testpiperace2.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testptelibrary.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testptelibrary.c.sisc new file mode 100644 index 0000000..0ffa4a2 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testptelibrary.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testpteshare.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testpteshare.c.sisc new file mode 100644 index 0000000..3033f9f Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testpteshare.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_testshell.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_testshell.c.sisc new file mode 100644 index 0000000..40d6116 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_testshell.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_writemotd.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_writemotd.c.sisc new file mode 100644 index 0000000..96f3ea7 Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_writemotd.c.sisc differ diff --git a/lab/Untitled Project.si4project/cache/parse/user_yield.c.sisc b/lab/Untitled Project.si4project/cache/parse/user_yield.c.sisc new file mode 100644 index 0000000..38c40dc Binary files /dev/null and b/lab/Untitled Project.si4project/cache/parse/user_yield.c.sisc differ diff --git a/lab/conf/lab.mk b/lab/conf/lab.mk index 74db46c..428f188 100644 --- a/lab/conf/lab.mk +++ b/lab/conf/lab.mk @@ -1,2 +1,2 @@ -LAB=4 -PACKAGEDATE=Mon Oct 8 21:31:51 PDT 2018 +LAB=5 +PACKAGEDATE=Wed Oct 24 20:44:37 EDT 2018 diff --git a/lab/fs/Makefrag b/lab/fs/Makefrag new file mode 100644 index 0000000..748e065 --- /dev/null +++ b/lab/fs/Makefrag @@ -0,0 +1,77 @@ + +OBJDIRS += fs + +FSOFILES := $(OBJDIR)/fs/ide.o \ + $(OBJDIR)/fs/bc.o \ + $(OBJDIR)/fs/fs.o \ + $(OBJDIR)/fs/serv.o \ + $(OBJDIR)/fs/test.o \ + +USERAPPS := $(OBJDIR)/user/init + +FSIMGTXTFILES := fs/newmotd \ + fs/motd + + +USERAPPS := $(USERAPPS) \ + $(OBJDIR)/user/cat \ + $(OBJDIR)/user/echo \ + $(OBJDIR)/user/init \ + $(OBJDIR)/user/ls \ + $(OBJDIR)/user/lsfd \ + $(OBJDIR)/user/num \ + $(OBJDIR)/user/forktree \ + $(OBJDIR)/user/primes \ + $(OBJDIR)/user/primespipe \ + $(OBJDIR)/user/sh \ + $(OBJDIR)/user/testfdsharing \ + $(OBJDIR)/user/testkbd \ + $(OBJDIR)/user/testpipe \ + $(OBJDIR)/user/testpteshare \ + $(OBJDIR)/user/testshell \ + $(OBJDIR)/user/hello \ + $(OBJDIR)/user/faultio \ + +FSIMGTXTFILES := $(FSIMGTXTFILES) \ + fs/lorem \ + fs/script \ + fs/testshell.key \ + fs/testshell.sh + + +FSIMGFILES := $(FSIMGTXTFILES) $(USERAPPS) + +$(OBJDIR)/fs/%.o: fs/%.c fs/fs.h inc/lib.h $(OBJDIR)/.vars.USER_CFLAGS + @echo + cc[USER] $< + @mkdir -p $(@D) + $(V)$(CC) -nostdinc $(USER_CFLAGS) -c -o $@ $< + +$(OBJDIR)/fs/fs: $(FSOFILES) $(OBJDIR)/lib/entry.o $(OBJDIR)/lib/libjos.a user/user.ld + @echo + ld $@ + $(V)mkdir -p $(@D) + $(V)$(LD) -o $@ $(ULDFLAGS) $(LDFLAGS) -nostdlib \ + $(OBJDIR)/lib/entry.o $(FSOFILES) \ + -L$(OBJDIR)/lib -ljos $(GCC_LIB) + $(V)$(OBJDUMP) -S $@ >$@.asm + +# How to build the file system image +$(OBJDIR)/fs/fsformat: fs/fsformat.c + @echo + mk $(OBJDIR)/fs/fsformat + $(V)mkdir -p $(@D) + $(V)$(NCC) $(NATIVE_CFLAGS) -o $(OBJDIR)/fs/fsformat fs/fsformat.c + +$(OBJDIR)/fs/clean-fs.img: $(OBJDIR)/fs/fsformat $(FSIMGFILES) + @echo + mk $(OBJDIR)/fs/clean-fs.img + $(V)mkdir -p $(@D) + $(V)$(OBJDIR)/fs/fsformat $(OBJDIR)/fs/clean-fs.img 1024 $(FSIMGFILES) + +$(OBJDIR)/fs/fs.img: $(OBJDIR)/fs/clean-fs.img + @echo + cp $(OBJDIR)/fs/clean-fs.img $@ + $(V)cp $(OBJDIR)/fs/clean-fs.img $@ + +all: $(OBJDIR)/fs/fs.img + +#all: $(addsuffix .sym, $(USERAPPS)) + +#all: $(addsuffix .asm, $(USERAPPS)) + diff --git a/lab/fs/bc.c b/lab/fs/bc.c new file mode 100644 index 0000000..dd5f20d --- /dev/null +++ b/lab/fs/bc.c @@ -0,0 +1,169 @@ + +#include "fs.h" + +// Return the virtual address of this disk block. +void* +diskaddr(uint32_t blockno) +{ + if (blockno == 0 || (super && blockno >= super->s_nblocks)) + panic("bad block number %08x in diskaddr", blockno); + return (char*) (DISKMAP + blockno * BLKSIZE); +} + +// Is this virtual address mapped? +bool +va_is_mapped(void *va) +{ + return (uvpd[PDX(va)] & PTE_P) && (uvpt[PGNUM(va)] & PTE_P); +} + +// Is this virtual address dirty? +bool +va_is_dirty(void *va) +{ + return (uvpt[PGNUM(va)] & PTE_D) != 0; +} + +// Fault any disk block that is read in to memory by +// loading it from disk. +static void +bc_pgfault(struct UTrapframe *utf) +{ + void *addr = (void *) utf->utf_fault_va; + uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; + int r; + + // Check that the fault was within the block cache region + if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) + panic("page fault in FS: eip %08x, va %08x, err %04x", + utf->utf_eip, addr, utf->utf_err); + + // Sanity check the block number. + if (super && blockno >= super->s_nblocks) + panic("reading non-existent block %08x\n", blockno); + + // Allocate a page in the disk map region, read the contents + // of the block from the disk into that page. + // Hint: first round addr to page boundary. fs/ide.c has code to read + // the disk. + // + // LAB 5: you code here: + // envid 传入 0? 在最初的哪个进程下 alloc 一个page ? + addr =(void *) ROUNDDOWN(addr, PGSIZE); + if ( (r = sys_page_alloc(0, addr, PTE_P |PTE_W|PTE_U)) < 0) { + panic("in bc_pgfault, sys_page_alloc: %e", r); + } + // size_t secno = (addr - DISKMAP) / BLKSIZE; + if ( (r = ide_read(blockno*BLKSECTS, addr, BLKSECTS)) < 0) { + panic("in bc_pgfault, ide_read: %e",r); + } + + // Clear the dirty bit for the disk block page since we just read the + // block from disk + // 只是为了修改标志位 + if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0) + panic("in bc_pgfault, sys_page_map: %e", r); + + // Check that the block we read was allocated. (exercise for + // the reader: why do we do this *after* reading the block + // in?) + if (bitmap && block_is_free(blockno)) + panic("reading free block %08x\n", blockno); +} + +// Flush the contents of the block containing VA out to disk if +// necessary, then clear the PTE_D bit using sys_page_map. +// If the block is not in the block cache or is not dirty, does +// nothing. +// Hint: Use va_is_mapped, va_is_dirty, and ide_write. +// Hint: Use the PTE_SYSCALL constant when calling sys_page_map. +// Hint: Don't forget to round addr down. +void +flush_block(void *addr) +{ + uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; + + if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) + panic("flush_block of bad va %08x", addr); + int r; + // LAB 5: Your code here. + addr = (void *)ROUNDDOWN(addr, PGSIZE); + if (va_is_mapped(addr) && va_is_dirty(addr)) { + + ide_write(blockno*BLKSECTS, addr , BLKSECTS); + if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0) + panic("in flush_block, sys_page_map: %e", r); + } + + // panic("flush_block not implemented"); +} + +// Test that the block cache works, by smashing the superblock and +// reading it back. +static void +check_bc(void) +{ + struct Super backup; + + // back up super block + memmove(&backup, diskaddr(1), sizeof backup); + + // smash it + strcpy(diskaddr(1), "OOPS!\n"); + flush_block(diskaddr(1)); + assert(va_is_mapped(diskaddr(1))); + assert(!va_is_dirty(diskaddr(1))); + + // clear it out + sys_page_unmap(0, diskaddr(1)); + assert(!va_is_mapped(diskaddr(1))); + + // read it back in + assert(strcmp(diskaddr(1), "OOPS!\n") == 0); + + // fix it + memmove(diskaddr(1), &backup, sizeof backup); + flush_block(diskaddr(1)); + + // Now repeat the same experiment, but pass an unaligned address to + // flush_block. + + // back up super block + memmove(&backup, diskaddr(1), sizeof backup); + + // smash it + strcpy(diskaddr(1), "OOPS!\n"); + + // Pass an unaligned address to flush_block. + flush_block(diskaddr(1) + 20); + assert(va_is_mapped(diskaddr(1))); + + // Skip the !va_is_dirty() check because it makes the bug somewhat + // obscure and hence harder to debug. + //assert(!va_is_dirty(diskaddr(1))); + + // clear it out + sys_page_unmap(0, diskaddr(1)); + assert(!va_is_mapped(diskaddr(1))); + + // read it back in + assert(strcmp(diskaddr(1), "OOPS!\n") == 0); + + // fix it + memmove(diskaddr(1), &backup, sizeof backup); + flush_block(diskaddr(1)); + + cprintf("block cache is good\n"); +} + +void +bc_init(void) +{ + struct Super super; + set_pgfault_handler(bc_pgfault); + check_bc(); + + // cache the super block by reading it once + memmove(&super, diskaddr(1), sizeof super); +} + diff --git a/lab/fs/fs.c b/lab/fs/fs.c new file mode 100644 index 0000000..0b9b76e --- /dev/null +++ b/lab/fs/fs.c @@ -0,0 +1,515 @@ +#include +#include + +#include "fs.h" + +// -------------------------------------------------------------- +// Super block +// -------------------------------------------------------------- + +// Validate the file system super-block. +void +check_super(void) +{ + if (super->s_magic != FS_MAGIC) + panic("bad file system magic number"); + + if (super->s_nblocks > DISKSIZE/BLKSIZE) + panic("file system is too large"); + + cprintf("superblock is good\n"); +} + +// -------------------------------------------------------------- +// Free block bitmap +// -------------------------------------------------------------- + +// Check to see if the block bitmap indicates that block 'blockno' is free. +// Return 1 if the block is free, 0 if not. +bool +block_is_free(uint32_t blockno) +{ + if (super == 0 || blockno >= super->s_nblocks) + return 0; + if (bitmap[blockno / 32] & (1 << (blockno % 32))) + return 1; + return 0; +} + +// Mark a block free in the bitmap +void +free_block(uint32_t blockno) +{ + // Blockno zero is the null pointer of block numbers. + // 0 块启动块 + if (blockno == 0) + panic("attempt to free zero block"); + bitmap[blockno/32] |= 1<<(blockno%32); +} + +// Search the bitmap for a free block and allocate it. When you +// allocate a block, immediately flush the changed bitmap block +// to disk. +// +// Return block number allocated on success, +// -E_NO_DISK if we are out of blocks. +// +// Hint: use free_block as an example for manipulating the bitmap. +int +alloc_block(void) +{ + // The bitmap consists of one or more blocks. A single bitmap block + // contains the in-use bits for BLKBITSIZE blocks. There are + // super->s_nblocks blocks in the disk altogether. + + // LAB 5: Your code here. + size_t i; + for(i=1; i < super->s_nblocks; i++) { + if (block_is_free(i)) { + bitmap[i/32] &= ~(1<<(i%32)); + flush_block(&bitmap[i/32]); + return i; + } + } + // panic("alloc_block not implemented"); + return -E_NO_DISK; +} + +// Validate the file system bitmap. +// +// Check that all reserved blocks -- 0, 1, and the bitmap blocks themselves -- +// are all marked as in-use. +void +check_bitmap(void) +{ + uint32_t i; + + // Make sure all bitmap blocks are marked in-use + for (i = 0; i * BLKBITSIZE < super->s_nblocks; i++) + assert(!block_is_free(2+i)); + + // Make sure the reserved and root blocks are marked in-use. + assert(!block_is_free(0)); + assert(!block_is_free(1)); + + cprintf("bitmap is good\n"); +} + +// -------------------------------------------------------------- +// File system structures +// -------------------------------------------------------------- + + + +// Initialize the file system +void +fs_init(void) +{ + static_assert(sizeof(struct File) == 256); + + // Find a JOS disk. Use the second IDE disk (number 1) if available + if (ide_probe_disk1()) + ide_set_disk(1); + else + ide_set_disk(0); + bc_init(); + + // Set "super" to point to the super block. + super = diskaddr(1); + check_super(); + + // Set "bitmap" to the beginning of the first bitmap block. + bitmap = diskaddr(2); + check_bitmap(); + +} + +// Find the disk block number slot for the 'filebno'th block in file 'f'. +// Set '*ppdiskbno' to point to that slot. +// The slot will be one of the f->f_direct[] entries, +// or an entry in the indirect block. +// When 'alloc' is set, this function will allocate an indirect block +// if necessary. +// +// Returns: +// 0 on success (but note that *ppdiskbno might equal 0). +// -E_NOT_FOUND if the function needed to allocate an indirect block, but +// alloc was 0. +// -E_NO_DISK if there's no space on the disk for an indirect block. +// -E_INVAL if filebno is out of range (it's >= NDIRECT + NINDIRECT). +// +// Analogy: This is like pgdir_walk for files. +// Hint: Don't forget to clear any block you allocate. +static int +file_block_walk(struct File *f, uint32_t filebno, uint32_t **ppdiskbno, bool alloc) +{ + // LAB 5: Your code here. + // ppdiskbno 块指针 + if (filebno < NDIRECT) { + // but note that *ppdiskbno might equal 0 + if(ppdiskbno) + *ppdiskbno = &(f->f_direct[filebno]); + + return 0; + } + + if (filebno >= (NDIRECT + NINDIRECT)) + return -E_INVAL; + + filebno -= NDIRECT; + // indirect 还未分配 + if (!f->f_indirect) { + if (alloc == 0) + return -E_NOT_FOUND; + // 分配一个 indirect block + uint32_t blockno; + if ( (blockno = alloc_block()) < 0) + return blockno; + // f_indirect 直接记录块号,而不是记地址 + // f->f_indirect = (uint32_t)diskaddr(blockno); + f->f_indirect = blockno; + memset(diskaddr(blockno), 0, BLKSIZE); + flush_block(diskaddr(blockno)); + } + if (ppdiskbno) + *ppdiskbno = (uint32_t *)diskaddr(f->f_indirect) + filebno; + return 0; + // panic("file_block_walk not implemented"); +} + +// Set *blk to the address in memory where the filebno'th +// block of file 'f' would be mapped. +// +// Returns 0 on success, < 0 on error. Errors are: +// -E_NO_DISK if a block needed to be allocated but the disk is full. +// -E_INVAL if filebno is out of range. +// +// Hint: Use file_block_walk and alloc_block. +int +file_get_block(struct File *f, uint32_t filebno, char **blk) +{ + // LAB 5: Your code here. + uint32_t *pdiskbno; + int r; + if ( (r = file_block_walk(f, filebno, &pdiskbno, 1))< 0) + return r; + + if(*pdiskbno == 0) { + // 文件块还未分配 + if ( (r = alloc_block()) < 0) + return r; + *pdiskbno = r; + memset(diskaddr(r), 0, BLKSIZE); + flush_block(diskaddr(r)); + } + + // 最终指向块 + *blk = diskaddr(*pdiskbno); + return 0; + //panic("file_get_block not implemented"); +} + +// Try to find a file named "name" in dir. If so, set *file to it. +// +// Returns 0 and sets *file on success, < 0 on error. Errors are: +// -E_NOT_FOUND if the file is not found +static int +dir_lookup(struct File *dir, const char *name, struct File **file) +{ + int r; + uint32_t i, j, nblock; + char *blk; + struct File *f; + + // Search dir for name. + // We maintain the invariant that the size of a directory-file + // is always a multiple of the file system's block size. + // 目录size 必须为 文件系统块size的倍数。 + assert((dir->f_size % BLKSIZE) == 0); + nblock = dir->f_size / BLKSIZE; + for (i = 0; i < nblock; i++) { + if ((r = file_get_block(dir, i, &blk)) < 0) + return r; + f = (struct File*) blk; + for (j = 0; j < BLKFILES; j++) + // 不会出现子目录与文件同名吗? + if (strcmp(f[j].f_name, name) == 0) { + *file = &f[j]; + return 0; + } + } + return -E_NOT_FOUND; +} + +// Set *file to point at a free File structure in dir. The caller is +// responsible for filling in the File fields. +static int +dir_alloc_file(struct File *dir, struct File **file) +{ + int r; + uint32_t nblock, i, j; + char *blk; + struct File *f; + + assert((dir->f_size % BLKSIZE) == 0); + nblock = dir->f_size / BLKSIZE; + for (i = 0; i < nblock; i++) { + if ((r = file_get_block(dir, i, &blk)) < 0) + return r; + f = (struct File*) blk; + for (j = 0; j < BLKFILES; j++) + if (f[j].f_name[0] == '\0') { + *file = &f[j]; + return 0; + } + } + // 目录里没有空项,增添一个块 + dir->f_size += BLKSIZE; + if ((r = file_get_block(dir, i, &blk)) < 0) + return r; + f = (struct File*) blk; + *file = &f[0]; + return 0; +} + +// Skip over slashes. +static const char* +skip_slash(const char *p) +{ + while (*p == '/') + p++; + return p; +} + +// Evaluate a path name, starting at the root. +// On success, set *pf to the file we found +// and set *pdir to the directory the file is in. +// If we cannot find the file but find the directory +// it should be in, set *pdir and copy the final path +// element into lastelem. +static int +walk_path(const char *path, struct File **pdir, struct File **pf, char *lastelem) +{ + const char *p; + char name[MAXNAMELEN]; + struct File *dir, *f; + int r; + + // if (*path != '/') + // return -E_BAD_PATH; + path = skip_slash(path); + f = &super->s_root; + dir = 0; + name[0] = 0; + + if (pdir) + *pdir = 0; + *pf = 0; + while (*path != '\0') { + dir = f; + p = path; + while (*path != '/' && *path != '\0') + path++; + if (path - p >= MAXNAMELEN) + return -E_BAD_PATH; + memmove(name, p, path - p); + name[path - p] = '\0'; + path = skip_slash(path); + + if (dir->f_type != FTYPE_DIR) + return -E_NOT_FOUND; + + if ((r = dir_lookup(dir, name, &f)) < 0) { + if (r == -E_NOT_FOUND && *path == '\0') { + if (pdir) + *pdir = dir; + if (lastelem) + strcpy(lastelem, name); + *pf = 0; + } + return r; + } + } + + if (pdir) + *pdir = dir; + *pf = f; + return 0; +} + +// -------------------------------------------------------------- +// File operations +// -------------------------------------------------------------- + +// Create "path". On success set *pf to point at the file and return 0. +// On error return < 0. +int +file_create(const char *path, struct File **pf) +{ + char name[MAXNAMELEN]; + int r; + struct File *dir, *f; + + if ((r = walk_path(path, &dir, &f, name)) == 0) + return -E_FILE_EXISTS; + if (r != -E_NOT_FOUND || dir == 0) + return r; + if ((r = dir_alloc_file(dir, &f)) < 0) + return r; + + strcpy(f->f_name, name); + *pf = f; + file_flush(dir); + return 0; +} + +// Open "path". On success set *pf to point at the file and return 0. +// On error return < 0. +int +file_open(const char *path, struct File **pf) +{ + return walk_path(path, 0, pf, 0); +} + +// Read count bytes from f into buf, starting from seek position +// offset. This meant to mimic the standard pread function. +// Returns the number of bytes read, < 0 on error. +ssize_t +file_read(struct File *f, void *buf, size_t count, off_t offset) +{ + int r, bn; + off_t pos; + char *blk; + + if (offset >= f->f_size) + return 0; + + count = MIN(count, f->f_size - offset); + + for (pos = offset; pos < offset + count; ) { + if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0) + return r; + bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos); + memmove(buf, blk + pos % BLKSIZE, bn); + pos += bn; + buf += bn; + } + + return count; +} + + +// Write count bytes from buf into f, starting at seek position +// offset. This is meant to mimic the standard pwrite function. +// Extends the file if necessary. +// Returns the number of bytes written, < 0 on error. +int +file_write(struct File *f, const void *buf, size_t count, off_t offset) +{ + int r, bn; + off_t pos; + char *blk; + + // Extend file if necessary + if (offset + count > f->f_size) + if ((r = file_set_size(f, offset + count)) < 0) + return r; + + for (pos = offset; pos < offset + count; ) { + if ((r = file_get_block(f, pos / BLKSIZE, &blk)) < 0) + return r; + bn = MIN(BLKSIZE - pos % BLKSIZE, offset + count - pos); + memmove(blk + pos % BLKSIZE, buf, bn); + pos += bn; + buf += bn; + } + + return count; +} + +// Remove a block from file f. If it's not there, just silently succeed. +// Returns 0 on success, < 0 on error. +static int +file_free_block(struct File *f, uint32_t filebno) +{ + int r; + uint32_t *ptr; + + if ((r = file_block_walk(f, filebno, &ptr, 0)) < 0) + return r; + if (*ptr) { + free_block(*ptr); + *ptr = 0; + } + return 0; +} + +// Remove any blocks currently used by file 'f', +// but not necessary for a file of size 'newsize'. +// For both the old and new sizes, figure out the number of blocks required, +// and then clear the blocks from new_nblocks to old_nblocks. +// If the new_nblocks is no more than NDIRECT, and the indirect block has +// been allocated (f->f_indirect != 0), then free the indirect block too. +// (Remember to clear the f->f_indirect pointer so you'll know +// whether it's valid!) +// Do not change f->f_size. +static void +file_truncate_blocks(struct File *f, off_t newsize) +{ + int r; + uint32_t bno, old_nblocks, new_nblocks; + + old_nblocks = (f->f_size + BLKSIZE - 1) / BLKSIZE; + new_nblocks = (newsize + BLKSIZE - 1) / BLKSIZE; + for (bno = new_nblocks; bno < old_nblocks; bno++) + if ((r = file_free_block(f, bno)) < 0) + cprintf("warning: file_free_block: %e", r); + + if (new_nblocks <= NDIRECT && f->f_indirect) { + free_block(f->f_indirect); + f->f_indirect = 0; + } +} + +// Set the size of file f, truncating or extending as necessary. +int +file_set_size(struct File *f, off_t newsize) +{ + if (f->f_size > newsize) + file_truncate_blocks(f, newsize); + f->f_size = newsize; + flush_block(f); + return 0; +} + +// Flush the contents and metadata of file f out to disk. +// Loop over all the blocks in file. +// Translate the file block number into a disk block number +// and then check whether that disk block is dirty. If so, write it out. +void +file_flush(struct File *f) +{ + int i; + uint32_t *pdiskbno; + + for (i = 0; i < (f->f_size + BLKSIZE - 1) / BLKSIZE; i++) { + if (file_block_walk(f, i, &pdiskbno, 0) < 0 || + pdiskbno == NULL || *pdiskbno == 0) + continue; + flush_block(diskaddr(*pdiskbno)); + } + flush_block(f); + if (f->f_indirect) + flush_block(diskaddr(f->f_indirect)); +} + + +// Sync the entire file system. A big hammer. +void +fs_sync(void) +{ + int i; + for (i = 1; i < super->s_nblocks; i++) + flush_block(diskaddr(i)); +} + diff --git a/lab/fs/fs.h b/lab/fs/fs.h new file mode 100644 index 0000000..0350d78 --- /dev/null +++ b/lab/fs/fs.h @@ -0,0 +1,49 @@ +#include +#include + +#define SECTSIZE 512 // bytes per disk sector +#define BLKSECTS (BLKSIZE / SECTSIZE) // sectors per block + +/* Disk block n, when in memory, is mapped into the file system + * server's address space at DISKMAP + (n*BLKSIZE). */ +#define DISKMAP 0x10000000 + +/* Maximum disk size we can handle (3GB) */ +#define DISKSIZE 0xC0000000 + +struct Super *super; // superblock +uint32_t *bitmap; // bitmap blocks mapped in memory + +/* ide.c */ +bool ide_probe_disk1(void); +void ide_set_disk(int diskno); +void ide_set_partition(uint32_t first_sect, uint32_t nsect); +int ide_read(uint32_t secno, void *dst, size_t nsecs); +int ide_write(uint32_t secno, const void *src, size_t nsecs); + +/* bc.c */ +void* diskaddr(uint32_t blockno); +bool va_is_mapped(void *va); +bool va_is_dirty(void *va); +void flush_block(void *addr); +void bc_init(void); + +/* fs.c */ +void fs_init(void); +int file_get_block(struct File *f, uint32_t file_blockno, char **pblk); +int file_create(const char *path, struct File **f); +int file_open(const char *path, struct File **f); +ssize_t file_read(struct File *f, void *buf, size_t count, off_t offset); +int file_write(struct File *f, const void *buf, size_t count, off_t offset); +int file_set_size(struct File *f, off_t newsize); +void file_flush(struct File *f); +int file_remove(const char *path); +void fs_sync(void); + +/* int map_block(uint32_t); */ +bool block_is_free(uint32_t blockno); +int alloc_block(void); + +/* test.c */ +void fs_test(void); + diff --git a/lab/fs/fsformat.c b/lab/fs/fsformat.c new file mode 100644 index 0000000..4dab07a --- /dev/null +++ b/lab/fs/fsformat.c @@ -0,0 +1,244 @@ +/* + * JOS file system format + */ + +// We don't actually want to define off_t! +#define off_t xxx_off_t +#define bool xxx_bool +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef off_t +#undef bool + +// Prevent inc/types.h, included from inc/fs.h, +// from attempting to redefine types defined in the host's inttypes.h. +#define JOS_INC_TYPES_H +// Typedef the types that inc/mmu.h needs. +typedef uint32_t physaddr_t; +typedef uint32_t off_t; +typedef int bool; + +#include +#include + +#define ROUNDUP(n, v) ((n) - 1 + (v) - ((n) - 1) % (v)) +#define MAX_DIR_ENTS 128 + +struct Dir +{ + struct File *f; + struct File *ents; + int n; +}; + +uint32_t nblocks; +char *diskmap, *diskpos; +struct Super *super; +uint32_t *bitmap; + +void +panic(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputc('\n', stderr); + abort(); +} + +void +readn(int f, void *out, size_t n) +{ + size_t p = 0; + while (p < n) { + ssize_t m = read(f, out + p, n - p); + if (m < 0) + panic("read: %s", strerror(errno)); + if (m == 0) + panic("read: Unexpected EOF"); + p += m; + } +} + +uint32_t +blockof(void *pos) +{ + return ((char*)pos - diskmap) / BLKSIZE; +} + +void * +alloc(uint32_t bytes) +{ + void *start = diskpos; + diskpos += ROUNDUP(bytes, BLKSIZE); + if (blockof(diskpos) >= nblocks) + panic("out of disk blocks"); + return start; +} + +void +opendisk(const char *name) +{ + int r, diskfd, nbitblocks; + + if ((diskfd = open(name, O_RDWR | O_CREAT, 0666)) < 0) + panic("open %s: %s", name, strerror(errno)); + + if ((r = ftruncate(diskfd, 0)) < 0 + || (r = ftruncate(diskfd, nblocks * BLKSIZE)) < 0) + panic("truncate %s: %s", name, strerror(errno)); + + if ((diskmap = mmap(NULL, nblocks * BLKSIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, diskfd, 0)) == MAP_FAILED) + panic("mmap %s: %s", name, strerror(errno)); + + close(diskfd); + + diskpos = diskmap; + alloc(BLKSIZE); + super = alloc(BLKSIZE); + super->s_magic = FS_MAGIC; + super->s_nblocks = nblocks; + super->s_root.f_type = FTYPE_DIR; + strcpy(super->s_root.f_name, "/"); + + nbitblocks = (nblocks + BLKBITSIZE - 1) / BLKBITSIZE; + bitmap = alloc(nbitblocks * BLKSIZE); + memset(bitmap, 0xFF, nbitblocks * BLKSIZE); +} + +void +finishdisk(void) +{ + int r, i; + + for (i = 0; i < blockof(diskpos); ++i) + bitmap[i/32] &= ~(1<<(i%32)); + + if ((r = msync(diskmap, nblocks * BLKSIZE, MS_SYNC)) < 0) + panic("msync: %s", strerror(errno)); +} + +void +finishfile(struct File *f, uint32_t start, uint32_t len) +{ + int i; + f->f_size = len; + len = ROUNDUP(len, BLKSIZE); + for (i = 0; i < len / BLKSIZE && i < NDIRECT; ++i) + f->f_direct[i] = start + i; + if (i == NDIRECT) { + uint32_t *ind = alloc(BLKSIZE); + f->f_indirect = blockof(ind); + for (; i < len / BLKSIZE; ++i) + ind[i - NDIRECT] = start + i; + } +} + +void +startdir(struct File *f, struct Dir *dout) +{ + dout->f = f; + dout->ents = malloc(MAX_DIR_ENTS * sizeof *dout->ents); + dout->n = 0; +} + +struct File * +diradd(struct Dir *d, uint32_t type, const char *name) +{ + struct File *out = &d->ents[d->n++]; + if (d->n > MAX_DIR_ENTS) + panic("too many directory entries"); + strcpy(out->f_name, name); + out->f_type = type; + return out; +} + +void +finishdir(struct Dir *d) +{ + int size = d->n * sizeof(struct File); + struct File *start = alloc(size); + memmove(start, d->ents, size); + finishfile(d->f, blockof(start), ROUNDUP(size, BLKSIZE)); + free(d->ents); + d->ents = NULL; +} + +void +writefile(struct Dir *dir, const char *name) +{ + int r, fd; + struct File *f; + struct stat st; + const char *last; + char *start; + + if ((fd = open(name, O_RDONLY)) < 0) + panic("open %s: %s", name, strerror(errno)); + if ((r = fstat(fd, &st)) < 0) + panic("stat %s: %s", name, strerror(errno)); + if (!S_ISREG(st.st_mode)) + panic("%s is not a regular file", name); + if (st.st_size >= MAXFILESIZE) + panic("%s too large", name); + + last = strrchr(name, '/'); + if (last) + last++; + else + last = name; + + f = diradd(dir, FTYPE_REG, last); + start = alloc(st.st_size); + readn(fd, start, st.st_size); + finishfile(f, blockof(start), st.st_size); + close(fd); +} + +void +usage(void) +{ + fprintf(stderr, "Usage: fsformat fs.img NBLOCKS files...\n"); + exit(2); +} + +int +main(int argc, char **argv) +{ + int i; + char *s; + struct Dir root; + + assert(BLKSIZE % sizeof(struct File) == 0); + + if (argc < 3) + usage(); + + nblocks = strtol(argv[2], &s, 0); + if (*s || s == argv[2] || nblocks < 2 || nblocks > 1024) + usage(); + + opendisk(argv[1]); + + startdir(&super->s_root, &root); + for (i = 3; i < argc; i++) + writefile(&root, argv[i]); + finishdir(&root); + + finishdisk(); + return 0; +} + diff --git a/lab/fs/ide.c b/lab/fs/ide.c new file mode 100644 index 0000000..2d8b4bf --- /dev/null +++ b/lab/fs/ide.c @@ -0,0 +1,112 @@ +/* + * Minimal PIO-based (non-interrupt-driven) IDE driver code. + * For information about what all this IDE/ATA magic means, + * see the materials available on the class references page. + */ + +#include "fs.h" +#include + +#define IDE_BSY 0x80 +#define IDE_DRDY 0x40 +#define IDE_DF 0x20 +#define IDE_ERR 0x01 + +static int diskno = 1; + +static int +ide_wait_ready(bool check_error) +{ + int r; + + while (((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) + /* do nothing */; + + if (check_error && (r & (IDE_DF|IDE_ERR)) != 0) + return -1; + return 0; +} + +bool +ide_probe_disk1(void) +{ + int r, x; + + // wait for Device 0 to be ready + ide_wait_ready(0); + + // switch to Device 1 + outb(0x1F6, 0xE0 | (1<<4)); + + // check for Device 1 to be ready for a while + for (x = 0; + x < 1000 && ((r = inb(0x1F7)) & (IDE_BSY|IDE_DF|IDE_ERR)) != 0; + x++) + /* do nothing */; + + // switch back to Device 0 + outb(0x1F6, 0xE0 | (0<<4)); + + cprintf("Device 1 presence: %d\n", (x < 1000)); + return (x < 1000); +} + +void +ide_set_disk(int d) +{ + if (d != 0 && d != 1) + panic("bad disk number"); + diskno = d; +} + + +int +ide_read(uint32_t secno, void *dst, size_t nsecs) +{ + int r; + + assert(nsecs <= 256); + + ide_wait_ready(0); + + outb(0x1F2, nsecs); + outb(0x1F3, secno & 0xFF); + outb(0x1F4, (secno >> 8) & 0xFF); + outb(0x1F5, (secno >> 16) & 0xFF); + outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); + outb(0x1F7, 0x20); // CMD 0x20 means read sector + + for (; nsecs > 0; nsecs--, dst += SECTSIZE) { + if ((r = ide_wait_ready(1)) < 0) + return r; + insl(0x1F0, dst, SECTSIZE/4); + } + + return 0; +} + +int +ide_write(uint32_t secno, const void *src, size_t nsecs) +{ + int r; + + assert(nsecs <= 256); + + ide_wait_ready(0); + + outb(0x1F2, nsecs); + outb(0x1F3, secno & 0xFF); + outb(0x1F4, (secno >> 8) & 0xFF); + outb(0x1F5, (secno >> 16) & 0xFF); + outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); + outb(0x1F7, 0x30); // CMD 0x30 means write sector + + for (; nsecs > 0; nsecs--, src += SECTSIZE) { + if ((r = ide_wait_ready(1)) < 0) + return r; + outsl(0x1F0, src, SECTSIZE/4); + } + + return 0; +} + diff --git a/lab/fs/lorem b/lab/fs/lorem new file mode 100644 index 0000000..c7c76e5 --- /dev/null +++ b/lab/fs/lorem @@ -0,0 +1,12 @@ +Lorem ipsum dolor sit amet, consectetur +adipisicing elit, sed do eiusmod tempor +incididunt ut labore et dolore magna +aliqua. Ut enim ad minim veniam, quis +nostrud exercitation ullamco laboris +nisi ut aliquip ex ea commodo consequat. +Duis aute irure dolor in reprehenderit +in voluptate velit esse cillum dolore eu +fugiat nulla pariatur. Excepteur sint +occaecat cupidatat non proident, sunt in +culpa qui officia deserunt mollit anim +id est laborum. diff --git a/lab/fs/motd b/lab/fs/motd new file mode 100644 index 0000000..3643fef --- /dev/null +++ b/lab/fs/motd @@ -0,0 +1,4 @@ +This is /motd, the message of the day. + +Welcome to the JOS kernel, now with a file system! + diff --git a/lab/fs/newmotd b/lab/fs/newmotd new file mode 100644 index 0000000..58c9cf2 --- /dev/null +++ b/lab/fs/newmotd @@ -0,0 +1,2 @@ +This is the NEW message of the day! + diff --git a/lab/fs/script b/lab/fs/script new file mode 100644 index 0000000..e4291d4 --- /dev/null +++ b/lab/fs/script @@ -0,0 +1,5 @@ +echo This is from the script. +cat lorem | num | cat +echo These are my file descriptors. +lsfd -1 +echo This is the end of the script. diff --git a/lab/fs/serv.c b/lab/fs/serv.c new file mode 100644 index 0000000..0d7e75f --- /dev/null +++ b/lab/fs/serv.c @@ -0,0 +1,365 @@ +/* + * File system server main loop - + * serves IPC requests from other environments. + */ + +#include +#include + +#include "fs.h" + + +#define debug 0 + +// The file system server maintains three structures +// for each open file. +// +// 1. The on-disk 'struct File' is mapped into the part of memory +// that maps the disk. This memory is kept private to the file +// server. +// 2. Each open file has a 'struct Fd' as well, which sort of +// corresponds to a Unix file descriptor. This 'struct Fd' is kept +// on *its own page* in memory, and it is shared with any +// environments that have the file open. +// 3. 'struct OpenFile' links these other two structures, and is kept +// private to the file server. The server maintains an array of +// all open files, indexed by "file ID". (There can be at most +// MAXOPEN files open concurrently.) The client uses file IDs to +// communicate with the server. File IDs are a lot like +// environment IDs in the kernel. Use openfile_lookup to translate +// file IDs to struct OpenFile. + +struct OpenFile { + uint32_t o_fileid; // file id + struct File *o_file; // mapped descriptor for open file + int o_mode; // open mode + struct Fd *o_fd; // Fd page +}; + +// Max number of open files in the file system at once +#define MAXOPEN 1024 +#define FILEVA 0xD0000000 + +// initialize to force into data section +struct OpenFile opentab[MAXOPEN] = { + { 0, 0, 1, 0 } +}; + +// Virtual address at which to receive page mappings containing client requests. +union Fsipc *fsreq = (union Fsipc *)0x0ffff000; + +void +serve_init(void) +{ + int i; + uintptr_t va = FILEVA; + for (i = 0; i < MAXOPEN; i++) { + opentab[i].o_fileid = i; + opentab[i].o_fd = (struct Fd*) va; + va += PGSIZE; + } +} + +// Allocate an open file. +int +openfile_alloc(struct OpenFile **o) +{ + int i, r; + + // Find an available open-file table entry + for (i = 0; i < MAXOPEN; i++) { + switch (pageref(opentab[i].o_fd)) { + case 0: + if ((r = sys_page_alloc(0, opentab[i].o_fd, PTE_P|PTE_U|PTE_W)) < 0) + return r; + /* fall through */ + case 1: + opentab[i].o_fileid += MAXOPEN; + *o = &opentab[i]; + memset(opentab[i].o_fd, 0, PGSIZE); + return (*o)->o_fileid; + } + } + return -E_MAX_OPEN; +} + +// Look up an open file for envid. +int +openfile_lookup(envid_t envid, uint32_t fileid, struct OpenFile **po) +{ + struct OpenFile *o; + + o = &opentab[fileid % MAXOPEN]; + if (pageref(o->o_fd) <= 1 || o->o_fileid != fileid) + return -E_INVAL; + *po = o; + return 0; +} + +// Open req->req_path in mode req->req_omode, storing the Fd page and +// permissions to return to the calling environment in *pg_store and +// *perm_store respectively. +int +serve_open(envid_t envid, struct Fsreq_open *req, + void **pg_store, int *perm_store) +{ + char path[MAXPATHLEN]; + struct File *f; + int fileid; + int r; + struct OpenFile *o; + + if (debug) + cprintf("serve_open %08x %s 0x%x\n", envid, req->req_path, req->req_omode); + + // Copy in the path, making sure it's null-terminated + memmove(path, req->req_path, MAXPATHLEN); + path[MAXPATHLEN-1] = 0; + + // Find an open file ID + if ((r = openfile_alloc(&o)) < 0) { + if (debug) + cprintf("openfile_alloc failed: %e", r); + return r; + } + fileid = r; + + // Open the file + if (req->req_omode & O_CREAT) { + if ((r = file_create(path, &f)) < 0) { + if (!(req->req_omode & O_EXCL) && r == -E_FILE_EXISTS) + goto try_open; + if (debug) + cprintf("file_create failed: %e", r); + return r; + } + } else { +try_open: + if ((r = file_open(path, &f)) < 0) { + if (debug) + cprintf("file_open failed: %e", r); + return r; + } + } + + // Truncate + if (req->req_omode & O_TRUNC) { + if ((r = file_set_size(f, 0)) < 0) { + if (debug) + cprintf("file_set_size failed: %e", r); + return r; + } + } + if ((r = file_open(path, &f)) < 0) { + if (debug) + cprintf("file_open failed: %e", r); + return r; + } + + // Save the file pointer + o->o_file = f; + + // Fill out the Fd structure + o->o_fd->fd_file.id = o->o_fileid; + o->o_fd->fd_omode = req->req_omode & O_ACCMODE; + o->o_fd->fd_dev_id = devfile.dev_id; + o->o_mode = req->req_omode; + + if (debug) + cprintf("sending success, page %08x\n", (uintptr_t) o->o_fd); + + // Share the FD page with the caller by setting *pg_store, + // store its permission in *perm_store + *pg_store = o->o_fd; + *perm_store = PTE_P|PTE_U|PTE_W|PTE_SHARE; + + return 0; +} + +// Set the size of req->req_fileid to req->req_size bytes, truncating +// or extending the file as necessary. +int +serve_set_size(envid_t envid, struct Fsreq_set_size *req) +{ + struct OpenFile *o; + int r; + + if (debug) + cprintf("serve_set_size %08x %08x %08x\n", envid, req->req_fileid, req->req_size); + + // Every file system IPC call has the same general structure. + // Here's how it goes. + + // First, use openfile_lookup to find the relevant open file. + // On failure, return the error code to the client with ipc_send. + if ((r = openfile_lookup(envid, req->req_fileid, &o)) < 0) + return r; + + // Second, call the relevant file system function (from fs/fs.c). + // On failure, return the error code to the client. + return file_set_size(o->o_file, req->req_size); +} + +// Read at most ipc->read.req_n bytes from the current seek position +// in ipc->read.req_fileid. Return the bytes read from the file to +// the caller in ipc->readRet, then update the seek position. Returns +// the number of bytes successfully read, or < 0 on error. +int +serve_read(envid_t envid, union Fsipc *ipc) +{ + struct Fsreq_read *req = &ipc->read; + struct Fsret_read *ret = &ipc->readRet; + int r; + if (debug) + cprintf("serve_read %08x %08x %08x\n", envid, req->req_fileid, req->req_n); + + // Lab 5: Your code here: + struct OpenFile *of; + if ( (r = openfile_lookup(envid, req->req_fileid, &of) )< 0) + return r; + + if ( (r = file_read(of->o_file, ret->ret_buf, req->req_n, of->o_fd->fd_offset))< 0) + return r; + + // then update the seek position. + of->o_fd->fd_offset += r; + return r; +} + + +// Write req->req_n bytes from req->req_buf to req_fileid, starting at +// the current seek position, and update the seek position +// accordingly. Extend the file if necessary. Returns the number of +// bytes written, or < 0 on error. +int +serve_write(envid_t envid, struct Fsreq_write *req) +{ + if (debug) + cprintf("serve_write %08x %08x %08x\n", envid, req->req_fileid, req->req_n); + int r; + struct OpenFile *of; + int reqn; + if ( (r = openfile_lookup(envid, req->req_fileid, &of)) < 0) + return r; + reqn = req->req_n > PGSIZE? PGSIZE:req->req_n; + + if ( (r = file_write(of->o_file, req->req_buf, reqn, of->o_fd->fd_offset)) < 0) + return r; + + of->o_fd->fd_offset += r; + return r; + // LAB 5: Your code here. + // panic("serve_write not implemented"); +} + +// Stat ipc->stat.req_fileid. Return the file's struct Stat to the +// caller in ipc->statRet. +int +serve_stat(envid_t envid, union Fsipc *ipc) +{ + struct Fsreq_stat *req = &ipc->stat; + struct Fsret_stat *ret = &ipc->statRet; + struct OpenFile *o; + int r; + + if (debug) + cprintf("serve_stat %08x %08x\n", envid, req->req_fileid); + + if ((r = openfile_lookup(envid, req->req_fileid, &o)) < 0) + return r; + + strcpy(ret->ret_name, o->o_file->f_name); + ret->ret_size = o->o_file->f_size; + ret->ret_isdir = (o->o_file->f_type == FTYPE_DIR); + return 0; +} + +// Flush all data and metadata of req->req_fileid to disk. +int +serve_flush(envid_t envid, struct Fsreq_flush *req) +{ + struct OpenFile *o; + int r; + + if (debug) + cprintf("serve_flush %08x %08x\n", envid, req->req_fileid); + + if ((r = openfile_lookup(envid, req->req_fileid, &o)) < 0) + return r; + file_flush(o->o_file); + return 0; +} + + +int +serve_sync(envid_t envid, union Fsipc *req) +{ + fs_sync(); + return 0; +} + +typedef int (*fshandler)(envid_t envid, union Fsipc *req); + +fshandler handlers[] = { + // Open is handled specially because it passes pages + /* [FSREQ_OPEN] = (fshandler)serve_open, */ + [FSREQ_READ] = serve_read, + [FSREQ_STAT] = serve_stat, + [FSREQ_FLUSH] = (fshandler)serve_flush, + [FSREQ_WRITE] = (fshandler)serve_write, + [FSREQ_SET_SIZE] = (fshandler)serve_set_size, + [FSREQ_SYNC] = serve_sync +}; + +void +serve(void) +{ + uint32_t req, whom; + int perm, r; + void *pg; + + while (1) { + perm = 0; + req = ipc_recv((int32_t *) &whom, fsreq, &perm); + if (debug) + cprintf("fs req %d from %08x [page %08x: %s]\n", + req, whom, uvpt[PGNUM(fsreq)], fsreq); + + // All requests must contain an argument page + if (!(perm & PTE_P)) { + cprintf("Invalid request from %08x: no argument page\n", + whom); + continue; // just leave it hanging... + } + + pg = NULL; + if (req == FSREQ_OPEN) { + r = serve_open(whom, (struct Fsreq_open*)fsreq, &pg, &perm); + } else if (req < ARRAY_SIZE(handlers) && handlers[req]) { + r = handlers[req](whom, fsreq); + } else { + cprintf("Invalid request code %d from %08x\n", req, whom); + r = -E_INVAL; + } + ipc_send(whom, r, pg, perm); + sys_page_unmap(0, fsreq); + } +} + +void +umain(int argc, char **argv) +{ + static_assert(sizeof(struct File) == 256); + binaryname = "fs"; + cprintf("FS is running\n"); + + // Check that we are able to do I/O + outw(0x8A00, 0x8A00); + cprintf("FS can do I/O\n"); + + serve_init(); + fs_init(); + fs_test(); + serve(); +} + diff --git a/lab/fs/testshell.sh b/lab/fs/testshell.sh new file mode 100644 index 0000000..c4f5984 --- /dev/null +++ b/lab/fs/testshell.sh @@ -0,0 +1,7 @@ +echo hello world | cat +cat lorem +cat lorem |num +cat lorem |num |num |num |num |num +lsfd -1 +cat script +sh