Merge branch 'lab3' into lab4

This commit is contained in:
Danila Fedorin 2019-04-25 20:01:26 -07:00
commit 4e4de7b836
19 changed files with 636 additions and 48 deletions

View File

@ -3,6 +3,10 @@
#include <inc/types.h> #include <inc/types.h>
#define MSR_IA32_SYSENTER_CS 0x174
#define MSR_IA32_SYSENTER_EIP 0x176
#define MSR_IA32_SYSENTER_ESP 0x175
static inline void static inline void
breakpoint(void) breakpoint(void)
{ {
@ -261,4 +265,19 @@ xchg(volatile uint32_t *addr, uint32_t newval)
return result; return result;
} }
static inline void
write_msr(uint32_t reg, uint32_t low, uint32_t high) {
asm volatile("wrmsr\n\t"
:: "c" (reg), "a" (low), "d" (high));
}
static inline void
read_msr(uint32_t reg, uint32_t* low, uint32_t* high) {
uint32_t eax, edx;
asm volatile("rdmsr\n\t"
: "=a" (eax), "=d" (edx) : "c" (reg));
*low = eax;
*high = edx;
}
#endif /* !JOS_INC_X86_H */ #endif /* !JOS_INC_X86_H */

View File

@ -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 \
@ -55,7 +56,8 @@ KERN_BINFILES := user/hello \
user/faultread \ user/faultread \
user/faultreadkernel \ user/faultreadkernel \
user/faultwrite \ user/faultwrite \
user/faultwritekernel user/faultwritekernel \
user/getc
# Binary files for LAB4 # Binary files for LAB4
KERN_BINFILES += user/idle \ KERN_BINFILES += user/idle \

49
kern/ansi.c Normal file
View 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
View 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

View File

@ -9,6 +9,7 @@
#include <kern/console.h> #include <kern/console.h>
#include <kern/trap.h> #include <kern/trap.h>
#include <kern/picirq.h> #include <kern/picirq.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);
@ -130,6 +131,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)
@ -138,6 +140,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;
@ -159,10 +165,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))

View File

@ -119,6 +119,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();
@ -180,8 +187,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(e->env_pgdir + PDX(UTOP), kern_pgdir + PDX(UTOP), sizeof(pde_t) * (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
@ -279,6 +287,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);
size_t count = ROUNDUP(len, PGSIZE) / PGSIZE;
struct PageInfo* p;
while(count--) {
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");
va += PGSIZE;
}
} }
// //
@ -336,10 +355,24 @@ 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));
}
e->env_tf.tf_eip = elf->e_entry;
// 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, (void*) USTACKTOP - PGSIZE, PGSIZE);
// LAB 3: Your code here.
} }
// //
@ -353,6 +386,11 @@ void
env_create(uint8_t *binary, enum EnvType type) env_create(uint8_t *binary, enum EnvType type)
{ {
// LAB 3: Your code here. // LAB 3: Your code here.
struct Env* new_env;
if(env_alloc(&new_env, 0) < 0)
panic("Failed to allocate environment");
new_env->env_type = type;
load_icode(new_env, binary);
} }
// //
@ -483,7 +521,13 @@ env_run(struct Env *e)
// e->env_tf to sensible values. // e->env_tf to sensible values.
// LAB 3: Your code here. // LAB 3: Your code here.
if(curenv && curenv->env_status == ENV_RUNNING) {
panic("env_run not yet implemented"); curenv->env_status = ENV_RUNNABLE;
}
curenv = e;
e->env_status = ENV_RUNNING;
e->env_runs++;
lcr3(PADDR(e->env_pgdir));
env_pop_tf(&e->env_tf);
} }

View File

@ -3,6 +3,7 @@
#include <inc/stdio.h> #include <inc/stdio.h>
#include <inc/string.h> #include <inc/string.h>
#include <inc/assert.h> #include <inc/assert.h>
#include <inc/x86.h>
#include <kern/monitor.h> #include <kern/monitor.h>
#include <kern/console.h> #include <kern/console.h>
@ -17,6 +18,7 @@
static void boot_aps(void); static void boot_aps(void);
void sysenter_handler();
void void
i386_init(void) i386_init(void)
@ -26,6 +28,16 @@ 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");
write_msr(MSR_IA32_SYSENTER_EIP, (uint32_t) sysenter_handler, 0);
write_msr(MSR_IA32_SYSENTER_ESP, KSTACKTOP, 0);
write_msr(MSR_IA32_SYSENTER_CS, GD_KT, 0);
// Lab 2 memory management initialization functions // Lab 2 memory management initialization functions
mem_init(); mem_init();

View File

@ -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

View File

@ -7,10 +7,14 @@
#include <inc/assert.h> #include <inc/assert.h>
#include <inc/x86.h> #include <inc/x86.h>
#include <kern/env.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 +30,12 @@ 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 },
{ "resume", "Resume from a breakpoint", mon_resume },
{ "step", "Step to next instruction", mon_step }
}; };
/***** Implementations of basic kernel monitor commands *****/ /***** Implementations of basic kernel monitor commands *****/
@ -62,10 +72,161 @@ 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;
}
// This is a nice thought and all...
// But we should modify the trap frame.
// I feel stupid.
static inline void
set_eflag(uint16_t flagno, int value) {
uint32_t temp;
uint32_t mask = ~(1 << flagno);
uint32_t regv = value << flagno;
asm volatile("pushfl\n\t"
"pop %w0\n\t"
"and %w1, %w0\n\t"
"or %w2, %w0\n\t"
"push %w0\n\t"
"popfl\n\t"
: "=r" (temp)
: "r" (mask), "r" (regv));
}
#define EXPECT_BRKPT if(!(tf->tf_trapno == T_BRKPT || tf->tf_trapno == T_DEBUG)) { \
cprintf(ACOL_ERR("I don't think I should resume from this.\n")); \
return 0; }
#define EFLAGS_TF 0x8
int mon_resume(int argc, char** argv, struct Trapframe* tf) {
EXPECT_BRKPT;
tf->tf_eflags &= ~(1 << EFLAGS_TF);
env_pop_tf(tf);
return 0;
}
int mon_step(int argc, char** argv, struct Trapframe* tf) {
EXPECT_BRKPT;
tf->tf_eflags |= 1 << EFLAGS_TF;
env_pop_tf(tf);
return 0;
}
/***** Kernel monitor command interpreter *****/ /***** Kernel monitor command interpreter *****/

View File

@ -15,5 +15,9 @@ 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);
int mon_resume(int argc, char** argv, struct Trapframe* tf);
int mon_step(int argc, char** argv, struct Trapframe* tf);
#endif // !JOS_KERN_MONITOR_H #endif // !JOS_KERN_MONITOR_H

View File

@ -6,6 +6,7 @@
#include <inc/string.h> #include <inc/string.h>
#include <inc/assert.h> #include <inc/assert.h>
#include <kern/monitor.h>
#include <kern/pmap.h> #include <kern/pmap.h>
#include <kern/kclock.h> #include <kern/kclock.h>
#include <kern/env.h> #include <kern/env.h>
@ -105,8 +106,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:
@ -127,9 +130,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);
@ -151,11 +151,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
@ -179,6 +184,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_U);
kern_pgdir[PDX(UPAGES)] |= PTE_U;
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
@ -187,6 +197,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_U);
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
@ -199,6 +214,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.
@ -208,6 +228,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;
// Initialize the SMP-related parts of the memory map // Initialize the SMP-related parts of the memory map
mem_init_mp(); mem_init_mp();
@ -267,6 +293,14 @@ mem_init_mp(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.
@ -300,10 +334,14 @@ 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++) {
if(is_reserved(i)) {
pages[i].pp_ref = 1;
} else {
pages[i].pp_ref = 0; pages[i].pp_ref = 0;
pages[i].pp_link = page_free_list; pages[i].pp_link = page_free_list;
page_free_list = &pages[i]; page_free_list = &pages[i];
} }
}
} }
// //
@ -321,8 +359,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;
} }
// //
@ -332,9 +379,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;
} }
// //
@ -373,8 +421,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)];
} }
// //
@ -391,7 +456,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;
}
} }
// //
@ -422,7 +496,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;
} }
@ -440,8 +521,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;
if(!(pte = pgdir_walk(pgdir, va, false))) {
if(pte_store) *pte_store = NULL;
return NULL; return NULL;
}
struct PageInfo* pp = pa2page(PTE_ADDR(*pte));
if(pte_store) *pte_store = pte;
return pp;
} }
// //
@ -462,7 +550,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);
} }
// //
@ -536,6 +632,23 @@ int
user_mem_check(struct Env *env, const void *va, size_t len, int perm) user_mem_check(struct Env *env, const void *va, size_t len, int perm)
{ {
// LAB 3: Your code here. // LAB 3: Your code here.
uintptr_t to_report = (uintptr_t) va;
const char* bottom = ROUNDDOWN(va, PGSIZE);
size_t aligned_count = ROUNDUP(len, PGSIZE) / PGSIZE;
pde_t mask = PTE_P | PTE_U | PTE_W;
pde_t perms = mask;
#define VALID ((perms & (perm | PTE_P)) == (perm | PTE_P))
#define DO_CHECK if(!VALID) { user_mem_check_addr = to_report; return -E_FAULT; }
while(aligned_count--) {
perms &= env->env_pgdir[PDX(bottom)] & mask;
DO_CHECK;
perms &= (*pgdir_walk(env->env_pgdir, bottom, 0)) & mask;
DO_CHECK;
bottom += PGSIZE;
to_report = (uintptr_t) bottom;
}
return 0; return 0;
} }

View File

@ -20,9 +20,7 @@ sys_cputs(const char *s, size_t len)
{ {
// Check that the user has permission to read memory [s, s+len). // Check that the user has permission to read memory [s, s+len).
// Destroy the environment if not. // Destroy the environment if not.
user_mem_assert(curenv, s, len, 0);
// LAB 3: Your code here.
// Print the string supplied by the user. // Print the string supplied by the user.
cprintf("%.*s", len, s); cprintf("%.*s", len, s);
} }
@ -271,9 +269,16 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
// Return any appropriate return value. // Return any appropriate return value.
// LAB 3: Your code here. // LAB 3: Your code here.
panic("syscall not implemented");
switch (syscallno) { switch (syscallno) {
case SYS_cputs:
sys_cputs((const char*) a1, a2);
return 0;
case SYS_cgetc:
return sys_cgetc();
case SYS_getenvid:
return sys_getenvid();
case SYS_env_destroy:
return sys_env_destroy(a1);
default: default:
return -E_INVAL; return -E_INVAL;
} }

View File

@ -68,6 +68,26 @@ static const char *trapname(int trapno)
// XYZ: write a function declaration here... // XYZ: write a function declaration here...
// e.g., void t_divide(); // e.g., void t_divide();
void t_divide();
void t_debug();
void t_nmi();
void t_brkpt();
void t_oflow();
void t_bound();
void t_illop();
void t_device();
void t_dblflt();
void t_tss();
void t_segnp();
void t_stack();
void t_gpflt();
void t_pgflt();
void t_fperr();
void t_align();
void t_mchk();
void t_simderr();
void t_syscall();
void t_default();
void void
trap_init(void) trap_init(void)
@ -84,6 +104,26 @@ trap_init(void)
* *
*/ */
// LAB 3: Your code here. // LAB 3: Your code here.
SETGATE(idt[T_DIVIDE], 0, GD_KT, t_divide, 0);
SETGATE(idt[T_DEBUG], 0, GD_KT, t_debug, 0);
SETGATE(idt[T_NMI], 0, GD_KT, t_nmi, 0);
SETGATE(idt[T_BRKPT], 0, GD_KT, t_brkpt, 3);
SETGATE(idt[T_OFLOW], 0, GD_KT, t_oflow, 0);
SETGATE(idt[T_BOUND], 0, GD_KT, t_bound, 0);
SETGATE(idt[T_ILLOP], 0, GD_KT, t_illop, 0);
SETGATE(idt[T_DEVICE], 0, GD_KT, t_device, 0);
SETGATE(idt[T_DBLFLT], 0, GD_KT, t_dblflt, 0);
SETGATE(idt[T_TSS], 0, GD_KT, t_tss, 0);
SETGATE(idt[T_SEGNP], 0, GD_KT, t_segnp, 0);
SETGATE(idt[T_STACK], 0, GD_KT, t_stack, 0);
SETGATE(idt[T_GPFLT], 0, GD_KT, t_gpflt, 0);
SETGATE(idt[T_PGFLT], 0, GD_KT, t_pgflt, 0);
SETGATE(idt[T_FPERR], 0, GD_KT, t_fperr, 0);
SETGATE(idt[T_ALIGN], 0, GD_KT, t_align, 0);
SETGATE(idt[T_MCHK], 0, GD_KT, t_mchk, 0);
SETGATE(idt[T_SIMDERR], 0, GD_KT, t_simderr, 0);
SETGATE(idt[T_SYSCALL], 0, GD_KT, t_syscall, 3);
SETGATE(idt[T_DEFAULT], 0, GD_KT, t_default, 0);
// Per-CPU setup // Per-CPU setup
trap_init_percpu(); trap_init_percpu();
@ -188,6 +228,22 @@ trap_dispatch(struct Trapframe *tf)
{ {
// Handle processor exceptions. // Handle processor exceptions.
// LAB 3: Your code here. // LAB 3: Your code here.
if (tf->tf_trapno == T_PGFLT) {
page_fault_handler(tf);
return;
} else if (tf->tf_trapno == T_BRKPT || tf->tf_trapno == T_DEBUG) {
monitor(tf);
return;
} else if (tf->tf_trapno == T_SYSCALL) {
int32_t returned = 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);
tf->tf_regs.reg_eax = returned;
return;
}
// Handle spurious interrupts // Handle spurious interrupts
// The hardware sometimes raises these because of noise on the // The hardware sometimes raises these because of noise on the

View File

@ -44,9 +44,44 @@
.text .text
.globl sysenter_handler
sysenter_handler:
push %ebp // holds env's stack pointer
push %esi // holds the env's return addr
push %edi
push %ebx
push %ecx
push %edx
push %eax
call syscall
add $0x14, %esp
pop %edx
pop %ecx
sysexit
/* /*
* Lab 3: Your code here for generating entry points for the different traps. * Lab 3: Your code here for generating entry points for the different traps.
*/ */
TRAPHANDLER_NOEC(t_divide, T_DIVIDE);
TRAPHANDLER_NOEC(t_debug, T_DEBUG);
TRAPHANDLER_NOEC(t_nmi, T_NMI);
TRAPHANDLER_NOEC(t_brkpt, T_BRKPT);
TRAPHANDLER_NOEC(t_oflow, T_OFLOW);
TRAPHANDLER_NOEC(t_bound, T_OFLOW);
TRAPHANDLER_NOEC(t_illop, T_OFLOW);
TRAPHANDLER_NOEC(t_device, T_OFLOW);
TRAPHANDLER(t_dblflt, T_OFLOW);
TRAPHANDLER(t_tss, T_TSS);
TRAPHANDLER(t_segnp, T_SEGNP);
TRAPHANDLER(t_stack, T_STACK);
TRAPHANDLER(t_gpflt, T_GPFLT);
TRAPHANDLER(t_pgflt, T_PGFLT);
TRAPHANDLER_NOEC(t_fperr, T_FPERR);
TRAPHANDLER(t_align, T_ALIGN);
TRAPHANDLER_NOEC(t_mchk, T_MCHK);
TRAPHANDLER_NOEC(t_simderr, T_SIMDERR);
TRAPHANDLER_NOEC(t_syscall, T_SYSCALL);
TRAPHANDLER(t_default, T_DEFAULT);
// HINT 1 : TRAPHANDLER_NOEC(t_divide, T_DIVIDE); // HINT 1 : TRAPHANDLER_NOEC(t_divide, T_DIVIDE);
// Do something like this if there is no error code for the trap // Do something like this if there is no error code for the trap
@ -59,4 +94,15 @@
* Lab 3: Your code here for _alltraps * Lab 3: Your code here for _alltraps
*/ */
.globl _alltraps
_alltraps:
sub $0x2, %esp
pushw %ds
sub $0x2, %esp
pushw %es
pushal
mov $(GD_KD), %eax
movw %ax, %ds
movw %ax, %es
pushl %esp
call trap

View File

@ -13,7 +13,8 @@ libmain(int argc, char **argv)
{ {
// set thisenv to point at our Env structure in envs[]. // set thisenv to point at our Env structure in envs[].
// LAB 3: Your code here. // LAB 3: Your code here.
thisenv = 0; envid_t id = sys_getenvid();
thisenv = &envs[ENVX(id)];
// save the name of the program so that panic() can use it // save the name of the program so that panic() can use it
if (argc > 0) if (argc > 0)

View File

@ -207,11 +207,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':

View File

@ -2,6 +2,7 @@
#include <inc/syscall.h> #include <inc/syscall.h>
#include <inc/lib.h> #include <inc/lib.h>
#include <inc/x86.h>
static inline int32_t static inline int32_t
syscall(int num, int check, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) syscall(int num, int check, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
@ -37,16 +38,30 @@ syscall(int num, int check, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
return ret; return ret;
} }
int32_t
fast_syscall(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4) {
asm volatile(
"push %%ebp\n\t"
"mov %%esp, %%ebp\n\t"
"lea syscall_ret_%=, %%esi\n\t"
"sysenter\n\t"
"syscall_ret_%=: pop %%ebp\n\t"
: "+a" (num)
: "d" (a1), "c" (a2), "b" (a3), "D" (a4)
: "esi");
return num;
}
void void
sys_cputs(const char *s, size_t len) sys_cputs(const char *s, size_t len)
{ {
syscall(SYS_cputs, 0, (uint32_t)s, len, 0, 0, 0); fast_syscall(SYS_cputs, (uint32_t)s, len, 0, 0);
} }
int int
sys_cgetc(void) sys_cgetc(void)
{ {
return syscall(SYS_cgetc, 0, 0, 0, 0, 0, 0); return fast_syscall(SYS_cgetc, 0, 0, 0, 0);
} }
int int

View File

@ -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

9
user/getc.c Normal file
View File

@ -0,0 +1,9 @@
#include <inc/lib.h>
void
umain(int argc, char **argv)
{
char c;
while(!(c = sys_cgetc()));
cprintf("got character %c\n", c);
}