diff --git a/.vscode/settings.json b/.vscode/settings.json index 9c0c36db..8ddd4749 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -124,12 +124,9 @@ "mm-types.h": "c", "vfs.h": "c", "current.h": "c", - "proc-types.h": "c", "traceback.h": "c", "bitcount.h": "c", "limits.h": "c", - "block.h": "c", - "blk_types.h": "c", "mutex.h": "c", "mount.h": "c", "internal.h": "c", @@ -173,7 +170,8 @@ "cmpxchg.h": "c", "mman.h": "c", "clocksource.h": "c", - "ata.h": "c" + "ata.h": "c", + "barrier": "c" }, "C_Cpp.errorSquiggles": "enabled", "esbonio.sphinx.confDir": "", diff --git a/build-scripts/kernel_build/src/cfiles/arch/x86_64.rs b/build-scripts/kernel_build/src/cfiles/arch/x86_64.rs index 88e6d18c..a0a12013 100644 --- a/build-scripts/kernel_build/src/cfiles/arch/x86_64.rs +++ b/build-scripts/kernel_build/src/cfiles/arch/x86_64.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use cc::Build; -use crate::utils::FileUtils; +use crate::{constant::ARCH_DIR_X86_64, utils::FileUtils}; use super::CFilesArch; @@ -18,10 +18,26 @@ impl CFilesArch for X86_64CFilesArch { } fn setup_files(&self, _c: &mut Build, files: &mut Vec) { - files.push(PathBuf::from("src/arch/x86_64/driver/hpet.c")); + files.push(arch_path("driver/hpet.c")); // 获取`kernel/src/arch/x86_64/driver/apic`下的所有C文件 files.append(&mut FileUtils::list_all_files( - &PathBuf::from("src/arch/x86_64/driver/apic"), + &arch_path("driver/apic"), + Some("c"), + true, + )); + + files.append(&mut FileUtils::list_all_files( + &arch_path("init"), + Some("c"), + true, + )); + files.append(&mut FileUtils::list_all_files( + &arch_path("asm"), + Some("c"), + true, + )); + files.append(&mut FileUtils::list_all_files( + &arch_path("interrupt"), Some("c"), true, )); @@ -36,3 +52,7 @@ impl CFilesArch for X86_64CFilesArch { c.asm_flag("-m64"); } } + +fn arch_path(relative_path: &str) -> PathBuf { + PathBuf::from(format!("{}/{}", ARCH_DIR_X86_64, relative_path)) +} diff --git a/build-scripts/kernel_build/src/constant/mod.rs b/build-scripts/kernel_build/src/constant/mod.rs new file mode 100644 index 00000000..7bd10304 --- /dev/null +++ b/build-scripts/kernel_build/src/constant/mod.rs @@ -0,0 +1 @@ +pub const ARCH_DIR_X86_64: &str = "src/arch/x86_64"; diff --git a/build-scripts/kernel_build/src/lib.rs b/build-scripts/kernel_build/src/lib.rs index 2cc809f1..21844c53 100644 --- a/build-scripts/kernel_build/src/lib.rs +++ b/build-scripts/kernel_build/src/lib.rs @@ -4,6 +4,7 @@ extern crate cc; mod bindgen; mod cfiles; +mod constant; mod kconfig; mod utils; diff --git a/kernel/src/Makefile b/kernel/src/Makefile index ac7ac8f4..0da4a15e 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -26,21 +26,16 @@ export ASFLAGS := --64 LD_LIST := "" -kernel_subdirs := common driver debug arch exception smp syscall ktest libs time +kernel_subdirs := common driver debug exception smp syscall ktest libs time -main.o: main.c -# -fno-builtin: 不使用C语言内建函数 -# The -m64 option sets int to 32bits and long and pointer to 64 bits and generates code for AMD’s x86-64 architecture. - $(CC) $(CFLAGS) -c main.c -o main.o - kernel_rust: RUSTFLAGS="$(RUSTFLAGS_UNWIND)" cargo +nightly-2023-01-21 build --release --target ./arch/x86_64/x86_64-unknown-none.json all: kernel @echo "Linking kernel..." - $(LD) -b elf64-x86-64 -z muldefs $(LDFLAGS_UNWIND) -o kernel main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a -T link.lds --no-relax + $(LD) -b elf64-x86-64 -z muldefs $(LDFLAGS_UNWIND) -o kernel $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a -T link.lds --no-relax # 生成kallsyms current_dir=$(pwd) @@ -54,7 +49,7 @@ all: kernel # 重新链接 @echo "Re-Linking kernel..." @echo $(shell find . -name "*.o") - $(LD) -b elf64-x86-64 -z muldefs $(LDFLAGS_UNWIND) -o kernel main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a ./debug/kallsyms.o -T link.lds --no-relax + $(LD) -b elf64-x86-64 -z muldefs $(LDFLAGS_UNWIND) -o kernel $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a ./debug/kallsyms.o -T link.lds --no-relax @echo "Generating kernel ELF file..." # 生成内核文件 ifeq ($(UNWIND_ENABLE), yes) @@ -71,7 +66,7 @@ $(kernel_subdirs): ECHO $(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" kernel_root_path="$(shell pwd)" -kernel: main.o $(kernel_subdirs) kernel_rust +kernel: $(kernel_subdirs) kernel_rust diff --git a/kernel/src/arch/Makefile b/kernel/src/arch/Makefile deleted file mode 100644 index e4b68c0f..00000000 --- a/kernel/src/arch/Makefile +++ /dev/null @@ -1,17 +0,0 @@ - -CFLAGS += -I . - -ifeq ($(ARCH), __x86_64__) -kernel_arch_subdirs:=x86_64 -endif - -all: - @list='$(kernel_arch_subdirs)'; for subdir in $$list; do \ - echo "make all in $$subdir";\ - cd $$subdir;\ - $(MAKE) all CFLAGS="$(CFLAGS)" ;\ - cd ..;\ - done - -clean: - echo "Done." \ No newline at end of file diff --git a/kernel/src/arch/x86_64/Makefile b/kernel/src/arch/x86_64/Makefile deleted file mode 100644 index e11e5a78..00000000 --- a/kernel/src/arch/x86_64/Makefile +++ /dev/null @@ -1,23 +0,0 @@ - -CFLAGS += -I . - -kernel_arch_x86_64_subdirs:= asm - -kernel_arch_x86_64_objs:= $(shell find ./*.c) - -ECHO: - @echo "$@" - - -$(kernel_arch_x86_64_objs): ECHO - $(CC) $(CFLAGS) -c $@ -o $@.o - -$(kernel_arch_x86_64_subdirs): ECHO - $(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" - -all: $(kernel_arch_x86_64_objs) $(kernel_arch_x86_64_subdirs) - - - -clean: - echo "Done." \ No newline at end of file diff --git a/kernel/src/arch/x86_64/asm/Makefile b/kernel/src/arch/x86_64/asm/Makefile deleted file mode 100644 index 6fa03e03..00000000 --- a/kernel/src/arch/x86_64/asm/Makefile +++ /dev/null @@ -1,22 +0,0 @@ - -CFLAGS += -I . - -# kernel_arch_x86_64_asm_subdirs:= - -kernel_arch_x86_64_asm_objs:= $(shell find ./*.c) - -ECHO: - @echo "$@" - - -$(kernel_arch_x86_64_asm_objs): ECHO - $(CC) $(CFLAGS) -c $@ -o $@.o - -# $(kernel_arch_x86_64_asm_subdirs): ECHO -# $(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" - -all: $(kernel_arch_x86_64_asm_objs) - - -clean: - echo "Done." \ No newline at end of file diff --git a/kernel/src/arch/x86_64/asm/head.S b/kernel/src/arch/x86_64/asm/head.S index 14962276..4e043db1 100644 --- a/kernel/src/arch/x86_64/asm/head.S +++ b/kernel/src/arch/x86_64/asm/head.S @@ -300,7 +300,7 @@ ENTRY(_start64) // 50-100M填0,共25个页表 mov $12800, %ecx .fill_pt_64_2: - mov $0, 0(%eax) + movq $0, 0(%eax) add $8, %eax loop .fill_pt_64_2 diff --git a/kernel/src/arch/x86_64/include/asm/asm.h b/kernel/src/arch/x86_64/include/asm/asm.h index ae7eee17..d65abb68 100644 --- a/kernel/src/arch/x86_64/include/asm/asm.h +++ b/kernel/src/arch/x86_64/include/asm/asm.h @@ -1,16 +1,26 @@ #pragma once #include +#include +#include + +// 定义类型的缩写 +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ul; +typedef unsigned long long int ull; +typedef long long int ll; #define sti() __asm__ __volatile__("sti\n\t" :: \ - : "memory") //开启外部中断 + : "memory") // 开启外部中断 #define cli() __asm__ __volatile__("cli\n\t" :: \ - : "memory") //关闭外部中断 + : "memory") // 关闭外部中断 #define nop() __asm__ __volatile__("nop\n\t") #define hlt() __asm__ __volatile__("hlt\n\t") #define pause() asm volatile("pause\n\t"); // 处理器等待一段时间 -//内存屏障 +// 内存屏障 #define io_mfence() __asm__ __volatile__("mfence\n\t" :: \ : "memory") // 在mfence指令前的读写操作必须在mfence指令后的读写操作前完成。 #define io_sfence() __asm__ __volatile__("sfence\n\t" :: \ @@ -54,6 +64,22 @@ unsigned long *get_rsp() return tmp; } +/** + * @brief 验证地址空间是否为用户地址空间 + * + * @param addr_start 地址起始值 + * @param length 地址长度 + * @return true + * @return false + */ +bool verify_area(uint64_t addr_start, uint64_t length) +{ + if ((addr_start + length) <= 0x00007fffffffffffUL) // 用户程序可用的的地址空间应<= 0x00007fffffffffffUL + return true; + else + return false; +} + /** * @brief 读取rbp寄存器的值(存储了页目录的基地址) * @@ -146,4 +172,248 @@ uint64_t get_rflags() "popfq \n\t" : "=r"(tmp)::"memory"); return tmp; +} + +void *memset(void *dst, unsigned char C, ul size) +{ + + int d0, d1; + unsigned long tmp = C * 0x0101010101010101UL; + __asm__ __volatile__("cld \n\t" + "rep \n\t" + "stosq \n\t" + "testb $4, %b3 \n\t" + "je 1f \n\t" + "stosl \n\t" + "1:\ttestb $2, %b3 \n\t" + "je 2f\n\t" + "stosw \n\t" + "2:\ttestb $1, %b3 \n\t" + "je 3f \n\t" + "stosb \n\t" + "3: \n\t" + : "=&c"(d0), "=&D"(d1) + : "a"(tmp), "q"(size), "0"(size / 8), "1"(dst) + : "memory"); + return dst; +} + +void *memset_c(void *dst, uint8_t c, size_t count) +{ + uint8_t *xs = (uint8_t *)dst; + + while (count--) + *xs++ = c; + + return dst; +} + +/** + * @brief 内存拷贝函数 + * + * @param dst 目标数组 + * @param src 源数组 + * @param Num 字节数 + * @return void* + */ +static void *memcpy(void *dst, const void *src, long Num) +{ + int d0 = 0, d1 = 0, d2 = 0; + __asm__ __volatile__("cld \n\t" + "rep \n\t" + "movsq \n\t" + "testb $4,%b4 \n\t" + "je 1f \n\t" + "movsl \n\t" + "1:\ttestb $2,%b4 \n\t" + "je 2f \n\t" + "movsw \n\t" + "2:\ttestb $1,%b4 \n\t" + "je 3f \n\t" + "movsb \n\t" + "3: \n\t" + : "=&c"(d0), "=&D"(d1), "=&S"(d2) + : "0"(Num / 8), "q"(Num), "1"(dst), "2"(src) + : "memory"); + return dst; +} + +// 从io口读入8个bit +unsigned char io_in8(unsigned short port) +{ + unsigned char ret = 0; + __asm__ __volatile__("inb %%dx, %0 \n\t" + "mfence \n\t" + : "=a"(ret) + : "d"(port) + : "memory"); + return ret; +} + +// 从io口读入32个bit +unsigned int io_in32(unsigned short port) +{ + unsigned int ret = 0; + __asm__ __volatile__("inl %%dx, %0 \n\t" + "mfence \n\t" + : "=a"(ret) + : "d"(port) + : "memory"); + return ret; +} + +// 输出8个bit到输出端口 +void io_out8(unsigned short port, unsigned char value) +{ + __asm__ __volatile__("outb %0, %%dx \n\t" + "mfence \n\t" + : + : "a"(value), "d"(port) + : "memory"); +} + +// 输出32个bit到输出端口 +void io_out32(unsigned short port, unsigned int value) +{ + __asm__ __volatile__("outl %0, %%dx \n\t" + "mfence \n\t" + : + : "a"(value), "d"(port) + : "memory"); +} + +/** + * @brief 从端口读入n个word到buffer + * + */ +#define io_insw(port, buffer, nr) \ + __asm__ __volatile__("cld;rep;insw;mfence;" ::"d"(port), "D"(buffer), "c"(nr) \ + : "memory") + +/** + * @brief 从输出buffer中的n个word到端口 + * + */ +#define io_outsw(port, buffer, nr) \ + __asm__ __volatile__("cld;rep;outsw;mfence;" ::"d"(port), "S"(buffer), "c"(nr) \ + : "memory") + +/** + * @brief 从用户空间搬运数据到内核空间 + * + * @param dst 目的地址 + * @param src 源地址 + * @param size 搬运的大小 + * @return uint64_t + */ +static inline uint64_t copy_from_user(void *dst, void *src, uint64_t size) +{ + uint64_t tmp0, tmp1; + if (!verify_area((uint64_t)src, size)) + return 0; + + /** + * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运 + * + */ + asm volatile("rep \n\t" + "movsq \n\t" + "movq %3, %0 \n\t" + "rep \n\t" + "movsb \n\t" + : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1) + : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src) + : "memory"); + return size; +} + +/** + * @brief 从内核空间搬运数据到用户空间 + * + * @param dst 目的地址 + * @param src 源地址 + * @param size 搬运的大小 + * @return uint64_t + */ +static inline uint64_t copy_to_user(void *dst, void *src, uint64_t size) +{ + if (verify_area((uint64_t)src, size)) + return 0; + + /** + * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运 + * + */ + // todo:编译有bug + // asm volatile("rep \n\t" + // "movsq \n\t" + // "movq %3, %0 \n\t" + // "rep \n\t" + // "movsb \n\t" + // : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1) + // : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src) + // : "memory"); + memcpy(dst, src, size); + + return size; +} + +/** + * @brief 往指定地址写入8字节 + * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候) + * + * @param vaddr 虚拟地址 + * @param value 要写入的值 + */ +static __always_inline void __write8b(uint64_t vaddr, uint64_t value) +{ + asm volatile("movq %%rdx, 0(%%rax)" ::"a"(vaddr), "d"(value) + : "memory"); +} + +/** + * @brief 往指定地址写入4字节 + * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候) + * + * @param vaddr 虚拟地址 + * @param value 要写入的值 + */ +static __always_inline void __write4b(uint64_t vaddr, uint32_t value) +{ + asm volatile("movl %%edx, 0(%%rax)" ::"a"(vaddr), "d"(value) + : "memory"); +} + +/** + * @brief 从指定地址读取8字节 + * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候) + * + * @param vaddr 虚拟地址 + * @return uint64_t 读取到的值 + */ +static __always_inline uint64_t __read8b(uint64_t vaddr) +{ + uint64_t retval; + asm volatile("movq 0(%%rax), %0" + : "=r"(retval) + : "a"(vaddr) + : "memory"); + return retval; +} + +/** + * @brief 从指定地址读取4字节 + * 防止由于编译器优化导致不支持的内存访问类型(尤其是在mmio的时候) + * + * @param vaddr 虚拟地址 + * @return uint64_t 读取到的值 + */ +static __always_inline uint32_t __read4b(uint64_t vaddr) +{ + uint32_t retval; + asm volatile("movl 0(%%rax), %0" + : "=d"(retval) + : "a"(vaddr) + : "memory"); + return retval; } \ No newline at end of file diff --git a/kernel/src/arch/x86_64/x86_64_ipi.h b/kernel/src/arch/x86_64/include/x86_64_ipi.h similarity index 100% rename from kernel/src/arch/x86_64/x86_64_ipi.h rename to kernel/src/arch/x86_64/include/x86_64_ipi.h diff --git a/kernel/src/arch/x86_64/init/main.c b/kernel/src/arch/x86_64/init/main.c new file mode 100644 index 00000000..cca47362 --- /dev/null +++ b/kernel/src/arch/x86_64/init/main.c @@ -0,0 +1,219 @@ +// +// Created by longjin on 2022/1/20. +// + +#include "common/glib.h" +#include "common/kprint.h" +#include "common/printk.h" +#include "exception/gate.h" +#include "exception/irq.h" +#include "exception/trap.h" +#include "mm/mm.h" +#include "mm/slab.h" +#include "process/process.h" +#include "smp/smp.h" +#include "syscall/syscall.h" +#include +#include +#include +#include +#include + +#include + +#include "driver/acpi/acpi.h" +#include "driver/disk/ata.h" +#include "driver/keyboard/ps2_keyboard.h" +#include "driver/mouse/ps2_mouse.h" +#include "driver/multiboot2/multiboot2.h" +#include