重构内存分配器、增加中断支持、整理rust运行时环境 #4

Merged
pointer-to-bios merged 39 commits from downstream into main 2024-04-11 00:36:14 +08:00
51 changed files with 1646 additions and 435 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
/.vscode
/test/metaverse.img /test/metaverse.img
*.o *.o
*.map *.map

16
.vscode/c_cpp_properties.json vendored Normal file
View File

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

9
.vscode/settings.json vendored Normal file
View File

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

View File

@ -2,6 +2,7 @@
name = "metaverse" name = "metaverse"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
crate-type = ["staticlib"]
# 此Cargo.toml仅用于rust-analyzer识别rust部分的代码 # 此Cargo.toml仅用于rust-analyzer识别rust部分的代码
# 不应使用cargo编译 # 不应使用cargo编译

View File

@ -1,27 +1,42 @@
SOURCE := $(shell pwd)/src/scripts SOURCE := $(shell pwd)/scripts
.PHONY: all clear run debug config .PHONY: all clear run debug disass
all: config all: metaverse_kernel
@make -C src all --no-print-directory @make -C src all --no-print-directory
clear: config clear: metaverse_kernel
@make -C src clear --no-print-directory @make -C src clear --no-print-directory
run: config run: metaverse_kernel
@make -C test run --no-print-directory @make -C test run --no-print-directory
debug: config debug: metaverse_kernel
@make -C test debug --no-print-directory @make -C test debug --no-print-directory
config: metaverse_kernel:
@if [ "${shell uname -s}" != "Linux" ]; then \ @if [ "${shell uname -s}" != "Linux" ]; then \
echo -e "\e[1;33mMetaverse\e[0m must build under \e[1;35mLinux\e[0m or itself."; \ echo -e "\e[1;33mMetaverse\e[0m must build under \e[1;35mLinux\e[0m or itself."; \
exit -1; \ exit -1; \
fi fi
@if [ -f "metaverse_kernel" ]; then \ @"${SOURCE}/depcheck";
echo; \ @if [ $$? != 0 ]; then \
else \ exit $$?; \
touch metaverse_kernel; \
"${SOURCE}/depcheck"; \
fi fi
@touch metaverse_kernel
disass:
objdump -D src/metaverse.elf > kerndisass.txt
install-grub:
@cp src/metaverse.elf /boot/
@if ! grep -q "Metaverse" /boot/grub/grub.cfg; then \
echo -e 'menuentry "Metaverse" {\n set root=(hd0,gpt1)\n multiboot2 /metaverse.elf\n}\n' >> \
/boot/grub/grub.cfg; \
echo -e 'Added Metaverse into grub entries.'; \
else \
echo -e 'Metaverse entry exists.'; \
fi
remove-grub:
@-rm /boot/metaverse.elf

View File

@ -57,6 +57,8 @@ make debug
* [x] raw_allocator * [x] raw_allocator
* [x] tty * [x] tty
* [x] 内核日志 * [x] 内核日志
* [ ] 系统调用
* [ ] 中断管理
* [ ] 文件系统 * [ ] 文件系统
* [ ] vfs * [ ] vfs
* [ ] fat32驱动移植 * [ ] fat32驱动移植
@ -64,9 +66,19 @@ make debug
* [ ] 驱动管理 * [ ] 驱动管理
* [ ] 进程管理 * [ ] 进程管理
## 文档
* 从源代码注释生成文档
```bash
make doc
```
(开发中)
## 作出贡献 ## 作出贡献
通过向此仓库发送PR为我们作出贡献。 通过向此仓库发送PR为我们作出贡献,详见[contribution.md](docs/contribution.md)
## 版权声明 ## 版权声明

20
docs/contribution.md Normal file
View File

@ -0,0 +1,20 @@
# 向Metaverse内核贡献代码
通过如下方式向内核增加你的代码:
* 从[github仓库](https://github.com/metaverse-kernel/kernel-dev)或[Random World Studio内部仓库](http://git.suthby.org:2024/metaverse/kernel-dev)创建一个分支
* 在你的分支中增加代码
* 测试你增加的代码的正确性,并尽量确保对原有代码没有影响
* 无需在注释中加入代码更改日志git可以做到
* 在文档的适当的位置增加对新特性的描述
* 完成编码和文档的工作后向主仓库发送PR
* 等待审核代码
若你的代码通过审核将会把你的PR合并到主分支中。
## 需要注意的还未解决的问题
* rust中所有有关字符串格式化的宏中出现超过一个不止是`{}`的格式化占位符时内核必然崩溃。
* rust中所有有关字符串格式化的宏中出现需要调用自定义的`Debug trait`的类型时内核必然崩溃,推荐定义`ToString trait`并调用`.to_string()`后传入宏参数。
* 鉴于以上两条原因,不建议在复杂的字符串格式化任务中使用`format!()`宏。推荐通过使用`::kernel::tty::tty::MessageBuilder`构造`kernel::tty::tty::Message`对象,或使用
`message`宏,并调用此对象的`.to_string()`方法实现格式化字符串。

View File

@ -0,0 +1,69 @@
#ifndef X86_64_INTERRUPT_H
#define X86_64_INTERRUPT_H 1
#include <types.h>
#include <utils.h>
/**
* @name gate_descriptor_t
* @addindex x86_64
*
*
*/
typedef struct __gate_descriptor_t
{
u16 offset_01;
u16 segment_selector; // for code segment
u16 flags;
u16 offset_23;
u32 offset_4567;
u32 reserved;
} DISALIGNED gate_descriptor_t;
/**
* @name INTERRUPT_DESCRIPTOR_FLAG_IST
* @addindex x86_64
*
* `gate_descriptor_t``flags`
*
* `ssp`tss描述符在任务段中的的索引
*/
#define INTERRUPT_DESCRIPTOR_FLAG_IST 1
// 在第15位上有一个表示代码段是否存在的标志位代码段总是存在故直接设置为1
#define INTERRUPT_DESCRIPTOR_FLAG_TYPE_INTERRUPT (0x8e << 8)
#define INTERRUPT_DESCRIPTOR_FLAG_TYPE_TRAP (0x8f << 8)
/**
* @name idt
*
*
*/
extern gate_descriptor_t idt[256];
#define interrupt_gate_generate(desc, addr) \
{ \
(desc).segment_selector = 0x8; \
(desc).flags = INTERRUPT_DESCRIPTOR_FLAG_TYPE_INTERRUPT | \
INTERRUPT_DESCRIPTOR_FLAG_IST; \
(desc).reserved = 0; \
(desc).offset_01 = (u16)((u64)(addr)); \
(desc).offset_23 = (u16)(((u64)(addr)) >> 16); \
(desc).offset_4567 = (u32)(((u64)(addr)) >> 32); \
}
#define trap_gate_generate(desc, addr) \
{ \
(desc).segment_selector = 0x8; \
(desc).flags = INTERRUPT_DESCRIPTOR_FLAG_TYPE_TRAP | \
INTERRUPT_DESCRIPTOR_FLAG_IST; \
(desc).reserved = 0; \
(desc).offset_01 = (u16)((u64)(addr)); \
(desc).offset_23 = (u16)(((u64)(addr)) >> 16); \
(desc).offset_4567 = (u32)(((u64)(addr)) >> 32); \
}
#define interrupt_register_gate(desc, index) \
idt[index] = desc;
#endif

View File

@ -0,0 +1,87 @@
#ifndef X86_64_INTERRUPT_PROCS_H
#define X86_64_INTERRUPT_PROCS_H 1
#include <utils.h>
/**
* @name interrupt_entry
* @addindex x86_64
*
*
*
* ```c
* void interrupt_entry();
* ```
*
* ```asm
* interrupt_entry_xx:
* ;
* interrupt_entry_enter
*
* ;
* ...
*
* ;
* interrupt_entry_leave
* iret
* ```
*/
typedef void (*interrupt_entry)();
/**
* @name interrupt_entry_gen
* @addindex x86_64
*
*
*
* ```c
* #define interrupt_entry_gen(interrupt)
* ```
*/
#define interrupt_entry_gen(interrupt) \
extern void interrupt_entry_##interrupt()
#define interrupt_entry_sym(interrupt) \
interrupt_entry_##interrupt
/**
* @name interrupt_request
* @addindex
*
*
*
* ```c
* void interrupt_request(u64 rip, u64 rsp);
* ```
*
*
*/
typedef void (*interrupt_request)(u64 rip, u64 rsp, u64 errcode);
/**
* @name interrupt_req_gen
* @addindex x86_64
*
*
*
* ```c
* #define interrupt_req_gen(interrupt)
* ```
*/
#define interrupt_req_gen(interrupt) \
void interrupt_req_##interrupt(u64 rip, u64 rsp, u64 errcode)
#define interrupt_req_sym(interrupt) \
interrupt_req_##interrupt
#define UNSUPPORTED
#define DE
#define NMI
#define BP
interrupt_entry_gen(UNSUPPORTED);
interrupt_entry_gen(DE);
interrupt_entry_gen(NMI);
interrupt_entry_gen(BP);
#endif

View File

@ -3,7 +3,15 @@
#include <types.h> #include <types.h>
// 具有返回值是为了留出一个寄存器用于调整栈顶 /**
extern usize prepare_stack(); * @name prepare_stack
*
* ```c
* void prepare_stack();
* ```
*/
extern void prepare_stack();
extern u32 TSS[26];
#endif #endif

View File

@ -4,8 +4,33 @@
#include <types.h> #include <types.h>
#include <libk/bits.h> #include <libk/bits.h>
/* 页大小以MEMM_PAGE_SIZE为单位 */ /**
* @details x86_64
*
*
*
* * 0 \~ 1MB
* * 1MB \~ 2MB
* * 2MB \~ 4MB
* * 4MB \~ 16MB
* * 16MB \~ ?
* * ? \~ 128MB
*/
/**
* @name MEMM_PAGE_SIZE
* @addindex
*
*
*
* @if arch == x86_64 then
* 4096
* @endif
*/
#define MEMM_PAGE_SIZE 4096 #define MEMM_PAGE_SIZE 4096
#define MEMM_PAGE_TABLE_SIZE 4096
typedef enum __memm_page_size typedef enum __memm_page_size
{ {
MEMM_PAGE_SIZE_4K = 1, // 1个4KB页大小 MEMM_PAGE_SIZE_4K = 1, // 1个4KB页大小
@ -15,14 +40,49 @@ typedef enum __memm_page_size
extern u64 PML4[512]; extern u64 PML4[512];
#define MEMM_PAGE_TABLE_FLAGS_AREA ((u64)0xfff) /**
* @name MEMM_PAGE_TABLE_FLAGS_MASK
* @addindex x86_64
*
* 使12`0xfff`
*/
#define MEMM_PAGE_TABLE_FLAGS_MASK ((u64)0xfff)
/* 页对齐掩码 */ /**
* @name MEMM_xx_ALIGN_MASK
* @addindex x86_64
*
*
* `xx``x86_64``4K``2M``1G`n位总为0的情况
* `4K``0xfff``2M``0x1fffff``1G``0x3fffffff`
*/
#define MEMM_4K_ALIGN_MASK ((u64)0xfff) #define MEMM_4K_ALIGN_MASK ((u64)0xfff)
#define MEMM_2M_ALIGN_MASK ((u64)0x1fffff) #define MEMM_2M_ALIGN_MASK ((u64)0x1fffff)
#define MEMM_1G_ALIGN_MASK ((u64)0x3fffffff) #define MEMM_1G_ALIGN_MASK ((u64)0x3fffffff)
/* 页表项属性FLAGS */ /**
* @name MEMM_ENTRY_FLAG_xx
* @addindex x86_64
*
*
*
* ```c
* #define MEMM_ENTRY_FLAG_PRESENT ((u64)1)
* #define MEMM_ENTRY_FLAG_WRITE ((u64)1 << 1)
* #define MEMM_ENTRY_FLAG_USER ((u64)1 << 2)
* #define MEMM_ENTRY_FLAG_PWT ((u64)1 << 3)
* #define MEMM_ENTRY_FLAG_PCD ((u64)1 << 4)
* #define MEMM_ENTRY_FLAG_ACCECED ((u64)1 << 5)
* #define MEMM_ENTRY_FLAG_DIRTY ((u64)1 << 6)
* #define MEMM_ENTRY_FLAG_PS ((u64)1 << 7)
* #define MEMM_ENTRY_FLAG_GLOBAL ((u64)1 << 8)
* #define MEMM_ENTRY_FLAG_PAT ((u64)1 << 12)
* #define MEMM_PTE_ENTRY_FLAG_PAT ((u64)1 << 7)
* #define MEMM_ENTRY_FLAG_XD ((u64)1 << 63)
* ```
*
* `MEMM_PTE_ENTRY_FLAG_PAT``pte``pte`
*/
#define MEMM_ENTRY_FLAG_PRESENT ((u64)1) #define MEMM_ENTRY_FLAG_PRESENT ((u64)1)
#define MEMM_ENTRY_FLAG_WRITE ((u64)1 << 1) #define MEMM_ENTRY_FLAG_WRITE ((u64)1 << 1)
#define MEMM_ENTRY_FLAG_USER ((u64)1 << 2) #define MEMM_ENTRY_FLAG_USER ((u64)1 << 2)
@ -35,18 +95,47 @@ extern u64 PML4[512];
#define MEMM_ENTRY_FLAG_PAT ((u64)1 << 12) #define MEMM_ENTRY_FLAG_PAT ((u64)1 << 12)
#define MEMM_PTE_ENTRY_FLAG_PAT ((u64)1 << 7) #define MEMM_PTE_ENTRY_FLAG_PAT ((u64)1 << 7)
#define MEMM_ENTRY_FLAG_XD ((u64)1 << 63) #define MEMM_ENTRY_FLAG_XD ((u64)1 << 63)
/**
* @name memm_entry_flag_get(entry, flag)
* @addindex x86_64
*
*
*
* `flag``MEMM_ENTRY_FLAG_xx`
*/
#define memm_entry_flag_get(entry, flag) \ #define memm_entry_flag_get(entry, flag) \
((entry & flag) ? true : false) ((entry & flag) ? true : false)
/* 页表(大型页)项地址域掩码 */ /**
* @name MEMM_ENTRY_ADDRESS_MASK, MEMM_BP_ENTRY_ADDRESS_MASK
* @addindex x86_64
*
* ********
*
* `BP`
*
*
*
* ```c
* #define MEMM_ENTRY_ADDRESS_MASK ((u64)0x000ffffffffff000)
* #define MEMM_BP_ENTRY_ADDRESS_MASK ((u64)0x000fffffffffe000)
* ```
*/
#define MEMM_ENTRY_ADDRESS_MASK ((u64)0x000ffffffffff000) #define MEMM_ENTRY_ADDRESS_MASK ((u64)0x000ffffffffff000)
#define MEMM_BP_ENTRY_ADDRESS_MASK ((u64)0x000fffffffffe000) #define MEMM_BP_ENTRY_ADDRESS_MASK ((u64)0x000fffffffffe000)
/**
* @name memm_entry_get_address(entry)
* @addindex x86_64
*
*
*/
#define memm_entry_get_address(entry) \ #define memm_entry_get_address(entry) \
((entry) & (memm_entry_flag_get(entry, MEMM_ENTRY_FLAG_PS) \ ((entry) & (memm_entry_flag_get(entry, MEMM_ENTRY_FLAG_PS) \
? MEMM_BP_ENTRY_ADDRESS_MASK \ ? MEMM_BP_ENTRY_ADDRESS_MASK \
: MEMM_ENTRY_ADDRESS_MASK)) : MEMM_ENTRY_ADDRESS_MASK))
/* 线性地址表项索引或页内偏移掩码 */
#define MEMM_LA_PML4EI_MASK ((u64)0x0000ff8000000000) #define MEMM_LA_PML4EI_MASK ((u64)0x0000ff8000000000)
#define MEMM_LA_PDPTEI_MASK ((u64)0x0000007fc0000000) #define MEMM_LA_PDPTEI_MASK ((u64)0x0000007fc0000000)
#define MEMM_LA_PDEI_MASK ((u64)0x000000003fe00000) #define MEMM_LA_PDEI_MASK ((u64)0x000000003fe00000)
@ -56,50 +145,119 @@ extern u64 PML4[512];
#define MEMM_LA_2MB_PAGE_OFFSET_MASK ((u64)0x00000000001fffff) #define MEMM_LA_2MB_PAGE_OFFSET_MASK ((u64)0x00000000001fffff)
#define MEMM_LA_4KB_PAGE_OFFSET_MASK ((u64)0x0000000000000fff) #define MEMM_LA_4KB_PAGE_OFFSET_MASK ((u64)0x0000000000000fff)
/* 线性地址表项索引偏移位数 */
#define MEMM_LA_PML4EI_OFFSET (39) #define MEMM_LA_PML4EI_OFFSET (39)
#define MEMM_LA_PDPTEI_OFFSET (30) #define MEMM_LA_PDPTEI_OFFSET (30)
#define MEMM_LA_PDEI_OFFSET (21) #define MEMM_LA_PDEI_OFFSET (21)
#define MEMM_LA_PEI_OFFSET (12) #define MEMM_LA_PEI_OFFSET (12)
/* 获取线性地址中某个表项索引以及获取页内偏移 */ /**
* @name MEMM_LA_xxxxI
* @addindex x86_64
*
* 4线`xxxx``PML4E``PDPTE``PDE``PE`
*/
#define MEMM_LA_PML4EI #define MEMM_LA_PML4EI
#define MEMM_LA_PDPTEI #define MEMM_LA_PDPTEI
#define MEMM_LA_PDEI #define MEMM_LA_PDEI
#define MEMM_LA_PEI #define MEMM_LA_PEI
/**
* @name memm_la_get_entry_index(addr, entry)
* @addindex x86_64
*
* 线`addr``entry`
*
* `entry``MEMM_LA_xxxxI`
*/
#define memm_la_get_entry_index(addr, entry) \ #define memm_la_get_entry_index(addr, entry) \
(((addr) & (entry##_MASK)) >> (entry##_OFFSET)) (((addr) & (entry##_MASK)) >> (entry##_OFFSET))
/**
* @name MEMM_LA_xxx_PAGE_OFFSET
* @addindex x86_64
*
* 线`xxx``4KB``2MB``1GB`
*/
#define MEMM_LA_1GB_PAGE_OFFSET #define MEMM_LA_1GB_PAGE_OFFSET
#define MEMM_LA_2MB_PAGE_OFFSET #define MEMM_LA_2MB_PAGE_OFFSET
#define MEMM_LA_4KB_PAGE_OFFSET #define MEMM_LA_4KB_PAGE_OFFSET
/**
* @name memm_la_get_offset(addr, page_type)
* @addindex x86_64
*
* 线
*
* `page_type``MEMM_LA_xxx_PAGE_OFFSET`
*/
#define memm_la_get_offset(addr, page_type) \ #define memm_la_get_offset(addr, page_type) \
((addr) & (page_type##_MASK)) ((addr) & (page_type##_MASK))
/* /**
canonical型地址 * @name memm_map_pageframes_to
*
target与physical至少都是以MEMM_PAGE_SIZE对齐的 * ```c
* bool memm_map_pageframes_to(
MEMM_PAGE_SIZE对齐的canonical型地址都会返回false * u64 target, u64 physical,
* usize size,
1GB的一半且地址1GB对齐1GB页 * bool user, bool write);
2MB的一半且地址2MB对齐2MB页 * ```
4KB页 *
* **canonical**
*
* `target``physical`MEMM_PAGE_SIZE对齐的
*
* MEMM_PAGE_SIZE对齐的canonical型地址都会返回false
*
* 1GB的一半且地址1GB对齐1GB页
* 2MB的一半且地址2MB对齐2MB页
* 4KB页
*/ */
bool memm_map_pageframes_to( bool memm_map_pageframes_to(
u64 target, u64 physical, u64 target, u64 physical,
usize size, usize size,
bool user, bool write); bool user, bool write);
/**
* @name reload_pml4
* @addindex x86_64
*
* ```c
* void reload_pml4();
* ```
*/
extern void reload_pml4(); extern void reload_pml4();
/**
* @name is_user_address(addr)
* @addindex
*
* `addr`
*
* @if arch == x86_64
* `canonical`
* @endif
*/
#define is_user_address(addr) \ #define is_user_address(addr) \
(((addr) > 0xffff7fffffffffff) ? true : false) (((addr) > 0xffff7fffffffffff) ? true : false)
/**
* @name is_cannonical(addr)
* @addindex x86_64
*
* `addr`cannonical型地址
*/
#define is_cannonical(addr) \ #define is_cannonical(addr) \
(((addr) < 0x0000800000000000 || (addr) > 0xffff7fffffffffff) ? true : false) (((addr) < 0x0000800000000000 || (addr) > 0xffff7fffffffffff) ? true : false)
/**
* @name memm_get_page_align(addr)
* @addindex x86_64
*
* `addr``memm_page_size`
*
* `addr`*4KB对齐**4KB对齐时*`MEMM_PAGE_SIZE_4K`
*/
#define memm_get_page_align(addr) \ #define memm_get_page_align(addr) \
(is_aligned(addr, MEMM_PAGE_SIZE_1G) \ (is_aligned(addr, MEMM_PAGE_SIZE_1G) \
? MEMM_PAGE_SIZE_1G \ ? MEMM_PAGE_SIZE_1G \
@ -107,4 +265,21 @@ extern void reload_pml4();
? MEMM_PAGE_SIZE_2M \ ? MEMM_PAGE_SIZE_2M \
: MEMM_PAGE_SIZE_4K)) : MEMM_PAGE_SIZE_4K))
/**
* @name memm_page_counter
* @addindex
*
*
*
* @if arch == x86_64
* 使`4KB``2MB``1GB`
* @endif
*/
typedef struct __memm_page_counter
{
usize mapped_4k_page;
usize mapped_2m_page;
usize mapped_1g_page;
} memm_page_counter;
#endif #endif

View File

@ -0,0 +1,25 @@
#ifndef X86_64_PROC_H
#define X86_64_PROC_H 1
#include <types.h>
/**
* @name proc_texture_registers_t
* @addindex x86_64
*
*
*/
typedef struct __proc_texture_registers_t
{
u16 es, ds;
u32 reserved;
u64 r15, r14, r13, r12;
u64 r11, r10, r9, r8;
u64 rdi, rsi, rdx, rbx, rcx, rax;
u64 rbp;
u64 rip, cs;
u64 rflags;
u64 rsp, ss;
} proc_texture_registers_t;
#endif

View File

@ -0,0 +1,56 @@
#ifndef X86_64_SYSCALL
#define X86_64_SYSCALL 1
#include <types.h>
extern void *system_calls_table[256];
/**
* @brief
* @addindex x86_64
*
* 使
* rax -
* rbx -
* rcx - rip寄存器缓存
* rdi -
* rdx - 1
* r8 - 2
* r9 - 3
* r10 - 4
* r11 - rflags寄存器缓存
* r12 - 5
* r13 - 6
* r14 - 7
* r15 - 8
*
* - rax
*
* 使
*/
/**
* @name set_kernel_stack_cache
* @addindex x86_64
*
* ```c
* void set_kernel_stack_cache(usize stack);
* ```
*
* `stack`
*/
extern void set_kernel_stack_cache(usize stack);
/**
* @name return_from_systemcall
* @addindex x86_64
*
* ```c
* void return_from_systemcall();
* ```
*
* `sysret`
*/
extern void return_from_systemcall();
#endif

View File

@ -4,12 +4,45 @@
#include <types.h> #include <types.h>
// 使用UNIX时间戳 // 使用UNIX时间戳
/**
* @name system_time_get
*
* ```c
* usize system_time_get();
* ```
*
*
*
* 使unix时间`0`1970-1-1 00:00:00
*/
usize system_time_get(); usize system_time_get();
// 如果硬件支持更高的计时精度, // 如果硬件支持更高的计时精度,
// 此函数提供从系统unix时间开始到现在的纳秒为单位的时间 // 此函数提供从系统unix时间开始到现在的纳秒为单位的时间
/**
* @name system_time_ns_get
*
* ```c
* usize system_time_ns_get();
* ```
*
*
*
*
*
* 使使
*/
usize system_time_ns_get(); usize system_time_ns_get();
/**
* @name system_time_increase
*
* ```c
* void system_time_increase();
* ```
*
*
*/
void system_time_increase(); void system_time_increase();
#endif #endif

View File

@ -0,0 +1,45 @@
#ifndef INTERRUPT_H
#define INTERRUPT_H 1
#ifdef __x86_64__
#include <kernel/arch/x86_64/interrupt.h>
#endif
/**
* @name interrupt_open
* @addindex
*
* ```c
* void interrupt_open();
* ```
*
*
*/
void interrupt_open();
/**
* @name interrupt_close
* @addindex
*
* ```c
* void interrupt_close();
* ```
*
*
*/
void interrupt_close();
/**
* @name interrupt_init
* @addindex
*
* ```c
* void interrupt_init();
* ```
*
*
*/
void interrupt_init();
#endif

View File

@ -0,0 +1,8 @@
#ifndef INTERRUPT_PROCS
#define INTERRUPT_PROCS 1
#ifdef __x86_64__
#include <kernel/arch/x86_64/interrupt_procs.h>
#endif
#endif

View File

@ -2,20 +2,44 @@
#define KERNEL_H 1 #define KERNEL_H 1
#include <types.h> #include <types.h>
#include <kernel/interrupt/procs.h>
#ifdef __x86_64__ #ifdef __x86_64__
#include <kernel/arch/x86_64/kernel.h> #include <kernel/arch/x86_64/kernel.h>
#define ISA_NAME "x86_64" #define ISA_NAME "x86_64"
#endif #endif
#ifndef BUILD_ID
#define BUILD_ID 0
#endif
/**
* @name KERNEL_TODO
*
*
*/
#define KERNEL_TODO() \ #define KERNEL_TODO() \
while (true) \ while (true) \
{ \ { \
} }
/**
* @name simple_lock
*
*
*
* ```c
* #define simple_lock_lock(lock)
* ```
*
*
*
* ```c
* #define simple_lock_unlock(lock)
* ```
*
*
*/
#define simple_lock_lock(lock) \ #define simple_lock_lock(lock) \
{ \ { \
while (lock == true) \ while (lock == true) \
@ -24,8 +48,20 @@
} }
#define simple_lock_unlock(lock) (lock) = false; #define simple_lock_unlock(lock) (lock) = false;
/**
* @name kmain_rust
*
* rust内核主程序
*/
extern void kmain_rust(); extern void kmain_rust();
extern void *kend; // 内核结束的标记 /**
* @name kend
*
*
*
*
*/
extern void *kend;
#endif #endif

View File

@ -1,15 +0,0 @@
#ifndef KLOG_H
#define KLOG_H 1
#include <types.h>
#define KLOG_BUFFER_SIZE 2 * 1024 * 1024
typedef struct __klogger
{
usize tty;
char buffer[KLOG_BUFFER_SIZE];
usize index;
} klogger;
#endif

View File

@ -8,153 +8,227 @@
#include <libk/lst.h> #include <libk/lst.h>
/** /**
* @brief * @name MEMM_MAX_SUPPORTED_MEMORY
* *
* TODO * `1TB`
*/ */
/* 最大支持1TB内存 */
#define MEMM_MAX_SUPPORTED_MEMORY (1024 * (1024 * (1024 * (usize)1024))) #define MEMM_MAX_SUPPORTED_MEMORY (1024 * (1024 * (1024 * (usize)1024)))
/* 最大支持的分页数量 */ /**
// 这里的页均以最小的页大小计算 * @name MEMM_MAX_SUPPORTED_PAGES
*
* `MEMM_MAX_SUPPORTED_MEMORY``MEMM_PAGE_SIZE`
*/
#define MEMM_MAX_SUPPORTED_PAGES (MEMM_MAX_SUPPORTED_MEMORY / MEMM_PAGE_SIZE) #define MEMM_MAX_SUPPORTED_PAGES (MEMM_MAX_SUPPORTED_MEMORY / MEMM_PAGE_SIZE)
/* 只分配不映射空间 */ /**
#define MEMM_ALLOC_ONLY_MEMORY (128 * 1024 * 1024) * @name MEMM_ALLOC_ONLY_MEMORY
*
* `64MB``0`\~`MEMM_ALLOC_ONLY_MEMORY`
*
* **1MB以内低地址******
*/
#define MEMM_ALLOC_ONLY_MEMORY (64 * 1024 * 1024)
typedef void *(*memm_allocate_t)(void *allocator, usize size, usize align); #define MEMM_PAGE_TABLE_AREA_MAX (4 * 1024 * 1024)
/**
* @name memm_allocate_t, memm_free_t
*
* ````使`allocator`
*
*
* `kernel/memm/allocator/`
*
* ****
*
* **`memm_allocate_t`**
*
* ```c
* typedef void *(*memm_allocate_t)(void *allocator, usize size);
* ```
*
* `allocator``size`
*
* `nullptr``size`0`nullptr`
* **16**8
*
* **`memm_free_t`**
*
* ```c
* typedef void (*memm_free_t)(void *allocator, void *mem);
* ```
*
* `allocator``mem`
*
* `mem``allocator`
*/
typedef void *(*memm_allocate_t)(void *allocator, usize size);
typedef void (*memm_free_t)(void *allocator, void *mem); typedef void (*memm_free_t)(void *allocator, void *mem);
/* /**
* @name allocator_t
MEMM_PAGE_SIZE对齐的 *
* ```c
* typedef struct { } allocator_t;
* ```
*
*
*
* `memm_allocate`
*
* ****`MEMM_ALLOC_ONLY_MEMORY```
*
* ****使
*
* @internal magic
*
* `MEMM_ALLOCATOR_MAGIC_NUM`
*
* @internal full
*
* `allocate``nullptr``true`
* `free``false`
*
* @internal pid
*
* 0
*
* @internal userspace
*
*
*
* @internal type
*
* `include/kernel/memm/allocator`
*
* @internal allocate
*
* allocate函数nullptrsize参数为0时
* nullptr
*
* @internal free
*
* free函数allocate得到的地址则什么都不做
*
* @internal allocator_instance
*
*
*/ */
typedef struct __allocator_t typedef struct __allocator_t
{ {
bool initialized; #ifndef MEMM_ALLOCATOR_MAGIC
#define MEMM_ALLOCATOR_MAGIC ((u32)0x271fe441)
#endif
// 分配器有效性由此检验,不为`MEMM_ALLOCATOR_MAGIC_NUM`说明获得了一个错误的分配器地址。
// 此值在编译时通过各种方式确定,若
u32 magic;
// 在本分配器中调用allocate返回nullptr后为true // 调用分配器的`allocate`方法后,在返回`nullptr`时会设为`true`。
// 调用free后为false // 调用分配器的`free`方法时设为`false`。
bool full; bool full;
// 进程id当pid=0时代表内核 // 分配器类型。在目录`include/kernel/memm/allocator`中对每个分配器分别定义一个唯一值。
usize pid;
// 分配器类型
usize type; usize type;
usize size; usize size;
// 分配器实例的allocate函数 // 分配器实例的allocate函数。当无法分配空间时返回nullptr。在size参数为0时
// 无法分配空间返回nullptr // 保证不可以分配空间但是如果空间已满依然返回nullptr。
// 在size参数为0时保证不可以分配空间但是如果空间已满依然返回nullptr
// 当参数align=0时表示不需要对齐
memm_allocate_t allocate; memm_allocate_t allocate;
// 分配器实例的free函数。若不是allocate得到的地址则什么都不做。
// 分配器实例的free函数
// 若不是allocate得到的地址则什么都不做
memm_free_t free; memm_free_t free;
// 分配器实例 // 分配器实例。
// 对应`type`类型使用
// 在kernel/memm/allocator/中是所有的内存分配器
u64 allocator_instance[0]; u64 allocator_instance[0];
} allocator_t; } allocator_t;
typedef struct __allocator_iterator_t /**
{ * @name
allocator_t *allocator; *
struct __allocator_iterator_t *left, *right; * @internal alloc_only_memory
} allocator_iterator_t; *
*
/* */
allocator记录中allocator完成
page_map中置位map_with_allocator中复位map_with_destructed_allocator中复位
available_pages_table中的页使
*/
typedef struct __mem_manager_t typedef struct __mem_manager_t
{ {
usize memory_size; usize memory_size;
usize page_amount; usize page_amount;
// 这里记录的数量为最小的页的数量
usize mapped_page_amount;
// 在进入内核主程序之前,有些不在内核中的虚拟内存空间已经被
// 页表映射,这部分内存不可以再映射到物理页框
usize alloc_only_memory; usize alloc_only_memory;
#ifdef __x86_64__
// 在这里三种页的数量分别记录
usize mapped_4k_page;
usize mapped_2m_page;
usize mapped_1g_page;
#endif
// 页地图
// 每个bit都表示这个页是否被映射
u8 *page_map;
// 分配器页地图
// 每个bit表示这个页是否被内存分配器控制
// (不代表每个页都包含完整的分配器)
u8 *map_with_allocator;
// 分配器释放页地图
// 每个bit表示这个页是否曾经被内存分配器控制且现在被释放
// 需要取消映射
u8 *map_with_destructed_allocator;
// 空闲页线段搜索表 allocator_t *kernel_base_allocator;
lst_iterator_t *available_pages_table;
// 分配器树 usize page_table_area;
// 为方便查找,以二叉树的形式存储 } memory_manager_t;
// index=0为无效项
allocator_iterator_t *allocators;
} mem_manager_t;
mem_manager_t *memm_new(usize mem_size); /**
* @name memm_new
*
* ```c
* memory_manager_t *memm_new(usize mem_size);
* ```
*
*
*/
memory_manager_t *memm_new(usize mem_size);
/* /**
`start``length` * @name memm_get_manager
`pid`0使 *
* ```c
* memory_manager_t *memm_get_manager();
* ```
*
*
*/
memory_manager_t *memm_get_manager();
/**
* @name memm_allocator_new
*
* ```c
* allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid);
* ```
*
* `start``length``pid`0使
*/ */
allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid); allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid);
/* /**
* @name memm_allocator_destruct
*
* ```c
* void memm_allocator_destruct(allocator_t *allocator);
* ```
*
*
*
* ****
*/ */
void memm_allocator_destruct(allocator_t *allocator); void memm_allocator_destruct(allocator_t *allocator);
/* /**
* @name memm_kernel_allocate
使 *
pid=0 * ```c
线 * void *memm_kernel_allocate(usize size);
* ```
allocator对象在进程与内核之间传递时一律使用内核空间的映射地址 *
*
## 要求在返回的地址前16字节处保留8字节空间作为它所在的allocator地址并且不需要分配器的具体实现做这个事
*/ */
void *memm_allocate(usize size, usize pid);
#define memm_addr_set_allocator(mem, allocator) \
*(allocator_t **)((void *)(mem) - 16) = allocator;
#define memm_addr_get_allocator(mem) \
((*(allocator_t **)((void *)(mem) - 16)))
void *memm_kernel_allocate(usize size); void *memm_kernel_allocate(usize size);
void *memm_user_allocate(usize size, usize pid); /**
* @name memm_free
/* *
* ```c
* void memm_free(void *mem);
* ```
*
*
*/ */
void memm_free(void *mem); void memm_free(void *mem);
/* void *memm_allcate_pagetable();
*/
usize find_fitable_pages(usize page_count);
#endif #endif

View File

@ -10,20 +10,25 @@ typedef struct __raw_allocator_cell
{ {
usize capacity; // 是content的长度 usize capacity; // 是content的长度
usize length; // 是实际使用的长度 usize length; // 是实际使用的长度
allocator_t *allocator; // 所在的分配器
usize reserved;
u8 content[0]; u8 content[0];
} raw_allocator_cell; } raw_allocator_cell;
#define raw_allocator_next_cell(cell) (raw_allocator_cell *)((void *)((cell)->content) + (cell)->capacity) #define raw_allocator_next_cell(cell) (raw_allocator_cell *)((void *)((cell)->content) + (cell)->capacity)
// 原始分配器 /**
// * @name raw_allocator_t
// 包括至少一个cell分配时像cell的分裂一样将空白的一段分成两段 *
// 释放时只把length归零并不将cell合并。 * cellcell的分裂一样将空白的一段分成两段length归零cell合并
// length=0的cell称为空cell *
// * `length`0cell称为空cell
// 统计从上次细胞合并以来free的调用次数当调用次数很多或可用空间不足时 *
// 触发细胞合并。 * free的调用次数`RAW_ALLOCATOR_FREE_MAX`
*
* 使allocate和free的情况下使用使allocate时效率低下并难以得到内存安全保证
*
* @internal free_count
*
* free方法的调用次数`RAW_ALLOCATOR_FREE_MAX`
*/
typedef struct __raw_allocator_t typedef struct __raw_allocator_t
{ {
usize size; usize size;
@ -34,9 +39,23 @@ typedef struct __raw_allocator_t
} raw_allocator_t; } raw_allocator_t;
#define raw_allocator_end(allocator) ((void *)(allocator) + (allocator)->size) #define raw_allocator_end(allocator) ((void *)(allocator) + (allocator)->size)
/**
* @name raw_allocator_new
*
* ```c
* void raw_allocator_new(raw_allocator_t *allocator, usize size);
* ```
*
* `raw_allocator`
*/
void raw_allocator_new(raw_allocator_t *allocator, usize size); void raw_allocator_new(raw_allocator_t *allocator, usize size);
void *raw_allocator_allocate(raw_allocator_t *allocator, usize size, usize align); /**
* @name raw_allocator_allocate, raw_allocator_free
*
* `raw_allocator`allocate, free方法
*/
void *raw_allocator_allocate(raw_allocator_t *allocator, usize size);
void raw_allocator_free(raw_allocator_t *allocator, void *mem); void raw_allocator_free(raw_allocator_t *allocator, void *mem);
#endif #endif

19
include/kernel/syscall.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef SYSCALL_H
#define SYSCALL_H 1
#ifdef __x86_64__
#include <kernel/arch/x86_64/syscall.h>
#endif
/**
* @name syscall_init
*
* ```c
* void syscall_init();
* ```
*
*
*/
void syscall_init();
#endif

View File

@ -99,8 +99,8 @@ tty **tty_get(usize id);
/** /**
* @brief tty的id * @brief tty的id
* *
* @return usize * @return usize
*/ */
usize tty_get_id(tty *__tty); usize tty_get_id(tty *__tty);
@ -121,6 +121,16 @@ void tty_set_framebuffer(tty *ttyx, framebuffer *fb);
void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor); void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor);
#define gen_color(r, g, b) (((r) << 16) | ((g) << 8) | (b)) #define gen_color(r, g, b) (((r) << 16) | ((g) << 8) | (b))
#define WHITE gen_color(0xee, 0xee, 0xee)
#define BLACK gen_color(0, 0, 0)
#define RED gen_color(0xee, 0x22, 0x22)
#define GREEN gen_color(0x22, 0xee, 0x22)
#define BLUE gen_color(0x22, 0x22, 0xee)
#define YELLOW gen_color(0xee, 0xee, 0x22)
#define ORANGE gen_color(0xee, 0xaa, 0x22)
#define PURPLE gen_color(0xee, 0, 0xee)
#define PINK gen_color(0xee, 0x44, 0x66)
#define GRAY gen_color(0xaa, 0xaa, 0xaa)
usize tty_get_width(tty *ttyx); usize tty_get_width(tty *ttyx);
usize tty_get_height(tty *ttyx); usize tty_get_height(tty *ttyx);
@ -132,8 +142,8 @@ bool tty_is_enabled(tty *ttyx);
/** /**
* @brief tty * @brief tty
* *
* @param ttyx * @param ttyx
* @return true * @return true
* @return false * @return false
* raw_framebuffer类型的ttyframebuffer已被其它raw_framebuffer * raw_framebuffer类型的ttyframebuffer已被其它raw_framebuffer

View File

@ -33,7 +33,7 @@ bool lst_remove(lst_iterator_t *lst, usize left, usize right, bool force);
/* /*
`lst`线[left,right) `lst`线[left,right)
force=true时忽略已经存在于`lst`线 force=true时忽略已经存在于`lst`线
force=false时若有存在于`lst`线线falsetrue force=false时若有存在于`lst`线线falsetrue
*/ */
bool lst_add(lst_iterator_t *lst, usize left, usize right, bool force); bool lst_add(lst_iterator_t *lst, usize left, usize right, bool force);

View File

@ -3,14 +3,25 @@
#include <types.h> #include <types.h>
#define UTILS_BIT_GET(byte, bit) ((byte) & (1 << (bit)))
#define UTILS_BIT_SET(byte, bit) ((byte) |= (1 << (bit)));
#define UTILS_BIT_RESET(byte, bit) ((byte) &= ~(1 << (bit)));
#define UTILS_BITMAP_GET(map, bit) (((u8 *)(map))[bit / 8] & (1 << ((bit) % 8)))
#define UTILS_BITMAP_SET(map, bit) (((u8 *)(map))[bit / 8] |= (1 << ((bit) % 8)));
#define UTILS_BITMAP_RESET(map, bit) (((u8 *)(map))[bit / 8] &= ~(1 << ((bit) % 8)));
#define DISALIGNED __attribute__((packed)) #define DISALIGNED __attribute__((packed))
#define into_bytes(addr) ((u8 *)(addr))
#define bytes_into(bytes, type) ((type *)(bytes))
void pointer_to_string(u64 addr, char *dest);
typedef struct __va_args
{
usize length;
void *args[0];
} va_args;
#define va_args_gen(result, length) \
void *__reserved__[length]; \
va_args __va_args__; \
result = &__va_args__;
#define va_args_set(vaargs, index, val) \
vaargs->args[index] = &val;
#endif #endif

2
rust-toolchain.toml Normal file
View File

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

@ -1 +1 @@
Subproject commit 087c4795bbc23cd0baee060bda8c1159a971a542 Subproject commit 6a2ca2afcd651e46f1c19f8d8a3f685fd982d824

View File

@ -49,15 +49,17 @@ for mod in kernel_modules:
print(" " + color['lpink'] + f"{mod}" + color['reset'] + " exists.") print(" " + color['lpink'] + f"{mod}" + color['reset'] + " exists.")
else: else:
print(" " + color['lred'] + f"{mod}" + color['reset'] + " not found.") print(" " + color['lred'] + f"{mod}" + color['reset'] + " not found.")
print("Kernel module " + print(
color['lred'] + f"{mod}" + color['reset'] + " is not installed.") "Kernel module " +
color['lred'] + f"{mod}" + color['reset'] + " is not installed.")
exit(-1) exit(-1)
# 检查软件依赖 # 检查软件依赖
pathsenv = os.environ.get("PATH").split(":") pathsenv = os.environ.get("PATH").split(":")
for software, progs in softwares.items(): for software, progs in softwares.items():
print("Checking " + color['lcyan'] + print(
f"{software}" + color['reset'] + " ...") "Checking " + color['lcyan'] +
f"{software}" + color['reset'] + " ...")
for program in progs: for program in progs:
exists = False exists = False
for path in pathsenv: for path in pathsenv:
@ -65,15 +67,19 @@ for software, progs in softwares.items():
exists = True exists = True
break break
if exists: if exists:
print(" " + color['lyellow'] + print(
f"{program}" + color['reset'] + " existed.") " " + color['lyellow'] +
f"{program}" + color['reset'] + " existed.")
else: else:
print(" " + color['lred'] + print(
f"{program}" + color['reset'] + " not found.") " " + color['lred'] +
f"{program}" + color['reset'] + " not found.")
print("Software " + color['lred'] + f"{software}" + print(
color['reset'] + " is not installed or completed.") "Software " + color['lred'] + f"{software}" +
color['reset'] + " is not installed or completed.")
exit(-2) exit(-2)
print("All dependencies are " + print(
color['lgreen'] + "satisfied." + color['reset']) "All dependencies are " +
color['lgreen'] + "satisfied." + color['reset'])

7
scripts/magicgen Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/python
import time
curtime = str(int(time.time() * 1000))
print(curtime)

View File

@ -2,7 +2,7 @@
ARCH := $(shell uname -m) ARCH := $(shell uname -m)
PWD := $(shell pwd) PWD := $(shell pwd)
SOURCE := ${PWD}/scripts SOURCE := ${PWD}/../scripts
ifeq (${ARCH},x86_64) ifeq (${ARCH},x86_64)
ASM = nasm ASM = nasm
ASMFLAGS = -f elf64 ASMFLAGS = -f elf64
@ -12,9 +12,14 @@ ifdef release
release = 1 release = 1
endif 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)
SUBOBJS = kernel/kernel.o libk/libk.o rust.o SUBOBJS = kernel/kernel.o libk/libk.o rust.o
DEFINES = ARCH="${ARCH}" ASM="${ASM}" ASMFLAGS="${ASMFLAGS}" SOURCE="${SOURCE}" PWD="${PWD}" DEFINES = ARCH="${ARCH}" ASM="${ASM}" ASMFLAGS="${ASMFLAGS}" SOURCE="${SOURCE}" PWD="${PWD}" \
ALLOCATOR_MAGIC="${ALLOCATOR_MAGIC}" BUILD_ID="${BUILD_ID}"
ifdef release ifdef release
DEFINES := ${DEFINES} release=1 DEFINES := ${DEFINES} release=1
endif endif
@ -25,24 +30,21 @@ endif
RSCFLAGS = --emit obj --crate-type staticlib --verbose \ RSCFLAGS = --emit obj --crate-type staticlib --verbose \
--crate-name=metaverse \ --crate-name=metaverse \
--edition 2021 \ --edition 2021 \
-L crate="${PWD}/../rustlib/${ARCH}/src/" \ -L crate="${PWD}/../rustlib/src/" \
-C code-model=large \ -C code-model=large \
-C relocation-model=static \ -C relocation-model=static \
-C embed-bitcode=no -C embed-bitcode=no
ifeq (${ARCH},x86_64) ifeq (${ARCH},x86_64)
RSCFLAGS := ${RSCFLAGS} --target x86_64-unknown-none RSCFLAGS := ${RSCFLAGS} --target x86_64-unknown-none
endif
ifdef release
RSCFLAGS := -O
endif
ifeq (${ARCH},x86_64)
RSCFLAGS := ${RSCFLAGS} -C target-feature=-sse RSCFLAGS := ${RSCFLAGS} -C target-feature=-sse
endif endif
RUSTLIB_PATH = ../rustlib/${ARCH}/lib ifdef release
RSCFLAGS := ${RSCFLAGS} -O
endif
RUSTLIB_PATH = ../rustlib/${ARCH}
RUST_LIBS = "${RUSTLIB_PATH}/liballoc.rlib" "${RUSTLIB_PATH}/libcompiler_builtins.rlib" \ RUST_LIBS = "${RUSTLIB_PATH}/liballoc.rlib" "${RUSTLIB_PATH}/libcompiler_builtins.rlib" \
"${RUSTLIB_PATH}/libcore.rlib" "${RUSTLIB_PATH}/librustc_std_workspace_core.rlib" "${RUSTLIB_PATH}/libcore.rlib" "${RUSTLIB_PATH}/librustc_std_workspace_core.rlib"
@ -56,6 +58,8 @@ metaverse.elf: kernel libk rust metaverse.lds
.PHONY: kernel libk all clear postproc rust .PHONY: kernel libk all clear postproc rust
all: postproc metaverse.elf all: postproc metaverse.elf
@echo -e "Build \e[1;32msucceeded\e[0m."
@echo -e "Build ID \e[1;31m${BUILD_ID}\e[0m."
postproc: postproc:
@echo -n -e "\e[36m" @echo -n -e "\e[36m"
@ -67,16 +71,24 @@ postproc:
@echo -e "\e[0m" @echo -e "\e[0m"
kernel: kernel:
@echo -e "\e[33m__\e[0m \e[1;35m[Building kernel]\e[0m \e[33m____\e[0m" @if [ ! ${release} ]; then \
echo -e "\e[33m__\e[0m \e[1;35m[Building kernel]\e[0m \e[33m____\e[0m"; \
fi
@make -C kernel all --no-print-directory ${DEFINES} @make -C kernel all --no-print-directory ${DEFINES}
@echo -e "\e[33m-------------------------\e[0m" @if [ ! ${release} ]; then \
echo -e "\e[33m-------------------------\e[0m"; \
fi
libk: libk:
@echo -e "\e[33m__\e[0m \e[1;35m[Building libk]\e[0m \e[33m______\e[0m" @if [ ! ${release} ]; then \
echo -e "\e[33m__\e[0m \e[1;35m[Building libk]\e[0m \e[33m______\e[0m"; \
fi
@make -C libk all --no-print-directory ${DEFINES} @make -C libk all --no-print-directory ${DEFINES}
@echo -e "\e[33m-------------------------\e[0m" @if [ ! ${release} ]; then \
echo -e "\e[33m-------------------------\e[0m"; \
fi
rust: rust: postproc
@echo -e "\e[1m\e[33mrustc\e[0m \e[34m-->\e[0m \e[1m\e[32m$@.o\e[0m" @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 @rustc ${RSCFLAGS} lib.rs -o rust.o

View File

@ -6,12 +6,15 @@
CC = gcc CC = gcc
CCFLAGS = -m64 -mcmodel=large -I ../../include \ CCFLAGS = -m64 -mcmodel=large -I ../../include \
-fno-stack-protector -fno-exceptions \ -fno-stack-protector -fno-exceptions \
-fno-builtin -nostdinc -nostdlib -fno-builtin -nostdinc -nostdlib \
-DMEMM_ALLOCATOR_MAGIC="(u32)(0x${ALLOCATOR_MAGIC})" \
-DBUILD_ID="${BUILD_ID}"
ifdef release ifdef release
CCFLAGS := ${CCFLAGS} -O2 CCFLAGS := ${CCFLAGS} -O2
endif endif
C_SRCS = main.c tty.c font.c memm.c memm_${ARCH}.c raw.c time.c 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_OBJS = ${C_SRCS:.c=.c.o} C_OBJS = ${C_SRCS:.c=.c.o}
################################ ################################
@ -26,7 +29,8 @@ endif
ASMFLAGS := ${ASMFLAGS} ASMFLAGS := ${ASMFLAGS}
ASMFLAGS32 = -f elf32 ASMFLAGS32 = -f elf32
S_SRCS = entry32.s entry.s memm_${ARCH}.s kernel.s S_SRCS = entry32.s entry.s memm_${ARCH}.s kernel.s syscall_${ARCH}.s interrupt_${ARCH}.s \
interrupt_procs.s
S_OBJS = ${S_SRCS:.s=.s.o} S_OBJS = ${S_SRCS:.s=.s.o}
################################ ################################

View File

@ -1,13 +1,32 @@
section .entry align=8 section .entry align=8
extern kmain extern kmain
extern systemcall_procedure
global init64 global init64
init64: init64:
endbr64 endbr64
cli cli
mov rax, 0x1000000 mov rax, 0x1000000
mov rbp, rax mov rbp, rax
mov rsp, rax mov rsp, rax
mov rdi, rbx mov rdi, rbx
lidt [0x104010]
; 加载系统调用相关寄存器
; IA32_STAR = 0x0018_0008_0000_0000
mov rcx, 0xc0000081
mov rax, 0x0018000800000000
wrmsr
; IA32_FMASK = 0xffff_ffff
inc rcx
mov rax, 0xffffffff
wrmsr
; IA32_LSTAR = [systemcall_procedure]
lea rcx, [rcx + 2]
lea rax, [systemcall_procedure]
wrmsr
jmp kmain jmp kmain
section .multiboot2 align=8 section .multiboot2 align=8

View File

@ -1,9 +1,6 @@
section .entry section .entry
extern init64 extern init64
; 寄存器ebx是multiboot2 information不可以使用 ; 寄存器ebx是multiboot2 information不可以使用
;
; 由于这个代码是32位环境的代码而链接器链接时会把它当作64位代码链接
; 所以这里所有的使用了常数的位置都要通过指令写入
init32: init32:
cli cli
@ -37,18 +34,17 @@ init32:
add edi, 4 add edi, 4
loop init32_loop0 loop init32_loop0
; 设置gdt_ptr ; 加载GDTR、段寄存器和TR寄存器
mov eax, 0x10402a ; gdt_ptr + 2
mov dword [eax], 0x104000 ; gdt
; 加载GDTR和段寄存器
db 0x66 db 0x66
lgdt [0x104028] ; gdt_ptr lgdt [0x104000] ; gdt_ptr
mov ax, 0x10 mov ax, 0x10
mov ds, ax mov ds, ax
mov ss, ax mov ss, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ax, 0x30
ltr ax
; 打开PAE ; 打开PAE
mov eax, cr4 mov eax, cr4
@ -77,7 +73,6 @@ init32:
section .cpumeta align=4096 section .cpumeta align=4096
global PML4 global PML4
; 分页 ; 分页
; 链接器会把这些数据替换掉所以要在代码中重新设置
PML4: PML4:
dq 0x003 + PDPT0 dq 0x003 + PDPT0
resq 511 resq 511
@ -89,15 +84,43 @@ PDPT0:
PD0: PD0:
resq 512 resq 512
; 分段 section .cpumeta.tblptrs
gdt:
dq 0
dq 0x0020980000000000 ; 内核态代码段
dq 0x0000920000000000 ; 内核态数据段
dq 0x0020f80000000000 ; 用户态代码段
dq 0x0000f20000000000 ; 用户态数据段
gdt_end:
gdt_ptr: gdt_ptr: ; 0x104000
dw gdt_end - gdt - 1 dw gdt_end - gdt - 1
dq gdt dq gdt
dd 0
dw 0
idt_ptr: ; 0x104010
dw 0x7ff
dq idt
section .cpumeta.gdt align=4096
gdt:
dq 0
dq 0x0020980000000000 ; 内核态代码段
dq 0x0000920000000000 ; 内核态数据段
dq 0x0020f80000000000 ; 用户态代码段
dq 0x0000f20000000000 ; 用户态数据段
dq 0
dq 0x0000891070000068 ; TSS段低64位
dq 0 ; TSS段高64位
gdt_end:
section .cpumeta.idt align=4096
global idt
idt:
resq 512 ; 16 bytes per descriptor (512 q-bytes)
section .cpumeta.tss align=4096
global TSS
TSS:
dd 0
dq 0x1000000 ; rsp0内核栈
dq 0 ; rsp1
dq 0 ; rsp2
dq 0
dq 0x400000 ; ist1中断栈
resb 104 - ($ - TSS)

View File

@ -0,0 +1,79 @@
%macro store_regs 0
push rax
push rcx
push rbx
push rdx
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
%endmacro
%macro retrieve_regs 0
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rdx
pop rbx
pop rcx
pop rax
%endmacro
%macro switch_section 0
sub rsp, 4
mov ax, ds
push ax
mov ax, es
push ax
mov ax, 0x10
mov ds, ax
mov es, ax
%endmacro
%macro retrieve_section 0
pop ax
mov es, ax
pop ax
mov ds, ax
add rsp, 4
%endmacro
%macro interrupt_entry_enter 0
push rbp
lea rbp, [rsp]
store_regs
switch_section
%endmacro
%macro interrupt_entry_leave 0
retrieve_section
retrieve_regs
leave
%endmacro
; 用于带有错误码的中断,创建一个没有错误码的上下文拷贝
%macro interrupt_stack_wrap_texture 0
extern memcpy
sub rsp, 21 * 8
mov rdi, rsp
lea rsi, [rsp + 21 * 8]
mov rdx, 16 * 8
call memcpy
lea rdi, [rsp + 16 * 8]
lea rsi, [rsp + 38 * 8]
mov rdx, 5 * 8
call memcpy
%endmacro

View File

@ -0,0 +1,190 @@
#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

@ -0,0 +1,97 @@
%include "arch/x86_64/interrupt.in"
; 栈中的寄存器上下文
; +------------
; | ss
; +------------<-- rsp+168(+160)
; | rsp
; +------------<-- rsp+160(+152)
; | rflags
; +------------<-- rsp+152(+144)
; | cs
; +------------<-- rsp+144(+136)
; | rip
; +------------<-- rsp+136(+128)
; | (err code)
; +------------<-- rsp+128
; | rbp
; +------------<-- rsp+120
; | rax
; +------------<-- rsp+112
; | rcx
; +------------<-- rsp+104
; | rbx
; +------------<-- rsp+96
; | rdx
; +------------<-- rsp+88
; | rsi
; +------------<-- rsp+80
; | rdi
; +------------<-- rsp+72
; | r8
; +------------<-- rsp+64
; | r9
; +------------<-- rsp+56
; | r10
; +------------<-- rsp+48
; | r11
; +------------<-- rsp+40
; | r12
; +------------<-- rsp+32
; | r13
; +------------<-- rsp+24
; | r14
; +------------<-- rsp+16
; | r15
; +------------<-- rsp+8
; | reserved
; +------------<-- rsp+4
; | ds
; +------------<-- rsp+2
; | es
; +------------<-- rsp+0
section .text
global interrupt_entry_UNSUPPORTED
extern interrupt_req_UNSUPPORTED
interrupt_entry_UNSUPPORTED:
interrupt_entry_enter
mov rdi, [rsp + 128]
mov rsi, [rsp + 152]
call interrupt_req_UNSUPPORTED
interrupt_entry_leave
iret
global interrupt_entry_DE
extern interrupt_req_DE
interrupt_entry_DE:
interrupt_entry_enter
mov rdi, [rsp + 128]
mov rsi, [rsp + 152]
call interrupt_req_DE
interrupt_entry_leave
iret
global interrupt_entry_DE
interrupt_entry_NMI:
; TODO 暂时不需要为这个中断实现任何功能
iret
global interrupt_entry_BP
extern interrupt_req_BP
interrupt_entry_BP:
interrupt_entry_enter
mov rdi, [rsp + 128]
mov rsi, [rsp + 152]
mov dword [rsp + 4], 0
mov rdx, rsp
call interrupt_req_BP
interrupt_entry_leave
iret

View File

@ -0,0 +1,25 @@
#include <kernel/interrupt.h>
#include <utils.h>
#include <kernel/arch/x86_64/interrupt_procs.h>
void interrupt_init()
{
gate_descriptor_t gate;
trap_gate_generate(gate, interrupt_entry_sym(UNSUPPORTED));
for (usize i = 4; i < 256; i++)
{
interrupt_register_gate(gate, i);
}
trap_gate_generate(gate, interrupt_entry_sym(DE));
interrupt_register_gate(gate, 0);
trap_gate_generate(gate, interrupt_entry_sym(UNSUPPORTED));
interrupt_register_gate(gate, 1);
trap_gate_generate(gate, interrupt_entry_sym(NMI));
interrupt_register_gate(gate, 2);
trap_gate_generate(gate, interrupt_entry_sym(BP));
interrupt_register_gate(gate, 3);
interrupt_open();
}

View File

@ -0,0 +1,11 @@
section .text
global interrupt_open
interrupt_open:
sti
ret
global interrupt_close
interrupt_close:
cli
ret

View File

@ -9,8 +9,9 @@
map_pageframe_to((u64)addr, (u64)addr, false, true, MEMM_PAGE_SIZE_4K); map_pageframe_to((u64)addr, (u64)addr, false, true, MEMM_PAGE_SIZE_4K);
// 这里的physical必须保证根据ps对齐 // 这里的physical必须保证根据ps对齐
static void map_pageframe_to(u64 target, u64 physical, static void map_pageframe_to(
bool user, bool write, memm_page_size ps) u64 target, u64 physical,
bool user, bool write, memm_page_size ps)
{ {
if (!is_cannonical(target)) if (!is_cannonical(target))
return; return;
@ -22,7 +23,7 @@ static void map_pageframe_to(u64 target, u64 physical,
PDPT = (u64 *)memm_entry_get_address(pml4e); PDPT = (u64 *)memm_entry_get_address(pml4e);
else else
{ {
PDPT = (u64 *)(find_fitable_pages(1) * MEMM_PAGE_SIZE); PDPT = memm_allcate_pagetable();
map_pagemap(PDPT); map_pagemap(PDPT);
memset(PDPT, 0, MEMM_PAGE_SIZE); memset(PDPT, 0, MEMM_PAGE_SIZE);
@ -50,7 +51,7 @@ static void map_pageframe_to(u64 target, u64 physical,
PDT = (u64 *)memm_entry_get_address(pdpte); PDT = (u64 *)memm_entry_get_address(pdpte);
else else
{ {
PDT = (u64 *)(find_fitable_pages(1) * MEMM_PAGE_SIZE); PDT = memm_allcate_pagetable();
map_pagemap(PDT); map_pagemap(PDT);
memset(PDT, 0, MEMM_PAGE_SIZE); memset(PDT, 0, MEMM_PAGE_SIZE);
@ -78,7 +79,7 @@ static void map_pageframe_to(u64 target, u64 physical,
PT = (u64 *)memm_entry_get_address(pde); PT = (u64 *)memm_entry_get_address(pde);
else else
{ {
PT = (u64 *)(find_fitable_pages(1) * MEMM_PAGE_SIZE); PT = memm_allcate_pagetable();
map_pagemap(PT); map_pagemap(PT);
memset(PT, 0, MEMM_PAGE_SIZE); memset(PT, 0, MEMM_PAGE_SIZE);
@ -110,7 +111,6 @@ bool memm_map_pageframes_to(
return false; return false;
while (size != 0) while (size != 0)
{ {
// 这是当前需要映射的页的内存对齐(或者说是当前映射的页的大小)
memm_page_size align = memm_get_page_align(physical); memm_page_size align = memm_get_page_align(physical);
if (align == MEMM_PAGE_SIZE_1G) if (align == MEMM_PAGE_SIZE_1G)
{ {

View File

@ -0,0 +1,8 @@
#include <kernel/syscall.h>
#include <libk/string.h>
void syscall_init()
{
memset(&system_calls_table, 0, sizeof(system_calls_table));
}

View File

@ -0,0 +1,91 @@
section .data
global system_calls_table
system_calls_table:
resq 256
kernel_stack_cache:
dq 0, 0 ; 分别为 rbp, rsp
section .text
global systemcall_procedure
global save_kernel_stack
systemcall_procedure:
endbr64
call load_kernel_stack
push rbp
mov rbp, rsp
shl rax, 3 ; rax *= 8
; 将对应调用号的系统调用加载至rax
lea rdi, [system_calls_table]
lea rax, [rax + rdi]
; 判断是否为空调用
cmp rax, 0
je systemcall_procedure_none_call
mov rax, [rax]
; 调用对应的系统调用
call rax
leave
call save_kernel_stack
sysret
systemcall_procedure_none_call:
; TODO 调用了不存在的系统调用,属于无法恢复的错误,应保存错误状态并结束调用进程
; 暂时直接sysret
leave
call save_kernel_stack
sysret
; void set_kernel_stack_cache(usize stack)
set_kernel_stack_cache:
endbr64
push rax
lea rax, [kernel_stack_cache]
mov [rax], rdi
lea rax, [rax + 8]
mov [rax], rdi
pop rax
ret
; void return_from_systemcall()
return_from_systemcall:
sysret
save_kernel_stack:
endbr64
lea rbx, [kernel_stack_cache]
; 交换[rbx]与rbp
mov rdi, [rbx]
xor rbp, rdi
xor rdi, rbp
xor rbp, rdi
mov [rbx], rdi
lea rbx, [rbx + 8]
; 交换[rbx]与rsp
mov rdi, [rbx]
xor rsp, rdi
xor rdi, rsp
xor rsp, rdi
mov [rbx], rdi
ret
load_kernel_stack:
endbr64
lea rbx, [kernel_stack_cache]
; 交换[rbx]与rbp
mov rdi, [rbx]
xor rbp, rdi
xor rdi, rbp
xor rbp, rdi
mov [rbx], rdi
lea rbx, [rbx + 8]
; 交换[rbx]与rsp
mov rdi, [rbx]
xor rsp, rdi
xor rdi, rsp
xor rsp, rdi
mov [rbx], rdi
ret

View File

@ -1,4 +1,3 @@
use alloc::string::ToString;
use alloc::vec; use alloc::vec;
use alloc::vec::Vec; use alloc::vec::Vec;
@ -140,7 +139,7 @@ impl KernelLogger {
return false; return false;
} }
} }
return true; true
}; };
while !all_end(&indeces, &logs) { while !all_end(&indeces, &logs) {
let mut min_ind = None; let mut min_ind = None;
@ -181,7 +180,7 @@ impl<'a> Iterator for LogIterator<'a> {
let res = if let Some((time, msg)) = self.logs.first() { let res = if let Some((time, msg)) = self.logs.first() {
Some( Some(
MessageBuilder::new() MessageBuilder::new()
.message(&time.to_string()) .message(time)
.append(MessageBuilder::from_message(msg.clone())) .append(MessageBuilder::from_message(msg.clone()))
.build(), .build(),
) )

View File

@ -1,6 +1,8 @@
#include <kernel/kernel.h> #include <kernel/kernel.h>
#include <kernel/tty.h> #include <kernel/tty.h>
#include <kernel/memm.h> #include <kernel/memm.h>
#include <kernel/interrupt.h>
#include <kernel/syscall.h>
#include <libk/multiboot2.h> #include <libk/multiboot2.h>
#include <libk/math.h> #include <libk/math.h>
@ -33,7 +35,7 @@ void kmain(void *mb2_bootinfo)
} }
// 初始化内存管理模块 // 初始化内存管理模块
mem_manager_t *memm = memm_new(mem_size); memory_manager_t *memm = memm_new(mem_size);
// 初始化tty模块 // 初始化tty模块
tty_controller_t *tty_controler = tty_controller_new(); tty_controller_t *tty_controler = tty_controller_new();
@ -41,6 +43,13 @@ void kmain(void *mb2_bootinfo)
get_frame_buffer_with_bootinfo(&fb, &bootinfo); get_frame_buffer_with_bootinfo(&fb, &bootinfo);
tty *tty0 = tty_new(tty_type_raw_framebuffer, tty_mode_text); tty *tty0 = tty_new(tty_type_raw_framebuffer, tty_mode_text);
tty_set_framebuffer(tty0, &fb); tty_set_framebuffer(tty0, &fb);
tty_enable(tty0);
// 初始化中断管理
interrupt_init();
// 初始化系统调用
syscall_init();
// 为rust准备正确对齐的栈 // 为rust准备正确对齐的栈
prepare_stack(); prepare_stack();

View File

@ -8,7 +8,6 @@ use super::{
#[no_mangle] #[no_mangle]
extern "C" fn kmain_rust() -> ! { extern "C" fn kmain_rust() -> ! {
let tty = Tty::from_id(0).unwrap(); let tty = Tty::from_id(0).unwrap();
tty.enable();
let mut logger = KernelLogger::new(); let mut logger = KernelLogger::new();
logger.info(message!( logger.info(message!(
Msg("Hello, "), Msg("Hello, "),

View File

@ -13,7 +13,7 @@ void raw_allocator_new(raw_allocator_t *allocator, usize size)
allocator->cells[0].length = 0; allocator->cells[0].length = 0;
} }
void *raw_allocator_allocate(raw_allocator_t *allocator, usize size, usize align) void *raw_allocator_allocate(raw_allocator_t *allocator, usize size)
{ {
usize real_size = size; usize real_size = size;
align_to(real_size, 16); align_to(real_size, 16);
@ -72,7 +72,7 @@ void raw_allocator_free(raw_allocator_t *allocator, void *mem)
{ {
raw_allocator_cell *cell = allocator->cells; raw_allocator_cell *cell = allocator->cells;
while ((void *)cell < raw_allocator_end(allocator)) while ((void *)cell < raw_allocator_end(allocator))
{ { // TODO 内存错误
if (mem == cell->content) if (mem == cell->content)
{ {
cell->length = 0; cell->length = 0;
@ -83,7 +83,7 @@ void raw_allocator_free(raw_allocator_t *allocator, void *mem)
allocator->rest_memory += cell->capacity + sizeof(raw_allocator_cell); allocator->rest_memory += cell->capacity + sizeof(raw_allocator_cell);
allocator->free_count++; allocator->free_count++;
if ( // 可用内存不超过当前allocator的 5% 或调用free次数很多时 if ( // 可用内存不超过当前allocator的 5% 或调用free次数很多时
allocator->size / allocator->rest_memory > 20 && allocator->size / allocator->rest_memory > 20 ||
allocator->free_count > RAW_ALLOCATOR_FREE_MAX) allocator->free_count > RAW_ALLOCATOR_FREE_MAX)
{ {
raw_allocator_cellmerge(allocator); raw_allocator_cellmerge(allocator);

View File

@ -5,9 +5,9 @@
#include <libk/string.h> #include <libk/string.h>
#include <libk/bits.h> #include <libk/bits.h>
mem_manager_t memory_manager; memory_manager_t memory_manager;
mem_manager_t *memm_new(usize mem_size) memory_manager_t *memm_new(usize mem_size)
{ {
memset(&memory_manager, 0, sizeof(memory_manager)); memset(&memory_manager, 0, sizeof(memory_manager));
memory_manager.memory_size = mem_size; memory_manager.memory_size = mem_size;
@ -17,62 +17,25 @@ mem_manager_t *memm_new(usize mem_size)
usize kernel_initial_size = (usize)&kend; usize kernel_initial_size = (usize)&kend;
align_to(kernel_initial_size, MEMM_PAGE_SIZE); align_to(kernel_initial_size, MEMM_PAGE_SIZE);
// 配置分配器树
allocator_t *allocator0 = memm_allocator_new( allocator_t *allocator0 = memm_allocator_new(
(void *)kernel_initial_size, (void *)kernel_initial_size,
memory_manager.alloc_only_memory - kernel_initial_size, memory_manager.alloc_only_memory - MEMM_PAGE_TABLE_AREA_MAX - kernel_initial_size,
MEMM_RAW_ALLOCATOR, 0); MEMM_RAW_ALLOCATOR, 0);
allocator_iterator_t *alcatr_ind = allocator0->allocate( memory_manager.kernel_base_allocator = allocator0;
&allocator0->allocator_instance, sizeof(allocator_iterator_t), 0);
alcatr_ind->allocator = allocator0; return &memory_manager;
alcatr_ind->left = nullptr; }
alcatr_ind->right = nullptr;
memory_manager.allocators = alcatr_ind;
// 配置页映射地图
usize pmc_size = memory_manager.page_amount;
align_to(pmc_size, 8);
pmc_size /= 8;
memory_manager.page_map = allocator0->allocate(&allocator0->allocator_instance, pmc_size, 0);
memset(memory_manager.page_map, 0, pmc_size);
memset(memory_manager.page_map, 0xff, MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE / 8);
for (usize i = (MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE / 8) * (u8)8;
i < MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE % 8; i++)
{
bitmap_set(memory_manager.page_map, i);
}
// 配置分配器页地图
memory_manager.map_with_allocator =
allocator0->allocate(&allocator0->allocator_instance, pmc_size, 0);
memset(memory_manager.map_with_allocator, 0, pmc_size);
for (usize i = kernel_initial_size / MEMM_PAGE_SIZE;
i < MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE;
i += MEMM_PAGE_SIZE)
{
bitmap_set(memory_manager.map_with_allocator, i);
}
// 分配器释放页地图
memory_manager.map_with_destructed_allocator =
allocator0->allocate(&allocator0->allocator_instance, pmc_size, 0);
memset(memory_manager.map_with_destructed_allocator, 0, pmc_size);
// 配置空闲页线段搜索表
memory_manager.available_pages_table = lst_new(0, memory_manager.page_amount);
lst_remove(memory_manager.available_pages_table, 0, MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE, false);
memory_manager_t *memm_get_manager()
{
return &memory_manager; return &memory_manager;
} }
allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid) allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid)
{ {
allocator_t *allocator = start; allocator_t *allocator = start;
allocator->initialized = true; allocator->magic = MEMM_ALLOCATOR_MAGIC;
allocator->full = false; allocator->full = false;
allocator->pid = 0; allocator->pid = 0;
allocator->size = length; allocator->size = length;
@ -85,166 +48,47 @@ allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid
allocator->free = (memm_free_t)raw_allocator_free; allocator->free = (memm_free_t)raw_allocator_free;
break; break;
default: default:
allocator->initialized = false; allocator->magic = 0;
break; break;
} }
} }
void memm_allocator_destruct(allocator_t *allocator) void memm_allocator_destruct(allocator_t *allocator)
{ {
allocator->initialized = false; allocator->magic = 0;
// TODO 从分配器树中删除这个分配器 // TODO 从分配器树中删除这个分配器
KERNEL_TODO(); KERNEL_TODO();
} }
void *memm_find_and_allocate(allocator_iterator_t *allocator_ind, usize size, usize pid, allocator_t **writeback)
{
void *ptr;
allocator_t *allocator = allocator_ind->allocator;
if (allocator->pid == pid && allocator->full == false)
{ // 尝试用本节点分配
if ((ptr = allocator->allocate(&allocator->allocator_instance, size, 0)) != nullptr)
{
*writeback = allocator;
return ptr;
}
else
{
if ((ptr = allocator->allocate(&allocator->allocator_instance, 0, 0)) == nullptr)
allocator->full = true;
}
}
if (allocator_ind->left != nullptr)
{ // 尝试用左子树分配
ptr = memm_find_and_allocate(allocator_ind->left, size, pid, writeback);
if (ptr != nullptr)
return ptr;
}
if (allocator_ind->right != nullptr)
{ // 尝试用右子树分配
ptr = memm_find_and_allocate(allocator_ind->right, size, pid, writeback);
if (ptr != nullptr)
return ptr;
}
// 都不行就只能返回nullptr
return nullptr;
}
static void insert_allocator(allocator_iterator_t *iter, allocator_iterator_t *inserter)
{
if (inserter->allocator < iter->allocator)
{
if (iter->left == nullptr)
{
iter->left = inserter;
return;
}
else
{
insert_allocator(iter->left, inserter);
}
}
else if (inserter->allocator > iter->allocator)
{
if (iter->right == nullptr)
{
iter->right = inserter;
return;
}
else
{
insert_allocator(iter->right, inserter);
}
}
}
void *memm_allocate(usize size, usize pid)
{
usize orgsize = size;
// 从分配器树中分配内存
allocator_t *allocator;
void *ptr = memm_find_and_allocate(memory_manager.allocators, size, pid, &allocator);
if (ptr != nullptr)
goto after_allocation;
// 分配器树中没有可分配的内存
size += sizeof(allocator_t) + MEMM_PAGE_SIZE;
align_to(size, MEMM_PAGE_SIZE);
size /= MEMM_PAGE_SIZE;
usize allocator_start = find_fitable_pages(size);
if (allocator_start == 0)
return nullptr; // 内存中已经没有可分配的页了
for (usize i = allocator_start; i < allocator_start + size; i++)
{
bitmap_set(memory_manager.map_with_allocator, i);
}
memm_map_pageframes_to(
allocator_start * MEMM_PAGE_SIZE, allocator_start * MEMM_PAGE_SIZE,
size * MEMM_PAGE_SIZE,
false, // 用户空间标志
true // 写权限
);
// 在新映射的页中创建一个分配器
// TODO 在用户态可能需要实现一个效率更高的分配器
allocator_t *new_allocator =
memm_allocator_new((void *)(allocator_start * MEMM_PAGE_SIZE), size * MEMM_PAGE_SIZE,
MEMM_RAW_ALLOCATOR, pid);
allocator = new_allocator;
allocator_iterator_t *allind = memm_kernel_allocate(sizeof(allocator_iterator_t));
allind->allocator = new_allocator;
allind->left = nullptr;
allind->right = nullptr;
insert_allocator(memory_manager.allocators, allind);
ptr = new_allocator->allocate(&new_allocator->allocator_instance, orgsize, 0);
after_allocation:
if (ptr != nullptr)
memm_addr_set_allocator(ptr, allocator);
return ptr;
}
void *memm_kernel_allocate(usize size) void *memm_kernel_allocate(usize size)
{ {
return memm_allocate(size, 0); allocator_t *allocator = memory_manager.kernel_base_allocator;
} return allocator->allocate(allocator->allocator_instance, size);
void *memm_user_allocate(usize size, usize pid)
{
void *res = memm_allocate(size, pid);
// TODO 将内存空间映射到用户空间
return res;
} }
void memm_free(void *mem) void memm_free(void *mem)
{ {
allocator_t *allocator = memm_addr_get_allocator(mem); allocator_t *allocator = memory_manager.kernel_base_allocator;
if (allocator->magic != MEMM_ALLOCATOR_MAGIC)
return;
if (is_user_address((u64)mem)) if (is_user_address((u64)mem))
{ // TODO 对于用户空间的地址需要先转换到内核地址后释放 {
mem = mem - allocator->userspace + (void *)allocator;
} }
allocator->free(allocator->allocator_instance, mem); allocator->free(allocator->allocator_instance, mem);
if (allocator->full) if (allocator->full)
allocator->full = false; allocator->full = false;
} }
usize find_fitable_pages(usize page_count) void *memm_allcate_pagetable()
{ {
usize res = 0; if (memory_manager.page_table_area < MEMM_PAGE_TABLE_AREA_MAX)
lst_iterator_t *iter = memory_manager.available_pages_table;
do
{ {
if (iter->line.right - iter->line.left > page_count) memory_manager.page_table_area += MEMM_PAGE_TABLE_SIZE;
{ return memory_manager.alloc_only_memory - memory_manager.page_table_area;
res = iter->line.left; }
lst_remove(iter, res, res + page_count, false); else
for (usize i = res; i < res + page_count; i++) {
{ // TODO
bitmap_set(memory_manager.page_map, i); }
}
break;
}
} while ((iter = lst_next(iter)) != nullptr);
memory_manager.mapped_page_amount += page_count;
return res;
} }

View File

@ -58,8 +58,8 @@ void tty_set_framebuffer(tty *ttyx, framebuffer *fb)
ttyx->height = ttyx->typeinfo.raw_framebuffer.height; ttyx->height = ttyx->typeinfo.raw_framebuffer.height;
if (ttyx->mode == tty_mode_text) if (ttyx->mode == tty_mode_text)
{ {
ttyx->text.width = fb->width / tty_get_font()->char_width; ttyx->text.width = fb->width / (TTY_FONT_SCALE * tty_get_font()->char_width);
ttyx->text.height = fb->height / tty_get_font()->char_height; ttyx->text.height = fb->height / (TTY_FONT_SCALE * tty_get_font()->char_height);
ttyx->text.line = 0; ttyx->text.line = 0;
ttyx->text.column = 0; ttyx->text.column = 0;
} }
@ -175,17 +175,20 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor)
} }
else if (c == '\t') else if (c == '\t')
{ // 水平制表符 { // 水平制表符
putchar(ttyx, ' ', 0, 0);
ttyx->text.column += 8; ttyx->text.column += 8;
ttyx->text.column -= ttyx->text.column % 8; ttyx->text.column -= ttyx->text.column % 8;
continue; continue;
} }
else if (c == '\r') else if (c == '\r')
{ // 回到行首 { // 回到行首
putchar(ttyx, ' ', 0, 0);
ttyx->text.column = 0; ttyx->text.column = 0;
continue; continue;
} }
else if (c == '\v') else if (c == '\v')
{ // 垂直制表符 { // 垂直制表符
putchar(ttyx, ' ', 0, 0);
ttyx->text.line++; ttyx->text.line++;
if (ttyx->text.line == ttyx->text.height) if (ttyx->text.line == ttyx->text.height)
{ {

View File

@ -150,10 +150,11 @@ impl Color {
pub const RED: Color = Color(0xee, 0x22, 0x22); pub const RED: Color = Color(0xee, 0x22, 0x22);
pub const GREEN: Color = Color(0x22, 0xee, 0x22); pub const GREEN: Color = Color(0x22, 0xee, 0x22);
pub const BLUE: Color = Color(0x22, 0x22, 0xee); pub const BLUE: Color = Color(0x22, 0x22, 0xee);
pub const YELLOW: Color = Color(0xee, 0x22, 0x22); pub const YELLOW: Color = Color(0xee, 0xee, 0x22);
pub const ORANGE: Color = Color(0xee, 0xee, 0x22); pub const ORANGE: Color = Color(0xee, 0xaa, 0x22);
pub const PURPLE: Color = Color(0xee, 0, 0xee); pub const PURPLE: Color = Color(0xee, 0x22, 0xee);
pub const PINK: Color = Color(0xee, 0x44, 0x66); pub const PINK: Color = Color(0xee, 0x44, 0x66);
pub const GRAY: Color = Color(0xaa, 0xaa, 0xaa);
} }
impl From<Color> for u32 { impl From<Color> for u32 {
@ -181,6 +182,16 @@ pub struct MessageSection {
#[derive(Clone)] #[derive(Clone)]
pub struct Message(Vec<MessageSection>); 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
}
}
/// ## MessageBuilder /// ## MessageBuilder
/// ///
/// 使用链式调用模式构造一个消息. /// 使用链式调用模式构造一个消息.
@ -196,6 +207,19 @@ pub struct Message(Vec<MessageSection>);
/// .build(); /// .build();
/// ``` /// ```
/// ///
/// 定义了`message!`宏,简化构造消息的代码:
///
/// ```rust
/// use crate::kernel::tty::tty::BuilderFunctions::*;
///
/// message!(
/// Msg("Hello, "),
/// Msg("Metaverse"),
/// FgColor(Color::GREEN),
/// Msg("!\n"),
/// );
/// ```
///
/// 对于特殊情况可以使用非链式调用: /// 对于特殊情况可以使用非链式调用:
/// ```rust /// ```rust
/// let mut msg = MessageBuilder::new(); /// let mut msg = MessageBuilder::new();
@ -226,7 +250,7 @@ impl MessageBuilder {
Self { msg } Self { msg }
} }
pub fn message(mut self, msg: &str) -> Self { pub fn message<T: ToString + ?Sized>(mut self, msg: &T) -> Self {
self.msg.0.push(MessageSection { self.msg.0.push(MessageSection {
msg: msg.to_string(), msg: msg.to_string(),
fgcolor: Color(0xee, 0xee, 0xee), fgcolor: Color(0xee, 0xee, 0xee),
@ -235,7 +259,7 @@ impl MessageBuilder {
self self
} }
pub fn message_mut(&mut self, msg: &str) { pub fn message_mut<T: ToString + ?Sized>(&mut self, msg: &T) {
self.msg.0.push(MessageSection { self.msg.0.push(MessageSection {
msg: msg.to_string(), msg: msg.to_string(),
fgcolor: Color(0xee, 0xee, 0xee), fgcolor: Color(0xee, 0xee, 0xee),

View File

@ -11,7 +11,7 @@ ifdef release
CCFLAGS := ${CCFLAGS} -O2 CCFLAGS := ${CCFLAGS} -O2
endif endif
C_SRCS = bootinfo.c lst.c C_SRCS = bootinfo.c lst.c utils.c
C_OBJS = ${C_SRCS:.c=.c.o} C_OBJS = ${C_SRCS:.c=.c.o}
################################ ################################

11
src/libk/utils.c Normal file
View File

@ -0,0 +1,11 @@
#include <utils.h>
void pointer_to_string(u64 addr, char *dest)
{
for (u8 i = 0; i < 16; i++)
{
char c = addr & 0xf;
dest[15 - i] = (c < 10) ? c + '0' : c - 10 + 'a';
addr >>= 4;
}
}

View File

@ -13,10 +13,26 @@ SECTIONS {
{ {
*(.multiboot2) *(.multiboot2)
} }
.cpumeta : .cpumeta ALIGN(4096) :
{ {
*(.cpumeta) *(.cpumeta)
} }
.cpumeta.tblptrs ALIGN(4096) :
{
*(cpumeta.tblptrs)
}
.cpumeta.gdt ALIGN(4096) :
{
*(.cpumeta.gdt)
}
.cpumeta.idt ALIGN(4096) :
{
*(.cpumeta.idt)
}
.cpumeta.tss ALIGN(4096) :
{
*(.cpumeta.tss)
}
. = 16M; . = 16M;
.text : .text :
{ {