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 Page *pages; // Physical page state array
static struct Page *page_free_list; // Free list of physical pages
struct Page {
struct Page *pp_link;
uint16_t pp_ref;
};
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 += (uint32_t)ROUNDUP((char *) n, PGSIZE);
if ( (uint32_t)nextfree > (KERNBASE + npages*PGSIZE)) {
panic("boot_alloc: Out of Memory!\n");
}
return result;
}
void
page_init(void)
{
// 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!
size_t i;
// Mark physical page 0 as in use.
pages[0].pp_ref = 1;
// Base memory, [PGSIZE, npages_basemem * PGSIZE) is free.
for (i = 1; i < (IOPHYSMEM / PGSIZE) ; i++) {
pages[i].pp_ref = 0;
pages[i].pp_link = page_free_list;
page_free_list = &pages[i];
}
// IO hole [IOPHYSMEM, EXTPHYSMEM).
for (i; i < (EXTPHYSMEM / PGSIZE) ; i++) {
pages[i].pp_ref = 1;
}
// Used in extended memory [EXTPHYSMEM, ...).
for (i; i < PADDR(boot_alloc(0)) / PGSIZE; i++) {
pages[i].pp_ref = 1;
}
for (i; i < npages; i++) {
pages[i].pp_ref = 0;
pages[i].pp_link = page_free_list;
page_free_list = &pages[i];
}
}
struct Page *
page_alloc(int alloc_flags)
{
// Fill this function in
struct Page *free_page;
if (page_free_list == NULL)
return NULL;
free_page = page_free_list;
page_free_list = page_free_list->pp_link;
//fills the entire physical page with '\0' bytes.
if (alloc_flags & ALLOC_ZERO)
memset(page2kva(free_page), 0, PGSIZE);
return free_page;
}
void
page_free(struct Page *pp)
{
// Fill this function in
assert(pp->pp_ref == 0);
memset(page2kva(pp), 0, PGSIZE);
pp->pp_link = page_free_list;
page_free_list = pp;
}
int
mon_backtrace(int argc, char **argv, struct Trapframe *tf)
{
// Your code here.
uint32_t *ebp, *eip;
uint32_t arg1, arg2, arg3, arg4, arg5;
struct Eipdebuginfo info;
char fn_name[101];
uint32_t i;
cprintf("Stack backtrace:\n");
// Get the ebp using read_ebp() in <x86.h>.
ebp = (uint32_t *)read_ebp();
// Stop when ebp == 0;
while(ebp != 0x0) {
eip = (uint32_t*) ebp[1];
arg1 = ebp[2];
arg2 = ebp[3];
arg3 = ebp[4];
arg4 = ebp[5];
arg5 = ebp[6];
cprintf(" ebp %08x eip %08x args %08x %08x %08x %08x %08x\n", ebp, eip, arg1, arg2, arg3, arg4, arg5);
// Get the info of function.
debuginfo_eip((uintptr_t)eip, &info);
// Remove unnecessary char in info.eip_fn_name.
// Store the fuction name to an array.
for(i = 0; i < info.eip_fn_namelen && i < 100; ++i)
fn_name[i] = info.eip_fn_name[i];
fn_name[i] = '\0';
cprintf(" %s:%d: %s+%d\n",info.eip_file, info.eip_line, fn_name, eip-info.eip_fn_addr, info.eip_fn_narg);
ebp = (uint32_t*)(*ebp);
}
return 0;
}
int get_color(char type)
{
int color = 0;
switch (type)
{
case 'R':
color = FORE_RED;
break;
case 'G':
color = FORE_GREEN;
break;
case 'B':
color = FORE_BLUE;
break;
case 'W':
color = FORE_WHITE;
case 'K':
color = FORE_BLACK;
default:
break;
}
return color;
}
while ((ch = *(unsigned char *) fmt++) != '%') {
if (ch == '\0')
return;
//putch(ch, putdat);
cflag = 1;
//foreground color
if (ch == '$')
{
ch = *(unsigned char *)fmt++;
color = get_color(ch);
cflag = 0;
}
if (cflag)
putch(ch, putdat);
}
#define FORE_BLACK 0x0000
#define FORE_RED 0x0400
#define FORE_GREEN 0x0200
#define FORE_BLUE 0x0100
#define FORE_WHITE 0x0700
int color = FORE_WHITE;
if (crt_pos >= CRT_SIZE) {
int i;
memmove(crt_buf, crt_buf + CRT_COLS, (CRT_SIZE - CRT_COLS) * sizeof(uint16_t));
for (i = CRT_SIZE - CRT_COLS; i < CRT_SIZE; i++)
crt_buf[i] = 0x0700 | ' ';
crt_pos -= CRT_COLS;
}
// (unsigned) octal
case 'o':
// Replace this with your code.
num = getuint(&ap, lflag);
base = 8;
goto number;