Browse Source

port kmalloc and printk to rust (#83)

* 暂时移除cbindgen

* 将lib文件夹更名为libs文件夹(解决rust的冲突)

* 实现了全局的allocator

* 实现了printk宏

* new: 完善了printk的颜色
login 2 years ago
parent
commit
fb6c29d01d
49 changed files with 208 additions and 49 deletions
  1. 1 1
      kernel/.cargo/config.toml
  2. 1 1
      kernel/build.rs
  3. 7 5
      kernel/src/Makefile
  4. 1 1
      kernel/src/common/printk.h
  5. 1 1
      kernel/src/driver/video/video.h
  6. 2 0
      kernel/src/include/bindings/wrapper.h
  7. 5 0
      kernel/src/include/gfp.rs
  8. 4 1
      kernel/src/include/mod.rs
  9. 45 0
      kernel/src/include/printk.rs
  10. 26 14
      kernel/src/lib.rs
  11. 0 0
      kernel/src/libs/Makefile
  12. 0 0
      kernel/src/libs/bitree.c
  13. 0 0
      kernel/src/libs/cpu.c
  14. 0 0
      kernel/src/libs/crc16.c
  15. 0 0
      kernel/src/libs/crc32.c
  16. 0 0
      kernel/src/libs/crc64.c
  17. 0 0
      kernel/src/libs/crc7.c
  18. 0 0
      kernel/src/libs/crc8.c
  19. 0 0
      kernel/src/libs/glib.c
  20. 0 0
      kernel/src/libs/idr.c
  21. 0 0
      kernel/src/libs/kfifo.c
  22. 0 0
      kernel/src/libs/libELF/Makefile
  23. 0 0
      kernel/src/libs/libELF/elf.c
  24. 0 0
      kernel/src/libs/libUI/Makefile
  25. 0 0
      kernel/src/libs/libUI/screen_manager.c
  26. 0 0
      kernel/src/libs/libUI/screen_manager.h
  27. 0 0
      kernel/src/libs/libUI/textui-render.c
  28. 0 0
      kernel/src/libs/libUI/textui.c
  29. 0 0
      kernel/src/libs/libUI/textui.h
  30. 0 0
      kernel/src/libs/lockref.c
  31. 0 0
      kernel/src/libs/lz4.c
  32. 1 0
      kernel/src/libs/mod.rs
  33. 0 0
      kernel/src/libs/mutex.c
  34. 1 1
      kernel/src/libs/printk.c
  35. 54 0
      kernel/src/libs/printk.rs
  36. 0 0
      kernel/src/libs/rust_helloworld/Makefile
  37. 0 0
      kernel/src/libs/rust_helloworld/helloworld.rs
  38. 0 0
      kernel/src/libs/semaphore.c
  39. 0 0
      kernel/src/libs/stdlib.c
  40. 0 0
      kernel/src/libs/string.c
  41. 0 0
      kernel/src/libs/sys/Makefile
  42. 0 0
      kernel/src/libs/sys/wait.c
  43. 0 0
      kernel/src/libs/unistd.c
  44. 0 0
      kernel/src/libs/wait_queue.c
  45. 0 0
      kernel/src/libs/wait_queue_head.c
  46. 2 0
      kernel/src/link.lds
  47. 3 3
      kernel/src/main.c
  48. 39 6
      kernel/src/mm/allocator.rs
  49. 15 15
      kernel/src/process/process.c

+ 1 - 1
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")']

+ 1 - 1
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

+ 7 - 5
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
 	
 
 

+ 1 - 1
kernel/src/common/printk.h

@@ -33,7 +33,7 @@
 
 #include "font.h"
 #include "glib.h"
-#include <lib/libUI/screen_manager.h>
+#include <libs/libUI/screen_manager.h>
 #include <stdarg.h>
 
 extern unsigned char font_ascii[256][16]; //导出ascii字体的bitmap(8*16大小) ps:位于font.h中

+ 1 - 1
kernel/src/driver/video/video.h

@@ -1,7 +1,7 @@
 #pragma once
 #include <common/glib.h>
 #include <stdbool.h>
-#include <lib/libUI/screen_manager.h>
+#include <libs/libUI/screen_manager.h>
 
 /**
  * @brief 重新初始化显示驱动,需先低级初始化才能高级初始化

+ 2 - 0
kernel/src/include/bindings/wrapper.h

@@ -15,12 +15,14 @@
 #include <common/crc64.h>
 #include <common/crc7.h>
 #include <common/crc8.h>
+#include <common/gfp.h>
 #include <common/kfifo.h>
 #include <common/list.h>
 #include <common/lz4.h>
 #include <common/printk.h>
 #include <common/spinlock.h>
 #include <common/unistd.h>
+#include <driver/uart/uart.h>
 #include <mm/mm.h>
 #include <mm/slab.h>
 #include <sched/cfs.h>

+ 5 - 0
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);

+ 4 - 1
kernel/src/include/mod.rs

@@ -1 +1,4 @@
-pub mod bindings;
+pub mod bindings;
+pub mod gfp;
+pub mod printk;
+

+ 45 - 0
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())
+    };
+}

+ 26 - 14
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;
 }

+ 0 - 0
kernel/src/lib/Makefile → kernel/src/libs/Makefile


+ 0 - 0
kernel/src/lib/bitree.c → kernel/src/libs/bitree.c


+ 0 - 0
kernel/src/lib/cpu.c → kernel/src/libs/cpu.c


+ 0 - 0
kernel/src/lib/crc16.c → kernel/src/libs/crc16.c


+ 0 - 0
kernel/src/lib/crc32.c → kernel/src/libs/crc32.c


+ 0 - 0
kernel/src/lib/crc64.c → kernel/src/libs/crc64.c


+ 0 - 0
kernel/src/lib/crc7.c → kernel/src/libs/crc7.c


+ 0 - 0
kernel/src/lib/crc8.c → kernel/src/libs/crc8.c


+ 0 - 0
kernel/src/lib/glib.c → kernel/src/libs/glib.c


+ 0 - 0
kernel/src/lib/idr.c → kernel/src/libs/idr.c


+ 0 - 0
kernel/src/lib/kfifo.c → kernel/src/libs/kfifo.c


+ 0 - 0
kernel/src/lib/libELF/Makefile → kernel/src/libs/libELF/Makefile


+ 0 - 0
kernel/src/lib/libELF/elf.c → kernel/src/libs/libELF/elf.c


+ 0 - 0
kernel/src/lib/libUI/Makefile → kernel/src/libs/libUI/Makefile


+ 0 - 0
kernel/src/lib/libUI/screen_manager.c → kernel/src/libs/libUI/screen_manager.c


+ 0 - 0
kernel/src/lib/libUI/screen_manager.h → kernel/src/libs/libUI/screen_manager.h


+ 0 - 0
kernel/src/lib/libUI/textui-render.c → kernel/src/libs/libUI/textui-render.c


+ 0 - 0
kernel/src/lib/libUI/textui.c → kernel/src/libs/libUI/textui.c


+ 0 - 0
kernel/src/lib/libUI/textui.h → kernel/src/libs/libUI/textui.h


+ 0 - 0
kernel/src/lib/lockref.c → kernel/src/libs/lockref.c


+ 0 - 0
kernel/src/lib/lz4.c → kernel/src/libs/lz4.c


+ 1 - 0
kernel/src/libs/mod.rs

@@ -0,0 +1 @@
+pub mod printk;

+ 0 - 0
kernel/src/lib/mutex.c → kernel/src/libs/mutex.c


+ 1 - 1
kernel/src/lib/printk.c → kernel/src/libs/printk.c

@@ -5,7 +5,7 @@
 #include <common/printk.h>
 
 #include <common/spinlock.h>
-#include <lib/libUI/textui.h>
+#include <libs/libUI/textui.h>
 #include <mm/mm.h>
 
 #include <common/math.h>

+ 54 - 0
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<u8> 转换结束后的Ascii字符串
+    pub fn __utf8_to_ascii(&self, s: &str) -> Vec<u8> {
+        let mut ascii_str: Vec<u8> = 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();
+}

+ 0 - 0
kernel/src/lib/rust_helloworld/Makefile → kernel/src/libs/rust_helloworld/Makefile


+ 0 - 0
kernel/src/lib/rust_helloworld/helloworld.rs → kernel/src/libs/rust_helloworld/helloworld.rs


+ 0 - 0
kernel/src/lib/semaphore.c → kernel/src/libs/semaphore.c


+ 0 - 0
kernel/src/lib/stdlib.c → kernel/src/libs/stdlib.c


+ 0 - 0
kernel/src/lib/string.c → kernel/src/libs/string.c


+ 0 - 0
kernel/src/lib/sys/Makefile → kernel/src/libs/sys/Makefile


+ 0 - 0
kernel/src/lib/sys/wait.c → kernel/src/libs/sys/wait.c


+ 0 - 0
kernel/src/lib/unistd.c → kernel/src/libs/unistd.c


+ 0 - 0
kernel/src/lib/wait_queue.c → kernel/src/libs/wait_queue.c


+ 0 - 0
kernel/src/lib/wait_queue_head.c → kernel/src/libs/wait_queue_head.c


+ 2 - 0
kernel/src/link.lds

@@ -47,6 +47,7 @@ SECTIONS
 	{
 		_rodata = .;	
 		*(.rodata)
+		*(.rodata.*)
 		_erodata = .;
 	}
 
@@ -62,6 +63,7 @@ SECTIONS
 	{
 		_bss = .;
 		*(.bss)
+		*(.bss.*)
 		_ebss = .;
 	}
 

+ 3 - 3
kernel/src/main.c

@@ -14,8 +14,8 @@
 #include "smp/smp.h"
 #include "syscall/syscall.h"
 #include <exception/softirq.h>
-#include <lib/libUI/screen_manager.h>
-#include <lib/libUI/textui.h>
+#include <libs/libUI/screen_manager.h>
+#include <libs/libUI/textui.h>
 #include <sched/sched.h>
 #include <smp/ipi.h>
 
@@ -209,7 +209,7 @@ void Start_Kernel(void)
         // 如果调用的时候,启用了中断,则hlt。否则认为是bug
         if (get_rflags() & 0x200)
         {
-            kdebug("hlt");
+            // kdebug("hlt");
             hlt();
         }
         else

+ 39 - 6
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");
+}

+ 15 - 15
kernel/src/process/process.c

@@ -31,7 +31,7 @@
 #include <mm/mmio.h>
 
 #include <common/lz4.h>
-
+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();
-
-    // 对一些组件进行单元测试
-    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.");
+    // __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.");
 
     // 准备切换到用户态
     struct pt_regs *regs;