diff --git a/kernel/.cargo/config.toml b/kernel/.cargo/config.toml index fbf166c4..3cacb135 100644 --- a/kernel/.cargo/config.toml +++ b/kernel/.cargo/config.toml @@ -2,7 +2,7 @@ target = "src/arch/x86_64/x86_64-unknown-none.json" [unstable] -build-std = ["core", "compiler_builtins"] +build-std = ["core", "compiler_builtins", "alloc"] build-std-features = ["compiler-builtins-mem"] [target.'cfg(target_os = "none")'] diff --git a/kernel/build.rs b/kernel/build.rs index c6d4a1eb..c2c90f90 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -11,7 +11,7 @@ fn main() { println!("cargo:rustc-link-search=src"); println!("cargo:rerun-if-changed=src/include/bindings/wrapper.h"); - let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + // let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let out_path = PathBuf::from(String::from("src/include/bindings/")); // The bindgen::Builder is the main entry point diff --git a/kernel/src/Makefile b/kernel/src/Makefile index feae39e6..e94bd5e3 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -3,7 +3,7 @@ DIRS := . $(shell find $(SUBDIR_ROOTS) -type d) GARBAGE_PATTERNS := *.o *.s~ *.s *.S~ *.c~ *.h~ kernel GARBAGE := $(foreach DIR,$(DIRS),$(addprefix $(DIR)/,$(GARBAGE_PATTERNS))) -DIR_LIB=lib +DIR_LIB=libs lib_patterns := *.a LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns))) @@ -17,7 +17,7 @@ export ASFLAGS := --64 LD_LIST := head.o -kernel_subdirs := common driver process debug filesystem time arch exception mm smp sched syscall ktest lib ipc +kernel_subdirs := common driver process debug filesystem time arch exception mm smp sched syscall ktest libs ipc @@ -34,8 +34,9 @@ main.o: main.c kernel_rust: rustup default nightly cargo +nightly build --release --target ./arch/x86_64/x86_64-unknown-none.json -all: kernel_rust - $(MAKE) kernel || exit 1 + +all: kernel + @echo "Linking kernel..." ld -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a -T link.lds # 生成kallsyms @@ -53,6 +54,7 @@ all: kernel_rust # 重新链接 @echo "Re-Linking kernel..." + @echo $(shell find . -name "*.o") ld -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a ./debug/kallsyms.o -T link.lds @echo "Generating kernel ELF file..." # 生成内核文件 @@ -66,7 +68,7 @@ $(kernel_subdirs): ECHO $(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" PIC="$(PIC)" kernel_root_path="$(shell pwd)" -kernel: head.o main.o $(kernel_subdirs) +kernel: head.o main.o $(kernel_subdirs) kernel_rust diff --git a/kernel/src/common/printk.h b/kernel/src/common/printk.h index 3698674c..74977743 100644 --- a/kernel/src/common/printk.h +++ b/kernel/src/common/printk.h @@ -33,7 +33,7 @@ #include "font.h" #include "glib.h" -#include +#include #include extern unsigned char font_ascii[256][16]; //导出ascii字体的bitmap(8*16大小) ps:位于font.h中 diff --git a/kernel/src/driver/video/video.h b/kernel/src/driver/video/video.h index a20bf26a..ce37252c 100644 --- a/kernel/src/driver/video/video.h +++ b/kernel/src/driver/video/video.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include /** * @brief 重新初始化显示驱动,需先低级初始化才能高级初始化 diff --git a/kernel/src/include/bindings/wrapper.h b/kernel/src/include/bindings/wrapper.h index db6bdbb7..c3dc0d0b 100644 --- a/kernel/src/include/bindings/wrapper.h +++ b/kernel/src/include/bindings/wrapper.h @@ -15,12 +15,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include diff --git a/kernel/src/include/gfp.rs b/kernel/src/include/gfp.rs new file mode 100644 index 00000000..2f4cba54 --- /dev/null +++ b/kernel/src/include/gfp.rs @@ -0,0 +1,5 @@ +use crate::include::bindings::bindings::gfp_t; + +#[allow(unused_parens)] +/// 定义__GFP_ZERO +pub const __GFP_ZERO: gfp_t = (1 << 0); diff --git a/kernel/src/include/mod.rs b/kernel/src/include/mod.rs index 44946577..e191dcdb 100644 --- a/kernel/src/include/mod.rs +++ b/kernel/src/include/mod.rs @@ -1 +1,4 @@ -pub mod bindings; \ No newline at end of file +pub mod bindings; +pub mod gfp; +pub mod printk; + diff --git a/kernel/src/include/printk.rs b/kernel/src/include/printk.rs new file mode 100644 index 00000000..a7aa30ab --- /dev/null +++ b/kernel/src/include/printk.rs @@ -0,0 +1,45 @@ +#![allow(unused)] +// ====== 定义颜色 ====== +/// 白色 +pub const COLOR_WHITE: u32 = 0x00ffffff; +/// 黑色 +pub const COLOR_BLACK: u32 = 0x00000000; +/// 红色 +pub const COLOR_RED:u32 = 0x00ff0000; +/// 橙色 +pub const COLOR_ORANGE:u32 = 0x00ff8000; +/// 黄色 +pub const COLOR_YELLOW:u32 = 0x00ffff00; +/// 绿色 +pub const COLOR_GREEN:u32 = 0x0000ff00; +/// 蓝色 +pub const COLOR_BLUE:u32 = 0x000000ff; +/// 靛色 +pub const COLOR_INDIGO:u32 = 0x0000ffff; +/// 紫色 +pub const COLOR_PURPLE:u32 = 0x008000ff; + +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::libs::printk::__printk(format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! println { + () => { + $crate::print!("\n"); + }; + ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); +} + +/// 指定颜色,彩色输出 +/// @param FRcolor 前景色 +/// @param BKcolor 背景色 +#[macro_export] +macro_rules! printk_color { + + ($FRcolor:expr, $BKcolor:expr, $($arg:tt)*) => { + use alloc; + $crate::libs::printk::PrintkWriter.__write_string_color($FRcolor, $BKcolor, alloc::fmt::format(format_args!($($arg)*)).as_str()) + }; +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 38eeac47..b30b8daf 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,32 +1,44 @@ -#![no_std] // <1> -#![no_main] // <1> -#![feature(core_intrinsics)] // <2> +#![no_std] // <1> +#![no_main] // <1> +#![feature(core_intrinsics)] // <2> +#![feature(alloc_error_handler)] + #[allow(non_upper_case_globals)] #[allow(non_camel_case_types)] #[allow(non_snake_case)] +use core::intrinsics; // <2> +use core::panic::PanicInfo; + + #[macro_use] mod mm; mod include; +mod libs; -use crate::mm::allocator; -use core::ffi::c_char; -use core::intrinsics; // <2> -use core::panic::PanicInfo; // <3> -use crate::include::bindings::bindings::{printk_color, GREEN, BLACK}; +extern crate alloc; +use mm::allocator::KernelAllocator; +// <3> +use crate::include::bindings::bindings::{BLACK, GREEN}; + +// 声明全局的slab分配器 +#[cfg_attr(not(test), global_allocator)] +pub static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator {}; + +/// 全局的panic处理函数 #[panic_handler] #[no_mangle] pub fn panic(_info: &PanicInfo) -> ! { - intrinsics::abort(); // <4> + intrinsics::abort(); // <4> } +/// 该函数用作测试,在process.c的initial_kernel_thread()中调用了此函数 #[no_mangle] pub extern "C" fn __rust_demo_func() -> i32 { - unsafe{ - let f = b"\nDragonOS's Rust lib called printk_color()\n".as_ptr() as *const c_char; - printk_color(GREEN, BLACK, f); - } - return 0; + + printk_color!(GREEN, BLACK, "__rust_demo_func()\n"); + + return 0; } diff --git a/kernel/src/lib/Makefile b/kernel/src/libs/Makefile similarity index 100% rename from kernel/src/lib/Makefile rename to kernel/src/libs/Makefile diff --git a/kernel/src/lib/bitree.c b/kernel/src/libs/bitree.c similarity index 100% rename from kernel/src/lib/bitree.c rename to kernel/src/libs/bitree.c diff --git a/kernel/src/lib/cpu.c b/kernel/src/libs/cpu.c similarity index 100% rename from kernel/src/lib/cpu.c rename to kernel/src/libs/cpu.c diff --git a/kernel/src/lib/crc16.c b/kernel/src/libs/crc16.c similarity index 100% rename from kernel/src/lib/crc16.c rename to kernel/src/libs/crc16.c diff --git a/kernel/src/lib/crc32.c b/kernel/src/libs/crc32.c similarity index 100% rename from kernel/src/lib/crc32.c rename to kernel/src/libs/crc32.c diff --git a/kernel/src/lib/crc64.c b/kernel/src/libs/crc64.c similarity index 100% rename from kernel/src/lib/crc64.c rename to kernel/src/libs/crc64.c diff --git a/kernel/src/lib/crc7.c b/kernel/src/libs/crc7.c similarity index 100% rename from kernel/src/lib/crc7.c rename to kernel/src/libs/crc7.c diff --git a/kernel/src/lib/crc8.c b/kernel/src/libs/crc8.c similarity index 100% rename from kernel/src/lib/crc8.c rename to kernel/src/libs/crc8.c diff --git a/kernel/src/lib/glib.c b/kernel/src/libs/glib.c similarity index 100% rename from kernel/src/lib/glib.c rename to kernel/src/libs/glib.c diff --git a/kernel/src/lib/idr.c b/kernel/src/libs/idr.c similarity index 100% rename from kernel/src/lib/idr.c rename to kernel/src/libs/idr.c diff --git a/kernel/src/lib/kfifo.c b/kernel/src/libs/kfifo.c similarity index 100% rename from kernel/src/lib/kfifo.c rename to kernel/src/libs/kfifo.c diff --git a/kernel/src/lib/libELF/Makefile b/kernel/src/libs/libELF/Makefile similarity index 100% rename from kernel/src/lib/libELF/Makefile rename to kernel/src/libs/libELF/Makefile diff --git a/kernel/src/lib/libELF/elf.c b/kernel/src/libs/libELF/elf.c similarity index 100% rename from kernel/src/lib/libELF/elf.c rename to kernel/src/libs/libELF/elf.c diff --git a/kernel/src/lib/libUI/Makefile b/kernel/src/libs/libUI/Makefile similarity index 100% rename from kernel/src/lib/libUI/Makefile rename to kernel/src/libs/libUI/Makefile diff --git a/kernel/src/lib/libUI/screen_manager.c b/kernel/src/libs/libUI/screen_manager.c similarity index 100% rename from kernel/src/lib/libUI/screen_manager.c rename to kernel/src/libs/libUI/screen_manager.c diff --git a/kernel/src/lib/libUI/screen_manager.h b/kernel/src/libs/libUI/screen_manager.h similarity index 100% rename from kernel/src/lib/libUI/screen_manager.h rename to kernel/src/libs/libUI/screen_manager.h diff --git a/kernel/src/lib/libUI/textui-render.c b/kernel/src/libs/libUI/textui-render.c similarity index 100% rename from kernel/src/lib/libUI/textui-render.c rename to kernel/src/libs/libUI/textui-render.c diff --git a/kernel/src/lib/libUI/textui.c b/kernel/src/libs/libUI/textui.c similarity index 100% rename from kernel/src/lib/libUI/textui.c rename to kernel/src/libs/libUI/textui.c diff --git a/kernel/src/lib/libUI/textui.h b/kernel/src/libs/libUI/textui.h similarity index 100% rename from kernel/src/lib/libUI/textui.h rename to kernel/src/libs/libUI/textui.h diff --git a/kernel/src/lib/lockref.c b/kernel/src/libs/lockref.c similarity index 100% rename from kernel/src/lib/lockref.c rename to kernel/src/libs/lockref.c diff --git a/kernel/src/lib/lz4.c b/kernel/src/libs/lz4.c similarity index 100% rename from kernel/src/lib/lz4.c rename to kernel/src/libs/lz4.c diff --git a/kernel/src/libs/mod.rs b/kernel/src/libs/mod.rs new file mode 100644 index 00000000..dee1127d --- /dev/null +++ b/kernel/src/libs/mod.rs @@ -0,0 +1 @@ +pub mod printk; \ No newline at end of file diff --git a/kernel/src/lib/mutex.c b/kernel/src/libs/mutex.c similarity index 100% rename from kernel/src/lib/mutex.c rename to kernel/src/libs/mutex.c diff --git a/kernel/src/lib/printk.c b/kernel/src/libs/printk.c similarity index 99% rename from kernel/src/lib/printk.c rename to kernel/src/libs/printk.c index bf0a22e1..871a574f 100644 --- a/kernel/src/lib/printk.c +++ b/kernel/src/libs/printk.c @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include diff --git a/kernel/src/libs/printk.rs b/kernel/src/libs/printk.rs new file mode 100644 index 00000000..756d235c --- /dev/null +++ b/kernel/src/libs/printk.rs @@ -0,0 +1,54 @@ +use crate::include::bindings::bindings::{printk_color, BLACK, WHITE}; +use ::core::ffi::c_char; +use alloc::vec::Vec; +use core::fmt; +pub struct PrintkWriter; + +impl PrintkWriter { + /// 调用C语言编写的printk_color,并输出白底黑字(暂时只支持ascii字符) + /// @param str: 要写入的字符 + pub fn __write_string(&mut self, s: &str) { + let str_to_print = self.__utf8_to_ascii(s); + unsafe { + printk_color(WHITE, BLACK, str_to_print.as_ptr() as *const c_char); + } + } + + pub fn __write_string_color(&self, fr_color: u32, bk_color: u32, s: &str) { + let str_to_print = self.__utf8_to_ascii(s); + unsafe { + printk_color(fr_color, bk_color, str_to_print.as_ptr() as *const c_char); + } + } + + /// 将s这个utf8字符串,转换为ascii字符串 + /// @param s 待转换的utf8字符串 + /// @return Vec 转换结束后的Ascii字符串 + pub fn __utf8_to_ascii(&self, s: &str) -> Vec { + let mut ascii_str: Vec = Vec::with_capacity(s.len() + 1); + for byte in s.bytes() { + match byte { + 0..=127 => { + ascii_str.push(byte); + } + _ => {} + } + } + ascii_str.push(b'\0'); + return ascii_str; + } +} + +/// 为Printk Writer实现core::fmt::Write, 使得能够借助Rust自带的格式化组件,格式化字符并输出 +impl fmt::Write for PrintkWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.__write_string(s); + Ok(()) + } +} + +#[doc(hidden)] +pub fn __printk(args: fmt::Arguments) { + use fmt::Write; + PrintkWriter.write_fmt(args).unwrap(); +} diff --git a/kernel/src/lib/rust_helloworld/Makefile b/kernel/src/libs/rust_helloworld/Makefile similarity index 100% rename from kernel/src/lib/rust_helloworld/Makefile rename to kernel/src/libs/rust_helloworld/Makefile diff --git a/kernel/src/lib/rust_helloworld/helloworld.rs b/kernel/src/libs/rust_helloworld/helloworld.rs similarity index 100% rename from kernel/src/lib/rust_helloworld/helloworld.rs rename to kernel/src/libs/rust_helloworld/helloworld.rs diff --git a/kernel/src/lib/semaphore.c b/kernel/src/libs/semaphore.c similarity index 100% rename from kernel/src/lib/semaphore.c rename to kernel/src/libs/semaphore.c diff --git a/kernel/src/lib/stdlib.c b/kernel/src/libs/stdlib.c similarity index 100% rename from kernel/src/lib/stdlib.c rename to kernel/src/libs/stdlib.c diff --git a/kernel/src/lib/string.c b/kernel/src/libs/string.c similarity index 100% rename from kernel/src/lib/string.c rename to kernel/src/libs/string.c diff --git a/kernel/src/lib/sys/Makefile b/kernel/src/libs/sys/Makefile similarity index 100% rename from kernel/src/lib/sys/Makefile rename to kernel/src/libs/sys/Makefile diff --git a/kernel/src/lib/sys/wait.c b/kernel/src/libs/sys/wait.c similarity index 100% rename from kernel/src/lib/sys/wait.c rename to kernel/src/libs/sys/wait.c diff --git a/kernel/src/lib/unistd.c b/kernel/src/libs/unistd.c similarity index 100% rename from kernel/src/lib/unistd.c rename to kernel/src/libs/unistd.c diff --git a/kernel/src/lib/wait_queue.c b/kernel/src/libs/wait_queue.c similarity index 100% rename from kernel/src/lib/wait_queue.c rename to kernel/src/libs/wait_queue.c diff --git a/kernel/src/lib/wait_queue_head.c b/kernel/src/libs/wait_queue_head.c similarity index 100% rename from kernel/src/lib/wait_queue_head.c rename to kernel/src/libs/wait_queue_head.c diff --git a/kernel/src/link.lds b/kernel/src/link.lds index 7c4267e7..7fc22033 100644 --- a/kernel/src/link.lds +++ b/kernel/src/link.lds @@ -47,6 +47,7 @@ SECTIONS { _rodata = .; *(.rodata) + *(.rodata.*) _erodata = .; } @@ -62,6 +63,7 @@ SECTIONS { _bss = .; *(.bss) + *(.bss.*) _ebss = .; } diff --git a/kernel/src/main.c b/kernel/src/main.c index ed01dc55..74aede30 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -14,8 +14,8 @@ #include "smp/smp.h" #include "syscall/syscall.h" #include -#include -#include +#include +#include #include #include @@ -209,7 +209,7 @@ void Start_Kernel(void) // 如果调用的时候,启用了中断,则hlt。否则认为是bug if (get_rflags() & 0x200) { - kdebug("hlt"); + // kdebug("hlt"); hlt(); } else diff --git a/kernel/src/mm/allocator.rs b/kernel/src/mm/allocator.rs index 2e351e64..82fe8b2d 100644 --- a/kernel/src/mm/allocator.rs +++ b/kernel/src/mm/allocator.rs @@ -1,22 +1,55 @@ -use crate::include::bindings::bindings::{gfp_t, PAGE_2M_SIZE, kmalloc}; +use crate::include::bindings::bindings::{gfp_t, kfree, kmalloc, PAGE_2M_SIZE}; +use crate::include::gfp::__GFP_ZERO; + use core::alloc::{GlobalAlloc, Layout}; /// 类kmalloc的分配器应当实现的trait pub trait LocalAlloc { - unsafe fn alloc(&mut self, layout: Layout, gfp: gfp_t) -> *mut u8; - unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout); + unsafe fn local_alloc(&self, layout: Layout, gfp: gfp_t) -> *mut u8; + unsafe fn local_alloc_zeroed(&self, layout: Layout, gfp: gfp_t) -> *mut u8; + unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout); } pub struct KernelAllocator {} +/// 为内核SLAB分配器实现LocalAlloc的trait impl LocalAlloc for KernelAllocator { - unsafe fn alloc(&mut self, layout: Layout, gfp: gfp_t) -> *mut u8 { + unsafe fn local_alloc(&self, layout: Layout, gfp: gfp_t) -> *mut u8 { if layout.size() > (PAGE_2M_SIZE as usize / 2) { return core::ptr::null_mut(); } return kmalloc(layout.size() as u64, gfp) as *mut u8; } - unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout){ - // todo: + + unsafe fn local_alloc_zeroed(&self, layout: Layout, gfp: gfp_t) -> *mut u8 { + if layout.size() > (PAGE_2M_SIZE as usize / 2) { + return core::ptr::null_mut(); + } + return kmalloc(layout.size() as u64, gfp | __GFP_ZERO) as *mut u8; + } + #[allow(unused_variables)] + unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout) { + kfree(ptr as *mut ::core::ffi::c_void); } } + +/// 为内核slab分配器实现GlobalAlloc特性 +unsafe impl GlobalAlloc for KernelAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + self.local_alloc(layout, 0) + } + + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + self.local_alloc_zeroed(layout, 0) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + self.local_dealloc(ptr, layout); + } +} + +/// 内存分配错误处理函数 +#[alloc_error_handler] +pub fn global_alloc_err_handler(_layout: Layout) -> ! { + panic!("global_alloc_error"); +} diff --git a/kernel/src/process/process.c b/kernel/src/process/process.c index ee5decd6..15c2ac0b 100644 --- a/kernel/src/process/process.c +++ b/kernel/src/process/process.c @@ -31,7 +31,7 @@ #include #include - +extern int __rust_demo_func(); // #pragma GCC push_options // #pragma GCC optimize("O0") @@ -499,21 +499,21 @@ ul initial_kernel_thread(ul arg) // int usb_pid = kernel_thread(usb_init, 0, 0); kinfo("LZ4 lib Version=%s", LZ4_versionString()); - + __rust_demo_func(); // 对completion完成量进行测试 - __test_completion(); + // __test_completion(); - // 对一些组件进行单元测试 - uint64_t tpid[] = { - ktest_start(ktest_test_bitree, 0), ktest_start(ktest_test_kfifo, 0), ktest_start(ktest_test_mutex, 0), - ktest_start(ktest_test_idr, 0), - // usb_pid, - }; - kinfo("Waiting test thread exit..."); - // 等待测试进程退出 - for (int i = 0; i < sizeof(tpid) / sizeof(uint64_t); ++i) - waitpid(tpid[i], NULL, NULL); - kinfo("All test done."); + // // 对一些组件进行单元测试 + // uint64_t tpid[] = { + // ktest_start(ktest_test_bitree, 0), ktest_start(ktest_test_kfifo, 0), ktest_start(ktest_test_mutex, 0), + // ktest_start(ktest_test_idr, 0), + // // usb_pid, + // }; + // kinfo("Waiting test thread exit..."); + // // 等待测试进程退出 + // for (int i = 0; i < sizeof(tpid) / sizeof(uint64_t); ++i) + // waitpid(tpid[i], NULL, NULL); + // kinfo("All test done."); // 准备切换到用户态 struct pt_regs *regs;