port kmalloc and printk to rust (#83)

* 暂时移除cbindgen

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

* 实现了全局的allocator

* 实现了printk宏

* new: 完善了printk的颜色
This commit is contained in:
login 2022-11-13 16:43:58 +08:00 committed by GitHub
parent 82d2e446a4
commit fb6c29d01d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 207 additions and 48 deletions

View File

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

View File

@ -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

View File

@ -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

View File

@ -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字体的bitmap8*16大小 ps:位于font.h中

View File

@ -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

View File

@ -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>

View File

@ -0,0 +1,5 @@
use crate::include::bindings::bindings::gfp_t;
#[allow(unused_parens)]
/// 定义__GFP_ZERO
pub const __GFP_ZERO: gfp_t = (1 << 0);

View File

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

View File

@ -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())
};
}

View File

@ -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;
}

1
kernel/src/libs/mod.rs Normal file
View File

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

View File

@ -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
kernel/src/libs/printk.rs Normal file
View File

@ -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();
}

View File

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

View File

@ -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

View File

@ -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");
}

View File

@ -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();
// __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;