From c96973cf0372ba9cba46f9c1a924f026be76db81 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 28 Nov 2014 01:49:03 +0100 Subject: [PATCH 1/7] improved some targets of the Makefiles used for debugging and testing --- Makefile.example | 20 +++++++++++++++----- debug.gdb | 7 +++++++ 2 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 debug.gdb diff --git a/Makefile.example b/Makefile.example index dd4ead8..cddd314 100644 --- a/Makefile.example +++ b/Makefile.example @@ -20,9 +20,18 @@ OBJCOPY_FOR_TARGET = $(CROSSCOMPREFIX)objcopy RANLIB_FOR_TARGET = $(CROSSCOMPREFIX)ranlib STRIP_FOR_TARGET = $(CROSSCOMPREFIX)strip READELF_FOR_TARGET = $(CROSSCOMPREFIX)readelf + NASM = nasm +GDB = gdb +QEMU = qemu-system-i386 NASMFLAGS = -felf32 -g -i$(TOPDIR)/include/eduos/ +GDBFLAGS = -x debug.gdb +QEMUFLAGS = -smp 2 -monitor stdio \ + -net nic,model=rtl8139 \ + -net user,hostfwd=tcp::12345-:7 \ + -serial tcp::12346,server,nowait + INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include # Compiler options for final code CFLAGS = -g -m32 -march=i586 -Wall -O2 -fno-builtin -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc $(INCLUDE) -fno-stack-protector @@ -62,14 +71,15 @@ veryclean: clean @echo Very cleaned qemu: $(NAME).elf - qemu-system-i386 -monitor stdio -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel $(NAME).elf + $(QEMU) $(QEMUFLAGS) -kernel $(NAME).elf -qemu-dbg: $(NAME).elf - qemu-system-i386 -monitor stdio -s -S -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel $(NAME).elf +debug: $(NAME).elf + $(TERM) -e $(GDB) $(GDBFLAGS) & + $(QEMU) $(QEMUFLAGS) -s -S -kernel $(NAME).elf doc: - @doxygen @echo Create documentation... + @doxygen %.o : %.c @echo [CC] $@ @@ -91,5 +101,5 @@ include/eduos/config.inc: include/eduos/config.h $Q$(CC_FOR_TARGET) $(CFLAGS) -c -o $@ $< .PHONY: default all clean emu gdb newlib tools - + include $(addsuffix /Makefile,$(SUBDIRS)) diff --git a/debug.gdb b/debug.gdb new file mode 100644 index 0000000..f1c08c0 --- /dev/null +++ b/debug.gdb @@ -0,0 +1,7 @@ +# Constant part of the script +symbol-file eduos.sym +target remote localhost:1234 + +set architecture i386 +break main +continue From b86e9d9a7d7956c1cf72aa26180b53531e39b627 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 28 Nov 2014 01:53:32 +0100 Subject: [PATCH 2/7] fixed external declarations --- kernel/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/main.c b/kernel/main.c index 617bd81..88798aa 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -52,9 +52,9 @@ extern char __BUILD_DATE; extern char __BUILD_TIME; /* Page frame counters */ -atomic_int32_t total_pages; -atomic_int32_t total_allocated_pages; -atomic_int32_t total_available_pages; +extern atomic_int32_t total_pages; +extern atomic_int32_t total_allocated_pages; +extern atomic_int32_t total_available_pages; static void userfoo(void* arg) { From b33107eef7a06faa65abce6a72ddd13d45d17a0c Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 28 Nov 2014 02:00:35 +0100 Subject: [PATCH 3/7] removed userspace fork/kill support to separate branch --- arch/x86/mm/page.c | 104 +-------------------------------------------- 1 file changed, 1 insertion(+), 103 deletions(-) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index a090d96..f8b11c8 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -97,36 +97,7 @@ int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits) for (lvl=PAGE_LEVELS-1; lvl>=0; lvl--) { for (vpn=first[lvl]; vpn<=last[lvl]; vpn++) { if (lvl) { /* PML4, PDPT, PGD */ - if (self[lvl][vpn] & PG_PRESENT) { - /* There already an existing table which only allows - * kernel accesses. We need to copy the table to create - * private copy for the user space process */ - if (!(self[lvl][vpn] & PG_USER) && (bits & PG_USER)) { - size_t phyaddr = get_pages(1); - if (BUILTIN_EXPECT(!phyaddr, 0)) { - spinlock_unlock(&kslock); - return -ENOMEM; - } - - atomic_int32_inc(¤t_task->user_usage); - - /* Copy old table contents to new one. - * We temporarily use page zero (PAGE_TMP) for this - * by mapping the new table to this address. */ - page_map(PAGE_TMP, phyaddr, 1, PG_RW | PG_PRESENT); - memcpy((void *) PAGE_TMP, CHILD(self, lvl, vpn), PAGE_SIZE); - - /* Update table by replacing address and altering flags */ - self[lvl][vpn] &= ~(PAGE_MASK | PG_GLOBAL); - self[lvl][vpn] |= phyaddr | PG_USER; - - /* We only need to flush the self-mapped table. - * TLB entries mapped by this table remain valid - * because we only made an identical copy. */ - tlb_flush_one_page((size_t) CHILD(self, lvl, vpn)); - } - } - else { + if (!(self[lvl][vpn] & PG_PRESENT)) { /* There's no table available which covers the region. * Therefore we need to create a new empty table. */ size_t phyaddr = get_pages(1); @@ -175,79 +146,6 @@ int page_unmap(size_t viraddr, size_t npages) return 0; } -/* @todo: complete -int page_map_drop() -{ - void traverse(int lvl, long vpn) { - kprintf("traverse(lvl=%d, vpn=%#lx)\n", lvl, vpn); - - long stop; - for (stop=vpn+PAGE_MAP_ENTRIES; vpn 1) - traverse(lvl-1, vpn<user_usage); - } - } - } - - spinlock_irqsave_lock(¤t_task->page_lock); - - traverse(PAGE_LEVELS-1, 0); - - spinlock_irqsave_unlock(¤t_task->page_lock); - - return 0; -} - -int page_map_copy(size_t dest) -{ - int traverse(int lvl, long vpn) { - long stop; - for (stop=vpn+PAGE_MAP_ENTRIES; vpn Date: Fri, 28 Nov 2014 02:15:15 +0100 Subject: [PATCH 4/7] smaller cleanups --- arch/x86/include/asm/page.h | 2 ++ arch/x86/mm/page.c | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index b91a80a..089c732 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -88,6 +88,8 @@ /// This page or table is used during the boot process #define PG_BOOT (1 << 9) +/// This page is reserved for copying +#define PAGE_TMP (PAGE_FLOOR((size_t) &kernel_start) - PAGE_SIZE) /** @brief Converts a virtual address to a physical * diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index f8b11c8..c3f70e1 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -63,9 +63,6 @@ static size_t * other[PAGE_LEVELS] = { #define CHILD(map, lvl, vpn) &map[lvl-1][vpn<>PAGE_MAP_BITS] -/** This page is reserved for copying */ -#define PAGE_TMP (PAGE_FLOOR((size_t) &kernel_start) - PAGE_SIZE) - /** @todo Does't handle huge pages for now * @todo This will cause a pagefaut if addr isn't mapped! */ size_t page_virt_to_phys(size_t addr) @@ -139,7 +136,7 @@ int page_unmap(size_t viraddr, size_t npages) spinlock_lock(&kslock); for (vpn=start; vpn Date: Fri, 28 Nov 2014 02:15:49 +0100 Subject: [PATCH 5/7] made pagefault handler more verbose --- arch/x86/mm/page.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index c3f70e1..f2de90f 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -147,10 +147,13 @@ void page_fault_handler(struct state *s) { size_t viraddr = read_cr2(); - kprintf("Page Fault Exception (%d) at cs:ip = %#x:%#lx, address = %#lx\n", - s->int_no, s->cs, s->eip, viraddr); - - outportb(0x20, 0x20); /** @todo: do we need this? */ + kprintf("Page Fault Exception (%d) at cs:ip = %#x:%#lx, task = %u, addr = %#lx, error = %#x [ %s %s %s %s %s ]\n", + s->int_no, s->cs, s->eip, current_task->id, viraddr, s->error, + (s->error & 0x4) ? "user" : "supervisor", + (s->error & 0x10) ? "instruction" : "data", + (s->error & 0x2) ? "write" : ((s->error & 0x10) ? "fetch" : "read"), + (s->error & 0x1) ? "protection" : "not present", + (s->error & 0x8) ? "reserved bit" : "\b"); while(1) HALT; } From 883756d0b4177e951808340a000e56251acb26f1 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 28 Nov 2014 02:26:40 +0100 Subject: [PATCH 6/7] improved documentation --- arch/x86/mm/page.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index f2de90f..5e9f373 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -24,6 +24,11 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * This is a 32/64 bit portable paging implementation for the x86 architecture + * using self-referenced page tables. + * See http://www.noteblok.net/2014/06/14/bachelor/ for a detailed description. + */ #include #include @@ -59,12 +64,10 @@ static size_t * other[PAGE_LEVELS] = { (size_t *) 0xFFFFE000 }; -/** Addresses of child/parent tables */ +/* Addresses of child/parent tables */ #define CHILD(map, lvl, vpn) &map[lvl-1][vpn<>PAGE_MAP_BITS] -/** @todo Does't handle huge pages for now - * @todo This will cause a pagefaut if addr isn't mapped! */ size_t page_virt_to_phys(size_t addr) { size_t vpn = addr >> PAGE_BITS; // virtual page number @@ -81,7 +84,7 @@ int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits) long vpn = viraddr >> PAGE_BITS; long first[PAGE_LEVELS], last[PAGE_LEVELS]; - // calculate index boundaries for page map traversal + /* Calculate index boundaries for page map traversal */ for (lvl=0; lvl> (lvl * PAGE_MAP_BITS); last[lvl] = (vpn+npages-1) >> (lvl * PAGE_MAP_BITS); @@ -89,8 +92,8 @@ int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits) spinlock_lock(&kslock); - /* We start now iterating through the entries - * beginning at the root table (PGD) */ + /* Start iterating through the entries + * beginning at the root table (PGD or PML4) */ for (lvl=PAGE_LEVELS-1; lvl>=0; lvl--) { for (vpn=first[lvl]; vpn<=last[lvl]; vpn++) { if (lvl) { /* PML4, PDPT, PGD */ @@ -135,6 +138,8 @@ int page_unmap(size_t viraddr, size_t npages) spinlock_lock(&kslock); + /* Start iterating through the entries. + * Only the PGT entries are removed. Tables remain allocated. */ for (vpn=start; vpn> PAGE_BITS; page_map(addr, addr, npages, PG_PRESENT | PG_RW | PG_GLOBAL); #ifdef CONFIG_VGA - // map video memory + /* Map video memory */ page_map(VIDEO_MEM_ADDR, VIDEO_MEM_ADDR, 1, PG_PRESENT | PG_RW | PG_PCD); #endif - // map multiboot information and modules + /* Map multiboot information and modules */ if (mb_info) { addr = (size_t) mb_info & PAGE_MASK; npages = PAGE_FLOOR(sizeof(*mb_info)) >> PAGE_BITS; @@ -197,7 +202,7 @@ int page_init() } } - // unmap all (identity mapped) pages with PG_BOOT flag in first PGT (boot_pgt) + /* Unmap bootstrap identity paging (see entry.asm, PG_BOOT) */ for (i=0; i Date: Fri, 28 Nov 2014 02:28:33 +0100 Subject: [PATCH 7/7] removed obsolescent variable --- arch/x86/mm/page.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 5e9f373..a0e6d4b 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -58,12 +58,6 @@ static size_t* self[PAGE_LEVELS] = { (size_t *) 0xFFFFF000 }; -/** @todo: replace these offset by something meaningful */ -static size_t * other[PAGE_LEVELS] = { - (size_t *) 0xFF800000, - (size_t *) 0xFFFFE000 -}; - /* Addresses of child/parent tables */ #define CHILD(map, lvl, vpn) &map[lvl-1][vpn<>PAGE_MAP_BITS]