From 2b727fc7c6ffec6aa5aa3f713a8bf81d0d7b2e99 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 21 Mar 2019 16:42:12 +0200 Subject: [PATCH] [*] initial commit --- .gitignore | 4 ++ Makefile | 28 ++++++++ conf/make/amd64.mk | 24 +++++++ conf/make/none.mk | 3 + doc/Doxyfile | 11 +++ doc/Makefile | 2 + src/arch/amd64/loader/boot.S | 40 +++++++++++ src/arch/amd64/loader/link.ld | 32 +++++++++ src/arch/amd64/loader/loader.c | 4 ++ src/arch/amd64/mm.h | 16 +++++ src/sys/mm.h | 128 +++++++++++++++++++++++++++++++++ 11 files changed, 292 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 conf/make/amd64.mk create mode 100644 conf/make/none.mk create mode 100644 doc/Doxyfile create mode 100644 doc/Makefile create mode 100644 src/arch/amd64/loader/boot.S create mode 100644 src/arch/amd64/loader/link.ld create mode 100644 src/arch/amd64/loader/loader.c create mode 100644 src/arch/amd64/mm.h create mode 100644 src/sys/mm.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..824d37a --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build +.env +doc/html +doc/latex diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0e0cd75 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +ifeq ($(ARCH),) +$(error Target architecture is not specified: $${ARCH}) +endif + +ifeq ($(ARCH),amd64) +CFLAGS+=-DARCH_AMD64 +endif + +export CC?=$(CC) +export CROSSCC?=$(CROSS_COMPILE)$(CC) +export LD?=$(LD) +export CROSSLD?=$(CROSS_COMPILE)$(LD) +export S=$(abspath src) +export O?=$(abspath build) + +include conf/make/none.mk +include conf/make/$(ARCH).mk + +all: mkdirs _doc $(TARGETS) + +clean: + @rm -rf $(O) + +mkdirs: + @mkdir -p $(O) $(DIRS) + +_doc: + @make -sC doc all diff --git a/conf/make/amd64.mk b/conf/make/amd64.mk new file mode 100644 index 0000000..6bd2a50 --- /dev/null +++ b/conf/make/amd64.mk @@ -0,0 +1,24 @@ +all: +### Kernel build +OBJS+= + +### Kernel loader build +TARGETS+=$(O)/loader.elf +DIRS+=$(O)/arch/amd64/loader +loader_OBJS+=$(O)/arch/amd64/loader/boot.o \ + $(O)/arch/amd64/loader/loader.o +loader_LINKER=$(S)/arch/amd64/loader/link.ld +loader_CFLAGS=-ffreestanding -nostdlib -I$(S) -m32 +loader_LDFLAGS=-nostdlib -melf_i386 -T$(loader_LINKER) + +$(O)/loader.elf: $(loader_OBJS) $(HEADERS) $(loader_LINKER) + @printf " LD\t%s\n" $@ + @$(CROSSLD) $(loader_LDFLAGS) -o $@ $(loader_OBJS) + +$(O)/arch/amd64/loader/%.o: $(S)/arch/amd64/loader/%.S + @printf " AS\t%s\n" $@ + @$(CROSSCC) $(loader_CFLAGS) -c -o $@ $< + +$(O)/arch/amd64/loader/%.o: $(S)/arch/amd64/loader/%.c + @printf " CC\t%s\n" $@ + @$(CROSSCC) $(loader_CFLAGS) -c -o $@ $< diff --git a/conf/make/none.mk b/conf/make/none.mk new file mode 100644 index 0000000..b27d7a0 --- /dev/null +++ b/conf/make/none.mk @@ -0,0 +1,3 @@ +HEADERS=$(shell find $(S) -name "*.h") + +OBJS+= diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..a213a6a --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,11 @@ +PROJECT_NAME = "Yggdrasil Kernel" +INPUT = $(S) +RECURSIVE = YES +EXTRACT_STATIC = YES +EXTRACT_PRIVATE = YES +EXTRACT_ALL = YES +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +ENABLE_PREPROCESSING = YES +HAVE_DOT = NO +SORT_MEMBER_DOCS = NO diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..f9911f6 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,2 @@ +all: + S=.. doxygen Doxyfile >/dev/null diff --git a/src/arch/amd64/loader/boot.S b/src/arch/amd64/loader/boot.S new file mode 100644 index 0000000..1ec6a40 --- /dev/null +++ b/src/arch/amd64/loader/boot.S @@ -0,0 +1,40 @@ +.set ALIGN, 1 << 0 +.set MEMINFO, 1 << 1 +.set FLAGS, ALIGN | MEMINFO +.set MAGIC, 0x1BADB002 +.set CHECKSUM, -(MAGIC + FLAGS) + +.section .multiboot +.align 4 +.long MAGIC +.long FLAGS +.long CHECKSUM + +.section .bss +stack_bottom: + .skip 65536 +stack_top: + +.section .text +.global _start +_start: + // Setup stack + mov $stack_top, %esp + + //push %ebx + //push %eax + + // Check if the CPU supports long mode + mov $0x80000001, %eax + cpuid + test $(1 << 29), %edx + jz .not_supported + + // call loader_entry + // add $8, %esp +1: + cli + hlt + jmp 1b +.not_supported: + jmp 1b diff --git a/src/arch/amd64/loader/link.ld b/src/arch/amd64/loader/link.ld new file mode 100644 index 0000000..795fa66 --- /dev/null +++ b/src/arch/amd64/loader/link.ld @@ -0,0 +1,32 @@ +/* + * amd64 loader linker script + * (this is not kernel) + */ + +ENTRY(_start) + +SECTIONS { + . = 0x100000; + + .text : ALIGN(4K) + { + *(.multiboot) + *(.text) + } + + .rodata : ALIGN(4K) + { + *(.rodata) + } + + .data : ALIGN(4K) + { + *(.data) + } + + .bss : ALIGN(4K) + { + *(COMMON) + *(.bss) + } +} diff --git a/src/arch/amd64/loader/loader.c b/src/arch/amd64/loader/loader.c new file mode 100644 index 0000000..69d9b47 --- /dev/null +++ b/src/arch/amd64/loader/loader.c @@ -0,0 +1,4 @@ + +void loader_main(void) { + while (1) {} +} diff --git a/src/arch/amd64/mm.h b/src/arch/amd64/mm.h new file mode 100644 index 0000000..551d99c --- /dev/null +++ b/src/arch/amd64/mm.h @@ -0,0 +1,16 @@ +#pragma once + +/// The place where the kernel pages are virtually mapped to +#define KERNEL_VIRT_BASE 0xFFFFFF0000000000 + +/// Page map level 4 +typedef uint64_t *mm_pml4_t; +/// Page directory pointer table +typedef uint64_t *mm_pdpt_t; +/// Page directory +typedef uint64_t *mm_pagedir_t; +/// Page table +typedef uint64_t *mm_pagetab_t; + +/// Virtual memory space +typedef mm_pml4_t mm_space_t; diff --git a/src/sys/mm.h b/src/sys/mm.h new file mode 100644 index 0000000..983969c --- /dev/null +++ b/src/sys/mm.h @@ -0,0 +1,128 @@ +#pragma once +#include +#include + +#if defined(ARCH_AMD64) +#include "arch/amd64/mm.h" +#endif + +/// An invalid address analogous to NULL +#define MM_NADDR ((uintptr_t) -1) + +#define userspace + +/** + * @brief Creates a virtual memory space with underlying data structures specific to current + * platform + */ +mm_space_t mm_space_create(void); + +/** + * @brief Copies the mappings from one memory space to another preserving the original physical + * pages + * @param dst - Destination space + * @param src - Source space + * @param flags - Flags: + * * MM_CLONE_FLG_KERNEL - clone kernel-region mappings + * * MM_CLONE_FLG_USER - clone userspace mappings + * @return 0 on success + * @return Non-zero values in case of error + */ +int mm_space_clone(mm_space_t dst, const mm_space_t src, uint32_t flags); + +/** + * @brief Performs a "fork" of a memory space: copies the original mappings to the destination space + * and optionally replaces userspace mappings with cloned physical pages + * @param dst - Destination space + * @param src - Source space + * @param flags - Flags: + * * MM_CLONE_FLG_KERNEL - clone kernel-region mappings + * * MM_CLONE_FLG_USER - clone userspace mappings and underlying physical pages + * @return 0 on success + * @return Non-zero values in case of error + */ +int mm_space_fork(mm_space_t dst, const mm_space_t src, uint32_t flags); + +/** + * @brief Destroy the virtual memory space and free used resources + * @param pd - Virtual memory space + */ +void mm_space_free(mm_space_t pd); + + +/** + * @brief Map a contiguous physical memory region to a contiguous virtual memory region + * @param pd - Memory space + * @param virt_base - Beginning of the virtual memory range + * @param phys_base - Beginning of the physical memory range + * @param count - Count of pages to be mapped + * @param flags - Flags: + * * MM_FLG_WR - Writable + * * MM_FLG_US - Available for userspace + * @return 0 on success + * @return Non-zero values in case of error + */ +int mm_map_pages_contiguous(mm_space_t pd, uintptr_t virt_base, uintptr_t phys_base, size_t count, uint32_t flags); + +/** + * @brief Map a set of physical pages to a virtual memory region + * @param pd - Memory space + * @param virt_base - Beginning of the virtual memory range + * @param pages - Array of physical pages to be mapped + * @param count - Count of pages to be mapped + * @param flags - Flags: + * * MM_FLG_WR - Writable + * * MM_FLG_US - Available for userspace + * @return 0 on success + * @return Non-zero values in case of error + */ +int mm_map_range_pages(mm_space_t pd, uintptr_t virt_base, uintptr_t *pages, size_t count, uint32_t flags); + +/** + * @brief Remove virtual memory mappings for the specified region, optionally de-allocating the + * underlying physical memory pages + * @param pd - Memory space + * @param virt_base - Beginning of the virtual memory range + * @param count - Count of pages to unmap + * @param flags - Flags: + * * MM_FLG_NOPHYS - Don't de-allocate the physical pages used by the mappings + * @return 0 on success + * @return Non-zero values in case of error + */ +int mm_umap_range(mm_space_t pd, uintptr_t virt_base, size_t count, uint32_t flags); + +/** + * @brief Translate a virtual memory address to its physical counterpart + * @param pd - Memory space + * @param virt - Virtual address + * @param rflags - (output, nullable) variable to store the mapping's flags: + * * MM_FLG_WR + * * MM_FLG_US + * @return Physical address if the mapping is present + * @return MM_NADDR if the mapping is not present + */ +uintptr_t mm_translate(mm_space_t pd, uintptr_t virt, uint32_t *rflags); + + + +/** + * @brief Copy data from kernel memory space to user + * @param pd - Memory space + * @param dst - Destination address + * @param src - Source address + * @param count - Number of bytes to transfer + * @return Number of bytes copied on success + * @return -1 on error + */ +int mm_memcpy_kernel_to_user(mm_space_t pd, userspace void *dst, const void *src, size_t count); + +/** + * @brief Copy data from user memory space to kernel + * @param pd - Memory space + * @param dst - Destination address + * @param src - Source address + * @param count - Number of bytes to transfer + * @return Number of bytes copied on success + * @return -1 on error + */ +int mm_memcpy_user_to_kernel(mm_space_t pd, void *dst, const userspace void *src, size_t count);