diff --git a/Makefile b/Makefile index ef4a381..2fbbb6e 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ endif CFLAGS = -fno-pic -ffreestanding -static -fno-builtin -fno-strict-aliasing \ -mno-sse \ + -I. \ -Wall -ggdb -m32 -Werror -fno-omit-frame-pointer CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) ASMFLAGS = -m32 -ffreestanding -c -g -I. @@ -75,7 +76,7 @@ debug: image.bin qemu-system-i386 -drive format=raw,file=$< -s -S & $(GDB) kernel.bin \ -ex "target remote localhost:1234" \ - -ex "break _start" \ + -ex "break kmain" \ -ex "continue" debug-nox: image.bin diff --git a/cpu/memlayout.h b/cpu/memlayout.h index 0702d52..d45326e 100644 --- a/cpu/memlayout.h +++ b/cpu/memlayout.h @@ -1,3 +1,8 @@ #pragma once -#define KERNBASE 0xf0000000 \ No newline at end of file +#define KERNBASE 0xf0000000 +#define PGSIZE 0x1000 +#define PHYSTOP 0x8000000 + +#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1)) +#define V2P(a) (((uintptr_t) (a)) - KERNBASE) diff --git a/cpu/x86.h b/cpu/x86.h new file mode 100644 index 0000000..ae0488e --- /dev/null +++ b/cpu/x86.h @@ -0,0 +1,13 @@ +#pragma once + +static inline void +stosl(void *addr, int data, int cnt) +{ + asm volatile("cld; rep stosl" : : "D"(addr), "c"(cnt), "a"(data) : "memory"); +} + +static inline void +stosb(void *addr, unsigned char data, int cnt) +{ + asm volatile("cld; rep stosb" : : "D"(addr), "c"(cnt), "a"(data) : "memory"); +} diff --git a/drivers/keyboard.c b/drivers/keyboard.c index d7ade6e..ad38a9b 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -1,8 +1,9 @@ #include "keyboard.h" -#include "../cpu/isr.h" -#include "../console.h" +#include "cpu/isr.h" +#include "cpu/memlayout.h" +#include "console.h" #include "port.h" -#include "../lib/mem.h" +#include "lib/mem.h" static const char sc_ascii[] = { '?', '?', '1', '2', '3', '4', '5', '6', @@ -12,7 +13,7 @@ static const char sc_ascii[] = { 'b', 'n', 'm', ',', '.', '/', '?', '?', '?', ' ', }; -enum { kbd_buf_capacity = 1024 }; +enum { kbd_buf_capacity = PGSIZE }; static void interrupt_handler(registers_t *r) { uint8_t scancode = port_byte_in(0x60); @@ -30,7 +31,7 @@ char* kbd_buf; unsigned kbd_buf_size; void init_keyboard() { - kbd_buf = kmalloc(kbd_buf_capacity); + kbd_buf = kalloc(); register_interrupt_handler(IRQ1, interrupt_handler); } diff --git a/lib/mem.c b/lib/mem.c index 0bf188b..c59f685 100644 --- a/lib/mem.c +++ b/lib/mem.c @@ -1,12 +1,70 @@ +// Physical memory allocator, intended to allocate +// memory for user processes, kernel stacks, page table pages, +// and pipe buffers. Allocates 4096-byte pages. + +#include #include "mem.h" +#include "console.h" +#include "cpu/memlayout.h" +#include "cpu/x86.h" -static void* freeptr; +struct run { + struct run *next; +}; -void* kmalloc(size_t size) { - if (!freeptr) { - freeptr = (void*)(1<<20); - } - void* result = freeptr; - freeptr += size; - return result; +struct { + struct run *freelist; +} kmem; + +void +freerange(void *vstart, void *vend) +{ + char *p; + p = (char*)PGROUNDUP((uintptr_t)vstart); + for(; p + PGSIZE <= (char*)vend; p += PGSIZE) + kfree(p); +} + +void* +memset(void *dst, unsigned c, uint64_t n) +{ + if ((uintptr_t)dst%4 == 0 && n%4 == 0){ + c &= 0xFF; + stosl(dst, (c<<24)|(c<<16)|(c<<8)|c, n/4); + } else + stosb(dst, c, n); + return dst; +} + +// Free the page of physical memory pointed at by v, +// which normally should have been returned by a +// call to kalloc(). (The exception is when +// initializing the allocator; see kinit above.) +void +kfree(char *v) +{ + struct run *r; + + if((uintptr_t)v % PGSIZE || V2P(v) >= PHYSTOP) + panic("kfree"); + + // Fill with junk to catch dangling refs. + memset(v, 1, PGSIZE); + + r = (struct run*)v; + r->next = kmem.freelist; + kmem.freelist = r; +} + +// Allocate one 4096-byte page of physical memory. +// Returns a pointer that the kernel can use. +// Returns 0 if the memory cannot be allocated. +void* kalloc(void) +{ + struct run *r; + + r = kmem.freelist; + if(r) + kmem.freelist = r->next; + return (char*)r; } diff --git a/lib/mem.h b/lib/mem.h index 1a77610..8af959f 100644 --- a/lib/mem.h +++ b/lib/mem.h @@ -1,5 +1,5 @@ #pragma once -typedef unsigned size_t; - -void* kmalloc(size_t size); +void freerange(void *vstart, void *vend); +void* kalloc(void); +void kfree(char*); diff --git a/lib/string.c b/lib/string.c index e269955..99e1171 100644 --- a/lib/string.c +++ b/lib/string.c @@ -26,10 +26,3 @@ int strncmp(const char* s1, const char* s2, size_t size) { } return (unsigned char)(*s1) - (unsigned char)(*s2); } - -void memset(void* b, char c, size_t len) { - char* p = b; - for (size_t i = 0; i < len; ++i) { - p[i] = c; - } -} diff --git a/proc.c b/proc.c index 6ec0971..47b9432 100644 --- a/proc.c +++ b/proc.c @@ -36,8 +36,8 @@ void swtch(void** oldstack, void* newstack); void run_elf(const char* name) { if (!vm) { - vm = kmalloc(sizeof(struct vm)); - vm->user_task = kmalloc(sizeof(struct task)); + vm = kalloc(); + vm->user_task = kalloc(); switchuvm(&vm->user_task->tss, vm->user_task->stack.bottom); } if (read_file(name, (void*)USER_BASE, 100 << 20) <= 0) {