Finish lab 5.
This commit is contained in:
parent
e9f683f6d6
commit
4199ce9c37
17
fs/bc.c
17
fs/bc.c
@ -31,6 +31,7 @@ bc_pgfault(struct UTrapframe *utf)
|
||||
{
|
||||
void *addr = (void *) utf->utf_fault_va;
|
||||
uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE;
|
||||
uint32_t secno = blockno * (BLKSIZE / SECTSIZE);
|
||||
int r;
|
||||
|
||||
// Check that the fault was within the block cache region
|
||||
@ -48,6 +49,11 @@ bc_pgfault(struct UTrapframe *utf)
|
||||
// the disk.
|
||||
//
|
||||
// LAB 5: you code here:
|
||||
addr = ROUNDDOWN(addr, PGSIZE);
|
||||
if((r = sys_page_alloc(0, addr, PTE_U | PTE_W | PTE_P)) < 0)
|
||||
panic("failed to allocate page for block cache");
|
||||
if((r = ide_read(secno, addr, BLKSIZE / SECTSIZE)) < 0)
|
||||
panic("failed to read from disk into block cache");
|
||||
|
||||
// Clear the dirty bit for the disk block page since we just read the
|
||||
// block from disk
|
||||
@ -72,12 +78,21 @@ void
|
||||
flush_block(void *addr)
|
||||
{
|
||||
uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE;
|
||||
uint32_t secno = blockno * (BLKSIZE / SECTSIZE);
|
||||
int r;
|
||||
|
||||
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");
|
||||
addr = ROUNDDOWN(addr, PGSIZE);
|
||||
if(!(va_is_mapped(addr) && va_is_dirty(addr))) return;
|
||||
|
||||
if((r = ide_write(secno, addr, BLKSIZE / SECTSIZE)) < 0)
|
||||
panic("failed to flush block into cache");
|
||||
|
||||
if((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0)
|
||||
panic("failed to remove dirty bit from page");
|
||||
}
|
||||
|
||||
// Test that the block cache works, by smashing the superblock and
|
||||
|
42
fs/fs.c
42
fs/fs.c
@ -60,9 +60,15 @@ 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.
|
||||
uint32_t* search = bitmap + 1;
|
||||
for(uint32_t block = 1; block < super->s_nblocks; block++) {
|
||||
if(bitmap[block / 32] & (1 << (block % 32))) {
|
||||
bitmap[block / 32] &= ~(1 << (block % 32));
|
||||
flush_block(&bitmap[block / 32]);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
// LAB 5: Your code here.
|
||||
panic("alloc_block not implemented");
|
||||
return -E_NO_DISK;
|
||||
}
|
||||
|
||||
@ -135,7 +141,23 @@ 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");
|
||||
int newblock;
|
||||
if(filebno < NDIRECT) {
|
||||
*ppdiskbno = &f->f_direct[filebno];
|
||||
return 0;
|
||||
} else if(filebno < NDIRECT + NINDIRECT) {
|
||||
filebno -= NDIRECT;
|
||||
if(!f->f_indirect) {
|
||||
if(!alloc) return -E_NOT_FOUND;
|
||||
if((newblock = alloc_block()) < 0) return newblock;
|
||||
f->f_indirect = newblock;
|
||||
}
|
||||
|
||||
uint32_t* indirect = diskaddr(f->f_indirect);
|
||||
*ppdiskbno = &indirect[filebno];
|
||||
return 0;
|
||||
}
|
||||
return -E_INVAL;
|
||||
}
|
||||
|
||||
// Set *blk to the address in memory where the filebno'th
|
||||
@ -150,7 +172,19 @@ int
|
||||
file_get_block(struct File *f, uint32_t filebno, char **blk)
|
||||
{
|
||||
// LAB 5: Your code here.
|
||||
panic("file_get_block not implemented");
|
||||
uint32_t* blockno;
|
||||
int r;
|
||||
|
||||
if ((r = file_block_walk(f, filebno, &blockno, 1)) < 0)
|
||||
return r;
|
||||
|
||||
if(*blockno == 0) {
|
||||
if((r = alloc_block()) < 0) return r;
|
||||
*blockno = r;
|
||||
}
|
||||
|
||||
*blk = diskaddr(*blockno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Try to find a file named "name" in dir. If so, set *file to it.
|
||||
|
24
fs/serv.c
24
fs/serv.c
@ -209,12 +209,20 @@ serve_read(envid_t envid, union Fsipc *ipc)
|
||||
{
|
||||
struct Fsreq_read *req = &ipc->read;
|
||||
struct Fsret_read *ret = &ipc->readRet;
|
||||
struct OpenFile* open_file;
|
||||
int r;
|
||||
|
||||
if (debug)
|
||||
cprintf("serve_read %08x %08x %08x\n", envid, req->req_fileid, req->req_n);
|
||||
|
||||
// Lab 5: Your code here:
|
||||
return 0;
|
||||
if((r = openfile_lookup(envid, req->req_fileid, &open_file)) < 0)
|
||||
return r;
|
||||
|
||||
if((r = file_read(open_file->o_file, ret->ret_buf, req->req_n, open_file->o_fd->fd_offset)) < 0)
|
||||
return r;
|
||||
|
||||
open_file->o_fd->fd_offset += r;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@ -227,9 +235,17 @@ 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);
|
||||
|
||||
struct OpenFile* open_file;
|
||||
int r;
|
||||
|
||||
// LAB 5: Your code here.
|
||||
panic("serve_write not implemented");
|
||||
if((r = openfile_lookup(envid, req->req_fileid, &open_file)) < 0)
|
||||
return r;
|
||||
if((r = file_write(open_file->o_file, req->req_buf, req->req_n, open_file->o_fd->fd_offset)) < 0)
|
||||
return r;
|
||||
|
||||
open_file->o_fd->fd_offset += r;
|
||||
return r;
|
||||
}
|
||||
|
||||
// Stat ipc->stat.req_fileid. Return the file's struct Stat to the
|
||||
|
@ -289,7 +289,7 @@ region_alloc(struct Env *e, void *va, size_t len)
|
||||
// You should round va down, and round (va + len) up.
|
||||
// (Watch out for corner-cases!)
|
||||
va = ROUNDDOWN(va, PGSIZE);
|
||||
size_t count = ROUNDUP(len, PGSIZE) / PGSIZE;
|
||||
size_t count = ROUNDUP(len, PGSIZE) / PGSIZE + 1;
|
||||
struct PageInfo* p;
|
||||
|
||||
while(count--) {
|
||||
@ -393,6 +393,10 @@ env_create(uint8_t *binary, enum EnvType type)
|
||||
if(env_alloc(&new_env, 0) < 0)
|
||||
panic("Failed to allocate environment");
|
||||
new_env->env_type = type;
|
||||
|
||||
if(type == ENV_TYPE_FS)
|
||||
new_env->env_tf.tf_eflags |= FL_IOPL_3;
|
||||
|
||||
load_icode(new_env, binary);
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,11 @@ sys_env_set_status(envid_t envid, int status)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SYS_CHECKPERMS(perm) \
|
||||
((((perm) & (PTE_P | PTE_U)) == (PTE_P | PTE_U)) && \
|
||||
(((perm) & ~(PTE_P | PTE_U | PTE_W | PTE_AVAIL)) == 0))
|
||||
#define SYS_CHECKADDR(addr) (((uintptr_t) (addr) < UTOP) && ((uintptr_t) (addr) % PGSIZE == 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.
|
||||
@ -129,7 +134,19 @@ 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");
|
||||
int r;
|
||||
struct Env* chenv;
|
||||
SYS_CHECKADDR(tf);
|
||||
|
||||
if((r = envid2env(envid, &chenv, true)) < 0)
|
||||
return r;
|
||||
|
||||
tf->tf_cs |= 3;
|
||||
tf->tf_eflags &= ~(FL_IOPL_3);
|
||||
tf->tf_eflags |= FL_IF;
|
||||
|
||||
chenv->env_tf = *tf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set the page fault upcall for 'envid' by modifying the corresponding struct
|
||||
@ -150,11 +167,6 @@ sys_env_set_pgfault_upcall(envid_t envid, void *func)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SYS_CHECKPERMS(perm) \
|
||||
((((perm) & (PTE_P | PTE_U)) == (PTE_P | PTE_U)) && \
|
||||
(((perm) & ~(PTE_P | PTE_U | PTE_W | PTE_AVAIL)) == 0))
|
||||
#define SYS_CHECKADDR(addr) (((uintptr_t) (addr) < UTOP) && ((uintptr_t) (addr) % PGSIZE == 0))
|
||||
|
||||
// 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.
|
||||
@ -408,6 +420,8 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
|
||||
return sys_ipc_try_send(a1, a2, (void*) a3, a4);
|
||||
case SYS_ipc_recv:
|
||||
return sys_ipc_recv((void*) a1);
|
||||
case SYS_env_set_trapframe:
|
||||
return sys_env_set_trapframe(a1, (void*) a2);
|
||||
default:
|
||||
return -E_INVAL;
|
||||
}
|
||||
|
@ -260,6 +260,12 @@ trap_dispatch(struct Trapframe *tf)
|
||||
} else if (tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) {
|
||||
lapic_eoi();
|
||||
sched_yield();
|
||||
} else if (tf->tf_trapno == IRQ_OFFSET + IRQ_KBD) {
|
||||
kbd_intr();
|
||||
return;
|
||||
} else if (tf->tf_trapno == IRQ_OFFSET + IRQ_SERIAL) {
|
||||
serial_intr();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle spurious interrupts
|
||||
@ -360,6 +366,8 @@ page_fault_handler(struct Trapframe *tf)
|
||||
// Handle kernel-mode page faults.
|
||||
|
||||
// LAB 3: Your code here.
|
||||
if(!curenv)
|
||||
panic("kernel-level page fault, va %p, eip %p", fault_va, tf->tf_eip);
|
||||
|
||||
// We've already handled kernel-mode exceptions, so if we get here,
|
||||
// the page fault happened in user mode.
|
||||
|
@ -141,7 +141,13 @@ devfile_write(struct Fd *fd, const void *buf, size_t n)
|
||||
// remember that write is always allowed to write *fewer*
|
||||
// bytes than requested.
|
||||
// LAB 5: Your code here
|
||||
panic("devfile_write not implemented");
|
||||
size_t writesize = MIN(sizeof(fsipcbuf.write.req_buf), n);
|
||||
|
||||
fsipcbuf.write.req_fileid = fd->fd_file.id;
|
||||
fsipcbuf.write.req_n = writesize;
|
||||
memcpy(fsipcbuf.write.req_buf, buf, writesize);
|
||||
|
||||
return fsipc(FSREQ_WRITE, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -62,7 +62,7 @@ duppage(envid_t envid, unsigned pn)
|
||||
void* addr = (void*) (pn * PGSIZE);
|
||||
|
||||
// If we're writable, remove write permission
|
||||
if((new_pte & PTE_W) || (new_pte & PTE_COW)) {
|
||||
if(((new_pte & PTE_W) && !(new_pte & PTE_SHARE)) || (new_pte & PTE_COW)) {
|
||||
perms = (perms & ~PTE_W) | PTE_COW;
|
||||
change_own = true;
|
||||
}
|
||||
|
15
lib/spawn.c
15
lib/spawn.c
@ -302,6 +302,21 @@ static int
|
||||
copy_shared_pages(envid_t child)
|
||||
{
|
||||
// LAB 5: Your code here.
|
||||
int r;
|
||||
for(int pde_i = 0; pde_i < PDX(UTOP); pde_i++) {
|
||||
pde_t pde = uvpd[pde_i];
|
||||
if(!(pde & PTE_P)) continue;
|
||||
|
||||
for(int pte_i = 0; pte_i < NPTENTRIES; pte_i++) {
|
||||
int pn = pde_i * NPTENTRIES + pte_i;
|
||||
pte_t pte = uvpt[pn];
|
||||
|
||||
if((pte & (PTE_P | PTE_SHARE)) != (PTE_P | PTE_SHARE)) continue;
|
||||
void* addr = (void*) (pn * PGSIZE);
|
||||
if((r = sys_page_map(0, addr, child, addr, pte & PTE_SYSCALL)) < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
11
user/sh.c
11
user/sh.c
@ -53,9 +53,16 @@ again:
|
||||
// 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");
|
||||
if ((fd = open(t, O_RDONLY)) < 0) {
|
||||
cprintf("open %s for read: %e", t, fd);
|
||||
}
|
||||
|
||||
if(fd != 0) {
|
||||
dup(fd, 0);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '>': // Output redirection
|
||||
|
Loading…
Reference in New Issue
Block a user