From f658145036cf9246a5b739327374da3a487ea8b6 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 2 Dec 2012 10:45:35 -0500 Subject: [PATCH 01/20] add tools to compile/install properly from linux --- Makefile | 23 +++++++-- module.mk | 5 +- tools_linux/installBootLoader.c | 89 +++++++++++++++++++++++++++++++++ tools_linux/module.mk | 5 ++ tools_linux/setup.sh | 34 +++++++++++++ 5 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 tools_linux/installBootLoader.c create mode 100644 tools_linux/module.mk create mode 100644 tools_linux/setup.sh diff --git a/Makefile b/Makefile index 4b34af7..9a99777 100644 --- a/Makefile +++ b/Makefile @@ -9,14 +9,19 @@ TESTS := include ./module.mk include boot/module.mk include kernel/module.mk -include tools/module.mk + +ifeq ($(UNAME),Darwin) + include tools/module.mk +else + include tools_linux/module.mk +endif # Standard Settings CC := gcc COMMON_CFLAGS := -I . -std=c99 -COMMON_CFLAGS += -Wall -Werror-implicit-function-declaration -Werror -Wno-array-bounds +COMMON_CFLAGS += -Wall -Werror-implicit-function-declaration -Wno-array-bounds COMMON_CFLAGS += -fno-common -fno-asynchronous-unwind-tables -COMMON_CFLAGS += -mno-red-zone +COMMON_CFLAGS += -mno-red-zone -fno-stack-protector COMMON_CFLAGS += -O2 FREESTANDING_CFLAGS := -fno-builtin @@ -71,8 +76,20 @@ usb_kernel_%: boot/loader.bin kernel/kernel.bin cp boot/loader.bin $*:/ cp kernel/kernel.bin $*:/ +ifeq ($(UNAME),Darwin) +install: os.img tools/img_edit.exe + tools/img_edit.exe create os.img boot/boot.bin + tools/img_edit.exe add os.img boot/loader.bin + tools/img_edit.exe add os.img kernel/kernel.bin +else +install: os.img + tools_linux/setup.sh + tools_linux/installBootLoader boot/boot.bin os.img -mbr +endif + clean: rm -f */*.bin */*.exe */*.exe.run */*.o */*.d + rm -f os.img -include $(SOURCES:.c=.host.d) -include $(SOURCES:.c=.cross.d) diff --git a/module.mk b/module.mk index 5c37f0f..3660cf9 100644 --- a/module.mk +++ b/module.mk @@ -1,6 +1,3 @@ TARGETS += os.img -os.img: tools/img_edit.exe boot/boot.bin boot/loader.bin kernel/kernel.bin - tools/img_edit.exe create os.img boot/boot.bin - tools/img_edit.exe add os.img boot/loader.bin - tools/img_edit.exe add os.img kernel/kernel.bin +os.img: boot/boot.bin boot/loader.bin kernel/kernel.bin \ No newline at end of file diff --git a/tools_linux/installBootLoader.c b/tools_linux/installBootLoader.c new file mode 100644 index 0000000..0045e37 --- /dev/null +++ b/tools_linux/installBootLoader.c @@ -0,0 +1,89 @@ +#include +#include +#include + +#define SECTOR_SIZE 512 +#define JMP_CODE_SIZE 3 +#define BIOS_BLOCK_SIZE 62 +#define PART_TABLE 446 + +int main(int argc, char *argv[]) { + + FILE *boot, *disk; + char *sboot, *sdisk; + int mbr = 0; + int diskoffset = 0; + + char bootloader[SECTOR_SIZE]; + char cursector[SECTOR_SIZE]; + char newsector[SECTOR_SIZE]; + size_t ret; + + if (!(argc == 3 || argc == 4)) { + fprintf(stderr, "Invalid parameters\n"); + exit(-1); + } + + if (argc == 4) { + if (strcmp(argv[3], "-mbr") == 0) { + mbr = 1; + } + } + if (!mbr) + diskoffset = 1048576; + + if (mbr) { + printf("Installing MBR from image %s to %s\n", argv[1], argv[2]); + } else { + printf("Installing boot sector image %s to %s\n", argv[1], argv[2]); + } + + sboot = argv[1]; + sdisk = argv[2]; + + boot = fopen(sboot, "rb"); + disk = fopen(sdisk, "rb+"); + + if (boot == NULL || disk == NULL) { + fprintf(stderr, "unable to open file(s)\n"); + exit(-1); + } + + fseek(boot, 0, SEEK_SET); + fseek(disk, diskoffset, SEEK_SET); + + ret = fread(bootloader, 1, SECTOR_SIZE, boot); + if (ret != SECTOR_SIZE) { + fprintf(stderr, "error reading %s or improper file size\n", sboot); + exit(-1); + } + + int i; + + ret = fread(cursector, 1, SECTOR_SIZE, disk); + if (ret != SECTOR_SIZE) { + fprintf(stderr, "error reading %s or improper file size\n", sdisk); + exit(-1); + } + + + fseek(disk, diskoffset, SEEK_SET); + + memcpy(newsector, bootloader, SECTOR_SIZE); + memcpy(newsector + JMP_CODE_SIZE, cursector + JMP_CODE_SIZE, BIOS_BLOCK_SIZE - JMP_CODE_SIZE); + + if (mbr) { + memcpy(newsector + PART_TABLE, cursector + PART_TABLE, SECTOR_SIZE - PART_TABLE); + } + + newsector[510] = 0x55; + newsector[511] = 0xAA; + + fwrite(newsector, 1, SECTOR_SIZE, disk); + + fclose(boot); + fclose(disk); + + + return 0; +} diff --git a/tools_linux/module.mk b/tools_linux/module.mk new file mode 100644 index 0000000..3bf83b1 --- /dev/null +++ b/tools_linux/module.mk @@ -0,0 +1,5 @@ +TARGETS += \ + tools_linux/installBootLoader + +installBootLoader: tools_linux/installBootLoader.c + $(CC) -c $< $(C_CFLAGS) -o $@ \ No newline at end of file diff --git a/tools_linux/setup.sh b/tools_linux/setup.sh new file mode 100644 index 0000000..6fc489d --- /dev/null +++ b/tools_linux/setup.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +harddisk_image_size=$((20*1024*1024)) # 20 megabytes +harddisk_image="os.img" +kernel_args="" +loader_binary="boot/loader.bin" +kernel_binary="kernel/kernel.bin" + +function fail() { echo "$1"; exit 1; } +function prereq() { + local c x + if [ "$1" = "f" ]; then c=stat;x=file; else c=which;x=program; fi + if [ -z "$3" ]; then + $c "$2" >/dev/null || fail "$x $2 not found" + else + $c "$2" >/dev/null || fail "$x $2 (from package $3) not found" + fi +} + +# check prerequisites +prereq x mkdosfs dosfstools +prereq x mcopy mtools + +if [ ! -f $harddisk_image ] +then + # create image + dd if=/dev/zero of="$harddisk_image" bs=4k count=$((harddisk_image_size/4096)) 2>/dev/null + # format image + mkdosfs -F 16 "$harddisk_image" || fail "could not format os.img" +fi + +# copy over kernel +mcopy -o -i "$harddisk_image" "$kernel_binary" ::kernel.bin || fail "could not copy over kernel" +mcopy -o -i "$harddisk_image" "$loader_binary" ::loader.bin || fail "could not copy over loader" From 66d10382efdf496ea1ccf06f4a4861a9e9bcab1e Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 2 Dec 2012 11:26:05 -0500 Subject: [PATCH 02/20] map the first 1G of memory instead of the first 2MB --- boot/loader.asm | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/boot/loader.asm b/boot/loader.asm index 6436864..0292032 100644 --- a/boot/loader.asm +++ b/boot/loader.asm @@ -139,24 +139,34 @@ build_memory_map: build_vm_tables: ; Define one 2MB page at memory address 0. + xor edi, edi mov di, vm_pml4 ; PML4 - mov ax, vm_pdp + 0xf + mov ax, vm_pdp + 0x3 ; Present + Read/Write stosw xor ax, ax mov cx, 0x07ff rep stosw - mov ax, vm_pd + 0xf ; PDP + mov ax, vm_pd + 0x3 ; Present + Read/Write stosw xor ax, ax mov cx, 0x07ff rep stosw - mov ax, 0x018f ; PD - stosw - xor ax, ax - mov cx, 0x07ff - rep stosw + ; Build 512 Page Directory Entries + ; Which should allow us early access to the first 1Gb of mem + mov edx, 0x0 +build: + mov eax, 0x0083 + mov esi, edx + inc edx + shl esi, 21 + add eax, esi + stosd + xor eax, eax + stosd + cmp edx, 512 + jne build ret From 8d84a580b515f03491c16dd1363c1eb7a406441c Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 2 Dec 2012 11:27:10 -0500 Subject: [PATCH 03/20] fix permission issue --- tools_linux/setup.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tools_linux/setup.sh diff --git a/tools_linux/setup.sh b/tools_linux/setup.sh old mode 100644 new mode 100755 From d6ac228609d737ed67ead76d9ec0eb53cec46245 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 2 Dec 2012 12:26:29 -0500 Subject: [PATCH 04/20] align segments to page and map start and end of kernel --- kernel/linker.ld | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/kernel/linker.ld b/kernel/linker.ld index 56f972b..cf99ac5 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -4,21 +4,27 @@ SECTIONS { g_localApicAddr = 0x00006000; g_activeCpuCount = 0x00006008; + + . = 0x0000000000100000; + + __begin_kernel = .; - .text 0x0000000000100000: + .text : { *(.text) } - .data : + .data ALIGN (0x1000) : { *(.data) } - .bss : + .bss ALIGN (0x1000) : { __bss_start = .; *(.bss) __bss_end = .; } + + __end_kernel = .; } From 81beb72875e556d50f507267b8ca76fb49e23106 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 2 Dec 2012 12:28:36 -0500 Subject: [PATCH 05/20] add physmem code to manage physical pages allocation --- kernel/kernel.c | 3 ++ kernel/module.mk | 1 + mem/physmem.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++ mem/physmem.h | 24 +++++++++ mem/vm.c | 10 +--- mem/vm.h | 21 ++++++++ stdlib/types.h | 2 + 7 files changed, 186 insertions(+), 9 deletions(-) create mode 100644 mem/physmem.c create mode 100644 mem/physmem.h diff --git a/kernel/kernel.c b/kernel/kernel.c index 961721a..d57347c 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -8,6 +8,7 @@ #include "gfx/gfx.h" #include "gfx/vga.h" #include "intr/intr.h" +#include "mem/physmem.h" #include "mem/vm.h" #include "net/net.h" #include "pci/pci.h" @@ -27,7 +28,9 @@ int kmain() ConsoleInit(); ConsolePrint("Welcome!\n"); + PhysmemInit(); VMInit(); + AcpiInit(); IntrInit(); PciInit(); diff --git a/kernel/module.mk b/kernel/module.mk index 29dd583..9bceddc 100644 --- a/kernel/module.mk +++ b/kernel/module.mk @@ -24,6 +24,7 @@ KERNEL_SOURCES := \ intr/pic.c \ mem/mem_dump.c \ mem/vm.c \ + mem/physmem.c \ net/addr.c \ net/arp.c \ net/buf.c \ diff --git a/mem/physmem.c b/mem/physmem.c new file mode 100644 index 0000000..5141169 --- /dev/null +++ b/mem/physmem.c @@ -0,0 +1,134 @@ +// ------------------------------------------------------------------------------------------------ +// mem/physmem.c +// ------------------------------------------------------------------------------------------------ + +#include "stdlib/types.h" +#include "stdlib/string.h" +#include "mem/lowmem.h" +#include "mem/physmem.h" + +// ------------------------------------------------------------------------------------------------ + +extern char __end_kernel; + +paddr_t kernel_start, kernel_end; +paddr_t memory_end; + +#define PAGE_ARRAY_ADDR PAGE_ALIGN_SUP((u64) (&__end_kernel)) + +#define PHYS_LOWMEM 0x100000 +#define PHYS_HIGHMEM 0x100000000 + +typedef struct mem_desc { + u64 freepages; + u64 totalpages; + paddr_t *page; +} __attribute__((packed)) mem_desc; + +static mem_desc low_physmem; +static mem_desc physmem; +static mem_desc high_physmem; + +paddr_t PhysmemAlloc() +{ + paddr_t page; + + if (physmem.freepages == 0) + return 0; + + page = *physmem.page; + physmem.page++; + physmem.freepages--; + + return page; +} + +void PhysmemFree(paddr_t page) +{ + if (!IS_PAGE_ALIGNED(page)) + return; // probably should ASSERT or something.. + + physmem.page++; + *physmem.page = page; + physmem.freepages++; + +} + +void PhysmemInit() +{ + struct MemoryRegion *mmap; + u64 numpages; + paddr_t mem; + + memset(&low_physmem, 0, sizeof(mem_desc)); + memset(&physmem, 0, sizeof(mem_desc)); + memset(&high_physmem, 0, sizeof(mem_desc)); + + numpages = 0; + + // first pass, determine number of pages necessary + mmap = (struct MemoryRegion *)MEMORY_MAP; + while (mmap->type) + { + if (mmap->type == 1) + numpages += (mmap->size / PAGE_SIZE) + 1; + mmap++; + } + + memory_end = kernel_end = PAGE_ALIGN_SUP(&__end_kernel) + + (numpages * sizeof(paddr_t)); + + mmap = (MemoryRegion *) MEMORY_MAP; + + while (mmap->type) + { + + if (mmap->type == 1) + { + for (mem = (paddr_t) mmap->start; mem < mmap->start + mmap->size; + mem += PAGE_SIZE) + { + if (mem < PHYS_LOWMEM) + { + if (low_physmem.page == NULL) + low_physmem.page = (paddr_t *) PAGE_ALIGN_SUP(&__end_kernel); + + low_physmem.freepages++; + low_physmem.totalpages++; + *low_physmem.page++ = mem; + + } + else if (mem >= PHYS_LOWMEM && mem < PHYS_HIGHMEM) + { + + if (physmem.page == NULL) + physmem.page = (paddr_t *) low_physmem.page; + + if (mem > kernel_end) + { + physmem.freepages++; + physmem.totalpages++; + *physmem.page++ = mem; + } + + } + else if (mem >= PHYS_HIGHMEM) + { + if (high_physmem.page == NULL) + high_physmem.page = (paddr_t *) physmem.page; + + high_physmem.freepages++; + high_physmem.totalpages++; + *high_physmem.page++ = mem; + } + } + } + + mmap++; + } + + high_physmem.page = physmem.page; + physmem.page = low_physmem.page; + low_physmem.page = (paddr_t *) PAGE_ALIGN_SUP(&__end_kernel); + +} diff --git a/mem/physmem.h b/mem/physmem.h new file mode 100644 index 0000000..690c69c --- /dev/null +++ b/mem/physmem.h @@ -0,0 +1,24 @@ +// ------------------------------------------------------------------------------------------------ +// mem/physmem.h +// ------------------------------------------------------------------------------------------------ + +#pragma once + +#include "stdlib/types.h" +#include "vm.h" + +// ------------------------------------------------------------------------------------------------ + +typedef struct MemoryRegion +{ + u64 start; + u64 size; + u32 type; + u32 acpi_3_0; +} MemoryRegion; + +typedef u64 paddr_t; + +void PhysmemInit(); +paddr_t PhysmemAlloc(); +void PhysmemFree(paddr_t page); diff --git a/mem/vm.c b/mem/vm.c index 1045fde..70cc396 100644 --- a/mem/vm.c +++ b/mem/vm.c @@ -3,6 +3,7 @@ // ------------------------------------------------------------------------------------------------ #include "mem/vm.h" +#include "mem/physmem.h" #include "mem/lowmem.h" #include "console/console.h" @@ -17,15 +18,6 @@ static uintptr_t s_nextAlloc; -// ------------------------------------------------------------------------------------------------ -typedef struct MemoryRegion -{ - u64 start; - u64 size; - u32 type; - u32 acpi_3_0; -} MemoryRegion; - // ------------------------------------------------------------------------------------------------ static void DumpMemoryMap() { diff --git a/mem/vm.h b/mem/vm.h index c1eea3f..be303b6 100644 --- a/mem/vm.h +++ b/mem/vm.h @@ -6,6 +6,27 @@ #include "stdlib/types.h" +#define PAGE_SIZE (0x1000) +#define PAGE_LARGE_SIZE (0x200000) + +#define ALIGN_INF(val,boundary) \ + (((unsigned long long)(val)) & (~((boundary)-1))) + +#define ALIGN_SUP(val,boundary) \ + ({ unsigned long long __bnd=(boundary); \ + (((((unsigned long long)(val))-1) & (~(__bnd - 1))) + __bnd); }) + +#define IS_ALIGNED(val,boundary) \ + ( 0 == (((unsigned long long)(val)) & ((boundary)-1)) ) + +#define PAGE_SHIFT 12 +#define PAGE_MASK ((1< Date: Mon, 3 Dec 2012 20:30:10 -0500 Subject: [PATCH 06/20] add proper virtual memory support still needs tons of work the acpi/apic code is rather ugly right now needs cleanup but works fine. --- acpi/acpi.c | 15 +++ boot/defines.asm | 1 + boot/loader.asm | 2 +- cpu/smp.c | 4 +- intr/idt.c | 6 +- intr/ioapic.c | 2 + intr/local_apic.c | 2 + mem/physmem.c | 11 +- mem/physmem.h | 1 - mem/vm.c | 325 ++++++++++++++++++++++++++++++++++------------ mem/vm.h | 135 ++++++++++++++++++- net/intel.c | 4 + 12 files changed, 412 insertions(+), 96 deletions(-) diff --git a/acpi/acpi.c b/acpi/acpi.c index 1e3147e..d349f67 100644 --- a/acpi/acpi.c +++ b/acpi/acpi.c @@ -6,6 +6,8 @@ #include "console/console.h" #include "intr/ioapic.h" #include "intr/local_apic.h" +#include "mem/physmem.h" +#include "mem/vm.h" #include "stdlib/string.h" // ------------------------------------------------------------------------------------------------ @@ -116,6 +118,10 @@ static void AcpiParseApic(AcpiMadt *madt) s_madt = madt; ConsolePrint("Local APIC Address = 0x%08x\n", madt->localApicAddr); + + page_map((paddr_t)madt->localApicAddr, (paddr_t)madt->localApicAddr); + page_map((paddr_t)&g_localApicAddr, (paddr_t)&g_localApicAddr); + g_localApicAddr = (u8 *)(uintptr_t)madt->localApicAddr; u8 *p = (u8 *)(madt + 1); @@ -127,6 +133,8 @@ static void AcpiParseApic(AcpiMadt *madt) u8 type = header->type; u8 length = header->length; + page_map((paddr_t)p, (paddr_t)p); + if (type == APIC_TYPE_LOCAL_APIC) { ApicLocalApic *s = (ApicLocalApic *)p; @@ -172,10 +180,12 @@ static void AcpiParseDT(AcpiHeader *header) if (signature == 0x50434146) { + page_map((paddr_t)header, (paddr_t)header); AcpiParseFacp((AcpiFadt *)header); } else if (signature == 0x43495041) { + page_map((paddr_t)header, (paddr_t)header); AcpiParseApic((AcpiMadt *)header); } } @@ -189,6 +199,7 @@ static void AcpiParseRsdt(AcpiHeader *rsdt) while (p < end) { u32 address = *p++; + page_map((paddr_t)address, (paddr_t)address); AcpiParseDT((AcpiHeader *)(uintptr_t)address); } } @@ -202,6 +213,7 @@ static void AcpiParseXsdt(AcpiHeader *xsdt) while (p < end) { u64 address = *p++; + page_map((paddr_t)address, (paddr_t)address); AcpiParseDT((AcpiHeader *)(uintptr_t)address); } } @@ -238,6 +250,7 @@ static bool AcpiParseRsdp(u8 *p) ConsolePrint("Version 1\n"); u32 rsdtAddr = *(u32 *)(p + 16); + page_map((paddr_t)rsdtAddr, (paddr_t)rsdtAddr); AcpiParseRsdt((AcpiHeader *)(uintptr_t)rsdtAddr); } else if (revision == 2) @@ -249,10 +262,12 @@ static bool AcpiParseRsdp(u8 *p) if (xsdtAddr) { + page_map((paddr_t)rsdtAddr, (paddr_t)xsdtAddr); AcpiParseXsdt((AcpiHeader *)(uintptr_t)xsdtAddr); } else { + page_map((paddr_t)rsdtAddr, (paddr_t)rsdtAddr); AcpiParseRsdt((AcpiHeader *)(uintptr_t)rsdtAddr); } } diff --git a/boot/defines.asm b/boot/defines.asm index e8bffd1..599ee99 100644 --- a/boot/defines.asm +++ b/boot/defines.asm @@ -10,6 +10,7 @@ %define memory_map 0x5000 %define local_apic_address 0x6000 %define active_cpu_count 0x6008 +%define new_vm_pml4 0x6010 %define boot_sector_base 0x7c00 %define temp_sector 0x7e00 %define loader_base 0x8000 diff --git a/boot/loader.asm b/boot/loader.asm index 0292032..9aae52e 100644 --- a/boot/loader.asm +++ b/boot/loader.asm @@ -434,7 +434,7 @@ ap32: mov eax, 0x000000a0 ; Set PAE and PGE mov cr4, eax - mov eax, vm_pml4 ; Assign PML4 + mov eax, [new_vm_pml4] ; Assign PML4 mov cr3, eax mov ecx, 0xc0000080 ; Read from EFER MSR diff --git a/cpu/smp.c b/cpu/smp.c index ca83786..f366499 100644 --- a/cpu/smp.c +++ b/cpu/smp.c @@ -4,6 +4,7 @@ #include "cpu/smp.h" #include "acpi/acpi.h" +#include "mem/vm.h" #include "console/console.h" #include "intr/local_apic.h" #include "time/pit.h" @@ -39,11 +40,12 @@ void SmpInit() } } + page_map((paddr_t)g_activeCpuCount, (paddr_t)g_activeCpuCount); + // Wait for all cpus to be active PitWait(1); while (g_activeCpuCount != g_acpiCpuCount) { - ConsolePrint("Waiting... %d\n", g_activeCpuCount); PitWait(1); } diff --git a/intr/idt.c b/intr/idt.c index e3e7a77..f44891a 100644 --- a/intr/idt.c +++ b/intr/idt.c @@ -4,6 +4,7 @@ #include "intr/idt.h" #include "mem/lowmem.h" +#include "mem/vm.h" // ------------------------------------------------------------------------------------------------ typedef struct IdtDesc @@ -31,6 +32,8 @@ extern void (*exception_handlers[20])(); // ------------------------------------------------------------------------------------------------ void IdtInit() { + page_map((paddr_t)IDT_BASE, (paddr_t)IDT_BASE); + // Build initial IDT for (uint i = 0; i < 20; ++i) { @@ -53,9 +56,6 @@ void IdtInit() .base = IDT_BASE }; __asm__ volatile("lidt %0" : : "m" (idtDesc) : "memory"); - - // Test interrupt - // __asm__ volatile("int $3"); } // ------------------------------------------------------------------------------------------------ diff --git a/intr/ioapic.c b/intr/ioapic.c index 0fd5529..27bea76 100644 --- a/intr/ioapic.c +++ b/intr/ioapic.c @@ -5,6 +5,7 @@ #include "intr/ioapic.h" #include "console/console.h" #include "cpu/io.h" +#include "mem/vm.h" // ------------------------------------------------------------------------------------------------ // Globals @@ -47,6 +48,7 @@ void IoApicSetEntry(u8 *base, u8 index, u64 data) void IoApicInit() { // Get number of entries supported by the IO APIC + page_map((paddr_t)g_ioApicAddr, (paddr_t)g_ioApicAddr); u32 x = IoApicIn(g_ioApicAddr, IOAPICVER); uint count = ((x >> 16) & 0xff) + 1; // maximum redirection entry diff --git a/intr/local_apic.c b/intr/local_apic.c index 5b9e34b..2a9dc0d 100644 --- a/intr/local_apic.c +++ b/intr/local_apic.c @@ -6,6 +6,7 @@ #include "intr/idt.h" #include "acpi/acpi.h" #include "console/console.h" +#include "mem/vm.h" #include "cpu/io.h" // ------------------------------------------------------------------------------------------------ @@ -87,6 +88,7 @@ static void LocalApicOut(uint reg, u32 data) // ------------------------------------------------------------------------------------------------ void LocalApicInit() { + page_map((paddr_t)g_localApicAddr, (paddr_t)g_localApicAddr); // Clear task priority to enable all interrupts LocalApicOut(LAPIC_TPR, 0); diff --git a/mem/physmem.c b/mem/physmem.c index 5141169..2082e33 100644 --- a/mem/physmem.c +++ b/mem/physmem.c @@ -6,15 +6,12 @@ #include "stdlib/string.h" #include "mem/lowmem.h" #include "mem/physmem.h" +#include "mem/vm.h" // ------------------------------------------------------------------------------------------------ extern char __end_kernel; - -paddr_t kernel_start, kernel_end; -paddr_t memory_end; - -#define PAGE_ARRAY_ADDR PAGE_ALIGN_SUP((u64) (&__end_kernel)) +paddr_t physmap_end; #define PHYS_LOWMEM 0x100000 #define PHYS_HIGHMEM 0x100000000 @@ -75,7 +72,7 @@ void PhysmemInit() mmap++; } - memory_end = kernel_end = PAGE_ALIGN_SUP(&__end_kernel) + physmap_end = PAGE_ALIGN_SUP(&__end_kernel) + (numpages * sizeof(paddr_t)); mmap = (MemoryRegion *) MEMORY_MAP; @@ -104,7 +101,7 @@ void PhysmemInit() if (physmem.page == NULL) physmem.page = (paddr_t *) low_physmem.page; - if (mem > kernel_end) + if (mem > physmap_end) { physmem.freepages++; physmem.totalpages++; diff --git a/mem/physmem.h b/mem/physmem.h index 690c69c..d0d167a 100644 --- a/mem/physmem.h +++ b/mem/physmem.h @@ -5,7 +5,6 @@ #pragma once #include "stdlib/types.h" -#include "vm.h" // ------------------------------------------------------------------------------------------------ diff --git a/mem/vm.c b/mem/vm.c index 70cc396..a2e1d3b 100644 --- a/mem/vm.c +++ b/mem/vm.c @@ -5,6 +5,7 @@ #include "mem/vm.h" #include "mem/physmem.h" #include "mem/lowmem.h" +#include "stdlib/string.h" #include "console/console.h" // ------------------------------------------------------------------------------------------------ @@ -16,7 +17,21 @@ #define PD_2MB 0x80 // 2MB Page -static uintptr_t s_nextAlloc; +static pml4_t *pml4; + +#define invlpg(vaddr) \ + do { \ + __asm__ __volatile__("invlpg %0"::"m"(*((unsigned long long*)(vaddr)))); \ + } while(0) + + + +#define flush_tlb() \ + do { \ + u64 tmpreg; \ + asm volatile("movq %%cr3,%0\n\tmovq %0,%%cr3" :"=r" \ + (tmpreg) : :"memory"); \ + } while (0) // ------------------------------------------------------------------------------------------------ static void DumpMemoryMap() @@ -33,115 +48,263 @@ static void DumpMemoryMap() } } -// ------------------------------------------------------------------------------------------------ -static void VMEnablePD(u64 pdOffset, u64 base, uint flags) +/* + * Get the physical address of any given virtual address. + */ +static paddr_t paging_get_paddr(vaddr_t vaddr) { - u64 *pd = (u64 *)pdOffset; - for (uint i = 0; i < 512; ++i) - { - pd[i] = base | PD_2MB | flags; - base += 0x200000; - } + pml4_t *pml4 = (pml4_t *)pml4_virt(vaddr); + pdp_t *pdp = (pdp_t *)pdp_virt(vaddr); + pd_t *pd = (pd_t *)pd_virt(vaddr); + pt_t *pt = (pt_t *)pt_virt(vaddr); + + unsigned int index_pml4 = virt_to_pml4_index(vaddr); + unsigned int index_pdp = virt_to_pdp_index(vaddr); + unsigned int index_pd = virt_to_pd_index(vaddr); + unsigned int index_pt = virt_to_pt_index(vaddr); + + unsigned offset_in_page = (((unsigned)(vaddr)) & PAGE_MASK); + + if (!pml4[index_pml4].present) + return (paddr_t)NULL; + + if (!pdp[index_pdp].present) + return (paddr_t)NULL; + + if (!pd[index_pd].present) + return (paddr_t)NULL; + + return (paddr_t)((page_getaddr(pt[index_pt])) + offset_in_page); } -// ------------------------------------------------------------------------------------------------ -static void VMEnablePDP(uint pdpIndex, u64 pdOffset, u64 base, uint flags) +/* + * unmap any virtual address + */ +int page_unmap(vaddr_t vaddr) { - VMEnablePD(pdOffset, base, flags); - u64 *pdp = (u64 *)VM_PDP; - pdp[pdpIndex] = pdOffset | flags; + pml4_t *pml4 = (pml4_t *)pml4_virt(vaddr); + pdp_t *pdp = (pdp_t *)pdp_virt(vaddr); + pd_t *pd = (pd_t *)pd_virt(vaddr); + pt_t *pt = (pt_t *)pt_virt(vaddr); + + unsigned int index_pml4 = virt_to_pml4_index(vaddr); + unsigned int index_pdp = virt_to_pdp_index(vaddr); + unsigned int index_pd = virt_to_pd_index(vaddr); + unsigned int index_pt = virt_to_pt_index(vaddr); + + if (!pml4[index_pml4].present) + return -1; + + if (!pdp[index_pdp].present) + return -1; + + if (!pd[index_pd].present) + return -1; + + if (!pd[index_pd].present) + return -1; + + if (!pt[index_pt].present) + return -1; + + pt[index_pt].present = 0; + + return 0; } -// ------------------------------------------------------------------------------------------------ -static void VMUpdatePage(uintptr_t addr, uint flags) +/* + * Map a physical address to a virtual address + */ +int page_map(paddr_t paddr, vaddr_t vaddr) { - // Break address into table indices - uint pdpIndex = (addr >> 30) & 0x1ff; - uint pdIndex = (addr >> 21) & 0x1ff; - uint ptIndex = (addr >> 12) & 0x1ff; - - u64 *pdpBase = (u64 *)VM_PDP; - u64 pdp = pdpBase[pdpIndex]; - u64 *pdBase = (u64 *)(pdp & ~0xfff); - u64 pd = pdBase[pdIndex]; - - u64 *ptBase = (u64 *)(pd & ~0xfff); - if (pd & PD_2MB) + pml4_t *pml4 = (pml4_t *)pml4_virt(vaddr); + pdp_t *pdp = (pdp_t *)pdp_virt(vaddr); + pd_t *pd = (pd_t *)pd_virt(vaddr); + pt_t *pt = (pt_t *)pt_virt(vaddr); + + paddr_t page; + + unsigned int index_pml4 = virt_to_pml4_index(vaddr); + unsigned int index_pdp = virt_to_pdp_index(vaddr); + unsigned int index_pd = virt_to_pd_index(vaddr); + unsigned int index_pt = virt_to_pt_index(vaddr); + + if (!pml4[index_pml4].present) { - // Switch to page table - u64 oldBase = (u64)ptBase; - uint oldFlags = pd & 0x1f; + page = PhysmemAlloc(); - ptBase = VMAlloc(4096); + pml4[index_pml4].present = 1; + pml4[index_pml4].write = 1; + page_setaddr(pml4[index_pml4], page); + invlpg(pdp); - for (uint i = 0; i < 512; ++i) - { - ptBase[i] = oldBase | oldFlags; - oldBase += 0x1000; - } + memset((void*)pdp, 0x0, PAGE_SIZE); + } + + if (!pdp[index_pdp].present) + { + page = PhysmemAlloc(); - pd = (uintptr_t)ptBase | PAGE_PRESENT | PAGE_WRITE | PAGE_USER; - pdBase[pdIndex] = pd; + pdp[index_pdp].present = 1; + pdp[index_pdp].write = 1; + page_setaddr(pdp[index_pdp], page); + invlpg(pd); + + memset((void*)pd, 0x0, PAGE_SIZE); } - // Update entry - ptBase[ptIndex] = addr | flags; -} + if (!pd[index_pd].present) + { + page = PhysmemAlloc(); -// ------------------------------------------------------------------------------------------------ -void VMInit() -{ - // Enable 4GB of memory access - uint flags = PAGE_PRESENT | PAGE_WRITE | PAGE_USER; - VMEnablePDP(0, VM_PD + 0x0000, 0x00000000, flags); - VMEnablePDP(1, VM_PD + 0x1000, 0x40000000, flags); - VMEnablePDP(2, VM_PD + 0x2000, 0x80000000, flags); - VMEnablePDP(3, VM_PD + 0x3000, 0xc0000000, flags | PAGE_CACHE_DISABLE); // TODO - call VMMapPages + pd[index_pd].present = 1; + pd[index_pd].write = 1; + page_setaddr(pd[index_pd], page); + invlpg(pt); + + memset((void*)pt, 0x0, PAGE_SIZE); + } - DumpMemoryMap(); + pt[index_pt].present = 1; + pt[index_pt].write = 1; + //pt[index_pt].cache = 1; + page_setaddr(pt[index_pt], paddr); - s_nextAlloc = 0x00200000; -} + invlpg(vaddr); -// ------------------------------------------------------------------------------------------------ -void *VMAlloc(uint size) -{ - // Align to 4k for now - return VMAllocAlign(size, 4096); + return 0; } -// ------------------------------------------------------------------------------------------------ -void *VMAllocAlign(uint size, uint align) +/* + * Initial paging only called during startup + */ +static int PagingInitialMap(pml4_t *pml4, paddr_t paddr, vaddr_t vaddr) { - // Align memory request - uintptr_t offset = s_nextAlloc & (align - 1); - if (offset) + unsigned int index_pml4 = virt_to_pml4_index(vaddr); + unsigned int index_pdp = virt_to_pdp_index(vaddr); + unsigned int index_pd = virt_to_pd_index(vaddr); + unsigned int index_pt = virt_to_pt_index(vaddr); + + pdp_t *pdp; + pd_t *pd; + pt_t *pt; + + if (!pml4[index_pml4].present) + { + pdp = (pdp_t *)PhysmemAlloc(); + memset((void*)pdp, 0x0, PAGE_SIZE); + + page_setaddr(pml4[index_pml4], pdp); + pml4[index_pml4].present = 1; + pml4[index_pml4].write = 1; + + } else { - s_nextAlloc += align - offset; + pdp = (pdp_t *)page_getaddr(pml4[index_pml4]); } - void *result = (void *)s_nextAlloc; - s_nextAlloc += size; - return result; + if (!pdp[index_pdp].present) + { + pd = (pd_t *)PhysmemAlloc(); + memset((void*)pd, 0x0, PAGE_SIZE); + + page_setaddr(pdp[index_pdp], pd); + pdp[index_pdp].present = 1; + pdp[index_pdp].write = 1; + + } else + { + pd = (pd_t *)page_getaddr(pdp[index_pdp]); + } + + if (!pd[index_pd].present) + { + pt = (pt_t *)PhysmemAlloc(); + memset((void*)pt, 0x0, PAGE_SIZE); + + page_setaddr(pd[index_pd], pt); + pd[index_pd].present = 1; + pd[index_pd].write = 1; + + } else + { + pt = (pt_t *)page_getaddr(pd[index_pd]); + } + + pt[index_pt].write = 1; + pt[index_pt].present = 1; + page_setaddr(pt[index_pt], paddr); + + return 0; } -// ------------------------------------------------------------------------------------------------ -void VMMapPages(void *addr, uint size, uint flags) +void VMInit() { - flags |= PAGE_PRESENT | PAGE_WRITE | PAGE_USER; + paddr_t paddr; + extern char __begin_kernel; + paddr_t *new_vm_pml4; + extern paddr_t physmap_end; - u8 *page = (u8 *)addr; - u8 *end = page + size; + new_vm_pml4 = (paddr_t *)0x6010; - while (page < end) + pml4 = (pml4_t *)PhysmemAlloc(); + *new_vm_pml4 = (paddr_t)pml4; + + memset((void*)pml4, 0x0, PAGE_SIZE); + + for (paddr = (paddr_t)&__begin_kernel; paddr < physmap_end; paddr += PAGE_SIZE) + { + PagingInitialMap(pml4, paddr, paddr); + } + + // this maps the GDT/loader base. + PagingInitialMap(pml4, 0x8000, 0x8000); + + // TODO: fix temporary stack map + for (paddr = 0x19000; paddr <= 0x20000; paddr += PAGE_SIZE) { - VMUpdatePage((uintptr_t)page & ~0xfff, flags); - page += 4096; + PagingInitialMap(pml4, paddr, paddr); } - // Flush TLBs - unsigned long val; - __asm__ volatile( - "mov %%cr3, %0\n\t" - "mov %0,%%cr3" : "=r" (val)); + // map bios area + for (paddr = 0xb8000; paddr < 0x100000; paddr += PAGE_SIZE) + { + PagingInitialMap(pml4, paddr, paddr); + } + + // Begin page table inception mind fuck + pml4[virt_to_pml4_index(PAGING_MIRROR_VADDR)].write = 1; + pml4[virt_to_pml4_index(PAGING_MIRROR_VADDR)].present = 1; + pml4[virt_to_pml4_index(PAGING_MIRROR_VADDR)].user = 0; + page_setaddr(pml4[virt_to_pml4_index(PAGING_MIRROR_VADDR)], pml4); + + __asm__ volatile ("movq %0,%%cr3\n\t" + "jmp 1f\n\t" + "1:\n\t" + "movq $2f, %%rax\n\t" + "jmp *%%rax\n\t" + "2:\n\t" ::"r"(pml4):"memory","rax"); + +} + +/* + * Grab a physical page, identity map it and return it + */ +void *VMIdentidyAlloc() +{ + paddr_t paddr = PhysmemAlloc(); + page_map((paddr_t)paddr, (vaddr_t)paddr); + + return (void *)paddr; +} + +/* + * Grab a physical page, identity map it and return it + */ +void *VMAlloc(uint size) +{ + paddr_t paddr = PhysmemAlloc(); + page_map((paddr_t)paddr, (vaddr_t)paddr); + + return (void *)paddr; } diff --git a/mem/vm.h b/mem/vm.h index be303b6..24f8eb8 100644 --- a/mem/vm.h +++ b/mem/vm.h @@ -5,6 +5,7 @@ #pragma once #include "stdlib/types.h" +#include "mem/physmem.h" #define PAGE_SIZE (0x1000) #define PAGE_LARGE_SIZE (0x200000) @@ -26,6 +27,135 @@ #define PAGE_ALIGN_SUP(val) ALIGN_SUP((val), PAGE_SIZE) #define IS_PAGE_ALIGNED(val) IS_ALIGNED((val), PAGE_SIZE) +typedef u64 vaddr_t; + +typedef struct pml4_t { + u8 present:1; + u8 write:1; + u8 user:1; + u8 writethrough:1; + u8 cache:1; + u8 accessed:1; + u8 reserved1:2; + + u8 reserved2:1; + u8 avail1:3; + u8 baseaddr_low:4; + u16 baseaddr_mid; + + u8 baseaddr_high; + u16 reserved3:11; + u16 avail2:5; + u8 avail3:7; + u8 exb:1; +} __attribute__ ((packed)) pml4_t; + +typedef struct pdp_t { + u8 present:1; + u8 write:1; + u8 user:1; + u8 writethrough:1; + u8 cache:1; + u8 accessed:1; + u8 reserved1:2; + + u8 reserved2:1; + u8 avail1:3; + u8 baseaddr_low:4; + u16 baseaddr_mid; + + u8 baseaddr_high; + u16 reserved3:11; + u16 avail2:5; + u8 avail3:7; + u8 exb:1; +} __attribute__ ((packed)) pdp_t; + +typedef struct pd_t { + u8 present:1; + u8 write:1; + u8 user:1; + u8 writethrough:1; + u8 cache:1; + u8 accessed:1; + u8 dirty:1; + u8 pat:1; + + u8 global:1; + u8 avail1:3; + u8 baseaddr_low:4; + u16 baseaddr_mid; + + u8 baseaddr_high; + u16 reserved3:11; + u16 avail2:5; + u8 avail3:7; + u8 exb:1; +} __attribute__ ((packed)) pd_t; + +typedef struct pt_t { + u8 present:1; + u8 write:1; + u8 user:1; + u8 writethrough:1; + u8 cache:1; + u8 accessed:1; + u8 dirty:1; + u8 pat:1; + + u8 global:1; + u8 avail1:3; + u8 baseaddr_low:4; + u16 baseaddr_mid; + + u8 baseaddr_high; + u16 reserved3:11; + u16 avail2:5; + u8 avail3:7; + u8 exb:1; +} __attribute__ ((packed)) pt_t; + + +#define page_setaddr(page, addr) \ + do { \ + (page).baseaddr_low = (((paddr_t)addr) >> 12) & 0xF; \ + (page).baseaddr_mid = (((paddr_t)addr) >> 16) & 0xFFFF; \ + (page).baseaddr_high = (((paddr_t)addr) >> 32) & 0xFF; \ + } while (0) + +#define page_getaddr(entry) \ + ((pd_t *)((((unsigned long long)((entry).baseaddr_low)) << 12) \ + + (((unsigned long long)((entry).baseaddr_mid)) << 16) \ + + (((unsigned long long)((entry).baseaddr_high)) << 32))) \ + +#define virt_to_pml4_index(vaddr) \ + ( (((unsigned long long)(vaddr)) >> 39) & 0x1ff ) + +#define virt_to_pdp_index(vaddr) \ + ( (((unsigned long long)(vaddr)) >> 30) & 0x1ff ) + +#define virt_to_pd_index(vaddr) \ + ( (((unsigned long long)(vaddr)) >> 21) & 0x1ff ) + +#define virt_to_pt_index(vaddr) \ + ( (((unsigned long long)(vaddr)) >> 12) & 0x1ff ) + +#define VIRT_MAX_MEM 0xFFFFFFFFFFFF +#define PAGING_MIRROR_VADDR 0x008000000000 + +#define VIRT_PT_BASE PAGING_MIRROR_VADDR +#define VIRT_PD_BASE (VIRT_PT_BASE + 0x40000000) +#define VIRT_PDP_BASE (VIRT_PD_BASE + 0x200000) +#define VIRT_PML4_BASE (VIRT_PDP_BASE + 0x1000) + +#define pml4_virt(vaddr) \ + ( PAGE_ALIGN_INF((((unsigned long long)(vaddr)) >> 36) + VIRT_PML4_BASE )) +#define pdp_virt(vaddr) \ + ( PAGE_ALIGN_INF((((unsigned long long)(vaddr)) >> 27) + VIRT_PDP_BASE )) +#define pd_virt(vaddr) \ + ( PAGE_ALIGN_INF((((unsigned long long)(vaddr)) >> 18) + VIRT_PD_BASE )) +#define pt_virt(vaddr) \ + ( PAGE_ALIGN_INF((((unsigned long long)(vaddr)) >> 9) + VIRT_PT_BASE )) // ------------------------------------------------------------------------------------------------ // Page Flags @@ -35,8 +165,9 @@ // ------------------------------------------------------------------------------------------------ void VMInit(); +void *PageIdentidyAlloc(); void *VMAlloc(uint size); -void *VMAllocAlign(uint size, uint align); -void VMMapPages(void *addr, uint size, uint flags); +int page_map(paddr_t paddr, vaddr_t vaddr); +int page_unmap(vaddr_t vaddr); diff --git a/net/intel.c b/net/intel.c index 8a5e407..c149fb8 100644 --- a/net/intel.c +++ b/net/intel.c @@ -12,6 +12,7 @@ #include "pci/driver.h" #include "stdlib/string.h" #include "time/pit.h" +#include "mem/vm.h" #define RX_DESC_COUNT 32 #define TX_DESC_COUNT 8 @@ -276,6 +277,9 @@ void EthIntelInit(uint id, PciDeviceInfo *info) u8 *mmioAddr = (u8 *)bar.u.address; s_device.mmioAddr = mmioAddr; + for (paddr_t page = (uint)bar.u.address;page < (uint)bar.u.address + bar.size;page += PAGE_SIZE) + page_map(PAGE_ALIGN_INF(page), PAGE_ALIGN_INF(page)); + // IRQ //u8 irq = PciRead8(id, PCI_CONFIG_INTERRUPT_LINE); From 7e7ecd2832307393db0644e8ebfe9d229d81307d Mon Sep 17 00:00:00 2001 From: Gabriel Date: Wed, 5 Dec 2012 19:26:01 -0500 Subject: [PATCH 07/20] pretty up makes, take it or leave it --- Makefile | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 9a99777..b246b58 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,9 @@ else endif # Standard Settings -CC := gcc +Q := @ +CC := $(Q)gcc +NASM := $(Q)nasm COMMON_CFLAGS := -I . -std=c99 COMMON_CFLAGS += -Wall -Werror-implicit-function-declaration -Wno-array-bounds COMMON_CFLAGS += -fno-common -fno-asynchronous-unwind-tables @@ -27,9 +29,9 @@ COMMON_CFLAGS += -O2 FREESTANDING_CFLAGS := -fno-builtin # Cross Compiler -CROSS_CC := x86_64-elf-gcc +CROSS_CC := $(Q)x86_64-elf-gcc CROSS_CFLAGS := -DCROSS $(FREESTANDING_CFLAGS) $(COMMON_CFLAGS) -CROSS_LD := x86_64-elf-ld +CROSS_LD := $(Q)x86_64-elf-ld # Host Compiler without standard library HOST_CFLAGS := -DHOST $(FREESTANDING_CFLAGS) $(COMMON_CFLAGS) @@ -41,21 +43,31 @@ TEST_CFLAGS := -DTEST $(FREESTANDING_CFLAGS) $(COMMON_CFLAGS) NATIVE_CFLAGS := -DNATIVE $(COMMON_CFLAGS) %.bin: %.asm - nasm -f bin -o $@ $< + @echo 'NASM $< -> $@' + $(NASM) -f bin -o $@ $< -%.cross.o: %.asm - nasm -f elf64 -o $@ $< +%.o: %.asm + @echo 'NASM $< -> $@' + $(NASM) -f elf64 -o $@ $< -%.cross.o: %.c +%.o: %.S + @echo 'GAS $< -> $@' + $(CROSS_CC) -c $(CROSS_CFLAGS) -DASM=1 -o $@ $< + +%.o: %.c + @echo 'CC $< -> $@' $(CROSS_CC) -c -MD $(CROSS_CFLAGS) $< -o $@ -%.host.o: %.c +%.o: %.c + @echo 'CC $< -> $@' $(CC) -c -MD $(HOST_CFLAGS) $< -o $@ %.test.o: %.c + @echo 'CC $< -> $@' $(CC) -c -MD $(TEST_CFLAGS) $< -o $@ %.native.o: %.c + @echo 'CC $< -> $@' $(CC) -c -MMD $(NATIVE_CFLAGS) $< -o $@ %.exe.run: %.exe @@ -91,7 +103,7 @@ clean: rm -f */*.bin */*.exe */*.exe.run */*.o */*.d rm -f os.img --include $(SOURCES:.c=.host.d) --include $(SOURCES:.c=.cross.d) --include $(SOURCES:.c=.test.d) --include $(SOURCES:.c=.native.d) +#-include $(SOURCES:.c=.host.d) +#-include $(SOURCES:.c=.cross.d) +#-include $(SOURCES:.c=.test.d) +#-include $(SOURCES:.c=.native.d) From 897b424bfe9471e1b1010c36592cbf0eadb1d9fe Mon Sep 17 00:00:00 2001 From: Gabriel Date: Wed, 5 Dec 2012 19:28:47 -0500 Subject: [PATCH 08/20] slightly better exception handler. Not using nasm but rather gcc --- intr/except.c | 96 +++++++++++++++----------- intr/except.h | 73 ++++++++++++++++++-- intr/exception.S | 167 +++++++++++++++++++++++++++++++++++++++++++++ intr/idt.c | 16 ++--- intr/interrupt.asm | 78 --------------------- kernel/module.mk | 5 +- stdlib/types.h | 2 - 7 files changed, 301 insertions(+), 136 deletions(-) create mode 100644 intr/exception.S diff --git a/intr/except.c b/intr/except.c index 1b2e990..c147411 100644 --- a/intr/except.c +++ b/intr/except.c @@ -6,50 +6,68 @@ #include "console/console.h" // ------------------------------------------------------------------------------------------------ + static const char *s_exceptionDesc[20] = { - [0] = "Divide Error", - [1] = "Debug", - [2] = "Nonmaskable Interrupt", - [3] = "Breakpoint", - [4] = "Overflow", - [5] = "Bound Range Exceeded", - [6] = "Invalid Opcode", - [7] = "Device Not Available", - [8] = "Double Fault", - [9] = "Coprocessor Segment Overrun", - [10] = "Invalid TSS", - [11] = "Segment Not Present", - [12] = "Stack-Segment Fault", - [13] = "General Protection", - [14] = "Page Fault", - [16] = "Floating Point Error", - [17] = "Alignment Check", - [18] = "Machine Check", - [19] = "SIMD Exception" + [EXCEPT_DIVIDE_ERROR] = "Divide Error", + [EXCEPT_DEBUG] = "Debug", + [EXCEPT_NMI_INTERRUPT] = "Nonmaskable Interrupt", + [EXCEPT_BREAKPOINT] = "Breakpoint", + [EXCEPT_OVERFLOW] = "Overflow", + [EXCEPT_BOUND_RANGE_EXCEDEED] = "Bound Range Exceeded", + [EXCEPT_INVALID_OPCODE] = "Invalid Opcode", + [EXCEPT_DEVICE_NOT_AVAILABLE] = "Device Not Available", + [EXCEPT_DOUBLE_FAULT] = "Double Fault", + [EXCEPT_COPROCESSOR_SEGMENT_OVERRUN] = "Coprocessor Segment Overrun", + [EXCEPT_INVALID_TSS] = "Invalid TSS", + [EXCEPT_SEGMENT_NOT_PRESENT] = "Segment Not Present", + [EXCEPT_STACK_SEGMENT_FAULT] = "Stack-Segment Fault", + [EXCEPT_GENERAL_PROTECTION] = "General Protection", + [EXCEPT_PAGE_FAULT] = "Page Fault", + [EXCEPT_RESERVED_1] = "Reserved", + [EXCEPT_FLOATING_POINT_ERROR] = "Floating Point Error", + [EXCEPT_ALIGNEMENT_CHECK] = "Alignment Check", + [EXCEPT_MACHINE_CHECK] = "Machine Check", + [EXCEPT_SIMD] = "SIMD Exception" }; // ------------------------------------------------------------------------------------------------ -void ExceptionDump(Registers regs) +void cpu_dump(cpu_state *ctxt) +{ + + ConsolePrint("CS:0x%016llx RIP:0x%016llx\n", ctxt->cs, ctxt->rip); + ConsolePrint("RSP = 0x%016llx RBP = 0x%016llx\n", ctxt->rsp, ctxt->rbp); + ConsolePrint("Flags = 0x%016llx, Error = %llx\n", ctxt->rflags, ctxt->error); + ConsolePrint("Registers\n"); + ConsolePrint("RAX:0x%016llx RBX:0x%016llx\n", ctxt->rax, ctxt->rbx); + ConsolePrint("RCX:0x%016llx RDX:0x%016llx\n", ctxt->rcx, ctxt->rdx); + ConsolePrint("RSI:0x%016llx RDI:0x%016llx\n", ctxt->rsi, ctxt->rdi); + ConsolePrint("R8 :0x%016llx R9 :0x%016llx\n", ctxt->r8, ctxt->r9); + ConsolePrint("R10:0x%016llx R11:0x%016llx\n", ctxt->r10, ctxt->r11); + ConsolePrint("R12:0x%016llx R13:0x%016llx\n", ctxt->r12, ctxt->r13); + ConsolePrint("R14:0x%016llx R15:0x%016llx\n", ctxt->r14, ctxt->r15); + + for(;;) { __asm__("hlt"); } +} + +/* + * Entry point for CPU exceptions (from except_wrap.S) + */ +void exception_entry(u64 ex, cpu_state *ctxt) { - const char *desc = "Unknown"; - if (regs.intNum < 20) - { - desc = s_exceptionDesc[regs.intNum]; + u64 cr2; + + __asm__ volatile ("movq %%cr2, %0" + :"=r"(cr2) + : ); + + if (ex == EXCEPT_PAGE_FAULT) { + ConsolePrint("%s Exception @ 0x%llx\n", s_exceptionDesc[ex], cr2); + + } else { + ConsolePrint("%s Exception @ 0x%x\n", s_exceptionDesc[ex], cr2); } - // TODO - don't use console system, but write to screen directly. - ConsolePrint("Exception: %s\n", desc); - ConsolePrint(" rax=%016x\n", regs.rax); - ConsolePrint(" rbx=%016x\n", regs.rbx); - ConsolePrint(" rcx=%016x\n", regs.rcx); - ConsolePrint(" rdx=%016x\n", regs.rdx); - ConsolePrint(" rsi=%016x\n", regs.rsi); - ConsolePrint(" rdi=%016x\n", regs.rdi); - ConsolePrint(" rip=%016x\n", regs.rip); - ConsolePrint(" rsp=%016x\n", regs.rsp); - ConsolePrint(" cs=%02x\n", regs.cs); - ConsolePrint(" ss=%02x\n", regs.ss); - - for (;;) {} -} \ No newline at end of file + cpu_dump(ctxt); + +} diff --git a/intr/except.h b/intr/except.h index e716c20..6771ada 100644 --- a/intr/except.h +++ b/intr/except.h @@ -4,15 +4,74 @@ #pragma once +#ifndef ASM #include "stdlib/types.h" +#endif + +#define EXCEPT_DIVIDE_ERROR 0 // Fault, no error code +#define EXCEPT_DEBUG 1 // Fault or Trap +#define EXCEPT_NMI_INTERRUPT 2 // +#define EXCEPT_BREAKPOINT 3 // Trap no error code +#define EXCEPT_OVERFLOW 4 // Trap no error code +#define EXCEPT_BOUND_RANGE_EXCEDEED 5 // Fault no error code +#define EXCEPT_INVALID_OPCODE 6 // Fault no error code +#define EXCEPT_DEVICE_NOT_AVAILABLE 7 // Fault no error code +#define EXCEPT_DOUBLE_FAULT 8 // Abort error code *should* be zero +#define EXCEPT_COPROCESSOR_SEGMENT_OVERRUN 9 // Should no longer exist +#define EXCEPT_INVALID_TSS 10 // Fault with error code +#define EXCEPT_SEGMENT_NOT_PRESENT 11 // Fault with error code, containts segment index +#define EXCEPT_STACK_SEGMENT_FAULT 12 // Fault with error code +#define EXCEPT_GENERAL_PROTECTION 13 // Fault with error code, segment index or zero +#define EXCEPT_PAGE_FAULT 14 // Fault CR2 contains virtual addr + error code +#define EXCEPT_RESERVED_1 15 // -- +#define EXCEPT_FLOATING_POINT_ERROR 16 // Fault no error code +#define EXCEPT_ALIGNEMENT_CHECK 17 // Fault error code = zero +#define EXCEPT_MACHINE_CHECK 18 // Abort no error code +#define EXCEPT_SIMD 19 // Fault no error code +#define EXCEPT_RESERVED_2 20 // -- +#define EXCEPT_RESERVED_3 21 // -- +#define EXCEPT_RESERVED_4 22 // -- +#define EXCEPT_RESERVED_5 23 // -- +#define EXCEPT_RESERVED_6 24 // -- +#define EXCEPT_RESERVED_7 25 // -- +#define EXCEPT_RESERVED_8 26 // -- +#define EXCEPT_RESERVED_9 27 // -- +#define EXCEPT_RESERVED_10 28 // -- +#define EXCEPT_RESERVED_11 29 // -- +#define EXCEPT_SECURITY 30 // -- +#define EXCEPT_RESERVED_12 31 // -- + +#define EXCEPT_NUM 32 + +#ifndef ASM // ------------------------------------------------------------------------------------------------ -typedef struct Registers -{ - u64 rdi, rsi, rbp, rbx, rdx, rcx, rax; - u64 intNum, errCode; - u64 rip, cs, eflags, rsp, ss; -} Registers; +typedef struct cpu_state { + u64 rax; + u64 rbx; + u64 rcx; + u64 rdx; + u64 rsi; + u64 rdi; + u64 r8; + u64 r9; + u64 r10; + u64 r11; + u64 r12; + u64 r13; + u64 r14; + u64 r15; + u64 rsp; + + u64 rbp; + u64 error; + u64 rip; + u64 cs; + u64 rflags; + +} __attribute__((packed)) cpu_state; // ------------------------------------------------------------------------------------------------ -void ExceptionDump(Registers regs); +void exception_entry(u64 ex, cpu_state *ctxt); + +#endif diff --git a/intr/exception.S b/intr/exception.S new file mode 100644 index 0000000..88f1fc6 --- /dev/null +++ b/intr/exception.S @@ -0,0 +1,167 @@ +#include "except.h" + +.file "exception.s" + +.text + +.extern exception_functions +.globl exception_wrappers + +.irp id, \ + EXCEPT_DIVIDE_ERROR, \ + EXCEPT_DEBUG, \ + EXCEPT_NMI_INTERRUPT, \ + EXCEPT_BREAKPOINT, \ + EXCEPT_OVERFLOW, \ + EXCEPT_BOUND_RANGE_EXCEDEED, \ + EXCEPT_INVALID_OPCODE, \ + EXCEPT_DEVICE_NOT_AVAILABLE, \ + EXCEPT_COPROCESSOR_SEGMENT_OVERRUN, \ + EXCEPT_RESERVED_1, \ + EXCEPT_FLOATING_POINT_ERROR, \ + EXCEPT_MACHINE_CHECK, \ + EXCEPT_SIMD, \ + EXCEPT_RESERVED_2, \ + EXCEPT_RESERVED_3, \ + EXCEPT_RESERVED_4, \ + EXCEPT_RESERVED_5, \ + EXCEPT_RESERVED_6, \ + EXCEPT_RESERVED_7, \ + EXCEPT_RESERVED_8, \ + EXCEPT_RESERVED_9, \ + EXCEPT_RESERVED_10, \ + EXCEPT_RESERVED_11, \ + EXCEPT_SECURITY, \ + EXCEPT_RESERVED_12 + + .p2align 4, 0x90 + exception_wrapper_\id: + .type exception_wrapper_\id,@function + + // push fake error code + pushq $0 + + pushq %rbp + movq %rsp, %rbp + + pushq %r15 + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + pushq %r9 + pushq %r8 + pushq %rdi + pushq %rsi + pushq %rdx + pushq %rcx + pushq %rbx + pushq %rax + + movq %rsp, %rsi // *cpu_state + // call exception handler + movq $\id, %rdi // Exception id + leaq exception_functions,%rax + call *\id*8(%rax) + + popq %rax + popq %rbx + popq %rcx + popq %rdx + popq %rsi + popq %rdi + popq %r8 + popq %r9 + popq %r10 + popq %r11 + popq %r12 + popq %r13 + popq %r14 + popq %r15 + + popq %rbp + + /* Remove fake error code */ + addq $4, %rsp + + iretq +.endr + +.irp id, \ + EXCEPT_INVALID_TSS, \ + EXCEPT_SEGMENT_NOT_PRESENT, \ + EXCEPT_STACK_SEGMENT_FAULT, \ + EXCEPT_GENERAL_PROTECTION, \ + EXCEPT_PAGE_FAULT, \ + EXCEPT_ALIGNEMENT_CHECK + + .p2align 4, 0x90 + exception_wrapper_\id: + .globl exception_wrapper_\id + .type exception_wrapper_\id,@function + + pushq %rbp + movq %rsp, %rbp + + pushq %rbp + pushq %r15 + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + pushq %r9 + pushq %r8 + pushq %rdi + pushq %rsi + pushq %rdx + pushq %rcx + pushq %rbx + pushq %rax + + movq %rsp, %rsi + // call exception handler + movq $\id, %rdi + leaq exception_functions,%rax + call *\id*8(%rax) + + popq %rax + popq %rbx + popq %rcx + popq %rdx + popq %rsi + popq %rdi + popq %r8 + popq %r9 + popq %r10 + popq %r11 + popq %r12 + popq %r13 + popq %r14 + popq %r15 + // bypass rsp + addq $8, %rsp + + popq %rbp + + /* Remove error code */ + addq $8, %rsp + + iretq +.endr + +.irp id, EXCEPT_DOUBLE_FAULT +.p2align 3, 0x90 +exception_wrapper_\id: +.type exception_wrapper_\id,@function +1: cli + hlt +.endr + +.p2align 5, 0x0 +exception_wrappers: + .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \ + 16,17,18,19,20,21,22,23,24,25,26,27,29,30,31 + .quad (exception_wrapper_\id) + .endr diff --git a/intr/idt.c b/intr/idt.c index f44891a..2230264 100644 --- a/intr/idt.c +++ b/intr/idt.c @@ -3,6 +3,7 @@ // ------------------------------------------------------------------------------------------------ #include "intr/idt.h" +#include "intr/except.h" #include "mem/lowmem.h" #include "mem/vm.h" @@ -25,9 +26,10 @@ typedef struct IdtEntry typedef void (*Handler)(); -extern void default_exception_handler(); + extern void default_interrupt_handler(); -extern void (*exception_handlers[20])(); +extern void (*exception_wrappers[EXCEPT_NUM])(); +volatile u64 exception_functions[EXCEPT_NUM] = { 0, }; // ------------------------------------------------------------------------------------------------ void IdtInit() @@ -35,14 +37,10 @@ void IdtInit() page_map((paddr_t)IDT_BASE, (paddr_t)IDT_BASE); // Build initial IDT - for (uint i = 0; i < 20; ++i) - { - IdtSetHandler(i, INTERRUPT_GATE, exception_handlers[i]); - } - - for (uint i = 20; i < 32; ++i) + for (uint i = 0; i < 32; ++i) { - IdtSetHandler(i, INTERRUPT_GATE, default_exception_handler); + IdtSetHandler(i, INTERRUPT_GATE, exception_wrappers[i]); + exception_functions[i] = exception_entry; } for (uint i = 32; i < 256; ++i) diff --git a/intr/interrupt.asm b/intr/interrupt.asm index e403e6a..817e15a 100644 --- a/intr/interrupt.asm +++ b/intr/interrupt.asm @@ -2,7 +2,6 @@ ; intr/interrupt.asm ; ------------------------------------------------------------------------------------------------- -[GLOBAL default_exception_handler] [GLOBAL default_interrupt_handler] [GLOBAL exception_handlers] [GLOBAL pit_interrupt] @@ -15,86 +14,9 @@ ; ------------------------------------------------------------------------------------------------- ; Default handlers -default_exception_handler: - jmp $ - default_interrupt_handler: iretq -; ------------------------------------------------------------------------------------------------- -; Specific exception handlers - -%macro make_exception_handler 1 -exception%1_handler: - cli - push byte 0 - push byte %1 - jmp exception_body -%endmacro - -%macro make_error_exception_handler 1 -exception%1_handler: - cli - push byte %1 - jmp exception_body -%endmacro - -make_exception_handler 0 -make_exception_handler 1 -make_exception_handler 2 -make_exception_handler 3 -make_exception_handler 4 -make_exception_handler 5 -make_exception_handler 6 -make_exception_handler 7 -make_error_exception_handler 8 -make_exception_handler 9 -make_error_exception_handler 10 -make_error_exception_handler 11 -make_error_exception_handler 12 -make_error_exception_handler 13 -make_error_exception_handler 14 -make_exception_handler 15 -make_exception_handler 16 -make_error_exception_handler 17 -make_exception_handler 18 -make_exception_handler 19 - -exception_handlers: - dq exception0_handler - dq exception1_handler - dq exception2_handler - dq exception3_handler - dq exception4_handler - dq exception5_handler - dq exception6_handler - dq exception7_handler - dq exception8_handler - dq exception9_handler - dq exception10_handler - dq exception11_handler - dq exception12_handler - dq exception13_handler - dq exception14_handler - dq exception15_handler - dq exception16_handler - dq exception17_handler - dq exception18_handler - dq exception19_handler - -exception_body: - push rax - push rcx - push rdx - push rbx - push rbp - push rsi - push rdi - - call ExceptionDump - - jmp $ - ; ------------------------------------------------------------------------------------------------- ; Prints a string to the screen ; in: rdi = screen address diff --git a/kernel/module.mk b/kernel/module.mk index 9bceddc..934f2ec 100644 --- a/kernel/module.mk +++ b/kernel/module.mk @@ -67,12 +67,15 @@ KERNEL_SOURCES := \ KERNEL_ASM := \ intr/interrupt.asm + +KERNEL_GAS := \ + intr/exception.S SOURCES += $(KERNEL_SOURCES) ASM_SOURCES += $(KERNEL_ASM) TARGETS += kernel/kernel.bin -KERNEL_OBJECTS := $(KERNEL_SOURCES:.c=.cross.o) $(KERNEL_ASM:.asm=.cross.o) +KERNEL_OBJECTS := $(KERNEL_SOURCES:.c=.o) $(KERNEL_ASM:.asm=.o) $(KERNEL_GAS:.S=.o) kernel/kernel.bin: $(KERNEL_OBJECTS) kernel/linker.ld $(CROSS_LD) -Map kernel/kernel.map -T kernel/linker.ld -o $@ $(KERNEL_OBJECTS) diff --git a/stdlib/types.h b/stdlib/types.h index bfac9a9..029a133 100644 --- a/stdlib/types.h +++ b/stdlib/types.h @@ -35,5 +35,3 @@ typedef unsigned int uint; #define KB 1024 #define MB (1024 * 1024) - -#define NULL ((void*)0) From b63c38f56f86f29a4d1ef2ea0477fcbd24427134 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sat, 8 Dec 2012 18:08:35 -0500 Subject: [PATCH 09/20] add code to handle gdt and interrupts now handled through gcc rather than nasm --- cpu/gdt.c | 102 +++++++++++++++++++++++++++++++++++++++++++++ cpu/gdt.h | 11 +++++ intr/interrupt.S | 47 +++++++++++++++++++++ intr/interrupt.asm | 58 -------------------------- kernel/kernel.c | 2 + kernel/module.mk | 11 +++-- mem/vm.h | 2 +- 7 files changed, 168 insertions(+), 65 deletions(-) create mode 100644 cpu/gdt.c create mode 100644 cpu/gdt.h create mode 100644 intr/interrupt.S delete mode 100644 intr/interrupt.asm diff --git a/cpu/gdt.c b/cpu/gdt.c new file mode 100644 index 0000000..7ab6ae3 --- /dev/null +++ b/cpu/gdt.c @@ -0,0 +1,102 @@ +#include "stdlib/types.h" +#include "mem/vm.h" +#include "cpu/gdt.h" + +typedef struct seg_desc +{ + u16 limit_15_0; // 0 + u16 base_15_0; // 16 + + u8 base_23_16; // 32 + u8 seg_type:4; // 40 + u8 type:1; // 44 1 = code/data + u8 dpl:2; // 45 + u8 present:1; // 47 + + u8 limit_19_16:4; // 48 + u8 avl:1; // 52 + u8 set64:1; // 53 set to 1 for 64 bit code + u8 op_size:1; // 54 + u8 granularity:1; // 55 + + u8 base_31_24; // 56 +} __attribute__ ((packed, aligned(8))) seg_desc; + +typedef struct gdtr +{ + u16 limit; + u64 base; +} __attribute__((packed, aligned(4))) gdtr; + +#define BUILD_GDT64(priv_lvl,code) ((seg_desc) { \ + .limit_15_0 = 0, \ + .base_15_0 = 0, \ + .base_23_16 = 0, \ + .seg_type = 8, \ + .type = 1, \ + .dpl = ((priv_lvl) & 0x3), \ + .present = 1, \ + .limit_19_16 = 0, \ + .avl = 0, \ + .set64 = 1, \ + .op_size = 0, \ + .granularity = 0, \ + .base_31_24 = 0, \ +}) + +#define BUILD_GDT64DATA(priv_lvl,code) ((seg_desc) { \ + .limit_15_0 = 0, \ + .base_15_0 = 0, \ + .base_23_16 = 0, \ + .seg_type = 2, \ + .type = 1, \ + .dpl = ((priv_lvl) & 0x3), \ + .present = 1, \ + .limit_19_16 = 0, \ + .avl = 0, \ + .set64 = 1, \ + .op_size = 0, \ + .granularity = 0, \ + .base_31_24 = 0, \ +}) + +#define BUILD_SEGMENT_REG(desc_priv,in_ldt,seg_index) \ + ( (((desc_priv) & 0x3) << 0) \ + | (((in_ldt)?1:0) << 2) \ + | ((seg_index) << 3) ) + +static void load_gdt(gdtr *gdt, const uint code, const uint data) +{ + + __asm__ volatile ("lgdt %0\n\ + movq %%rsp, %%rax\n\ + pushq %2\n\ + pushq %%rax\n\ + pushfq\n\ + pushq %1\n\ + movabs $1f, %%rax\n\ + pushq %%rax\n\ + iretq\n\ + 1:" + : + :"m"(gdt->limit),"i"(code),"i"(data) + :"memory","rax", "rsp"); +} + +void gdt64Init() +{ + + gdtr gdt_r; + seg_desc *gdt = (seg_desc *)VMIdentidyAlloc(); + + gdt[0] = (seg_desc){0,}; // NULL + gdt[1] = BUILD_GDT64(0, 1); // Kernel Code segment + gdt[2] = BUILD_GDT64DATA(0, 0); // Kernel Data segment + gdt[3] = BUILD_GDT64(3, 1); // User code segment + gdt[4] = BUILD_GDT64DATA(3, 0); // User Data segment + + gdt_r.base = (u64) gdt; + gdt_r.limit = (sizeof(seg_desc) * GDT_SEG_COUNT) - 1; + + load_gdt(&gdt_r, SEG_KCODE, SEG_KDATA); +} diff --git a/cpu/gdt.h b/cpu/gdt.h new file mode 100644 index 0000000..1fb92cf --- /dev/null +++ b/cpu/gdt.h @@ -0,0 +1,11 @@ +#pragma once + +#define GDT_SEG_COUNT 5 + +#define SEG_NULL 0 +#define SEG_KCODE 0x8 +#define SEG_KDATA 0x10 +#define SEG_UCODE 0x18 +#define SEG_UDATA 0x20 + +void gdt64Init(); diff --git a/intr/interrupt.S b/intr/interrupt.S new file mode 100644 index 0000000..0f37a6d --- /dev/null +++ b/intr/interrupt.S @@ -0,0 +1,47 @@ +.file "interrupt.S" + +.text + +.globl g_pitTicks +.globl local_apic_address + +.globl spurious_int +.p2align 2, 0x90 +spurious_int: +.type spurious_int,@function + iretq + +.globl default_interrupt_handler +.p2align 2, 0x90 +default_interrupt_handler: +.type default_interrupt_handler,@function + iretq + +.globl timer_irq +.p2align 2, 0x90 +timer_irq: +.type timer_irq,@function + pushq %rdi + pushq %rsi + pushq %rdx + pushq %rcx + pushq %rbx + pushq %rax + + movl pit_ticks, %eax + incl %eax + movl %eax, pit_ticks + + movq local_apic_address, %rdi + addq $0xb0, %rdi + xorl %eax, %eax + stosl + + popq %rax + popq %rbx + popq %rcx + popq %rdx + popq %rsi + popq %rdi + + iretq diff --git a/intr/interrupt.asm b/intr/interrupt.asm deleted file mode 100644 index 817e15a..0000000 --- a/intr/interrupt.asm +++ /dev/null @@ -1,58 +0,0 @@ -; ------------------------------------------------------------------------------------------------- -; intr/interrupt.asm -; ------------------------------------------------------------------------------------------------- - -[GLOBAL default_interrupt_handler] -[GLOBAL exception_handlers] -[GLOBAL pit_interrupt] -[GLOBAL spurious_interrupt] - -[EXTERN g_pitTicks] -[EXTERN g_localApicAddr] -[EXTERN ExceptionDump] - -; ------------------------------------------------------------------------------------------------- -; Default handlers - -default_interrupt_handler: - iretq - -; ------------------------------------------------------------------------------------------------- -; Prints a string to the screen -; in: rdi = screen address -; rsi = string address -vga_print: - lodsb - cmp al, 0 - je .done - stosb - mov al, 0x1f - stosb - jmp vga_print -.done: - ret - -; ------------------------------------------------------------------------------------------------- -; PIT interrupt -pit_interrupt: - push rax - push rdi - - mov eax, dword [g_pitTicks] - inc eax - mov dword [g_pitTicks], eax - - ; Acknowledge interrupt - mov rdi, [g_localApicAddr] - add rdi, 0xb0 - xor eax, eax - stosd - - pop rdi - pop rax - iretq - -; ------------------------------------------------------------------------------------------------- -; Spurious interrupt -spurious_interrupt: - iretq diff --git a/kernel/kernel.c b/kernel/kernel.c index d57347c..ba28612 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -5,6 +5,7 @@ #include "acpi/acpi.h" #include "console/console.h" #include "cpu/smp.h" +#include "cpu/gdt.h" #include "gfx/gfx.h" #include "gfx/vga.h" #include "intr/intr.h" @@ -30,6 +31,7 @@ int kmain() PhysmemInit(); VMInit(); + gdt64Init(); AcpiInit(); IntrInit(); diff --git a/kernel/module.mk b/kernel/module.mk index 934f2ec..e368630 100644 --- a/kernel/module.mk +++ b/kernel/module.mk @@ -7,6 +7,7 @@ KERNEL_SOURCES := \ console/cmd.c \ cpu/detect.c \ cpu/smp.c \ + cpu/gdt.c \ gfx/gfx.c \ gfx/gfxdisplay.c \ gfx/gfxmem.c \ @@ -64,18 +65,16 @@ KERNEL_SOURCES := \ usb/hub.c \ usb/kbd.c \ usb/mouse.c - -KERNEL_ASM := \ - intr/interrupt.asm -KERNEL_GAS := \ - intr/exception.S +KERNEL_ASM := \ + intr/exception.S \ + intr/interrupt.S SOURCES += $(KERNEL_SOURCES) ASM_SOURCES += $(KERNEL_ASM) TARGETS += kernel/kernel.bin -KERNEL_OBJECTS := $(KERNEL_SOURCES:.c=.o) $(KERNEL_ASM:.asm=.o) $(KERNEL_GAS:.S=.o) +KERNEL_OBJECTS := $(KERNEL_SOURCES:.c=.o) $(KERNEL_ASM:.S=.o) kernel/kernel.bin: $(KERNEL_OBJECTS) kernel/linker.ld $(CROSS_LD) -Map kernel/kernel.map -T kernel/linker.ld -o $@ $(KERNEL_OBJECTS) diff --git a/mem/vm.h b/mem/vm.h index 24f8eb8..2f16a44 100644 --- a/mem/vm.h +++ b/mem/vm.h @@ -165,7 +165,7 @@ typedef struct pt_t { // ------------------------------------------------------------------------------------------------ void VMInit(); -void *PageIdentidyAlloc(); +void *VMIdentidyAlloc(); void *VMAlloc(uint size); From 154d17b662ab0be3cb02be0f68e906077419dcdc Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sat, 8 Dec 2012 18:25:07 -0500 Subject: [PATCH 10/20] separate tests from the rest --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b246b58..7c3ef12 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -all: all_targets check +all: all_targets + +test: check UNAME := $(shell uname) From 5c37a9d88823f709b99c8750644af17f96863cf8 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sat, 8 Dec 2012 18:27:28 -0500 Subject: [PATCH 11/20] fix mistake --- intr/interrupt.S | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/intr/interrupt.S b/intr/interrupt.S index 0f37a6d..a6d15c9 100644 --- a/intr/interrupt.S +++ b/intr/interrupt.S @@ -1,14 +1,15 @@ .file "interrupt.S" +#define local_apic_address 0x6000 + .text .globl g_pitTicks -.globl local_apic_address -.globl spurious_int +.globl spurious_interrupt .p2align 2, 0x90 -spurious_int: -.type spurious_int,@function +spurious_interrupt: +.type spurious_interrupt,@function iretq .globl default_interrupt_handler @@ -17,10 +18,10 @@ default_interrupt_handler: .type default_interrupt_handler,@function iretq -.globl timer_irq +.globl pit_interrupt .p2align 2, 0x90 -timer_irq: -.type timer_irq,@function +pit_interrupt: +.type pit_interrupt,@function pushq %rdi pushq %rsi pushq %rdx @@ -28,9 +29,9 @@ timer_irq: pushq %rbx pushq %rax - movl pit_ticks, %eax + movl g_pitTicks, %eax incl %eax - movl %eax, pit_ticks + movl %eax, g_pitTicks movq local_apic_address, %rdi addq $0xb0, %rdi From ee22f6fc735036421e91e18c9fdf19c1fce7b073 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sat, 8 Dec 2012 18:27:51 -0500 Subject: [PATCH 12/20] fix warnings --- intr/idt.c | 2 +- net/intel.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/intr/idt.c b/intr/idt.c index 2230264..380ab01 100644 --- a/intr/idt.c +++ b/intr/idt.c @@ -40,7 +40,7 @@ void IdtInit() for (uint i = 0; i < 32; ++i) { IdtSetHandler(i, INTERRUPT_GATE, exception_wrappers[i]); - exception_functions[i] = exception_entry; + exception_functions[i] = (u64)exception_entry; } for (uint i = 32; i < 256; ++i) diff --git a/net/intel.c b/net/intel.c index c149fb8..ab1a2f5 100644 --- a/net/intel.c +++ b/net/intel.c @@ -277,7 +277,7 @@ void EthIntelInit(uint id, PciDeviceInfo *info) u8 *mmioAddr = (u8 *)bar.u.address; s_device.mmioAddr = mmioAddr; - for (paddr_t page = (uint)bar.u.address;page < (uint)bar.u.address + bar.size;page += PAGE_SIZE) + for (paddr_t page = (u64)bar.u.address;page < (u64)bar.u.address + bar.size;page += PAGE_SIZE) page_map(PAGE_ALIGN_INF(page), PAGE_ALIGN_INF(page)); // IRQ From 604684b23aef173590829acee5359d385e272149 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sat, 8 Dec 2012 18:29:13 -0500 Subject: [PATCH 13/20] add me ;-) --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 69c0032..0502a6d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,3 +4,4 @@ Craig Tiller MWDD Patrick Doane William Warnecke +Gabriel Blanchard From d655e99d17955e1ea3de5cefdab25e4c888f8599 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sat, 8 Dec 2012 20:54:38 -0500 Subject: [PATCH 14/20] improve exception handler --- intr/except.h | 1 + intr/exception.S | 94 ++++++++++++++---------------------------------- 2 files changed, 27 insertions(+), 68 deletions(-) diff --git a/intr/except.h b/intr/except.h index 6771ada..9d87189 100644 --- a/intr/except.h +++ b/intr/except.h @@ -64,6 +64,7 @@ typedef struct cpu_state { u64 rsp; u64 rbp; + u64 exceptionid; u64 error; u64 rip; u64 cs; diff --git a/intr/exception.S b/intr/exception.S index 88f1fc6..f371b14 100644 --- a/intr/exception.S +++ b/intr/exception.S @@ -39,53 +39,9 @@ .type exception_wrapper_\id,@function // push fake error code - pushq $0 + pushq $0 // 128 - pushq %rbp - movq %rsp, %rbp - - pushq %r15 - pushq %r14 - pushq %r13 - pushq %r12 - pushq %r11 - pushq %r10 - pushq %r9 - pushq %r8 - pushq %rdi - pushq %rsi - pushq %rdx - pushq %rcx - pushq %rbx - pushq %rax - - movq %rsp, %rsi // *cpu_state - // call exception handler - movq $\id, %rdi // Exception id - leaq exception_functions,%rax - call *\id*8(%rax) - - popq %rax - popq %rbx - popq %rcx - popq %rdx - popq %rsi - popq %rdi - popq %r8 - popq %r9 - popq %r10 - popq %r11 - popq %r12 - popq %r13 - popq %r14 - popq %r15 - - popq %rbp - - /* Remove fake error code */ - addq $4, %rsp - - iretq + jmp exception_routine .endr .irp id, \ @@ -101,30 +57,34 @@ .globl exception_wrapper_\id .type exception_wrapper_\id,@function - pushq %rbp + pushq $\id // 128 + jmp exception_routine +.endr + +exception_routine: + pushq %rbp // 120 movq %rsp, %rbp - pushq %rbp - pushq %r15 - pushq %r14 - pushq %r13 - pushq %r12 - pushq %r11 - pushq %r10 - pushq %r9 - pushq %r8 - pushq %rdi - pushq %rsi - pushq %rdx - pushq %rcx - pushq %rbx - pushq %rax + pushq %rbp // 112 + pushq %r15 // 104 + pushq %r14 // 96 + pushq %r13 // 88 + pushq %r12 // 80 + pushq %r11 // 72 + pushq %r10 // 64 + pushq %r9 // 56 + pushq %r8 // 48 + pushq %rdi // 40 + pushq %rsi // 32 + pushq %rdx // 24 + pushq %rcx // 16 + pushq %rbx // 8 + pushq %rax // 0 movq %rsp, %rsi - // call exception handler - movq $\id, %rdi - leaq exception_functions,%rax - call *\id*8(%rax) + + movq 128(%rsp), %rdi // exception id + call *exception_functions(, %rdi, 8) // exception_functions + (rdi * 8) popq %rax popq %rbx @@ -147,9 +107,7 @@ /* Remove error code */ addq $8, %rsp - iretq -.endr .irp id, EXCEPT_DOUBLE_FAULT .p2align 3, 0x90 From 7910a448c9fb303d6e274cb0d56a89d0738f5053 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 9 Dec 2012 09:46:50 -0500 Subject: [PATCH 15/20] add debug symbols --- Makefile | 4 ++-- kernel/linker.ld | 2 +- kernel/module.mk | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 7c3ef12..ebef8bb 100644 --- a/Makefile +++ b/Makefile @@ -26,14 +26,14 @@ COMMON_CFLAGS := -I . -std=c99 COMMON_CFLAGS += -Wall -Werror-implicit-function-declaration -Wno-array-bounds COMMON_CFLAGS += -fno-common -fno-asynchronous-unwind-tables COMMON_CFLAGS += -mno-red-zone -fno-stack-protector -COMMON_CFLAGS += -O2 +COMMON_CFLAGS += -g -O2 FREESTANDING_CFLAGS := -fno-builtin # Cross Compiler CROSS_CC := $(Q)x86_64-elf-gcc CROSS_CFLAGS := -DCROSS $(FREESTANDING_CFLAGS) $(COMMON_CFLAGS) -CROSS_LD := $(Q)x86_64-elf-ld +CROSS_LD := x86_64-elf-ld # Host Compiler without standard library HOST_CFLAGS := -DHOST $(FREESTANDING_CFLAGS) $(COMMON_CFLAGS) diff --git a/kernel/linker.ld b/kernel/linker.ld index cf99ac5..7976168 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -1,4 +1,4 @@ -OUTPUT_FORMAT("binary") +OUTPUT_FORMAT("elf64-x86-64") ENTRY(kmain) SECTIONS { diff --git a/kernel/module.mk b/kernel/module.mk index e368630..77112d2 100644 --- a/kernel/module.mk +++ b/kernel/module.mk @@ -76,9 +76,13 @@ TARGETS += kernel/kernel.bin KERNEL_OBJECTS := $(KERNEL_SOURCES:.c=.o) $(KERNEL_ASM:.S=.o) -kernel/kernel.bin: $(KERNEL_OBJECTS) kernel/linker.ld +kernel/kernel.elf: $(KERNEL_OBJECTS) kernel/linker.ld $(CROSS_LD) -Map kernel/kernel.map -T kernel/linker.ld -o $@ $(KERNEL_OBJECTS) +kernel/kernel.bin: kernel/kernel.elf + objcopy --only-keep-debug kernel/kernel.elf kernel/kernel.sym + objcopy -O binary kernel/kernel.elf kernel/kernel.bin + # ------------------------------------------------------------------------------------------------- # Tests From 8cdde832998d53bf7e884fb042fb466b790af202 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 9 Dec 2012 18:11:32 -0500 Subject: [PATCH 16/20] change stdlib includes --- Makefile | 5 +++-- console/console.c | 7 +++++++ cpu/detect.h | 2 +- cpu/gdt.c | 2 +- cpu/io.h | 2 +- cpu/smp.c | 48 +++++++++++++++++++++++++++++++++++++++++++++-- cpu/smp.h | 13 ++++++++++++- gfx/gfx.c | 4 ++-- input/input.h | 2 +- input/keymap.h | 2 +- intr/except.h | 2 +- intr/idt.h | 2 +- intr/intr.h | 2 +- intr/ioapic.h | 2 +- intr/local_apic.c | 10 ++++++++++ intr/local_apic.h | 3 ++- intr/pic.h | 2 +- kernel/kernel.c | 3 ++- kernel/module.mk | 1 + mem/mem_dump.h | 2 +- mem/physmem.c | 10 +++++----- mem/physmem.h | 2 +- mem/vm.c | 15 +++------------ mem/vm.h | 4 ++-- net/addr.c | 2 +- net/addr.h | 2 +- net/arp.c | 2 +- net/buf.h | 2 +- net/dhcp.c | 2 +- net/dns.c | 2 +- net/icmp.c | 2 +- net/intel.c | 2 +- net/intf.c | 2 +- net/intf.h | 2 +- net/net.h | 2 +- net/port.h | 2 +- net/rlog.c | 9 +++++---- net/rlog.h | 2 +- net/route.c | 2 +- net/swap.h | 2 +- net/tcp.c | 2 +- net/tcp_test.c | 2 +- pci/driver.h | 2 +- pci/pci.h | 2 +- pci/registry.h | 2 +- qemu.sh | 2 +- stdlib/types.h | 2 ++ time/pit.h | 2 +- time/time.c | 2 +- time/time.h | 2 +- usb/controller.h | 2 +- usb/desc.h | 2 +- usb/ehci.c | 4 ++-- usb/kbd.c | 2 +- usb/req.h | 2 +- usb/uhci.c | 4 ++-- usb/usb.h | 2 +- 57 files changed, 147 insertions(+), 77 deletions(-) diff --git a/Makefile b/Makefile index ebef8bb..9914d0a 100644 --- a/Makefile +++ b/Makefile @@ -22,10 +22,11 @@ endif Q := @ CC := $(Q)gcc NASM := $(Q)nasm -COMMON_CFLAGS := -I . -std=c99 +COMMON_CFLAGS := -I . -I stdlib/ -std=c99 COMMON_CFLAGS += -Wall -Werror-implicit-function-declaration -Wno-array-bounds COMMON_CFLAGS += -fno-common -fno-asynchronous-unwind-tables -COMMON_CFLAGS += -mno-red-zone -fno-stack-protector +COMMON_CFLAGS += -mno-red-zone -fno-stack-protector -ffreestanding -nostdlib +COMMON_CFLAGS += -mcmodel=large -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow COMMON_CFLAGS += -g -O2 FREESTANDING_CFLAGS := -fno-builtin diff --git a/console/console.c b/console/console.c index 77d4f38..d091893 100644 --- a/console/console.c +++ b/console/console.c @@ -4,6 +4,7 @@ #include "console/console.h" #include "console/cmd.h" +#include "cpu/smp.h" #include "gfx/vga.h" #include "input/keycode.h" #include "mem/lowmem.h" @@ -35,6 +36,8 @@ static uint s_lineIndex; static HistoryLine s_history[MAX_HISTORY_SIZE]; static uint s_historyCount; +static lock_t console_lock; + // ------------------------------------------------------------------------------------------------ static void ConsoleUpdateInput() { @@ -163,6 +166,7 @@ static void ConsoleExec() // ------------------------------------------------------------------------------------------------ void ConsoleInit() { + spin_lock_init(&console_lock); ConsoleUpdateInput(); } @@ -215,10 +219,13 @@ void ConsolePrint(const char *fmt, ...) char c; char *s = buf; + + spin_lock(&console_lock); while ((c = *s++)) { ConsolePutChar(c); } + spin_unlock(&console_lock); } // ------------------------------------------------------------------------------------------------ diff --git a/cpu/detect.h b/cpu/detect.h index d3566eb..23132dd 100644 --- a/cpu/detect.h +++ b/cpu/detect.h @@ -4,6 +4,6 @@ #pragma once -#include "stdlib/types.h" +#include void CpuDetect(); diff --git a/cpu/gdt.c b/cpu/gdt.c index 7ab6ae3..1d567ab 100644 --- a/cpu/gdt.c +++ b/cpu/gdt.c @@ -1,4 +1,4 @@ -#include "stdlib/types.h" +#include #include "mem/vm.h" #include "cpu/gdt.h" diff --git a/cpu/io.h b/cpu/io.h index 6a66b13..e5cbe1a 100644 --- a/cpu/io.h +++ b/cpu/io.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ // x86 in/out instructions diff --git a/cpu/smp.c b/cpu/smp.c index f366499..3f35432 100644 --- a/cpu/smp.c +++ b/cpu/smp.c @@ -7,8 +7,42 @@ #include "mem/vm.h" #include "console/console.h" #include "intr/local_apic.h" +#include "intr/idt.h" #include "time/pit.h" +#define barrier() __asm__ volatile("": : :"memory") +#define cpu_relax() __asm__ volatile("pause\n": : :"memory") + +void spin_lock_init(lock_t *lock) +{ + if (lock == NULL) + return; + + lock->current = lock->next = 0; +} + +void spin_lock(lock_t *lock) +{ + u8 ticket; + + ticket = fetch_and_add(&lock->next, 1); + while (ticket != lock->current) { cpu_relax(); } + barrier(); +} + +void spin_unlock(lock_t *lock) +{ + barrier(); + lock->current++; +} + +void testcpu() +{ + ConsolePrint("Hello from CPU %d\n", LocalApicGetId()); + + for (;;) __asm__("hlt"); +} + // ------------------------------------------------------------------------------------------------ void SmpInit() { @@ -17,6 +51,8 @@ void SmpInit() g_activeCpuCount = 1; uint localId = LocalApicGetId(); + IdtSetHandler(64, INTERRUPT_GATE, testcpu); + // Send Init to all cpus except self for (uint i = 0; i < g_acpiCpuCount; ++i) { @@ -29,6 +65,7 @@ void SmpInit() // wait PitWait(10); + page_map((paddr_t)g_activeCpuCount, (paddr_t)g_activeCpuCount); // Send Startup to all cpus except self for (uint i = 0; i < g_acpiCpuCount; ++i) @@ -40,8 +77,6 @@ void SmpInit() } } - page_map((paddr_t)g_activeCpuCount, (paddr_t)g_activeCpuCount); - // Wait for all cpus to be active PitWait(1); while (g_activeCpuCount != g_acpiCpuCount) @@ -49,5 +84,14 @@ void SmpInit() PitWait(1); } + for (uint i = 0; i < g_acpiCpuCount; ++i) + { + uint apicId = g_acpiCpuIds[i]; + if (apicId != localId) + { + LocalApicSendInt(apicId, 64); + //for(;;); + } + } ConsolePrint("All CPUs activated\n"); } diff --git a/cpu/smp.h b/cpu/smp.h index fc64f05..cd32840 100644 --- a/cpu/smp.h +++ b/cpu/smp.h @@ -4,8 +4,19 @@ #pragma once -#include "stdlib/types.h" +#include + +typedef struct lock_t { + volatile u16 current; + volatile u16 next; +} lock_t; + +#define fetch_and_add(ptr, value) __sync_fetch_and_add(ptr, value) +#define test_and_set(ptr, value) __sync_test_and_set(ptr, value) extern volatile u8 g_activeCpuCount; void SmpInit(); +void spin_lock(lock_t *lock); +void spin_unlock(lock_t *lock); +void spin_lock_init(lock_t *lock); diff --git a/gfx/gfx.c b/gfx/gfx.c index 941fe2e..3a4cc2b 100644 --- a/gfx/gfx.c +++ b/gfx/gfx.c @@ -2,6 +2,8 @@ // gfx/gfx.c // ------------------------------------------------------------------------------------------------ +#include +#include #include "gfx/gfx.h" #include "gfx/gfxpci.h" #include "gfx/gtt.h" @@ -14,8 +16,6 @@ #include "mem/vm.h" #include "net/rlog.h" #include "pci/registry.h" -#include "stdlib/limits.h" -#include "stdlib/string.h" #include "time/pit.h" #include "cursor.c" diff --git a/input/input.h b/input/input.h index d6c88d6..72aa15d 100644 --- a/input/input.h +++ b/input/input.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ extern int g_mouseX; diff --git a/input/keymap.h b/input/keymap.h index 4bdac23..d024e84 100644 --- a/input/keymap.h +++ b/input/keymap.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ typedef struct Keymap diff --git a/intr/except.h b/intr/except.h index 9d87189..67ce84e 100644 --- a/intr/except.h +++ b/intr/except.h @@ -5,7 +5,7 @@ #pragma once #ifndef ASM -#include "stdlib/types.h" +#include #endif #define EXCEPT_DIVIDE_ERROR 0 // Fault, no error code diff --git a/intr/idt.h b/intr/idt.h index ce0ce43..1654271 100644 --- a/intr/idt.h +++ b/intr/idt.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ #define INTERRUPT_GATE 0x8e00 diff --git a/intr/intr.h b/intr/intr.h index 44ce50f..16d21db 100644 --- a/intr/intr.h +++ b/intr/intr.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ #define IRQ_BASE 0x20 diff --git a/intr/ioapic.h b/intr/ioapic.h index 074c132..e5c92b7 100644 --- a/intr/ioapic.h +++ b/intr/ioapic.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include extern u8 *g_ioApicAddr; diff --git a/intr/local_apic.c b/intr/local_apic.c index 2a9dc0d..f81ea76 100644 --- a/intr/local_apic.c +++ b/intr/local_apic.c @@ -106,6 +106,16 @@ uint LocalApicGetId() return LocalApicIn(LAPIC_ID) >> 24; } +void LocalApicSendInt(uint apic_id, u8 interrupt) +{ + LocalApicOut(LAPIC_ICRHI, apic_id << ICR_DESTINATION_SHIFT); + LocalApicOut(LAPIC_ICRLO, ICR_PHYSICAL + | ICR_ASSERT | ICR_EDGE | ICR_NO_SHORTHAND | interrupt); + + while (LocalApicIn(LAPIC_ICRLO) & ICR_SEND_PENDING) + ; +} + // ------------------------------------------------------------------------------------------------ void LocalApicSendInit(uint apic_id) { diff --git a/intr/local_apic.h b/intr/local_apic.h index bc18aef..0899267 100644 --- a/intr/local_apic.h +++ b/intr/local_apic.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include extern u8 *g_localApicAddr; @@ -13,3 +13,4 @@ void LocalApicInit(); uint LocalApicGetId(); void LocalApicSendInit(uint apic_id); void LocalApicSendStartup(uint apic_id, uint vector); +void LocalApicSendInt(uint apic_id, u8 interrupt); diff --git a/intr/pic.h b/intr/pic.h index a979f7a..789dc04 100644 --- a/intr/pic.h +++ b/intr/pic.h @@ -4,6 +4,6 @@ #pragma once -#include "stdlib/types.h" +#include void PicInit(); diff --git a/kernel/kernel.c b/kernel/kernel.c index ba28612..18ea3e1 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -2,6 +2,8 @@ // kernel/kernel.c // ------------------------------------------------------------------------------------------------ +#include + #include "acpi/acpi.h" #include "console/console.h" #include "cpu/smp.h" @@ -13,7 +15,6 @@ #include "mem/vm.h" #include "net/net.h" #include "pci/pci.h" -#include "stdlib/string.h" #include "usb/usb.h" // ------------------------------------------------------------------------------------------------ diff --git a/kernel/module.mk b/kernel/module.mk index 77112d2..ba16faa 100644 --- a/kernel/module.mk +++ b/kernel/module.mk @@ -26,6 +26,7 @@ KERNEL_SOURCES := \ mem/mem_dump.c \ mem/vm.c \ mem/physmem.c \ + mem/kmalloc.c \ net/addr.c \ net/arp.c \ net/buf.c \ diff --git a/mem/mem_dump.h b/mem/mem_dump.h index 3918399..3a36a75 100644 --- a/mem/mem_dump.h +++ b/mem/mem_dump.h @@ -4,6 +4,6 @@ #pragma once -#include "stdlib/types.h" +#include void MemDump(const void *start, const void *end); diff --git a/mem/physmem.c b/mem/physmem.c index 2082e33..dd5f6fd 100644 --- a/mem/physmem.c +++ b/mem/physmem.c @@ -2,11 +2,11 @@ // mem/physmem.c // ------------------------------------------------------------------------------------------------ -#include "stdlib/types.h" -#include "stdlib/string.h" -#include "mem/lowmem.h" -#include "mem/physmem.h" -#include "mem/vm.h" +#include +#include +#include "lowmem.h" +#include "physmem.h" +#include "vm.h" // ------------------------------------------------------------------------------------------------ diff --git a/mem/physmem.h b/mem/physmem.h index d0d167a..4fdf12b 100644 --- a/mem/physmem.h +++ b/mem/physmem.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ diff --git a/mem/vm.c b/mem/vm.c index a2e1d3b..860d7d7 100644 --- a/mem/vm.c +++ b/mem/vm.c @@ -2,21 +2,14 @@ // mem/vm.c // ------------------------------------------------------------------------------------------------ +#include + #include "mem/vm.h" #include "mem/physmem.h" #include "mem/lowmem.h" -#include "stdlib/string.h" #include "console/console.h" // ------------------------------------------------------------------------------------------------ -#define PAGE_PRESENT 0x01 // Must be 1 to reference page-directory -#define PAGE_WRITE 0x02 // Write access -#define PAGE_USER 0x04 // User-mode access -#define PAGE_WRITE_THROUGH 0x08 // Page-level write-through -#define PAGE_CACHE_DISABLE 0x10 // Page-level cache-disable - -#define PD_2MB 0x80 // 2MB Page - static pml4_t *pml4; #define invlpg(vaddr) \ @@ -24,8 +17,6 @@ static pml4_t *pml4; __asm__ __volatile__("invlpg %0"::"m"(*((unsigned long long*)(vaddr)))); \ } while(0) - - #define flush_tlb() \ do { \ u64 tmpreg; \ @@ -261,7 +252,7 @@ void VMInit() PagingInitialMap(pml4, 0x8000, 0x8000); // TODO: fix temporary stack map - for (paddr = 0x19000; paddr <= 0x20000; paddr += PAGE_SIZE) + for (paddr = 0x19000; paddr <= 0x28000; paddr += PAGE_SIZE) { PagingInitialMap(pml4, paddr, paddr); } diff --git a/mem/vm.h b/mem/vm.h index 2f16a44..b3f6567 100644 --- a/mem/vm.h +++ b/mem/vm.h @@ -4,8 +4,8 @@ #pragma once -#include "stdlib/types.h" -#include "mem/physmem.h" +#include +#include "physmem.h" #define PAGE_SIZE (0x1000) #define PAGE_LARGE_SIZE (0x200000) diff --git a/net/addr.c b/net/addr.c index 150b4bf..6af2856 100644 --- a/net/addr.c +++ b/net/addr.c @@ -2,8 +2,8 @@ // net/addr.c // ------------------------------------------------------------------------------------------------ +#include #include "net/addr.h" -#include "stdlib/format.h" // ------------------------------------------------------------------------------------------------ const EthAddr g_nullEthAddr = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; diff --git a/net/addr.h b/net/addr.h index df276ac..4c8c94f 100644 --- a/net/addr.h +++ b/net/addr.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ // Ethernet Address diff --git a/net/arp.c b/net/arp.c index 343873d..1c53745 100644 --- a/net/arp.c +++ b/net/arp.c @@ -2,6 +2,7 @@ // net/arp.c // ------------------------------------------------------------------------------------------------ +#include #include "net/arp.h" #include "net/buf.h" #include "net/eth.h" @@ -9,7 +10,6 @@ #include "net/net.h" #include "net/swap.h" #include "console/console.h" -#include "stdlib/string.h" // ------------------------------------------------------------------------------------------------ // ARP Protocol diff --git a/net/buf.h b/net/buf.h index cc88655..11a1479 100644 --- a/net/buf.h +++ b/net/buf.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/link.h" +#include // ------------------------------------------------------------------------------------------------ // Net Buffer diff --git a/net/dhcp.c b/net/dhcp.c index 124020d..b6f2bc5 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -2,6 +2,7 @@ // net/dhcp.c // ------------------------------------------------------------------------------------------------ +#include #include "net/dhcp.h" #include "net/buf.h" #include "net/dns.h" @@ -12,7 +13,6 @@ #include "net/swap.h" #include "net/udp.h" #include "console/console.h" -#include "stdlib/string.h" // ------------------------------------------------------------------------------------------------ // DHCP Header diff --git a/net/dns.c b/net/dns.c index a8d25be..b41c951 100644 --- a/net/dns.c +++ b/net/dns.c @@ -2,13 +2,13 @@ // net/dns.c // ------------------------------------------------------------------------------------------------ +#include #include "net/dns.h" #include "net/buf.h" #include "net/port.h" #include "net/swap.h" #include "net/udp.h" #include "console/console.h" -#include "stdlib/string.h" // ------------------------------------------------------------------------------------------------ // DNS Header diff --git a/net/icmp.c b/net/icmp.c index 26a47a6..f4ba582 100644 --- a/net/icmp.c +++ b/net/icmp.c @@ -2,13 +2,13 @@ // net/icmp.c // ------------------------------------------------------------------------------------------------ +#include #include "net/icmp.h" #include "net/buf.h" #include "net/checksum.h" #include "net/ipv4.h" #include "net/net.h" #include "console/console.h" -#include "stdlib/string.h" // ------------------------------------------------------------------------------------------------ #define ICMP_TYPE_ECHO_REPLY 0 diff --git a/net/intel.c b/net/intel.c index ab1a2f5..301ce0e 100644 --- a/net/intel.c +++ b/net/intel.c @@ -2,6 +2,7 @@ // net/intel.c // ------------------------------------------------------------------------------------------------ +#include #include "net/intel.h" #include "net/buf.h" #include "net/ipv4.h" @@ -10,7 +11,6 @@ #include "cpu/io.h" #include "mem/vm.h" #include "pci/driver.h" -#include "stdlib/string.h" #include "time/pit.h" #include "mem/vm.h" diff --git a/net/intf.c b/net/intf.c index 41d7ec3..692f955 100644 --- a/net/intf.c +++ b/net/intf.c @@ -2,9 +2,9 @@ // net/intf.c // ------------------------------------------------------------------------------------------------ +#include #include "net/intf.h" #include "mem/vm.h" -#include "stdlib/string.h" // ------------------------------------------------------------------------------------------------ // Globals diff --git a/net/intf.h b/net/intf.h index 054c178..491184e 100644 --- a/net/intf.h +++ b/net/intf.h @@ -4,9 +4,9 @@ #pragma once +#include #include "net/addr.h" #include "net/buf.h" -#include "stdlib/link.h" // ------------------------------------------------------------------------------------------------ // Net Interface diff --git a/net/net.h b/net/net.h index 45f41bb..cf1e9a9 100644 --- a/net/net.h +++ b/net/net.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/link.h" +#include // ------------------------------------------------------------------------------------------------ // Trace mask diff --git a/net/port.h b/net/port.h index b61059a..349767b 100644 --- a/net/port.h +++ b/net/port.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ // Internet Ports diff --git a/net/rlog.c b/net/rlog.c index 6273f6f..97e558f 100644 --- a/net/rlog.c +++ b/net/rlog.c @@ -2,15 +2,16 @@ // net/rlog.c // ------------------------------------------------------------------------------------------------ +#include +#include +#include +#include #include "net/rlog.h" #include "net/buf.h" #include "net/intf.h" #include "net/port.h" #include "net/udp.h" -#include "stdlib/link.h" -#include "stdlib/format.h" -#include "stdlib/stdarg.h" -#include "stdlib/string.h" + #include "console/console.h" diff --git a/net/rlog.h b/net/rlog.h index d38440d..14b4f30 100644 --- a/net/rlog.h +++ b/net/rlog.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ void RlogPrint(const char *fmt, ...); diff --git a/net/route.c b/net/route.c index 8553359..27107e8 100644 --- a/net/route.c +++ b/net/route.c @@ -2,10 +2,10 @@ // net/route.c // ------------------------------------------------------------------------------------------------ +#include #include "net/route.h" #include "console/console.h" #include "mem/vm.h" -#include "stdlib/string.h" // ------------------------------------------------------------------------------------------------ static Link s_routeTable = { &s_routeTable, &s_routeTable }; diff --git a/net/swap.h b/net/swap.h index 63742f9..751fc62 100644 --- a/net/swap.h +++ b/net/swap.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ static inline u16 NetSwap16(u16 x) diff --git a/net/tcp.c b/net/tcp.c index dd113ed..31e79b9 100644 --- a/net/tcp.c +++ b/net/tcp.c @@ -2,6 +2,7 @@ // net/tcp.c // ------------------------------------------------------------------------------------------------ +#include #include "net/tcp.h" #include "net/buf.h" #include "net/checksum.h" @@ -12,7 +13,6 @@ #include "net/swap.h" #include "console/console.h" #include "mem/vm.h" -#include "stdlib/string.h" #include "time/pit.h" #include "time/rtc.h" diff --git a/net/tcp_test.c b/net/tcp_test.c index ee92b10..deb5cad 100644 --- a/net/tcp_test.c +++ b/net/tcp_test.c @@ -2,6 +2,7 @@ // net/tcp_test.c // ------------------------------------------------------------------------------------------------ +#include #include "test/test.h" #include "net/checksum.h" #include "net/ipv4.h" @@ -9,7 +10,6 @@ #include "net/route.h" #include "net/swap.h" #include "net/tcp.h" -#include "stdlib/string.h" #include "time/time.h" #include diff --git a/pci/driver.h b/pci/driver.h index ebf93be..f35e22b 100644 --- a/pci/driver.h +++ b/pci/driver.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ #define PCI_MAKE_ID(bus, dev, func) ((bus) << 16) | ((dev) << 11) | ((func) << 8) diff --git a/pci/pci.h b/pci/pci.h index 1b7110d..99c087e 100644 --- a/pci/pci.h +++ b/pci/pci.h @@ -4,6 +4,6 @@ #pragma once -#include "stdlib/types.h" +#include void PciInit(); diff --git a/pci/registry.h b/pci/registry.h index 5a02d61..3626421 100644 --- a/pci/registry.h +++ b/pci/registry.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include const char *PciDeviceName(uint vendorId, uint deviceId); const char *PciClassName(uint classCode, uint subclass, uint progIntf); diff --git a/qemu.sh b/qemu.sh index 960547b..0d3b064 100755 --- a/qemu.sh +++ b/qemu.sh @@ -1,4 +1,4 @@ #!/bin/bash set -ex -qemu-system-x86_64 -hda os.img -smp cores=4,threads=2 -usbdevice mouse -usbdevice keyboard +kvm -m 5048 -hda os.img -smp cores=4,threads=2 -usbdevice mouse -usbdevice keyboard #sudo qemu-system-x86_64 -hda os.img -smp cores=4,threads=2 -net nic -net tap,ifname=mac -usbdevice mouse -usbdevice keyboard diff --git a/stdlib/types.h b/stdlib/types.h index 029a133..a4f5d33 100644 --- a/stdlib/types.h +++ b/stdlib/types.h @@ -17,6 +17,8 @@ typedef float f32; typedef double f64; #ifdef CROSS +#undef NULL +#define NULL ((void*)0) typedef u64 size_t; typedef u64 uintptr_t; #else diff --git a/time/pit.h b/time/pit.h index 6269930..0b81bab 100644 --- a/time/pit.h +++ b/time/pit.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include extern volatile u32 g_pitTicks; diff --git a/time/time.c b/time/time.c index 7aafd3f..b626b2c 100644 --- a/time/time.c +++ b/time/time.c @@ -2,8 +2,8 @@ // time/time.c // ------------------------------------------------------------------------------------------------ +#include #include "time/time.h" -#include "stdlib/format.h" // ------------------------------------------------------------------------------------------------ diff --git a/time/time.h b/time/time.h index 0ea7405..566aa27 100644 --- a/time/time.h +++ b/time/time.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ // Elapsed Time diff --git a/usb/controller.h b/usb/controller.h index 0ee37e8..6c73971 100644 --- a/usb/controller.h +++ b/usb/controller.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ // USB Controller diff --git a/usb/desc.h b/usb/desc.h index f207b46..a658971 100644 --- a/usb/desc.h +++ b/usb/desc.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ // USB Base Descriptor Types diff --git a/usb/ehci.c b/usb/ehci.c index 4cfe0c5..288baf5 100644 --- a/usb/ehci.c +++ b/usb/ehci.c @@ -2,6 +2,8 @@ // usb/ehci.c // ------------------------------------------------------------------------------------------------ +#include +#include #include "usb/ehci.h" #include "usb/controller.h" #include "usb/dev.h" @@ -11,8 +13,6 @@ #include "pci/registry.h" #include "pci/driver.h" #include "time/pit.h" -#include "stdlib/link.h" -#include "stdlib/string.h" // ------------------------------------------------------------------------------------------------ // Limits diff --git a/usb/kbd.c b/usb/kbd.c index 1571bc6..e60e536 100644 --- a/usb/kbd.c +++ b/usb/kbd.c @@ -2,13 +2,13 @@ // usb/kbd.c // ------------------------------------------------------------------------------------------------ +#include #include "usb/kbd.h" #include "usb/registry.h" #include "console/console.h" #include "input/input.h" #include "input/keycode.h" #include "mem/vm.h" -#include "stdlib/string.h" // ------------------------------------------------------------------------------------------------ typedef struct UsbKbd diff --git a/usb/req.h b/usb/req.h index 691aa9a..bc87b48 100644 --- a/usb/req.h +++ b/usb/req.h @@ -4,7 +4,7 @@ #pragma once -#include "stdlib/types.h" +#include // ------------------------------------------------------------------------------------------------ // USB Request Type diff --git a/usb/uhci.c b/usb/uhci.c index add23a1..6060e5e 100644 --- a/usb/uhci.c +++ b/usb/uhci.c @@ -2,6 +2,8 @@ // usb/uhci.c // ------------------------------------------------------------------------------------------------ +#include +#include #include "usb/uhci.h" #include "usb/controller.h" #include "usb/dev.h" @@ -10,8 +12,6 @@ #include "pci/driver.h" #include "pci/registry.h" #include "mem/vm.h" -#include "stdlib/link.h" -#include "stdlib/string.h" #include "time/pit.h" // ------------------------------------------------------------------------------------------------ diff --git a/usb/usb.h b/usb/usb.h index f26df04..54bcb23 100644 --- a/usb/usb.h +++ b/usb/usb.h @@ -4,6 +4,6 @@ #pragma once -#include "stdlib/types.h" +#include void UsbPoll(); From c593a0d506c0c0b68d23ad1b5f8a9e08a35a584a Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 9 Dec 2012 18:12:08 -0500 Subject: [PATCH 17/20] add very basic kmalloc --- mem/kmalloc.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ mem/kmalloc.h | 5 +++ 2 files changed, 121 insertions(+) create mode 100644 mem/kmalloc.c create mode 100644 mem/kmalloc.h diff --git a/mem/kmalloc.c b/mem/kmalloc.c new file mode 100644 index 0000000..ab725ab --- /dev/null +++ b/mem/kmalloc.c @@ -0,0 +1,116 @@ +#include +#include "physmem.h" +#include "vm.h" + +#include "kmalloc.h" + +vaddr_t page_head; +vaddr_t page_current; + +typedef struct vmheader +{ + struct vmheader *ptr; + u64 size; +} __attribute__((packed)) vmheader; + +static vmheader vmhead; +static vmheader *vmfree = NULL; + +static void *sbrk(size_t size) +{ + vaddr_t page, pageret; + + if (size == 0) + return 0; + + pageret = page_current; + + for (page=page_current;page < (vaddr_t)page_current + size;page += PAGE_SIZE) { + page_map((paddr_t)PhysmemAlloc(), (vaddr_t)page); + } + + page_current = page; + + return (void *)pageret; +} + +void free(void *ap) +{ + vmheader *bp, *p; + + bp = (vmheader *)ap - 1; + + for (p = vmfree; !(bp > p && bp < p->ptr); p = p->ptr) { + if (p >= p->ptr && (bp > p || bp < p->ptr)) + break; + } + + if (bp + bp->size == p->ptr) { + bp->size += p->ptr->size; + bp->ptr = p->ptr->ptr; + } else { + bp->ptr = p->ptr; + } + if (p + p->size == bp) { + p->size += bp->size; + p->ptr = bp->ptr; + } else { + p->ptr = bp; + } + + vmfree = p; +} + +static vmheader *kmalloc_stretch(size_t size) +{ + char *cp; + vmheader *up; + + if (size < PAGE_SIZE) + size = PAGE_SIZE; + + cp = (char *)sbrk(size * sizeof(vmheader)); + + up = (vmheader *)cp; + up->size = size; + free((void *)(up +1)); + + return vmfree; +} + +void *kmalloc(size_t size) +{ + vmheader *p, *prevp; + size_t cnt; + + cnt = (size + sizeof(vmheader) - 1)/sizeof(vmheader) + 1; + prevp = vmfree; + + if (vmfree == NULL) { + vmhead.ptr = vmfree = prevp = &vmhead; + vmhead.size = 0; + } + + for (p = prevp->ptr; ; prevp = p, p = p->ptr) { + if (p->size >= cnt) { + if (p->size == cnt) { + prevp->ptr = p->ptr; + } else { + p->size -= cnt; + p += p->size; + p->size = cnt; + } + vmfree = prevp; + return (void *)(p+1); + } + if (p == vmfree) + if ((p = kmalloc_stretch(cnt)) == NULL) + return NULL; + } +} + +void kmalloc_init() +{ + page_head = page_current = (vaddr_t)VMBLOCKS_BASE; + vmfree = NULL; +} diff --git a/mem/kmalloc.h b/mem/kmalloc.h new file mode 100644 index 0000000..9434d27 --- /dev/null +++ b/mem/kmalloc.h @@ -0,0 +1,5 @@ +#pragma once + +#define VMBLOCKS_BASE 0x10000000000 // = 1TB +#define VMBLOCKS_SIZE 0x8000000000 +#define VMBLOCKS_TOP (VMBLOCKS_BASE + VMBLOCKS_SIZE) From 20f95117827f027361d4ab908aa395b37c25cbc3 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 9 Dec 2012 18:15:10 -0500 Subject: [PATCH 18/20] fix qemu launch script --- qemu.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qemu.sh b/qemu.sh index 0d3b064..e0780c1 100755 --- a/qemu.sh +++ b/qemu.sh @@ -1,4 +1,3 @@ #!/bin/bash set -ex -kvm -m 5048 -hda os.img -smp cores=4,threads=2 -usbdevice mouse -usbdevice keyboard -#sudo qemu-system-x86_64 -hda os.img -smp cores=4,threads=2 -net nic -net tap,ifname=mac -usbdevice mouse -usbdevice keyboard +kvm -hda os.img -smp cores=4,threads=2 -net nic -net tap,ifname=mac -usbdevice mouse -usbdevice keyboard From ca58cae8a5e10e5bbabd3e1946fe37b2f476f5f7 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sun, 9 Dec 2012 19:59:07 -0500 Subject: [PATCH 19/20] simplify ap init code --- cpu/smp.c | 31 ++++++------------------------- intr/local_apic.c | 21 +++++++++++++++++++++ intr/local_apic.h | 2 ++ 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/cpu/smp.c b/cpu/smp.c index 3f35432..0197c66 100644 --- a/cpu/smp.c +++ b/cpu/smp.c @@ -36,7 +36,7 @@ void spin_unlock(lock_t *lock) lock->current++; } -void testcpu() +static void ap_entrypoint() { ConsolePrint("Hello from CPU %d\n", LocalApicGetId()); @@ -51,34 +51,16 @@ void SmpInit() g_activeCpuCount = 1; uint localId = LocalApicGetId(); - IdtSetHandler(64, INTERRUPT_GATE, testcpu); + // setup temporary interrupt to get CPUs out of trampoline code + IdtSetHandler(64, INTERRUPT_GATE, ap_entrypoint); - // Send Init to all cpus except self - for (uint i = 0; i < g_acpiCpuCount; ++i) - { - uint apicId = g_acpiCpuIds[i]; - if (apicId != localId) - { - LocalApicSendInit(apicId); - } - } - - // wait - PitWait(10); page_map((paddr_t)g_activeCpuCount, (paddr_t)g_activeCpuCount); - // Send Startup to all cpus except self - for (uint i = 0; i < g_acpiCpuCount; ++i) - { - uint apicId = g_acpiCpuIds[i]; - if (apicId != localId) - { - LocalApicSendStartup(apicId, 0x8); - } - } + LocalApicBroadcastInit(); + PitWait(10); + LocalApicBroadcastStartup(0x8); // Wait for all cpus to be active - PitWait(1); while (g_activeCpuCount != g_acpiCpuCount) { PitWait(1); @@ -90,7 +72,6 @@ void SmpInit() if (apicId != localId) { LocalApicSendInt(apicId, 64); - //for(;;); } } ConsolePrint("All CPUs activated\n"); diff --git a/intr/local_apic.c b/intr/local_apic.c index f81ea76..dc16ced 100644 --- a/intr/local_apic.c +++ b/intr/local_apic.c @@ -115,6 +115,27 @@ void LocalApicSendInt(uint apic_id, u8 interrupt) while (LocalApicIn(LAPIC_ICRLO) & ICR_SEND_PENDING) ; } +// ------------------------------------------------------------------------------------------------ +void LocalApicBroadcastInit() +{ + LocalApicOut(LAPIC_ICRHI, 0); + LocalApicOut(LAPIC_ICRLO, ICR_INIT | ICR_PHYSICAL + | ICR_ASSERT | ICR_EDGE | ICR_ALL_EXCLUDING_SELF); + + while (LocalApicIn(LAPIC_ICRLO) & ICR_SEND_PENDING) + ; +} + +// ------------------------------------------------------------------------------------------------ +void LocalApicBroadcastStartup(uint vector) +{ + LocalApicOut(LAPIC_ICRHI, 0); + LocalApicOut(LAPIC_ICRLO, vector | ICR_STARTUP + | ICR_PHYSICAL | ICR_ASSERT | ICR_EDGE | ICR_ALL_EXCLUDING_SELF); + + while (LocalApicIn(LAPIC_ICRLO) & ICR_SEND_PENDING) + ; +} // ------------------------------------------------------------------------------------------------ void LocalApicSendInit(uint apic_id) diff --git a/intr/local_apic.h b/intr/local_apic.h index 0899267..009a55f 100644 --- a/intr/local_apic.h +++ b/intr/local_apic.h @@ -14,3 +14,5 @@ uint LocalApicGetId(); void LocalApicSendInit(uint apic_id); void LocalApicSendStartup(uint apic_id, uint vector); void LocalApicSendInt(uint apic_id, u8 interrupt); +void LocalApicBroadcastInit(); +void LocalApicBroadcastStartup(uint vector); From 82a00141ddd95a0b2c8e51e63c52f863e3202981 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sat, 15 Dec 2012 13:57:51 -0500 Subject: [PATCH 20/20] handle more IDT types --- cpu/smp.c | 2 +- intr/idt.c | 31 +++++++++++++++++++++++++------ intr/idt.h | 5 +++-- intr/intr.c | 4 ++-- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/cpu/smp.c b/cpu/smp.c index 0197c66..0b2c9a4 100644 --- a/cpu/smp.c +++ b/cpu/smp.c @@ -52,7 +52,7 @@ void SmpInit() uint localId = LocalApicGetId(); // setup temporary interrupt to get CPUs out of trampoline code - IdtSetHandler(64, INTERRUPT_GATE, ap_entrypoint); + IdtSetHandler(64, IDT_INT_GATE, ap_entrypoint); page_map((paddr_t)g_activeCpuCount, (paddr_t)g_activeCpuCount); diff --git a/intr/idt.c b/intr/idt.c index 380ab01..cfa820e 100644 --- a/intr/idt.c +++ b/intr/idt.c @@ -18,12 +18,28 @@ typedef struct IdtEntry { u16 offset0; u16 selector; - u16 type; + u8 ist:3; + u8 :5; + u8 type:4; + u8 :1; + u8 dpl:2; + u8 present:1; u16 offset1; u32 offset2; u32 reserved; } PACKED IdtEntry; +typedef struct TaskStateSegment +{ + u32 reserved1; + u64 rsp[3]; + u32 reserved2; + u64 ist[7]; + u32 reserved3; + u16 reserved4; + u16 iomap; +} PACKED TaskStateSegment; + typedef void (*Handler)(); @@ -39,13 +55,13 @@ void IdtInit() // Build initial IDT for (uint i = 0; i < 32; ++i) { - IdtSetHandler(i, INTERRUPT_GATE, exception_wrappers[i]); + IdtSetHandler(i, IDT_INT_GATE, exception_wrappers[i]); exception_functions[i] = (u64)exception_entry; } for (uint i = 32; i < 256; ++i) { - IdtSetHandler(i, TRAP_GATE, default_interrupt_handler); + IdtSetHandler(i, IDT_TRAP_GATE, default_interrupt_handler); } IdtDesc idtDesc = @@ -57,13 +73,16 @@ void IdtInit() } // ------------------------------------------------------------------------------------------------ -static void IdtSetEntry(u8 index, u64 base, u16 selector, u16 type) +static void IdtSetEntry(u8 index, u64 base, u16 selector, u16 type, u8 ist, u8 dpl) { IdtEntry *entry = (IdtEntry *)IDT_BASE + index; entry->offset0 = (u16)base; entry->selector = selector; entry->type = type; + entry->present = 1; + entry->dpl = dpl; + entry->ist = ist; entry->offset1 = (u16)(base >> 16); entry->offset2 = (u32)(base >> 32); entry->reserved = 0; @@ -75,10 +94,10 @@ void IdtSetHandler(u8 index, u16 type, void (*handler)()) if (handler) { u16 selector = 0x8; // gdt.code - IdtSetEntry(index, (u64)handler, selector, type); + IdtSetEntry(index, (u64)handler, selector, type, 0, 0); } else { - IdtSetEntry(index, 0, 0, 0); + IdtSetEntry(index, 0, 0, 0, 0, 0); } } diff --git a/intr/idt.h b/intr/idt.h index 1654271..12a283d 100644 --- a/intr/idt.h +++ b/intr/idt.h @@ -7,8 +7,9 @@ #include // ------------------------------------------------------------------------------------------------ -#define INTERRUPT_GATE 0x8e00 -#define TRAP_GATE 0x8f00 +#define IDT_TASK_GATE 0x5 +#define IDT_INT_GATE 0xE +#define IDT_TRAP_GATE 0xF // ------------------------------------------------------------------------------------------------ void IdtInit(); diff --git a/intr/intr.c b/intr/intr.c index 70eefbb..859f5d9 100644 --- a/intr/intr.c +++ b/intr/intr.c @@ -19,8 +19,8 @@ void IntrInit() { // Build Interrupt Table IdtInit(); - IdtSetHandler(INT_TIMER, INTERRUPT_GATE, pit_interrupt); - IdtSetHandler(INT_SPURIOUS, INTERRUPT_GATE, spurious_interrupt); + IdtSetHandler(INT_TIMER, IDT_INT_GATE, pit_interrupt); + IdtSetHandler(INT_SPURIOUS, IDT_INT_GATE, spurious_interrupt); // Initialize subsystems PicInit();