Intermediate commit of lab 3 changes
This commit is contained in:
commit
73dad8b484
|
@ -17,6 +17,7 @@ KERN_SRCFILES := kern/entry.S \
|
||||||
kern/entrypgdir.c \
|
kern/entrypgdir.c \
|
||||||
kern/init.c \
|
kern/init.c \
|
||||||
kern/console.c \
|
kern/console.c \
|
||||||
|
kern/ansi.c \
|
||||||
kern/monitor.c \
|
kern/monitor.c \
|
||||||
kern/pmap.c \
|
kern/pmap.c \
|
||||||
kern/env.c \
|
kern/env.c \
|
||||||
|
|
49
kern/ansi.c
Normal file
49
kern/ansi.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include <kern/ansi.h>
|
||||||
|
|
||||||
|
uint8_t vga_colors[8] = {
|
||||||
|
[0] = 0,
|
||||||
|
[1] = 4,
|
||||||
|
[2] = 2,
|
||||||
|
[3] = 6,
|
||||||
|
[4] = 1,
|
||||||
|
[5] = 5,
|
||||||
|
[6] = 3,
|
||||||
|
[7] = 7
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
ansi_step(void (*putcf)(int), int c, struct AttrState* s) {
|
||||||
|
switch(s->state) {
|
||||||
|
case NORMAL:
|
||||||
|
if(c != 27) putcf(c | (s->cattrs << 8));
|
||||||
|
else s->state = ESC;
|
||||||
|
return;
|
||||||
|
case ESC:
|
||||||
|
s->state = (c == '[') ? BRACKET : NORMAL;
|
||||||
|
return;
|
||||||
|
case BRACKET:
|
||||||
|
if(c == '3') {
|
||||||
|
s->state = COLOR_FG;
|
||||||
|
} else if(c == '0') {
|
||||||
|
s->state = COLOR;
|
||||||
|
s->attrs = 0;
|
||||||
|
} else {
|
||||||
|
s->state = NORMAL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case COLOR_FG:
|
||||||
|
if(c >= '0' && c <= '9') {
|
||||||
|
s->attrs = (s->attrs & ~(0x07)) | vga_colors[c - '0'];
|
||||||
|
c |= ((c - '0') << 8);
|
||||||
|
s->state = COLOR;
|
||||||
|
} else {
|
||||||
|
s->state = NORMAL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case COLOR:
|
||||||
|
s->state = (c == ';') ? BRACKET : NORMAL;
|
||||||
|
if(c == 'm') s->cattrs = s->attrs;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
36
kern/ansi.h
Normal file
36
kern/ansi.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef _ANSI_H_
|
||||||
|
#define _ANSI_H_
|
||||||
|
|
||||||
|
#include <inc/types.h>
|
||||||
|
|
||||||
|
#define ACOL_WRAP(s) "\33[" s "m"
|
||||||
|
#define ACOL_BLACK ACOL_WRAP("30")
|
||||||
|
#define ACOL_RED ACOL_WRAP("31")
|
||||||
|
#define ACOL_GREEN ACOL_WRAP("32")
|
||||||
|
#define ACOL_YELLOW ACOL_WRAP("33")
|
||||||
|
#define ACOL_BLUE ACOL_WRAP("34")
|
||||||
|
#define ACOL_MAGENTA ACOL_WRAP("35")
|
||||||
|
#define ACOL_CYAN ACOL_WRAP("36")
|
||||||
|
#define ACOL_WHITE ACOL_WRAP("37")
|
||||||
|
#define ACOL_CLEAR ACOL_WRAP("0")
|
||||||
|
|
||||||
|
#define ACOL_TAG(c, s) "[" c s ACOL_CLEAR "] "
|
||||||
|
#define ACOL_NOTE(s) ACOL_TAG(ACOL_WHITE, " Note ") s
|
||||||
|
#define ACOL_WARN(s) ACOL_TAG(ACOL_YELLOW, "Warning") s
|
||||||
|
#define ACOL_ERR(s) ACOL_TAG(ACOL_RED, " Error ") s
|
||||||
|
|
||||||
|
struct AttrState {
|
||||||
|
uint8_t cattrs;
|
||||||
|
uint8_t attrs;
|
||||||
|
enum {
|
||||||
|
NORMAL,
|
||||||
|
ESC,
|
||||||
|
BRACKET,
|
||||||
|
COLOR_FG,
|
||||||
|
COLOR
|
||||||
|
} state;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ansi_step(void (*putcf)(int), int c, struct AttrState* s);
|
||||||
|
|
||||||
|
#endif
|
|
@ -7,6 +7,7 @@
|
||||||
#include <inc/assert.h>
|
#include <inc/assert.h>
|
||||||
|
|
||||||
#include <kern/console.h>
|
#include <kern/console.h>
|
||||||
|
#include <kern/ansi.h>
|
||||||
|
|
||||||
static void cons_intr(int (*proc)(void));
|
static void cons_intr(int (*proc)(void));
|
||||||
static void cons_putc(int c);
|
static void cons_putc(int c);
|
||||||
|
@ -128,6 +129,7 @@ lpt_putc(int c)
|
||||||
static unsigned addr_6845;
|
static unsigned addr_6845;
|
||||||
static uint16_t *crt_buf;
|
static uint16_t *crt_buf;
|
||||||
static uint16_t crt_pos;
|
static uint16_t crt_pos;
|
||||||
|
static struct AttrState attst;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cga_init(void)
|
cga_init(void)
|
||||||
|
@ -136,6 +138,10 @@ cga_init(void)
|
||||||
uint16_t was;
|
uint16_t was;
|
||||||
unsigned pos;
|
unsigned pos;
|
||||||
|
|
||||||
|
attst.cattrs = 0;
|
||||||
|
attst.attrs = 0;
|
||||||
|
attst.state = NORMAL;
|
||||||
|
|
||||||
cp = (uint16_t*) (KERNBASE + CGA_BUF);
|
cp = (uint16_t*) (KERNBASE + CGA_BUF);
|
||||||
was = *cp;
|
was = *cp;
|
||||||
*cp = (uint16_t) 0xA55A;
|
*cp = (uint16_t) 0xA55A;
|
||||||
|
@ -157,10 +163,15 @@ cga_init(void)
|
||||||
crt_pos = pos;
|
crt_pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cga_putc_internal(int c);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cga_putc(int c)
|
cga_putc(int c){
|
||||||
|
ansi_step(cga_putc_internal, c, &attst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cga_putc_internal(int c)
|
||||||
{
|
{
|
||||||
// if no attribute given, then use black on white
|
// if no attribute given, then use black on white
|
||||||
if (!(c & ~0xFF))
|
if (!(c & ~0xFF))
|
||||||
|
|
38
kern/env.c
38
kern/env.c
|
@ -116,6 +116,13 @@ env_init(void)
|
||||||
{
|
{
|
||||||
// Set up envs array
|
// Set up envs array
|
||||||
// LAB 3: Your code here.
|
// LAB 3: Your code here.
|
||||||
|
size_t i = NENV;
|
||||||
|
while(true) {
|
||||||
|
i--;
|
||||||
|
envs[i].env_link = env_free_list;
|
||||||
|
env_free_list = &envs[i];
|
||||||
|
if(i == 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
// Per-CPU part of the initialization
|
// Per-CPU part of the initialization
|
||||||
env_init_percpu();
|
env_init_percpu();
|
||||||
|
@ -177,8 +184,9 @@ env_setup_vm(struct Env *e)
|
||||||
// is an exception -- you need to increment env_pgdir's
|
// is an exception -- you need to increment env_pgdir's
|
||||||
// pp_ref for env_free to work correctly.
|
// pp_ref for env_free to work correctly.
|
||||||
// - The functions in kern/pmap.h are handy.
|
// - The functions in kern/pmap.h are handy.
|
||||||
|
p->pp_ref++;
|
||||||
// LAB 3: Your code here.
|
e->env_pgdir = page2kva(p);
|
||||||
|
memcpy(p + PDX(UTOP), kern_pgdir + PDX(UTOP), NPDENTRIES - PDX(UTOP));
|
||||||
|
|
||||||
// UVPT maps the env's own page table read-only.
|
// UVPT maps the env's own page table read-only.
|
||||||
// Permissions: kernel R, user R
|
// Permissions: kernel R, user R
|
||||||
|
@ -267,6 +275,17 @@ region_alloc(struct Env *e, void *va, size_t len)
|
||||||
// 'va' and 'len' values that are not page-aligned.
|
// 'va' and 'len' values that are not page-aligned.
|
||||||
// You should round va down, and round (va + len) up.
|
// You should round va down, and round (va + len) up.
|
||||||
// (Watch out for corner-cases!)
|
// (Watch out for corner-cases!)
|
||||||
|
va = ROUNDDOWN(va, PGSIZE);
|
||||||
|
len = ROUNDUP(len, PGSIZE);
|
||||||
|
void* last_va = va + len;
|
||||||
|
struct PageInfo* p;
|
||||||
|
|
||||||
|
while(va < last_va) {
|
||||||
|
if(!(p = page_alloc(0)))
|
||||||
|
panic("Failed to allocate memory");
|
||||||
|
if(page_insert(e->env_pgdir, p, va, PTE_U | PTE_W))
|
||||||
|
panic("Failed to allocate memory for page table");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -324,8 +343,23 @@ load_icode(struct Env *e, uint8_t *binary)
|
||||||
|
|
||||||
// LAB 3: Your code here.
|
// LAB 3: Your code here.
|
||||||
|
|
||||||
|
// TODO validate the headers
|
||||||
|
struct Elf* elf = (struct Elf*) binary;
|
||||||
|
struct Proghdr* ph = (struct Proghdr*) (binary + elf->e_phoff);
|
||||||
|
struct Proghdr* phend = ph + elf->e_phnum;
|
||||||
|
for(; ph < phend; ph++) {
|
||||||
|
if(ph->p_type != ELF_PROG_LOAD) continue;
|
||||||
|
|
||||||
|
region_alloc(e, (void*) ph->p_va, ph->p_memsz);
|
||||||
|
lcr3(PADDR(e->env_pgdir));
|
||||||
|
memcpy((void*) ph->p_va, binary + ph->p_offset, ph->p_filesz);
|
||||||
|
memset((void*) ph->p_va + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz);
|
||||||
|
lcr3(PADDR(kern_pgdir));
|
||||||
|
}
|
||||||
|
|
||||||
// Now map one page for the program's initial stack
|
// Now map one page for the program's initial stack
|
||||||
// at virtual address USTACKTOP - PGSIZE.
|
// at virtual address USTACKTOP - PGSIZE.
|
||||||
|
region_alloc(e, USTACKTOP - PGSIZE, PGSIZE);
|
||||||
|
|
||||||
// LAB 3: Your code here.
|
// LAB 3: Your code here.
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,12 @@ i386_init(void)
|
||||||
cons_init();
|
cons_init();
|
||||||
|
|
||||||
cprintf("444544 decimal is %o octal!\n", 444544);
|
cprintf("444544 decimal is %o octal!\n", 444544);
|
||||||
|
cprintf("\33[31m" "C"
|
||||||
|
"\33[33m" "o"
|
||||||
|
"\33[32m" "l"
|
||||||
|
"\33[36m" "o"
|
||||||
|
"\33[34m" "r"
|
||||||
|
"\33[0m" " Works!" "\n");
|
||||||
|
|
||||||
// Lab 2 memory management initialization functions
|
// Lab 2 memory management initialization functions
|
||||||
mem_init();
|
mem_init();
|
||||||
|
|
|
@ -196,7 +196,8 @@ debuginfo_eip(uintptr_t addr, struct Eipdebuginfo *info)
|
||||||
|
|
||||||
|
|
||||||
// Search within [lline, rline] for the line number stab.
|
// Search within [lline, rline] for the line number stab.
|
||||||
// If found, set info->eip_line to the right line number.
|
// If found, set info->eip_line to the correct line number.
|
||||||
|
// e.g., info->eip_line = stabs[lline].n_desc
|
||||||
// If not found, return -1.
|
// If not found, return -1.
|
||||||
//
|
//
|
||||||
// Hint:
|
// Hint:
|
||||||
|
@ -204,6 +205,12 @@ debuginfo_eip(uintptr_t addr, struct Eipdebuginfo *info)
|
||||||
// Look at the STABS documentation and <inc/stab.h> to find
|
// Look at the STABS documentation and <inc/stab.h> to find
|
||||||
// which one.
|
// which one.
|
||||||
// Your code here.
|
// Your code here.
|
||||||
|
stab_binsearch(stabs, &lline, &rline, N_SLINE, addr);
|
||||||
|
if(lline <= rline) {
|
||||||
|
info->eip_line = stabs[lline].n_desc;
|
||||||
|
} else {
|
||||||
|
info->eip_line = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Search backwards from the line number for the relevant filename
|
// Search backwards from the line number for the relevant filename
|
||||||
|
|
123
kern/monitor.c
123
kern/monitor.c
|
@ -7,10 +7,13 @@
|
||||||
#include <inc/assert.h>
|
#include <inc/assert.h>
|
||||||
#include <inc/x86.h>
|
#include <inc/x86.h>
|
||||||
|
|
||||||
|
#include <kern/ansi.h>
|
||||||
#include <kern/console.h>
|
#include <kern/console.h>
|
||||||
#include <kern/monitor.h>
|
#include <kern/monitor.h>
|
||||||
#include <kern/kdebug.h>
|
#include <kern/kdebug.h>
|
||||||
#include <kern/trap.h>
|
#include <kern/trap.h>
|
||||||
|
#include <kern/pmap.h>
|
||||||
|
#include <inc/string.h>
|
||||||
|
|
||||||
#define CMDBUF_SIZE 80 // enough for one VGA text line
|
#define CMDBUF_SIZE 80 // enough for one VGA text line
|
||||||
|
|
||||||
|
@ -26,6 +29,10 @@ struct Command {
|
||||||
static struct Command commands[] = {
|
static struct Command commands[] = {
|
||||||
{ "help", "Display this list of commands", mon_help },
|
{ "help", "Display this list of commands", mon_help },
|
||||||
{ "kerninfo", "Display information about the kernel", mon_kerninfo },
|
{ "kerninfo", "Display information about the kernel", mon_kerninfo },
|
||||||
|
{ "backtrace", "Display current backtrace", mon_backtrace },
|
||||||
|
{ "showmappings", "Display the physical mappings for range", mon_showmappings },
|
||||||
|
{ "mperms", "Change the permissions of a memory range", mon_mperms }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/***** Implementations of basic kernel monitor commands *****/
|
/***** Implementations of basic kernel monitor commands *****/
|
||||||
|
@ -46,7 +53,7 @@ mon_kerninfo(int argc, char **argv, struct Trapframe *tf)
|
||||||
extern char _start[], entry[], etext[], edata[], end[];
|
extern char _start[], entry[], etext[], edata[], end[];
|
||||||
|
|
||||||
cprintf("Special kernel symbols:\n");
|
cprintf("Special kernel symbols:\n");
|
||||||
cprintf(" _start %08x (phys)\n", _start);
|
cprintf(" _start %08x (phys)\n", _start);
|
||||||
cprintf(" entry %08x (virt) %08x (phys)\n", entry, entry - KERNBASE);
|
cprintf(" entry %08x (virt) %08x (phys)\n", entry, entry - KERNBASE);
|
||||||
cprintf(" etext %08x (virt) %08x (phys)\n", etext, etext - KERNBASE);
|
cprintf(" etext %08x (virt) %08x (phys)\n", etext, etext - KERNBASE);
|
||||||
cprintf(" edata %08x (virt) %08x (phys)\n", edata, edata - KERNBASE);
|
cprintf(" edata %08x (virt) %08x (phys)\n", edata, edata - KERNBASE);
|
||||||
|
@ -62,10 +69,124 @@ mon_backtrace(int argc, char **argv, struct Trapframe *tf)
|
||||||
// LAB 1: Your code here.
|
// LAB 1: Your code here.
|
||||||
// HINT 1: use read_ebp().
|
// HINT 1: use read_ebp().
|
||||||
// HINT 2: print the current ebp on the first line (not current_ebp[0])
|
// HINT 2: print the current ebp on the first line (not current_ebp[0])
|
||||||
|
uint32_t* ebp;
|
||||||
|
uint32_t eip;
|
||||||
|
struct Eipdebuginfo info;
|
||||||
|
|
||||||
|
ebp = (uint32_t*) read_ebp();
|
||||||
|
cprintf("Stack backtrace:\n");
|
||||||
|
while(ebp) {
|
||||||
|
eip = ebp[1];
|
||||||
|
cprintf(" ebp %08x eip %08x args %08x %08x %08x %08x %08x\n",
|
||||||
|
ebp, eip, ebp[2], ebp[3], ebp[4], ebp[5], ebp[6]);
|
||||||
|
ebp = (uint32_t*) ebp[0];
|
||||||
|
|
||||||
|
debuginfo_eip(eip, &info);
|
||||||
|
cprintf(" %s:%d: %.*s+%d\n",
|
||||||
|
info.eip_file, info.eip_line,
|
||||||
|
info.eip_fn_namelen, info.eip_fn_name,
|
||||||
|
eip - info.eip_fn_addr);
|
||||||
|
};
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define EXPECT_ARGS(n, ac) if(ac - 1 != n) { \
|
||||||
|
cprintf(ACOL_ERR("Expected %d arguments, " \
|
||||||
|
"got %d\n"), n, ac - 1); \
|
||||||
|
return 1; }
|
||||||
|
|
||||||
|
#define VA_TXT ACOL_CYAN "VA" ACOL_CLEAR
|
||||||
|
#define PA_TXT ACOL_GREEN "PA" ACOL_CLEAR
|
||||||
|
|
||||||
|
char*
|
||||||
|
decode_pte_perms(pte_t pte, char* buffer) {
|
||||||
|
buffer[0] = (pte & PTE_W) ? 'w' : 'r';
|
||||||
|
buffer[1] = (pte & PTE_U) ? 'u' : 'k';
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
get_pagebounds(char* one, char* two, uintptr_t* pone, uintptr_t* ptwo) {
|
||||||
|
long from = strtol(one, NULL, 0);
|
||||||
|
long to = strtol(two, NULL, 0);
|
||||||
|
*pone = ROUNDDOWN(from, PGSIZE);
|
||||||
|
*ptwo = ROUNDUP(to, PGSIZE);
|
||||||
|
if(*pone != from) cprintf(ACOL_WARN("Aligning start address %p down to %p\n"),
|
||||||
|
from, *pone);
|
||||||
|
if(*ptwo != to) cprintf(ACOL_WARN("Aligning end address %p up to %p\n"),
|
||||||
|
to, *ptwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mon_showmappings(int argc, char** argv, struct Trapframe* tf) {
|
||||||
|
EXPECT_ARGS(2, argc);
|
||||||
|
uintptr_t va_start, va_end;
|
||||||
|
char buffer[3] = {0};
|
||||||
|
|
||||||
|
get_pagebounds(argv[1], argv[2], &va_start, &va_end);
|
||||||
|
|
||||||
|
if(va_start == va_end) va_end += PGSIZE;
|
||||||
|
while(va_start < va_end) {
|
||||||
|
pte_t* pte = pgdir_walk(kern_pgdir, (const void*) va_start, 0);
|
||||||
|
cprintf(VA_TXT " 0x%08p -> ", va_start);
|
||||||
|
|
||||||
|
if(pte && (*pte & PTE_P)) {
|
||||||
|
cprintf(PA_TXT " 0x%08p (%s)\n", PTE_ADDR(*pte),
|
||||||
|
decode_pte_perms(*pte, buffer));
|
||||||
|
} else {
|
||||||
|
cprintf(PA_TXT " ------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start += PGSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mon_mperms(int argc, char** argv, struct Trapframe* tf) {
|
||||||
|
EXPECT_ARGS(3, argc);
|
||||||
|
pte_t perms = 0;
|
||||||
|
enum {
|
||||||
|
PERM_ADD,
|
||||||
|
PERM_REMOVE,
|
||||||
|
PERM_SET
|
||||||
|
} pmode;
|
||||||
|
|
||||||
|
const char* str = argv[1];
|
||||||
|
if(str[0] == '+') { pmode = PERM_ADD; str++; }
|
||||||
|
else if(str[0] == '-') { pmode = PERM_REMOVE; str++; }
|
||||||
|
else pmode = PERM_SET;
|
||||||
|
|
||||||
|
while(*str) {
|
||||||
|
if(*str == 'w') perms |= PTE_W;
|
||||||
|
else if(*str == 'u') perms |= PTE_U;
|
||||||
|
else {
|
||||||
|
cprintf(ACOL_ERR("Unknown permission character %c\n"), *str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t va_start, va_end;
|
||||||
|
get_pagebounds(argv[2], argv[3], &va_start, &va_end);
|
||||||
|
if(va_start == va_end) va_end += PGSIZE;
|
||||||
|
while(va_start < va_end) {
|
||||||
|
pte_t* pte = pgdir_walk(kern_pgdir, (void*) va_start, 0);
|
||||||
|
if(!pte || !(*pte & PTE_P)) { va_start += PGSIZE; continue; }
|
||||||
|
|
||||||
|
if(pmode == PERM_ADD) {
|
||||||
|
*pte |= perms;
|
||||||
|
} else if(pmode == PERM_REMOVE) {
|
||||||
|
*pte &= ~perms;
|
||||||
|
} else if(pmode == PERM_SET) {
|
||||||
|
*pte = PTE_ADDR(*pte) | perms | PTE_P;
|
||||||
|
}
|
||||||
|
va_start += PGSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/***** Kernel monitor command interpreter *****/
|
/***** Kernel monitor command interpreter *****/
|
||||||
|
|
||||||
|
|
|
@ -15,5 +15,7 @@ void monitor(struct Trapframe *tf);
|
||||||
int mon_help(int argc, char **argv, struct Trapframe *tf);
|
int mon_help(int argc, char **argv, struct Trapframe *tf);
|
||||||
int mon_kerninfo(int argc, char **argv, struct Trapframe *tf);
|
int mon_kerninfo(int argc, char **argv, struct Trapframe *tf);
|
||||||
int mon_backtrace(int argc, char **argv, struct Trapframe *tf);
|
int mon_backtrace(int argc, char **argv, struct Trapframe *tf);
|
||||||
|
int mon_showmappings(int argc, char **argv, struct Trapframe *tf);
|
||||||
|
int mon_mperms(int argc, char** argv, struct Trapframe* tf);
|
||||||
|
|
||||||
#endif // !JOS_KERN_MONITOR_H
|
#endif // !JOS_KERN_MONITOR_H
|
||||||
|
|
133
kern/pmap.c
133
kern/pmap.c
|
@ -103,8 +103,10 @@ boot_alloc(uint32_t n)
|
||||||
// to a multiple of PGSIZE.
|
// to a multiple of PGSIZE.
|
||||||
//
|
//
|
||||||
// LAB 2: Your code here.
|
// LAB 2: Your code here.
|
||||||
|
result = nextfree;
|
||||||
|
nextfree = ROUNDUP(nextfree + n, PGSIZE);
|
||||||
|
|
||||||
return NULL;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up a two-level page table:
|
// Set up a two-level page table:
|
||||||
|
@ -125,9 +127,6 @@ mem_init(void)
|
||||||
// Find out how much memory the machine has (npages & npages_basemem).
|
// Find out how much memory the machine has (npages & npages_basemem).
|
||||||
i386_detect_memory();
|
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.
|
// create initial page directory.
|
||||||
kern_pgdir = (pde_t *) boot_alloc(PGSIZE);
|
kern_pgdir = (pde_t *) boot_alloc(PGSIZE);
|
||||||
|
@ -149,11 +148,16 @@ mem_init(void)
|
||||||
// array. 'npages' is the number of physical pages in memory. Use memset
|
// array. 'npages' is the number of physical pages in memory. Use memset
|
||||||
// to initialize all fields of each struct PageInfo to 0.
|
// to initialize all fields of each struct PageInfo to 0.
|
||||||
// Your code goes here:
|
// Your code goes here:
|
||||||
|
size_t pages_size = sizeof(struct PageInfo) * npages;
|
||||||
|
pages = boot_alloc(pages_size);
|
||||||
|
memset(pages, 0, pages_size);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Make 'envs' point to an array of size 'NENV' of 'struct Env'.
|
// Make 'envs' point to an array of size 'NENV' of 'struct Env'.
|
||||||
// LAB 3: Your code here.
|
// LAB 3: Your code here.
|
||||||
|
size_t envs_size = sizeof(struct Env) * NENV;
|
||||||
|
envs = boot_alloc(envs_size);
|
||||||
|
memset(envs, 0, envs_size);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Now that we've allocated the initial kernel data structures, we set
|
// Now that we've allocated the initial kernel data structures, we set
|
||||||
|
@ -177,6 +181,11 @@ mem_init(void)
|
||||||
// (ie. perm = PTE_U | PTE_P)
|
// (ie. perm = PTE_U | PTE_P)
|
||||||
// - pages itself -- kernel RW, user NONE
|
// - pages itself -- kernel RW, user NONE
|
||||||
// Your code goes here:
|
// Your code goes here:
|
||||||
|
boot_map_region(kern_pgdir,
|
||||||
|
UPAGES, ROUNDUP(pages_size, PGSIZE),
|
||||||
|
PADDR(pages), PTE_W);
|
||||||
|
kern_pgdir[PDX(UPAGES)] |= PTE_U | PTE_P;
|
||||||
|
kern_pgdir[PDX(UPAGES)] &= ~PTE_W;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Map the 'envs' array read-only by the user at linear address UENVS
|
// Map the 'envs' array read-only by the user at linear address UENVS
|
||||||
|
@ -185,6 +194,11 @@ mem_init(void)
|
||||||
// - the new image at UENVS -- kernel R, user R
|
// - the new image at UENVS -- kernel R, user R
|
||||||
// - envs itself -- kernel RW, user NONE
|
// - envs itself -- kernel RW, user NONE
|
||||||
// LAB 3: Your code here.
|
// LAB 3: Your code here.
|
||||||
|
boot_map_region(kern_pgdir,
|
||||||
|
UENVS, ROUNDUP(envs_size, PGSIZE),
|
||||||
|
PADDR(envs), PTE_W);
|
||||||
|
kern_pgdir[PDX(UENVS)] |= PTE_U;
|
||||||
|
kern_pgdir[PDX(UPAGES)] &= ~PTE_W;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Use the physical memory that 'bootstack' refers to as the kernel
|
// Use the physical memory that 'bootstack' refers to as the kernel
|
||||||
|
@ -197,6 +211,11 @@ mem_init(void)
|
||||||
// overwrite memory. Known as a "guard page".
|
// overwrite memory. Known as a "guard page".
|
||||||
// Permissions: kernel RW, user NONE
|
// Permissions: kernel RW, user NONE
|
||||||
// Your code goes here:
|
// Your code goes here:
|
||||||
|
boot_map_region(kern_pgdir,
|
||||||
|
KSTACKTOP-KSTKSIZE, KSTKSIZE,
|
||||||
|
PADDR(bootstack), PTE_W);
|
||||||
|
kern_pgdir[PDX(KSTACKTOP-KSTKSIZE)] |= PTE_W;
|
||||||
|
kern_pgdir[PDX(KSTACKTOP-KSTKSIZE)] &= ~PTE_U;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Map all of physical memory at KERNBASE.
|
// Map all of physical memory at KERNBASE.
|
||||||
|
@ -206,6 +225,12 @@ mem_init(void)
|
||||||
// we just set up the mapping anyway.
|
// we just set up the mapping anyway.
|
||||||
// Permissions: kernel RW, user NONE
|
// Permissions: kernel RW, user NONE
|
||||||
// Your code goes here:
|
// Your code goes here:
|
||||||
|
boot_map_region(kern_pgdir,
|
||||||
|
KERNBASE, 0x100000000 - KERNBASE,
|
||||||
|
0, PTE_W);
|
||||||
|
kern_pgdir[PDX(KERNBASE)] |= PTE_W | PTE_P;
|
||||||
|
kern_pgdir[PDX(KERNBASE)] &= ~PTE_U;
|
||||||
|
|
||||||
|
|
||||||
// Check that the initial page directory has been set up correctly.
|
// Check that the initial page directory has been set up correctly.
|
||||||
check_kern_pgdir();
|
check_kern_pgdir();
|
||||||
|
@ -237,6 +262,14 @@ mem_init(void)
|
||||||
// The 'pages' array has one 'struct PageInfo' entry per physical page.
|
// The 'pages' array has one 'struct PageInfo' entry per physical page.
|
||||||
// Pages are reference counted, and free pages are kept on a linked list.
|
// Pages are reference counted, and free pages are kept on a linked list.
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
is_reserved(size_t pagenum) {
|
||||||
|
if(pagenum == 0) return true;
|
||||||
|
if(pagenum >= PGNUM(IOPHYSMEM) &&
|
||||||
|
pagenum < PGNUM(PADDR(boot_alloc(0)))) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize page structure and memory free list.
|
// Initialize page structure and memory free list.
|
||||||
|
@ -266,9 +299,13 @@ page_init(void)
|
||||||
// free pages!
|
// free pages!
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < npages; i++) {
|
for (i = 0; i < npages; i++) {
|
||||||
pages[i].pp_ref = 0;
|
if(is_reserved(i)) {
|
||||||
pages[i].pp_link = page_free_list;
|
pages[i].pp_ref = 1;
|
||||||
page_free_list = &pages[i];
|
} else {
|
||||||
|
pages[i].pp_ref = 0;
|
||||||
|
pages[i].pp_link = page_free_list;
|
||||||
|
page_free_list = &pages[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,8 +324,17 @@ page_init(void)
|
||||||
struct PageInfo *
|
struct PageInfo *
|
||||||
page_alloc(int alloc_flags)
|
page_alloc(int alloc_flags)
|
||||||
{
|
{
|
||||||
// Fill this function in
|
struct PageInfo* to_return = page_free_list;
|
||||||
return 0;
|
if(to_return == 0) return NULL;
|
||||||
|
|
||||||
|
page_free_list = to_return->pp_link;
|
||||||
|
to_return->pp_link = NULL;
|
||||||
|
|
||||||
|
if(alloc_flags & ALLOC_ZERO) {
|
||||||
|
memset(page2kva(to_return), 0, PGSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return to_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -298,9 +344,10 @@ page_alloc(int alloc_flags)
|
||||||
void
|
void
|
||||||
page_free(struct PageInfo *pp)
|
page_free(struct PageInfo *pp)
|
||||||
{
|
{
|
||||||
// Fill this function in
|
if(pp->pp_ref || pp->pp_link != NULL)
|
||||||
// Hint: You may want to panic if pp->pp_ref is nonzero or
|
panic("Freeing page with nonzero reference count!");
|
||||||
// pp->pp_link is not NULL.
|
pp->pp_link = page_free_list;
|
||||||
|
page_free_list = pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -339,8 +386,25 @@ page_decref(struct PageInfo* pp)
|
||||||
pte_t *
|
pte_t *
|
||||||
pgdir_walk(pde_t *pgdir, const void *va, int create)
|
pgdir_walk(pde_t *pgdir, const void *va, int create)
|
||||||
{
|
{
|
||||||
|
pte_t* base_table = NULL;
|
||||||
|
|
||||||
|
if(pgdir[PDX(va)] & PTE_P) {
|
||||||
|
// We have a valid page table; awesome!
|
||||||
|
base_table = KADDR(PTE_ADDR(pgdir[PDX(va)]));
|
||||||
|
} else {
|
||||||
|
if(!create) return NULL;
|
||||||
|
|
||||||
|
struct PageInfo* page = page_alloc(ALLOC_ZERO);
|
||||||
|
if(!page) return NULL;
|
||||||
|
|
||||||
|
page->pp_ref++;
|
||||||
|
physaddr_t ppa = page2pa(page);
|
||||||
|
pgdir[PDX(va)] = ppa | PTE_P | PTE_U | PTE_W;
|
||||||
|
base_table = KADDR(ppa);
|
||||||
|
}
|
||||||
|
|
||||||
// Fill this function in
|
// Fill this function in
|
||||||
return NULL;
|
return &base_table[PTX(va)];
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -357,7 +421,16 @@ pgdir_walk(pde_t *pgdir, const void *va, int create)
|
||||||
static void
|
static void
|
||||||
boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm)
|
boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm)
|
||||||
{
|
{
|
||||||
// Fill this function in
|
size_t count = size / PGSIZE;
|
||||||
|
uintptr_t start_va = va;
|
||||||
|
physaddr_t start_pa = pa;
|
||||||
|
while(count-- && start_va <= va && start_pa <= pa) {
|
||||||
|
pte_t* pte = pgdir_walk(pgdir, (void*) va, true);
|
||||||
|
*pte = pa | perm | PTE_P;
|
||||||
|
|
||||||
|
va += PGSIZE;
|
||||||
|
pa += PGSIZE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -388,7 +461,14 @@ boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm
|
||||||
int
|
int
|
||||||
page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm)
|
page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm)
|
||||||
{
|
{
|
||||||
// Fill this function in
|
pte_t* pte;
|
||||||
|
if(!(pte = pgdir_walk(pgdir, va, true))) return -E_NO_MEM;
|
||||||
|
|
||||||
|
pp->pp_ref++;
|
||||||
|
if(*pte & PTE_P) page_remove(pgdir, va);
|
||||||
|
*pte = page2pa(pp) | PTE_P | perm;
|
||||||
|
tlb_invalidate(pgdir, va);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,8 +486,15 @@ page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm)
|
||||||
struct PageInfo *
|
struct PageInfo *
|
||||||
page_lookup(pde_t *pgdir, void *va, pte_t **pte_store)
|
page_lookup(pde_t *pgdir, void *va, pte_t **pte_store)
|
||||||
{
|
{
|
||||||
// Fill this function in
|
pte_t* pte;
|
||||||
return NULL;
|
if(!(pte = pgdir_walk(pgdir, va, false))) {
|
||||||
|
if(pte_store) *pte_store = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PageInfo* pp = pa2page(PTE_ADDR(*pte));
|
||||||
|
if(pte_store) *pte_store = pte;
|
||||||
|
return pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -428,7 +515,15 @@ page_lookup(pde_t *pgdir, void *va, pte_t **pte_store)
|
||||||
void
|
void
|
||||||
page_remove(pde_t *pgdir, void *va)
|
page_remove(pde_t *pgdir, void *va)
|
||||||
{
|
{
|
||||||
// Fill this function in
|
pte_t* pte;
|
||||||
|
struct PageInfo* pp;
|
||||||
|
|
||||||
|
pp = page_lookup(pgdir, va, &pte);
|
||||||
|
if(!(*pte & PTE_P)) return;
|
||||||
|
|
||||||
|
if(!(--(pp->pp_ref))) page_free(pp);
|
||||||
|
*pte = 0;
|
||||||
|
tlb_invalidate(pgdir, va);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -205,11 +205,9 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap)
|
||||||
|
|
||||||
// (unsigned) octal
|
// (unsigned) octal
|
||||||
case 'o':
|
case 'o':
|
||||||
// LAB 1: Replace this with your code.
|
num = getuint(&ap, lflag);
|
||||||
putch('X', putdat);
|
base = 8;
|
||||||
putch('X', putdat);
|
goto number;
|
||||||
putch('X', putdat);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// pointer
|
// pointer
|
||||||
case 'p':
|
case 'p':
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
OSU ID (xxx-yyy-zzz) : 933456789
|
OSU ID (xxx-yyy-zzz) : 932700867
|
||||||
FLIP ID (e.g., jangye) : jangye
|
FLIP ID (e.g., jangye) : fedorind
|
||||||
Name : Yeongjin Jang
|
Name : Danila Fedorin
|
||||||
CS 444/544 ? : 444
|
CS 444/544 ? : 444
|
||||||
Lab Class # : Lab 1
|
Lab Class # : Lab 2
|
||||||
|
|
Loading…
Reference in New Issue
Block a user