Merge pull request '重写rust核心库,构建中断处理框架' (#6) from pointer-to-bios/metaverse-dev:main into main

Reviewed-on: metaverse/kernel-dev#6
This commit is contained in:
pointer-to-bios 2024-05-03 05:45:43 +08:00
commit 87f2767499
51 changed files with 3116 additions and 2503 deletions

2
.cargo/config.toml Normal file
View File

@ -0,0 +1,2 @@
[build]
target = ["x86_64-unknown-none"]

2
.gitignore vendored
View File

@ -1,5 +1,7 @@
.vscode
/test/metaverse.img
*.o
*.tfo
*.map
*.elf
metaverse_kernel

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "rustlib"]
path = rustlib
url = http://git.suthby.org:2024/metaverse/rustenv

View File

@ -1,16 +0,0 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/include"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4
}

View File

@ -1,9 +0,0 @@
{
"C_Cpp.errorSquiggles": "disabled",
"files.associations": {
"*.s": "nasm",
"LICENCE": "plaintext",
"*.h": "c"
},
"rust-analyzer.imports.preferNoStd" : true,
}

View File

@ -2,10 +2,10 @@
name = "metaverse"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
test = false
# 此Cargo.toml仅用于rust-analyzer识别rust部分的代码
# 不应使用cargo编译
[target.'cfg(target_arch = "x86_64")']
target = "x86_64-unknown-none"

55
debug/2024-04.txt Normal file
View File

@ -0,0 +1,55 @@
======== 04-21 16:50 ========
Hit null pointer at 0x100370a
Stack trace:
1 0x0000000001007b90 -> interrupt_req_DE
2 0x00000000010072b0 -> metaverse::kernel::tty::tty::MessageBuilder::message_mut
3 0x0000000001007e60 -> <metaverse::libk::alloc::string::String as core::iter::traits::collect::FromIterator::<char>>::from_iter
4 0x0000000001005eb0 -> <alloc::string::String as core::iter::traits::collect::FromIterator<char>>::from_iter
5 0x0000000001005d80 -> <alloc::string::String as core::iter::traits::collect::Extend<char>>::extend
6 0x0000000001004840 -> alloc::vec::Vec::reserve
7 0x0000000001005900 -> alloc::raw_vec::RawVec::reserve::{do_reserve_and_handle}
8 0x00000000010055c0 -> alloc::raw_vec::RawVec::grow_amortized
9 0x00000000010051e0 -> alloc::raw_vec::finish_grow
10 0x0000000001005a90 -> <alloc::alloc::Global as core::alloc::Allocator>::allocate
11 0x0000000001004900 -> alloc::alloc::Global::alloc_impl
12 0x00000000010048a0 -> alloc::alloc::alloc
13 0x00000000010036e0 -> core::ptr::read_volatile::precondition_check
使用了core crate中的String导致最终调用了一个含有未正确链接的函数。
======== 04-23 13:55 ========
Hit null pointer at 0x100351a.
Stack trace:
0x00000000010054d0 -> metaverse::kernel::tty::tty::MessageBuilder::message_mut
0x0000000001006170 -> <str as metaverse::libk::alloc::string::ToString>::to_string
0x0000000001006080 -> <metaverse::libk::alloc::string::String as core::iter::traits::collect::FromIterator<char>>::from_iter
0x0000000001007450 -> <metaverse::libk::alloc::vec::Vec as core::iter::traits::collect::FromIterator>::from_iter
0x0000000001006a10 -> metaverse::libk::alloc::vec::Vec::push
0x0000000001003f60 -> alloc::alloc::alloc
0x00000000010034f0 -> core::ptr::read_volatile::precondition_check
使用了core crate的alloc函数其中含有未正确链接的函数。
======== 04-26 02:56 ========
Hit null pointer in metaverse::libk::alloc::string::String::clone()
Stack trace:
0x0000000001005520 -> metaverse::kernel::tty::tty::format_message
0x00000000010052f0 -> metaverse::kernel::tty::tty::MessageBuilder::message_mut
0x00000000010073f0 -> <metaverse::libk::alloc::string::String as metaverse::libk::alloc::string::ToString>::to_string
0x0000000001009a90 -> <metaverse::libk::alloc::string::String as core::clone::Clone>::clone
使用了Clone的derive宏含有未正确链接的函数。
======== 04-26 15:55 ========
Hit null pointer at 0x1003672.
Stack trace:
0x0000000001007600 -> <u64 as metaverse::libk::alloc::string::ToString>::to_string
0x0000000001007030 -> metaverse::libk::alloc::string::String::insert
0x0000000001008330 -> metaverse::libk::alloc::vec::Vec::insert
0x0000000001007950 -> metaverse::libk::alloc::vec::Vec::extend_capacity
0x0000000001003630 -> core::intrinsics::copy::precondition_check
将*mut u8转换为*mut T时调用了此函数导致调用了一个未正确链接的函数。
======== 04-27 16:06 ========
Trapped into a infinite loop.
Stack trace:
0x0000000001006c30 -> interrupt_req_DE
0x0000000001005420 -> metaverse::kernel::tty::tty::MessageBuilder::append
0x0000000001008410 -> metaverse::libk::alloc::vec::Vec::append

View File

@ -12,9 +12,22 @@
若你的代码通过审核将会把你的PR合并到主分支中。
## 需要注意的还未解决的问题
## 开发引导
* rust中所有有关字符串格式化的宏中出现超过一个不止是`{}`的格式化占位符时内核必然崩溃。
* rust中所有有关字符串格式化的宏中出现需要调用自定义的`Debug trait`的类型时内核必然崩溃,推荐定义`ToString trait`并调用`.to_string()`后传入宏参数。
* 鉴于以上两条原因,不建议在复杂的字符串格式化任务中使用`format!()`宏。推荐通过使用`::kernel::tty::tty::MessageBuilder`构造`kernel::tty::tty::Message`对象,或使用
`message`宏,并调用此对象的`.to_string()`方法实现格式化字符串。
## vscode
vscode下的`rust-analyzer`插件会在`src/lib.rs`中误报`can't find crate for test`,实际上在`Cargo.toml`中已经增加了`test = false`选项。
解决方法是在`.vscode/settings.json`中增加两项:
```json
"rust-analyzer.cargo.allTargets": false,
"rust-analyzer.cargo.extraArgs": [
"--target",
"开发的目标平台的unknown-none类型目标如x86_64-unknown-none"
]
```
## 需要注意的问题
* 在任何情况下不要使用Rust的panic。

View File

@ -46,13 +46,13 @@ typedef void (*interrupt_entry)();
/**
* @name interrupt_request
* @addindex
*
*
*
*
*
* ```c
* void interrupt_request(u64 rip, u64 rsp);
* ```
*
*
*
*/
typedef void (*interrupt_request)(u64 rip, u64 rsp, u64 errcode);
@ -77,11 +77,13 @@ typedef void (*interrupt_request)(u64 rip, u64 rsp, u64 errcode);
#define DE
#define NMI
#define BP
#define OF
interrupt_entry_gen(UNSUPPORTED);
interrupt_entry_gen(DE);
interrupt_entry_gen(NMI);
interrupt_entry_gen(BP);
interrupt_entry_gen(DE); // irq0
interrupt_entry_gen(NMI); // irq2
interrupt_entry_gen(BP); // irq3
interrupt_entry_gen(OF); // ira4
#endif

View File

@ -156,6 +156,7 @@ void tty_disable(tty *ttyx);
typedef struct __tty_font_t
{
bool initialized;
u16 char_width, char_height;
u64 **font;
} tty_font_t;

View File

@ -1,2 +1,2 @@
[toolchain]
channel = "stable"
channel = "nightly"

@ -1 +0,0 @@
Subproject commit 6a2ca2afcd651e46f1c19f8d8a3f685fd982d824

57
scripts/tfgen Executable file
View File

@ -0,0 +1,57 @@
#!/usr/bin/python
from io import TextIOWrapper
import sys
import struct
def main(infile: TextIOWrapper, outfile: TextIOWrapper):
size = infile.readline().strip().split(",")
size = (int(size[0].strip()), int(size[1].strip()))
outfile.write(struct.pack('q', size[0]))
outfile.write(struct.pack('q', size[1]))
for _ in range(62):
outfile.write(struct.pack('q', int(0)))
in_char = False
char_buffer = []
char_count = 0
for line in infile:
line = line.split("//")[0].strip()
if len(line) == 0:
continue
if line.startswith("{"):
char_buffer = []
line = line[1:]
in_char = True
if line.endswith("},"):
i = 0
for d in char_buffer:
outfile.write(struct.pack('q', d))
i += 1
while i < 64:
outfile.write(struct.pack('q', int(0)))
i += 1
char_count += 1
in_char = False
continue
if len(line) == 0:
continue
if in_char:
data = line.split(",")[0].strip()
data = int(data, 2)
char_buffer.append(data)
while char_count < 256:
for _ in range(64):
outfile.write(struct.pack('q', int(0)))
char_count += 1
if __name__ == "__main__":
if len(sys.argv) < 3:
print("tfgen: Input file and Output file needed.")
exit(1)
infile_name = sys.argv[1]
outfile_name = sys.argv[2]
with open(infile_name) as infile:
with open(outfile_name, "wb") as outfile:
main(infile, outfile)

View File

@ -12,11 +12,15 @@ ifdef release
release = 1
endif
ifndef ttyfont
ttyfont = metamono
endif
ALLOCATOR_MAGIC = $(shell "${SOURCE}/magicgen" | sha512sum | head -c 128 | md5sum | head -c 8)
BUILD_ID = $(shell "${SOURCE}/magicgen" | sha512sum | head -c 128 | md5sum | head -c 4)
BUILD_ID = $(shell "${SOURCE}/magicgen" | sha512sum | head -c 128 | md5sum | head -c 8)
SUBOBJS = kernel/kernel.o libk/libk.o rust.o
SUBOBJS = kernel/kernel.o libk/libk.o rust.o font_file.o
DEFINES = ARCH="${ARCH}" ASM="${ASM}" ASMFLAGS="${ASMFLAGS}" SOURCE="${SOURCE}" PWD="${PWD}" \
ALLOCATOR_MAGIC="${ALLOCATOR_MAGIC}" BUILD_ID="${BUILD_ID}"
@ -27,16 +31,24 @@ endif
################################
# rust语言环境变量
TARGET_TRIPLE =
ifeq (${ARCH},x86_64)
TARGET_TRIPLE := x86_64-unknown-none
endif
RUSTLIB_PATH = ../target/sysroot/lib/rustlib/${TARGET_TRIPLE}/lib
RUST_LIBS = $(shell ls -d ${RUSTLIB_PATH}/lib*.rlib)
RSCFLAGS = --emit obj --crate-type staticlib --verbose \
--crate-name=metaverse \
--edition 2021 \
-L crate="${PWD}/../rustlib/src/" \
-C code-model=large \
-C relocation-model=static \
-C embed-bitcode=no
-C embed-bitcode=no \
-C panic=abort
ifeq (${ARCH},x86_64)
RSCFLAGS := ${RSCFLAGS} --target x86_64-unknown-none
RSCFLAGS := ${RSCFLAGS} -C target-feature=-sse
endif
@ -44,18 +56,14 @@ ifdef release
RSCFLAGS := ${RSCFLAGS} -O
endif
RUSTLIB_PATH = ../rustlib/${ARCH}
RUST_LIBS = "${RUSTLIB_PATH}/liballoc.rlib" "${RUSTLIB_PATH}/libcompiler_builtins.rlib" \
"${RUSTLIB_PATH}/libcore.rlib" "${RUSTLIB_PATH}/librustc_std_workspace_core.rlib"
################################
metaverse.elf: kernel libk rust metaverse.lds
metaverse.elf: kernel libk rust metaverse.lds font_file.o
@echo -e "\e[1;33mld\e[0m \e[1;32m$@\e[0m \e[34m<--\e[0m \e[32m${SUBOBJS}\e[0m"
@ld -T metaverse.lds -Map=metaverse.map -unresolved-symbols=ignore-all -o $@ ${SUBOBJS} ${RUST_LIBS} \
2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
2>&1 | "${SOURCE}/colorize" "warning:=lpink" "error:=red" "ld=lyellow"
.PHONY: kernel libk all clear postproc rust
.PHONY: kernel libk all clear postproc rust rustlib
all: postproc metaverse.elf
@echo -e "Build \e[1;32msucceeded\e[0m."
@ -88,11 +96,18 @@ libk:
echo -e "\e[33m-------------------------\e[0m"; \
fi
rust: postproc
../target:
@-cargo xbuild --target ${TARGET_TRIPLE} --release
rust: postproc ../target
@echo -e "\e[1m\e[33mrustc\e[0m \e[34m-->\e[0m \e[1m\e[32m$@.o\e[0m"
@rustc ${RSCFLAGS} lib.rs -o rust.o
font_file.o: ttyfonts/${ttyfont}.tfn
@"${SOURCE}/tfgen" $< font_file.tfo
@ld -r -b binary -o $@ font_file.tfo
clear:
@make -C kernel clear --no-print-directory ${DEFINES}
@make -C libk clear --no-print-directory ${DEFINES}
@-rm metaverse.elf metaverse.map rust.o
@-rm metaverse.elf metaverse.map rust.o font_file.{o,tfo}

View File

@ -13,8 +13,7 @@ ifdef release
CCFLAGS := ${CCFLAGS} -O2
endif
C_SRCS = main.c tty.c font.c memm.c memm_${ARCH}.c raw.c time.c syscall_${ARCH}.c interrupt_${ARCH}.c \
interrupt_procs.c
C_SRCS = main.c tty.c font.c memm.c memm_${ARCH}.c raw.c time.c syscall_${ARCH}.c interrupt_${ARCH}.c
C_OBJS = ${C_SRCS:.c=.c.o}
################################

2
src/kernel/arch.rs Normal file
View File

@ -0,0 +1,2 @@
#[cfg(target_arch = "x86_64")]
pub mod x86_64;

View File

@ -11,7 +11,8 @@ init64:
mov rsp, rax
mov rdi, rbx
lidt [0x104010]
; 加载idt
lidt [0x104010] ; idt_ptr
; 加载系统调用相关寄存器
; IA32_STAR = 0x0018_0008_0000_0000

View File

@ -21,17 +21,18 @@ init32:
mov dword [edi], 0
; 设置PD0中的PDE
mov ecx, 64
; 以2MB页映射前64MB
mov ecx, 32
mov eax, 0
mov edi, 0x103000 ; PD0
init32_loop0:
mov edx, eax
add edx, 0x183
mov dword [edi], edx
add eax, 0x200000 ; 2MB
add edi, 4
mov dword [edi], 0
add edi, 4
add eax, 0x200000 ; 2MB
loop init32_loop0
; 加载GDTR、段寄存器和TR寄存器

View File

@ -51,7 +51,10 @@
add rsp, 4
%endmacro
; 此处的cli在进入rust的中断处理函数后才会对应sti
; 因为在保存栈帧前中断不可以被打断
%macro interrupt_entry_enter 0
cli
push rbp
lea rbp, [rsp]
store_regs
@ -62,6 +65,7 @@
retrieve_section
retrieve_regs
leave
sti
%endmacro
; 用于带有错误码的中断,创建一个没有错误码的上下文拷贝

View File

@ -0,0 +1,48 @@
use crate::{kernel::tty::tty::Tty, message};
extern "C" {
pub fn interrupt_open();
pub fn interrupt_close();
// 以下两个函数签名的返回值用于使编译器保留rax寄存器
pub fn interrupt_rust_enter() -> usize;
pub fn interrupt_rust_leave() -> usize;
}
#[no_mangle]
unsafe extern "C" fn interrupt_req_UNSUPPORTED(rip: u64, rsp: u64, errcode: u64) -> ! {
interrupt_rust_enter();
let tty = Tty::from_id(0).unwrap();
tty.enable();
tty.print(message!(
"{Panic}: Kernel hit an {Unsupported} interrupt on rip=0x{} and rsp=0x{}.\n",
FmtMeta::Color(Color::RED),
FmtMeta::Color(Color::YELLOW),
FmtMeta::Pointer(rip as usize),
FmtMeta::Pointer(rsp as usize)
));
loop {}
}
#[no_mangle]
unsafe extern "C" fn interrupt_req_DE(rip: u64, rsp: u64, errcode: u64) {
interrupt_rust_enter();
let tty = Tty::from_id(0).unwrap();
tty.enable();
tty.print(message!(
"{Warning}: Kernel hit {Divid Error} on rip=0x{} and rsp=0x{}.\n",
FmtMeta::Color(Color::PURPLE),
FmtMeta::Color(Color::YELLOW),
FmtMeta::Pointer(rip as usize),
FmtMeta::Pointer(rsp as usize)
));
interrupt_rust_leave();
}
#[no_mangle]
unsafe extern "C" fn interrupt_req_NMI(rip: u64, rsp: u64, errcode: u64) {}
#[no_mangle]
unsafe extern "C" fn interrupt_req_BP(rip: u64, rsp: u64, errcode: u64) {}
#[no_mangle]
unsafe extern "C" fn interrupt_req_OF(rip: u64, rsp: u64, errcode: u64) {}

View File

@ -1,190 +0,0 @@
#include <kernel/arch/x86_64/interrupt_procs.h>
#include <kernel/arch/x86_64/memm.h>
#include <kernel/arch/x86_64/proc.h>
#include <kernel/kernel.h>
#include <kernel/tty.h>
#include <libk/string.h>
interrupt_req_gen(UNSUPPORTED)
{
tty **tty0_option = tty_get(0);
if (tty0_option == nullptr)
{
KERNEL_TODO();
}
tty *tty0 = *tty0_option;
tty_text_print(tty0, "Panic: Unsupported interrupt.", RED, BLACK);
KERNEL_TODO();
}
static void rip_not_cannonical(u64 rip, tty *tty0)
{
char num[17];
memset(num, 0, sizeof(num));
pointer_to_string(rip, num);
tty_text_print(tty0, "Panic", RED, BLACK);
tty_text_print(tty0, ": Unexpected non-cannonical %rip value ", WHITE, BLACK);
tty_text_print(tty0, num, ORANGE, BLACK);
tty_text_print(tty0, ".\n", WHITE, BLACK);
KERNEL_TODO();
}
interrupt_req_gen(DE)
{
tty **tty0_option = tty_get(0);
if (tty0_option == nullptr)
{
KERNEL_TODO();
}
tty *tty0 = *tty0_option;
if (!is_cannonical(rip))
{
rip_not_cannonical(rip, tty0);
}
if (!is_user_address(rip))
{
char nums[34];
memset(nums, 0, sizeof(nums));
pointer_to_string(rip, nums);
pointer_to_string(rsp, nums + 17);
tty_text_print(tty0, "Panic", RED, BLACK);
tty_text_print(tty0, ": Divided by zero occurs in kernel,\n\t", WHITE, BLACK);
tty_text_print(tty0, "with %rip=", WHITE, BLACK);
tty_text_print(tty0, "0x", ORANGE, BLACK);
tty_text_print(tty0, nums, ORANGE, BLACK);
tty_text_print(tty0, ", %rsp=", WHITE, BLACK);
tty_text_print(tty0, "0x", ORANGE, BLACK);
tty_text_print(tty0, nums + 17, ORANGE, BLACK);
tty_text_print(tty0, ".\n", WHITE, BLACK);
KERNEL_TODO();
}
else
{ // TODO 转储并结束进程
KERNEL_TODO();
}
}
interrupt_req_gen(BP)
{
tty **tty0_option = tty_get(0);
if (tty0_option == nullptr)
{
KERNEL_TODO();
}
tty *tty0 = *tty0_option;
if (!is_cannonical(rip))
{
rip_not_cannonical(rip, tty0);
}
proc_texture_registers_t *texture = (void *)errcode;
if (!is_user_address(rip))
{
char nums[34];
memset(nums, 0, sizeof(nums));
pointer_to_string(rip, nums);
pointer_to_string(rsp, nums + 17);
tty_text_print(tty0, "Debug", PURPLE, BLACK);
tty_text_print(tty0, ": Kernel hit a breakpoint,\n\t", WHITE, BLACK);
tty_text_print(tty0, "with %rip=", WHITE, BLACK);
tty_text_print(tty0, "0x", ORANGE, BLACK);
tty_text_print(tty0, nums, ORANGE, BLACK);
tty_text_print(tty0, ", %rsp=", WHITE, BLACK);
tty_text_print(tty0, "0x", ORANGE, BLACK);
tty_text_print(tty0, nums + 17, ORANGE, BLACK);
tty_text_print(tty0, ",\n\t", WHITE, BLACK);
tty_text_print(tty0, "on texture: \n", WHITE, BLACK);
pointer_to_string(texture->rax, nums);
tty_text_print(tty0, "rax\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->rcx, nums);
tty_text_print(tty0, "rcx\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->rbx, nums);
tty_text_print(tty0, "rbx\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->rdx, nums);
tty_text_print(tty0, "rdx\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->rsi, nums);
tty_text_print(tty0, "rsi\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->rdi, nums);
tty_text_print(tty0, "rdi\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->rbp, nums);
tty_text_print(tty0, "rbp\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->rsp, nums);
tty_text_print(tty0, "rsp\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->rip, nums);
tty_text_print(tty0, "rip\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->rflags, nums);
tty_text_print(tty0, "rflags\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->r8, nums);
tty_text_print(tty0, "r8\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->r9, nums);
tty_text_print(tty0, "r9\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->r10, nums);
tty_text_print(tty0, "r10\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->r11, nums);
tty_text_print(tty0, "r11\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->r12, nums);
tty_text_print(tty0, "r12\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->r13, nums);
tty_text_print(tty0, "r13\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->r14, nums);
tty_text_print(tty0, "r14\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->r15, nums);
tty_text_print(tty0, "r15\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->cs, nums);
tty_text_print(tty0, "cs\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->ss, nums);
tty_text_print(tty0, "ss\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
pointer_to_string(texture->ds, nums);
tty_text_print(tty0, "ds\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\t", WHITE, BLACK);
pointer_to_string(texture->es, nums);
tty_text_print(tty0, "es\t", WHITE, BLACK);
tty_text_print(tty0, nums, BLUE, BLACK);
tty_text_print(tty0, "\n", WHITE, BLACK);
KERNEL_TODO();
}
else
{ // TODO 将当前进程的状态设置为暂停并通知当前进程的调试程序
KERNEL_TODO();
}
}

View File

@ -63,7 +63,7 @@ interrupt_entry_UNSUPPORTED:
call interrupt_req_UNSUPPORTED
interrupt_entry_leave
iret
iretq
global interrupt_entry_DE
extern interrupt_req_DE
@ -75,12 +75,12 @@ interrupt_entry_DE:
call interrupt_req_DE
interrupt_entry_leave
iret
iretq
global interrupt_entry_DE
global interrupt_entry_NMI
interrupt_entry_NMI:
; TODO 暂时不需要为这个中断实现任何功能
iret
iretq
global interrupt_entry_BP
extern interrupt_req_BP
@ -94,4 +94,16 @@ interrupt_entry_BP:
call interrupt_req_BP
interrupt_entry_leave
iret
iretq
global interrupt_entry_OF
extern interrupt_req_OF
interrupt_entry_OF:
interrupt_entry_enter
mov rdi, [rsp + 128]
mov rsi, [rsp + 152]
call interrupt_req_OF
interrupt_entry_leave
iretq

View File

@ -20,6 +20,8 @@ void interrupt_init()
interrupt_register_gate(gate, 2);
trap_gate_generate(gate, interrupt_entry_sym(BP));
interrupt_register_gate(gate, 3);
trap_gate_generate(gate, interrupt_entry_sym(OF));
interrupt_register_gate(gate, 4);
interrupt_open();
}

View File

@ -9,3 +9,30 @@ interrupt_open:
interrupt_close:
cli
ret
global interrupt_rust_enter
extern TSS
; usize interrupt_rust_enter()
; 返回值用于为寄存器rax占位
interrupt_rust_enter:
; *(rsp - 8) = *(TSS + 36)
mov rax, [TSS + 36]
mov qword [rsp - 8], rax
; *(TSS + 36) = rsp - 8
mov rax, TSS
lea rax, [rax + 36]
mov [rax], rsp
sub qword [rax], 8
sti
ret
global interrupt_rust_leave
extern TSS
; usize interrupt_rust_leave()
; 返回值用于为寄存器rax占位
interrupt_rust_leave:
cli
; *(TSS + 36) = *(rsp - 8)
mov rax, [rsp - 8]
mov [TSS + 36], rax
ret

View File

@ -0,0 +1,2 @@
pub mod interrupt;
pub mod proc;

View File

@ -0,0 +1,32 @@
#[repr(C)]
#[derive(Debug)]
pub struct RegisterTexture {
es: u16,
ds: u16,
reserved: u32,
r15: u64,
r14: u64,
r13: u64,
r12: u64,
r11: u64,
r10: u64,
r9: u64,
r8: u64,
rdi: u64,
rsi: u64,
rdx: u64,
rbx: u64,
rcx: u64,
rax: u64,
rbp: u64,
rip: u64,
cs: u64,
rflags: u64,
rsp: u64,
ss: u64,
}
#[derive(Debug)]
pub struct ProcessTexture {
register: RegisterTexture,
}

View File

@ -11,6 +11,7 @@ extern "C" {
pub struct SystemTimeError(Duration);
#[derive(Clone, Copy, Hash)]
#[derive(Default)]
pub struct SystemTime {
unix_time: usize,
ns_time: usize,

View File

@ -1,5 +1,4 @@
use alloc::vec;
use alloc::vec::Vec;
use crate::libk::alloc::vec::Vec;
use super::{
clock::time::SystemTime,
@ -28,12 +27,12 @@ pub struct KernelLogger {
impl KernelLogger {
pub fn new() -> Self {
Self {
fatal_queue: vec![],
error_queue: vec![],
warning_queue: vec![],
info_queue: vec![],
debug_queue: vec![],
trace_queue: vec![],
fatal_queue: Vec::new(),
error_queue: Vec::new(),
warning_queue: Vec::new(),
info_queue: Vec::new(),
debug_queue: Vec::new(),
trace_queue: Vec::new(),
}
}
@ -91,105 +90,18 @@ impl KernelLogger {
self.trace_queue.push((SystemTime::now(), msg));
}
pub fn iter(&self, level: LoggerLevel) -> LogIterator {
let mut logs = vec![];
match level {
LoggerLevel::Fatal => {
logs.push(&self.fatal_queue);
}
LoggerLevel::Error => {
logs.push(&self.fatal_queue);
logs.push(&self.error_queue);
}
LoggerLevel::Warning => {
logs.push(&self.fatal_queue);
logs.push(&self.error_queue);
logs.push(&self.warning_queue);
}
LoggerLevel::Info => {
logs.push(&self.fatal_queue);
logs.push(&self.error_queue);
logs.push(&self.warning_queue);
logs.push(&self.info_queue);
}
LoggerLevel::Debug => {
logs.push(&self.fatal_queue);
logs.push(&self.error_queue);
logs.push(&self.warning_queue);
logs.push(&self.info_queue);
logs.push(&self.debug_queue);
}
LoggerLevel::Trace => {
logs.push(&self.fatal_queue);
logs.push(&self.error_queue);
logs.push(&self.warning_queue);
logs.push(&self.info_queue);
logs.push(&self.debug_queue);
logs.push(&self.trace_queue);
}
}
let mut res = vec![];
let mut indeces = Vec::new();
for _ in 0..logs.len() {
indeces.push(0usize);
}
let all_end = |indeces: &Vec<usize>, logs: &Vec<&Vec<(SystemTime, Message)>>| {
for i in 0..indeces.len() {
if indeces[i] < logs.len() {
return false;
}
}
true
};
while !all_end(&indeces, &logs) {
let mut min_ind = None;
let mut min = None;
for i in 0..indeces.len() {
if indeces[i] >= logs[i].len() {
continue;
}
if let Some(minx) = min.as_mut() {
if logs[i][indeces[i]].0 < *minx {
*minx = logs[i][indeces[i]].0;
min_ind = Some(i);
}
} else {
min = Some(logs[i][indeces[i]].0);
min_ind = Some(i);
}
}
if let Some(mini) = min_ind {
res.push(&logs[mini][indeces[mini]]);
indeces[mini] += 1;
} else {
break;
}
}
LogIterator { logs: res }
pub fn iter(&self, _level: LoggerLevel) -> LogIterator {
todo!()
}
}
pub struct LogIterator<'a> {
logs: Vec<&'a (SystemTime, Message)>,
pub struct LogIterator {
}
impl<'a> Iterator for LogIterator<'a> {
impl Iterator for LogIterator {
type Item = Message;
fn next(&mut self) -> Option<Self::Item> {
let res = if let Some((time, msg)) = self.logs.first() {
Some(
MessageBuilder::new()
.message(time)
.append(MessageBuilder::from_message(msg.clone()))
.build(),
)
} else {
None
};
if let Some(_) = res {
self.logs.remove(0);
}
res
todo!()
}
}

View File

@ -48,6 +48,8 @@ void kmain(void *mb2_bootinfo)
// 初始化中断管理
interrupt_init();
int i = 1 / 0;
// 初始化系统调用
syscall_init();

View File

@ -1,22 +1,7 @@
use crate::message;
use super::{
klog::{KernelLogger, LoggerLevel},
tty::tty::{BuilderFunctions::*, Color, Tty},
};
use crate::kernel::tty::tty::Tty;
#[no_mangle]
extern "C" fn kmain_rust() -> ! {
let tty = Tty::from_id(0).unwrap();
let mut logger = KernelLogger::new();
logger.info(message!(
Msg("Hello, "),
Msg("Metaverse"),
FgColor(Color::GREEN),
Msg("!\n")
));
for msg in logger.iter(LoggerLevel::Info) {
tty.print(msg);
}
loop {}
}

View File

@ -37,7 +37,6 @@ allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid
allocator_t *allocator = start;
allocator->magic = MEMM_ALLOCATOR_MAGIC;
allocator->full = false;
allocator->pid = 0;
allocator->size = length;
allocator->type = type;
switch (type)
@ -71,10 +70,6 @@ void memm_free(void *mem)
allocator_t *allocator = memory_manager.kernel_base_allocator;
if (allocator->magic != MEMM_ALLOCATOR_MAGIC)
return;
if (is_user_address((u64)mem))
{
mem = mem - allocator->userspace + (void *)allocator;
}
allocator->free(allocator->allocator_instance, mem);
if (allocator->full)
allocator->full = false;

View File

@ -6,9 +6,9 @@ use core::{
};
extern "C" {
pub fn memm_kernel_allocate(size: usize) -> *mut u8;
fn memm_kernel_allocate(size: usize) -> *mut u8;
// pub fn memm_user_allocate(size: usize, pid: usize);
pub fn memm_free(mem: *mut u8);
fn memm_free(mem: *mut u8);
}
pub struct KernelAllocator {}
@ -31,4 +31,4 @@ unsafe impl GlobalAlloc for KernelAllocator {
}
#[global_allocator]
static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator {};
pub static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator {};

View File

@ -1 +1 @@
mod memm;
pub mod memm;

View File

@ -3,4 +3,4 @@ pub mod klog;
pub mod main;
pub mod memm;
pub mod tty;
pub mod sync;
pub mod arch;

View File

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

View File

@ -1,129 +0,0 @@
use core::{ops::{Deref, DerefMut}, ptr::null_mut};
use alloc::{vec, vec::Vec};
/// ## RwLock<T>
/// 读写锁
///
/// * 对于写入操作:
///
/// 锁没有占用时,获取锁,并执行闭包。
///
/// 当锁已经被占用,将闭包悬挂。
///
/// 释放锁时,将所有悬挂的闭包都执行。
///
/// 正在释放锁时,`write`方法返回`Err(())`
///
/// ```
/// let num = 6;
/// let num = RwLock::new(num);
/// if let Err(()) = num.write(
/// |n| *n = 10
/// ) {}
/// let numstr = format!("{}", num.read());
/// ````
pub struct RwLock<'a, T> {
obj: T,
locked: bool,
dealing_hanged: bool,
ptr: *mut RwLockWriteGuard<'a, T>,
hanging: Vec<&'a dyn Fn(&mut T)>,
}
unsafe impl<T> Send for RwLock<'_, T> {}
unsafe impl<T> Sync for RwLock<'_, T> {}
impl<'a, T> RwLock<'a, T> {
pub fn new(obj: T) -> Self {
Self {
obj,
locked: false,
dealing_hanged: false,
ptr: null_mut(),
hanging: vec![],
}
}
pub fn read(&self) -> RwLockReadGuard<T> {
RwLockReadGuard { obj: &self.obj }
}
pub fn write(&'a mut self, f: &'a dyn Fn(&mut T)) -> Result<RwLockWriteGuard<T>, ()> {
if self.dealing_hanged {
Err(())
} else if !self.locked {
self.locked = true;
f(&mut self.obj);
let ptr = { self as *mut RwLock<'a, T> };
let obj = &mut self.obj;
let mut res = RwLockWriteGuard {
obj,
ptr,
must_deal_hang: false,
};
self.ptr = &mut res as *mut RwLockWriteGuard<'_, T>;
Ok(res)
} else {
self.hanging.push(f);
let ptr = { self as *mut RwLock<'a, T> };
let obj = &mut self.obj;
Ok(RwLockWriteGuard {
obj,
ptr,
must_deal_hang: false,
})
}
}
}
pub struct RwLockReadGuard<'a, T> {
obj: &'a T,
}
impl<'a, T> Deref for RwLockReadGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.obj
}
}
impl<'a, T> Drop for RwLockReadGuard<'a, T> {
fn drop(&mut self) {}
}
pub struct RwLockWriteGuard<'a, T> {
obj: &'a mut T,
ptr: *mut RwLock<'a, T>,
must_deal_hang: bool,
}
impl<'a, T> Deref for RwLockWriteGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.obj
}
}
impl<'a, T> DerefMut for RwLockWriteGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.obj
}
}
impl<'a, T> Drop for RwLockWriteGuard<'a, T> {
fn drop(&mut self) {
if self.must_deal_hang {
let p = unsafe { &mut *self.ptr };
p.dealing_hanged = true;
for f in p.hanging.iter() {
f(self.obj);
}
p.hanging.clear();
p.dealing_hanged = false;
p.locked = false;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,46 +1,28 @@
pub mod tty;
#[macro_export]
macro_rules! message_msg {
() => {};
( $builder : expr, $e : expr) => {
$builder.message_mut($e);
};
}
#[macro_export]
macro_rules! message_fgc {
() => {};
( $builder : expr, $e : expr) => {
$builder.foreground_color_mut($e);
};
}
#[macro_export]
macro_rules! message_bgc {
() => {};
( $builder : expr, $e : expr ) => {
$builder.background_color_mut($e);
};
}
#[macro_export]
macro_rules! message {
( $( $e : expr ),* ) => {{
( $fmtter : expr ) => {{
use crate::kernel::tty::tty::MessageBuilder;
MessageBuilder::new()
.message($fmtter)
.build()
}};
( $fmtter : expr, $( $e : expr ),* ) => {{
use crate::{
kernel::tty::tty::{MessageBuilder, BuilderFunctions},
message_msg, message_fgc, message_bgc
kernel::tty::tty::{
MessageBuilder,
FmtMeta,
Color,
format_message
},
libk::alloc::vec::Vec,
};
let mut tmp_builder = MessageBuilder::new();
let mut formatter = $fmtter.chars().collect::<Vec<char>>();
let builder = MessageBuilder::new();
$(
if let BuilderFunctions::Msg(e) = $e {
message_msg!(tmp_builder, e);
} else if let BuilderFunctions::FgColor(c) = $e {
message_fgc!(tmp_builder, c);
} else if let BuilderFunctions::BgColor(c) = $e {
message_bgc!(tmp_builder, c);
}
let builder = builder.append(format_message(&mut formatter, $e));
)*
tmp_builder.build()
builder.build()
}};
}

View File

@ -77,6 +77,7 @@ inline static void scroll_buffer(
usize dist)
{
memcpy(buffer, buffer + width * pixsize * dist, (height - dist) * width * pixsize);
memset(buffer + (height - dist) * width * pixsize, 0, dist * width * pixsize);
}
inline static void putchar(

View File

@ -1,8 +1,8 @@
use core::ptr::null_mut;
use alloc::{
use crate::libk::alloc::{
boxed::Box,
string::{String, ToString},
vec,
vec::Vec,
};
@ -141,7 +141,7 @@ impl Tty {
}
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Default)]
pub struct Color(pub u8, pub u8, pub u8);
impl Color {
@ -169,7 +169,7 @@ pub struct Resolution {
pub height: usize,
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct MessageSection {
msg: String,
fgcolor: Color,
@ -179,14 +179,14 @@ pub struct MessageSection {
/// ## Message
///
/// 用`MessageBuilder`构造一个`Message`对象
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct Message(Vec<MessageSection>);
impl ToString for Message {
fn to_string(&self) -> String {
let mut res = String::new();
for MessageSection { msg, .. } in self.0.iter() {
res += msg;
res += msg.clone();
}
res
}
@ -212,7 +212,7 @@ impl ToString for Message {
/// ```rust
/// use crate::kernel::tty::tty::BuilderFunctions::*;
///
/// message!(
/// message_raw!(
/// Msg("Hello, "),
/// Msg("Metaverse"),
/// FgColor(Color::GREEN),
@ -233,8 +233,8 @@ pub struct MessageBuilder {
msg: Message,
}
pub enum BuilderFunctions<'a> {
Msg(&'a str),
pub enum BuilderFunctions<T: ToString> {
Msg(T),
FgColor(Color),
BgColor(Color),
}
@ -242,10 +242,14 @@ pub enum BuilderFunctions<'a> {
impl MessageBuilder {
pub fn new() -> Self {
Self {
msg: Message(vec![]),
msg: Message(Vec::new()),
}
}
pub fn is_empty(&self) -> bool {
self.msg.0.is_empty()
}
pub fn from_message(msg: Message) -> Self {
Self { msg }
}
@ -302,3 +306,82 @@ impl MessageBuilder {
self.msg
}
}
pub enum FmtMeta {
Color(Color),
String(String),
ToStringable(Box<dyn ToString>),
Hex(u8),
Pointer(usize),
}
pub fn format_message(fmt: &mut Vec<char>, meta: FmtMeta) -> MessageBuilder {
let mut msgbuilder = MessageBuilder::new();
let mut fmt_start = None;
let mut fmt_end = None;
for i in 0..fmt.len() {
if fmt[i] == '{' {
fmt_start = Some(i);
}
if fmt[i] == '}' {
fmt_end = Some(i);
break;
}
}
let tohex = |n: u8| {
if n < 10 {
(b'0' + n) as char
} else {
(b'a' + n - 10) as char
}
};
if fmt_start == None || fmt_end == None {
msgbuilder.message_mut(&String::from_iter(fmt.iter()));
} else {
let fmt_start = fmt_start.unwrap();
let fmt_end = fmt_end.unwrap();
let mut formatter = Vec::new();
for _ in fmt_start..=fmt_end {
formatter.push(fmt.remove(fmt_start));
}
formatter.remove(formatter.len() - 1);
formatter.remove(0);
match meta {
FmtMeta::Color(color) => {
let first = fmt.split_at(fmt_start).0;
msgbuilder.message_mut(&String::from_iter(first.iter()));
for _ in 0..fmt_start {
fmt.remove(0);
}
msgbuilder.message_mut(&String::from_iter(formatter.iter()));
msgbuilder.foreground_color_mut(color);
}
FmtMeta::String(s) => {
for c in s.chars().rev() {
fmt.insert(fmt_start, *c);
}
}
FmtMeta::ToStringable(s) => {
for c in s.to_string().chars().rev() {
fmt.insert(fmt_start, *c);
}
}
FmtMeta::Hex(num) => {
fmt.insert(fmt_start, tohex(num >> 4));
fmt.insert(fmt_start, tohex(num & 0xf));
}
FmtMeta::Pointer(mut p) => {
for _ in 0..16 {
fmt.insert(fmt_start, tohex((p & 0xf) as u8));
p >>= 4;
}
}
}
}
let mut rests = Vec::new();
while !fmt.is_empty() && fmt[0] != '{' {
rests.push(fmt.remove(0));
}
msgbuilder.message_mut(&String::from_iter(rests.iter()));
msgbuilder
}

View File

@ -1,69 +1,23 @@
#![no_std]
#![feature(strict_provenance)]
#![feature(layout_for_ptr)]
extern crate alloc;
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::{panic::PanicInfo, ptr::null_mut};
use core::panic::PanicInfo;
use kernel::tty::tty::{self, tty_enable, tty_text_print, Color};
use kernel::tty::tty::Tty;
pub mod kernel;
pub mod libk;
#[panic_handler]
unsafe fn kernel_panic_handler(info: &PanicInfo) -> ! {
let line_in_file = if let Some(loca) = info.location() {
loca.line().to_string()
} else {
String::new()
};
let info = {
let mut v = Vec::new();
v.push(("Kernel Panic: ", (Color::RED, Color::BLACK)));
v.push((
if let Some(loca) = info.location() {
loca.file()
} else {
"NoFile"
},
(Color::GREEN, Color::BLACK),
));
v.push((":", (Color::WHITE, Color::BLACK)));
v.push((
if let Some(_) = info.location() {
line_in_file.as_str()
} else {
"NoLine"
},
(Color::WHITE, Color::BLACK),
));
v.push((": ", (Color::WHITE, Color::BLACK)));
v.push((
if let Some(&s) = info.payload().downcast_ref::<&str>() {
s
} else {
"Unknown panic."
},
(Color::BLUE, Color::BLACK),
));
v.push(("\n", (Color::BLACK, Color::BLACK)));
v
};
let tty = tty::tty_get(0);
if tty != null_mut() {
let tty = *tty;
tty_enable(tty);
for (msgo, (fgc, bgc)) in info.into_iter() {
let msg = String::from(msgo).as_bytes_mut() as *mut [u8] as *mut u8;
let p = msg.offset(msgo.len() as isize);
let swp = *p;
*p = 0;
tty_text_print(tty, msg, u32::from(fgc), u32::from(bgc));
*p = swp;
}
}
unsafe fn kernel_panic_handler(_info: &PanicInfo) -> ! {
let tty = Tty::from_id(0).unwrap();
tty.enable();
tty.print(message!(
"Hit a {Rust} panic.",
FmtMeta::Color(Color::ORANGE)
));
loop {}
}

11
src/libk/alloc/alloc.rs Normal file
View File

@ -0,0 +1,11 @@
use core::alloc::{GlobalAlloc, Layout};
use crate::kernel::memm::memm::KERNEL_ALLOCATOR;
pub unsafe fn alloc(layout: Layout) -> *mut u8 {
KERNEL_ALLOCATOR.alloc(layout)
}
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
KERNEL_ALLOCATOR.dealloc(ptr, layout);
}

49
src/libk/alloc/boxed.rs Normal file
View File

@ -0,0 +1,49 @@
use core::{
alloc::Layout,
mem::transmute,
ops::{Deref, DerefMut},
ptr::addr_of,
};
use crate::libk::alloc::alloc::{alloc, dealloc};
pub struct Box<T: ?Sized> {
inner: *mut T,
}
impl<T> Box<T> {
pub fn new(t: T) -> Self {
unsafe {
let inner = alloc(Layout::for_value(&t));
inner.copy_from(addr_of!(t).cast(), 1);
Self {
inner: transmute(inner),
}
}
}
}
impl<T: ?Sized> Deref for Box<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.inner.as_ref().unwrap() }
}
}
impl<T: ?Sized> DerefMut for Box<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.inner.as_mut().unwrap() }
}
}
impl<T: ?Sized> Drop for Box<T> {
fn drop(&mut self) {
unsafe {
dealloc(
self.inner.cast(),
Layout::for_value_raw(self.inner.cast_const()),
)
}
}
}

4
src/libk/alloc/mod.rs Normal file
View File

@ -0,0 +1,4 @@
pub mod alloc;
pub mod boxed;
pub mod string;
pub mod vec;

386
src/libk/alloc/string.rs Normal file
View File

@ -0,0 +1,386 @@
use core::ops::{Add, AddAssign};
use super::vec::{Vec, VecIterator};
#[derive(Default)]
pub struct String {
data: Vec<char>,
u8data: Vec<u8>,
}
impl String {
pub fn new() -> Self {
Self {
data: Vec::new(),
u8data: Vec::new(),
}
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn chars(&self) -> VecIterator<char> {
self.data.iter()
}
pub fn as_bytes(&self) -> &[u8] {
&self.u8data[..]
}
pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
&mut self.u8data[..]
}
pub fn insert(&mut self, index: usize, item: char) {
self.data.insert(index, item);
self.u8data.insert(index, item as u8);
}
}
impl FromIterator<char> for String {
fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
let data = Vec::from_iter(iter);
let u8data = Vec::from_iter(data.iter().map(|c| *c as u8));
Self { data, u8data }
}
}
impl<'a> FromIterator<&'a char> for String {
fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
let data = Vec::from_iter(iter.into_iter().map(|c| *c));
let u8data = Vec::from_iter(data.iter().map(|c| *c as u8));
Self { data, u8data }
}
}
impl ToString for String {
fn to_string(&self) -> String {
self.clone()
}
}
impl Add for String {
type Output = Self;
fn add(mut self, rhs: Self) -> Self::Output {
self.data.append(&mut rhs.chars().map(|c| *c).collect());
self
}
}
impl AddAssign for String {
fn add_assign(&mut self, rhs: String) {
*self = self.clone() + rhs;
}
}
impl Clone for String {
fn clone(&self) -> Self {
Self {
data: self.data.clone(),
u8data: self.u8data.clone(),
}
}
}
pub trait ToString {
fn to_string(&self) -> String;
fn to_octal_string(&self) -> String {
String::new()
}
fn to_hex_string(&self) -> String {
String::new()
}
}
impl ToString for str {
fn to_string(&self) -> String {
String::from_iter(self.chars())
}
}
impl ToString for &'static str {
fn to_string(&self) -> String {
(*self).to_string()
}
}
impl ToString for u8 {
fn to_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 10) as u8 + b'0') as char);
num /= 10;
}
res
}
fn to_octal_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 8) as u8 + b'0') as char);
num /= 8;
}
res
}
fn to_hex_string(&self) -> String {
let tohex = |x| {
if x < 10 {
x as u8 + b'0'
} else {
x as u8 - 10 + b'a'
}
};
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, tohex(num % 16) as char);
num /= 16;
}
res
}
}
impl ToString for u16 {
fn to_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 10) as u8 + b'0') as char);
num /= 10;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_octal_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 8) as u8 + b'0') as char);
num /= 8;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_hex_string(&self) -> String {
let tohex = |x| {
if x < 10 {
x as u8 + b'0'
} else {
x as u8 - 10 + b'a'
}
};
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, tohex(num % 16) as char);
num /= 16;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
}
impl ToString for u32 {
fn to_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 10) as u8 + b'0') as char);
num /= 10;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_octal_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 8) as u8 + b'0') as char);
num /= 8;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_hex_string(&self) -> String {
let tohex = |x| {
if x < 10 {
x as u8 + b'0'
} else {
x as u8 - 10 + b'a'
}
};
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, tohex(num % 16) as char);
num /= 16;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
}
impl ToString for u64 {
fn to_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 10) as u8 + b'0') as char);
num /= 10;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_octal_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 8) as u8 + b'0') as char);
num /= 8;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_hex_string(&self) -> String {
let tohex = |x| {
if x < 10 {
x as u8 + b'0'
} else {
x as u8 - 10 + b'a'
}
};
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, tohex(num % 16) as char);
num /= 16;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
}
impl ToString for u128 {
fn to_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 10) as u8 + b'0') as char);
num /= 10;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_octal_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 8) as u8 + b'0') as char);
num /= 8;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_hex_string(&self) -> String {
let tohex = |x| {
if x < 10 {
x as u8 + b'0'
} else {
x as u8 - 10 + b'a'
}
};
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, tohex(num % 16) as char);
num /= 16;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
}
impl ToString for usize {
fn to_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 10) as u8 + b'0') as char);
num /= 10;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_octal_string(&self) -> String {
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, ((num % 8) as u8 + b'0') as char);
num /= 8;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
fn to_hex_string(&self) -> String {
let tohex = |x| {
if x < 10 {
x as u8 + b'0'
} else {
x as u8 - 10 + b'a'
}
};
let mut num = *self;
let mut res = String::new();
while num != 0 {
res.insert(0, tohex(num % 16) as char);
num /= 16;
}
if res.len() == 0 {
res.insert(0, '0');
}
res
}
}

284
src/libk/alloc/vec.rs Normal file
View File

@ -0,0 +1,284 @@
use core::{
alloc::Layout,
ops::{Index, IndexMut, Range, RangeFull},
ptr::addr_of_mut,
slice,
};
use crate::libk::{
alloc::alloc::{alloc, dealloc},
core::ptr::PtrOptions,
};
pub struct Vec<T> {
pointer: *mut T,
length: usize,
capacity: usize,
}
impl<T: Default> Vec<T> {
pub fn new() -> Self {
Self {
pointer: unsafe { alloc(Layout::array::<T>(4).unwrap()).cast() },
length: 0,
capacity: 4,
}
}
unsafe fn extend_capacity(&mut self) {
let newp: *mut T = alloc(Layout::array::<T>(self.capacity * 2).unwrap()).cast();
self.pointer.kcopy_to(newp, self.length);
dealloc(
self.pointer.cast(),
Layout::array::<T>(self.capacity).unwrap(),
);
self.pointer = newp;
self.capacity *= 2;
}
pub fn push(&mut self, item: T) {
if self.capacity == self.length {
unsafe { self.extend_capacity() }
}
unsafe { self.pointer.offset(self.length as isize).write(item) };
self.length += 1;
}
pub fn insert(&mut self, index: usize, item: T) {
if self.capacity == self.length {
unsafe { self.extend_capacity() }
}
let rearlen = self.length - index;
unsafe {
if rearlen != 0 {
let tmp = alloc(Layout::array::<T>(rearlen).unwrap()).cast();
self.pointer.offset(index as isize).kcopy_to(tmp, rearlen);
self.pointer.offset(index as isize).write(item);
self.pointer
.offset(index as isize + 1)
.kcopy_from(tmp, rearlen);
} else {
self.pointer.offset(self.length as isize).write(item);
}
}
self.length += 1;
}
pub fn append(&mut self, v: &mut Self) {
while self.capacity < self.length + v.length {
unsafe { self.extend_capacity() }
}
unsafe {
self.pointer
.offset(self.length as isize)
.kcopy_from(v.pointer.cast_const(), v.length)
};
self.length += v.length;
}
pub fn split_at(&self, index: usize) -> (&[T], &[T]) {
if index >= self.length {
panic!("Index out of bound.");
}
(&self[0..index], &self[index..self.length])
}
pub fn len(&self) -> usize {
self.length
}
pub fn is_empty(&self) -> bool {
self.length == 0
}
pub fn last_mut(&mut self) -> Option<&mut T> {
unsafe { self.pointer.offset(self.length as isize - 1).as_mut() }
}
pub fn last(&self) -> Option<&T> {
unsafe { self.pointer.offset(self.length as isize - 1).as_ref() }
}
pub fn remove(&mut self, index: usize) -> T {
if index >= self.length {
panic!("Index out of bound.");
}
let mut t: T = T::default();
let pt = addr_of_mut!(t);
unsafe {
pt.kcopy_from(self.pointer.offset(index as isize).cast_const(), 1);
self.pointer.offset(index as isize).kcopy_from(
self.pointer.offset(index as isize + 1),
self.length - index - 1,
);
}
self.length -= 1;
t
}
pub fn iter(&self) -> VecIterator<T> {
VecIterator {
pointer: self.pointer,
index: 0,
length: self.length,
_phantom: &(),
}
}
}
impl<T: Default> Default for Vec<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Default> Index<usize> for Vec<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
unsafe { self.pointer.offset(index as isize).as_ref().unwrap() }
}
}
impl<T: Default> Index<Range<usize>> for Vec<T> {
type Output = [T];
fn index(&self, index: Range<usize>) -> &Self::Output {
unsafe { &slice::from_raw_parts_mut(self.pointer, self.length)[index] }
}
}
impl<T: Default> Index<RangeFull> for Vec<T> {
type Output = [T];
fn index(&self, _: RangeFull) -> &Self::Output {
unsafe { slice::from_raw_parts(self.pointer.cast(), self.length) }
}
}
impl<T: Default> IndexMut<RangeFull> for Vec<T> {
fn index_mut(&mut self, _: RangeFull) -> &mut Self::Output {
unsafe { slice::from_raw_parts_mut(self.pointer.cast(), self.length) }
}
}
impl<T: Default> Clone for Vec<T> {
fn clone(&self) -> Self {
let res = Self {
pointer: unsafe { alloc(Layout::array::<T>(self.capacity).unwrap()).cast() },
length: self.length,
capacity: self.capacity,
};
unsafe {
res.pointer
.kcopy_from(self.pointer.cast_const(), self.length)
};
res
}
}
impl<T> Drop for Vec<T> {
fn drop(&mut self) {
unsafe {
dealloc(
self.pointer.cast(),
Layout::array::<T>(self.capacity).unwrap(),
)
};
}
}
impl<T: Default> FromIterator<T> for Vec<T> {
fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> Self {
let mut res = Vec::new();
for i in iter {
res.push(i);
}
res
}
}
impl<T: Default> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = VecIter<T>;
fn into_iter(self) -> Self::IntoIter {
VecIter {
pointer: self.pointer,
index: 0,
length: self.length,
capacity: self.capacity,
}
}
}
pub struct VecIterator<'a, T> {
pointer: *mut T,
index: usize,
length: usize,
_phantom: &'a (),
}
impl<'a, T: 'a> Iterator for VecIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.length {
None
} else {
let res = unsafe { Some(self.pointer.offset(self.index as isize).as_ref().unwrap()) };
self.index += 1;
res
}
}
}
impl<'a, T: 'a> DoubleEndedIterator for VecIterator<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.index == 0 {
None
} else {
self.index -= 1;
unsafe { Some(self.pointer.offset(self.index as isize).as_ref().unwrap()) }
}
}
}
pub struct VecIter<T> {
pointer: *mut T,
index: usize,
length: usize,
capacity: usize,
}
impl<T: Default> Iterator for VecIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.length {
None
} else {
let mut t = T::default();
let res = unsafe {
self.pointer
.offset(self.index as isize)
.kcopy_to(addr_of_mut!(t), 1);
Some(t)
};
self.index += 1;
res
}
}
}
impl<T> Drop for VecIter<T> {
fn drop(&mut self) {
unsafe {
dealloc(
self.pointer.cast(),
Layout::array::<T>(self.capacity).unwrap(),
)
};
}
}

1
src/libk/core/mod.rs Normal file
View File

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

30
src/libk/core/ptr/mod.rs Normal file
View File

@ -0,0 +1,30 @@
use core::mem::{size_of, transmute};
extern "C" {
pub fn memset(des: *const u8, src: u8, len: usize);
pub fn memcpy(des: *const u8, src: *const u8, len: usize);
pub fn strlen(des: *const u8) -> usize;
}
pub trait PtrOptions<T> {
unsafe fn kcopy_from(self, src: *const T, count: usize);
unsafe fn kcopy_to(self, des: *const T, count: usize);
}
impl<T> PtrOptions<T> for *mut T {
unsafe fn kcopy_from(self, src: *const T, count: usize) {
memcpy(
transmute(self.cast_const()),
transmute(src),
count * size_of::<T>(),
);
}
unsafe fn kcopy_to(self, des: *const T, count: usize) {
memcpy(
transmute(des),
transmute(self.cast_const()),
count * size_of::<T>(),
);
}
}

View File

@ -1 +1,2 @@
pub mod string;
pub mod alloc;
pub mod core;

View File

1878
src/ttyfonts/metamono.tfn Normal file

File diff suppressed because it is too large Load Diff