Merge pull request #2 from pointertobios/main
重构内存分配器、增加中断支持、整理rust运行时环境
This commit is contained in:
commit
327c10963c
|
@ -1,4 +1,3 @@
|
|||
/.vscode
|
||||
/test/metaverse.img
|
||||
*.o
|
||||
*.map
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"C_Cpp.errorSquiggles": "disabled",
|
||||
"files.associations": {
|
||||
"*.s": "nasm",
|
||||
"LICENCE": "plaintext",
|
||||
"*.h": "c"
|
||||
},
|
||||
"rust-analyzer.imports.preferNoStd" : true,
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
name = "metaverse"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
# 此Cargo.toml仅用于rust-analyzer识别rust部分的代码
|
||||
# 不应使用cargo编译
|
||||
|
|
39
Makefile
39
Makefile
|
@ -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
|
||||
|
||||
clear: config
|
||||
clear: metaverse_kernel
|
||||
@make -C src clear --no-print-directory
|
||||
|
||||
run: config
|
||||
run: metaverse_kernel
|
||||
@make -C test run --no-print-directory
|
||||
|
||||
debug: config
|
||||
debug: metaverse_kernel
|
||||
@make -C test debug --no-print-directory
|
||||
|
||||
config:
|
||||
metaverse_kernel:
|
||||
@if [ "${shell uname -s}" != "Linux" ]; then \
|
||||
echo -e "\e[1;33mMetaverse\e[0m must build under \e[1;35mLinux\e[0m or itself."; \
|
||||
exit -1; \
|
||||
fi
|
||||
@if [ -f "metaverse_kernel" ]; then \
|
||||
echo; \
|
||||
else \
|
||||
touch metaverse_kernel; \
|
||||
"${SOURCE}/depcheck"; \
|
||||
@"${SOURCE}/depcheck";
|
||||
@if [ $$? != 0 ]; then \
|
||||
exit $$?; \
|
||||
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
|
||||
|
|
14
README.md
14
README.md
|
@ -57,6 +57,8 @@ make debug
|
|||
* [x] raw_allocator
|
||||
* [x] tty
|
||||
* [x] 内核日志
|
||||
* [ ] 系统调用
|
||||
* [ ] 中断管理
|
||||
* [ ] 文件系统
|
||||
* [ ] vfs
|
||||
* [ ] fat32驱动(移植)
|
||||
|
@ -64,9 +66,19 @@ make debug
|
|||
* [ ] 驱动管理
|
||||
* [ ] 进程管理
|
||||
|
||||
## 文档
|
||||
|
||||
* 从源代码注释生成文档
|
||||
|
||||
```bash
|
||||
make doc
|
||||
```
|
||||
|
||||
(开发中)
|
||||
|
||||
## 作出贡献
|
||||
|
||||
通过向此仓库发送PR为我们作出贡献。
|
||||
通过向此仓库发送PR为我们作出贡献,详见[contribution.md](docs/contribution.md)。
|
||||
|
||||
## 版权声明
|
||||
|
||||
|
|
|
@ -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()`方法实现格式化字符串。
|
|
@ -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
|
|
@ -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
|
|
@ -3,7 +3,15 @@
|
|||
|
||||
#include <types.h>
|
||||
|
||||
// 具有返回值是为了留出一个寄存器用于调整栈顶
|
||||
extern usize prepare_stack();
|
||||
/**
|
||||
* @name prepare_stack
|
||||
*
|
||||
* ```c
|
||||
* void prepare_stack();
|
||||
* ```
|
||||
*/
|
||||
extern void prepare_stack();
|
||||
|
||||
extern u32 TSS[26];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,8 +4,33 @@
|
|||
#include <types.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_TABLE_SIZE 4096
|
||||
|
||||
typedef enum __memm_page_size
|
||||
{
|
||||
MEMM_PAGE_SIZE_4K = 1, // 1个4KB页大小
|
||||
|
@ -15,14 +40,49 @@ typedef enum __memm_page_size
|
|||
|
||||
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_2M_ALIGN_MASK ((u64)0x1fffff)
|
||||
#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_WRITE ((u64)1 << 1)
|
||||
#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_PTE_ENTRY_FLAG_PAT ((u64)1 << 7)
|
||||
#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) \
|
||||
((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_BP_ENTRY_ADDRESS_MASK ((u64)0x000fffffffffe000)
|
||||
|
||||
/**
|
||||
* @name memm_entry_get_address(entry)
|
||||
* @addindex 平台依赖宏 x86_64
|
||||
*
|
||||
* 获取页表项指向的地址。
|
||||
*/
|
||||
#define memm_entry_get_address(entry) \
|
||||
((entry) & (memm_entry_flag_get(entry, MEMM_ENTRY_FLAG_PS) \
|
||||
? MEMM_BP_ENTRY_ADDRESS_MASK \
|
||||
: MEMM_ENTRY_ADDRESS_MASK))
|
||||
|
||||
/* 线性地址表项索引或页内偏移掩码 */
|
||||
#define MEMM_LA_PML4EI_MASK ((u64)0x0000ff8000000000)
|
||||
#define MEMM_LA_PDPTEI_MASK ((u64)0x0000007fc0000000)
|
||||
#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_4KB_PAGE_OFFSET_MASK ((u64)0x0000000000000fff)
|
||||
|
||||
/* 线性地址表项索引偏移位数 */
|
||||
#define MEMM_LA_PML4EI_OFFSET (39)
|
||||
#define MEMM_LA_PDPTEI_OFFSET (30)
|
||||
#define MEMM_LA_PDEI_OFFSET (21)
|
||||
#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_PDPTEI
|
||||
#define MEMM_LA_PDEI
|
||||
#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) \
|
||||
(((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_2MB_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) \
|
||||
((addr) & (page_type##_MASK))
|
||||
|
||||
/*
|
||||
仅支持canonical型地址
|
||||
|
||||
target与physical至少都是以MEMM_PAGE_SIZE对齐的
|
||||
|
||||
没有MEMM_PAGE_SIZE对齐的,和非canonical型地址都会返回false
|
||||
|
||||
当剩余长度超过1GB的一半且地址1GB对齐,则会映射一个1GB页;
|
||||
当剩余长度超过2MB的一半且地址2MB对齐,则会映射一个2MB页;
|
||||
否则映射4KB页。
|
||||
/**
|
||||
* @name memm_map_pageframes_to
|
||||
*
|
||||
* ```c
|
||||
* bool memm_map_pageframes_to(
|
||||
* u64 target, u64 physical,
|
||||
* usize size,
|
||||
* bool user, bool write);
|
||||
* ```
|
||||
*
|
||||
* 仅支持**canonical**型地址
|
||||
*
|
||||
* `target`与`physical`保证至少都是以MEMM_PAGE_SIZE对齐的。
|
||||
*
|
||||
* 没有MEMM_PAGE_SIZE对齐的,和非canonical型地址都会返回false
|
||||
*
|
||||
* 当剩余长度超过1GB的一半且地址1GB对齐,则会映射一个1GB页;
|
||||
* 当剩余长度超过2MB的一半且地址2MB对齐,则会映射一个2MB页;
|
||||
* 否则映射4KB页。
|
||||
*/
|
||||
bool memm_map_pageframes_to(
|
||||
u64 target, u64 physical,
|
||||
usize size,
|
||||
bool user, bool write);
|
||||
|
||||
/**
|
||||
* @name reload_pml4
|
||||
* @addindex 平台依赖宏 x86_64
|
||||
*
|
||||
* ```c
|
||||
* 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) \
|
||||
(((addr) > 0xffff7fffffffffff) ? true : false)
|
||||
|
||||
/**
|
||||
* @name is_cannonical(addr)
|
||||
* @addindex 平台依赖宏 x86_64
|
||||
*
|
||||
* 判断`addr`是否是一个cannonical型地址。
|
||||
*/
|
||||
#define is_cannonical(addr) \
|
||||
(((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) \
|
||||
(is_aligned(addr, MEMM_PAGE_SIZE_1G) \
|
||||
? MEMM_PAGE_SIZE_1G \
|
||||
|
@ -107,4 +265,21 @@ extern void reload_pml4();
|
|||
? MEMM_PAGE_SIZE_2M \
|
||||
: 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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -4,12 +4,45 @@
|
|||
#include <types.h>
|
||||
|
||||
// 使用UNIX时间戳
|
||||
/**
|
||||
* @name system_time_get
|
||||
*
|
||||
* ```c
|
||||
* usize system_time_get();
|
||||
* ```
|
||||
*
|
||||
* 系统时间。
|
||||
*
|
||||
* 系统时间使用精确到毫秒的unix时间,即值`0`代表1970-1-1 00:00:00的第一毫秒前。
|
||||
*/
|
||||
usize system_time_get();
|
||||
|
||||
// 如果硬件支持更高的计时精度,
|
||||
// 此函数提供从系统unix时间开始到现在的纳秒为单位的时间
|
||||
/**
|
||||
* @name system_time_ns_get
|
||||
*
|
||||
* ```c
|
||||
* usize system_time_ns_get();
|
||||
* ```
|
||||
*
|
||||
* 纳秒级系统时间。
|
||||
*
|
||||
* 如果硬件支持更高的计时精度,此函数返回以纳秒为单位的时间。但不表明硬件必须支持纳秒级的计时。
|
||||
*
|
||||
* 即使硬件支持更高的计时精度,内核也会根据情况自主选择是否使用更高的精度计时。
|
||||
*/
|
||||
usize system_time_ns_get();
|
||||
|
||||
/**
|
||||
* @name system_time_increase
|
||||
*
|
||||
* ```c
|
||||
* void system_time_increase();
|
||||
* ```
|
||||
*
|
||||
* 将毫秒级系统时间增加。
|
||||
*/
|
||||
void system_time_increase();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef INTERRUPT_PROCS
|
||||
#define INTERRUPT_PROCS 1
|
||||
|
||||
#ifdef __x86_64__
|
||||
#include <kernel/arch/x86_64/interrupt_procs.h>
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -2,20 +2,44 @@
|
|||
#define KERNEL_H 1
|
||||
|
||||
#include <types.h>
|
||||
#include <kernel/interrupt/procs.h>
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
#include <kernel/arch/x86_64/kernel.h>
|
||||
|
||||
#define ISA_NAME "x86_64"
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_ID
|
||||
#define BUILD_ID 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name KERNEL_TODO
|
||||
*
|
||||
* 表示此处还没有实现代码。
|
||||
*/
|
||||
#define KERNEL_TODO() \
|
||||
while (true) \
|
||||
{ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @name simple_lock
|
||||
*
|
||||
* 简易同步锁。有如下两个方法:
|
||||
*
|
||||
* ```c
|
||||
* #define simple_lock_lock(lock)
|
||||
* ```
|
||||
*
|
||||
* 获取一个锁。
|
||||
*
|
||||
* ```c
|
||||
* #define simple_lock_unlock(lock)
|
||||
* ```
|
||||
*
|
||||
* 解开一个锁。
|
||||
*/
|
||||
#define simple_lock_lock(lock) \
|
||||
{ \
|
||||
while (lock == true) \
|
||||
|
@ -24,8 +48,20 @@
|
|||
}
|
||||
#define simple_lock_unlock(lock) (lock) = false;
|
||||
|
||||
/**
|
||||
* @name kmain_rust
|
||||
*
|
||||
* rust内核主程序。
|
||||
*/
|
||||
extern void kmain_rust();
|
||||
|
||||
extern void *kend; // 内核结束的标记
|
||||
/**
|
||||
* @name kend
|
||||
*
|
||||
* 内核结束的标记。
|
||||
*
|
||||
* 此变量不代表任何值,但是此变量的地址被安排到了内核镜像的末尾,用于标志内核结束的位置。
|
||||
*/
|
||||
extern void *kend;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
|
@ -8,153 +8,227 @@
|
|||
#include <libk/lst.h>
|
||||
|
||||
/**
|
||||
* @brief 内存管理模块
|
||||
* @name MEMM_MAX_SUPPORTED_MEMORY
|
||||
*
|
||||
* TODO 还没设计页回收算法
|
||||
* 支持的最大物理内存,为固定值`1TB`。
|
||||
*/
|
||||
|
||||
/* 最大支持1TB内存 */
|
||||
#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_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);
|
||||
|
||||
/*
|
||||
内存分配器
|
||||
分配器对象的首地址永远是MEMM_PAGE_SIZE对齐的
|
||||
/**
|
||||
* @name allocator_t
|
||||
*
|
||||
* ```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函数。当无法分配空间时返回nullptr。在size参数为0时,保证不可以分配空间,
|
||||
* 但是如果空间已满依然返回nullptr。
|
||||
*
|
||||
* @internal free
|
||||
*
|
||||
* 分配器实例的free函数。若不是allocate得到的地址则什么都不做。
|
||||
*
|
||||
* @internal allocator_instance
|
||||
*
|
||||
* 分配器实例。
|
||||
*/
|
||||
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
|
||||
// 调用free后为false
|
||||
// 调用分配器的`allocate`方法后,在返回`nullptr`时会设为`true`。
|
||||
// 调用分配器的`free`方法时设为`false`。
|
||||
bool full;
|
||||
|
||||
// 进程id,当pid=0时代表内核
|
||||
usize pid;
|
||||
// 分配器类型
|
||||
// 分配器类型。在目录`include/kernel/memm/allocator`中对每个分配器分别定义一个唯一值。
|
||||
usize type;
|
||||
usize size;
|
||||
|
||||
// 分配器实例的allocate函数
|
||||
// 无法分配空间返回nullptr
|
||||
// 在size参数为0时,保证不可以分配空间,但是如果空间已满依然返回nullptr
|
||||
// 当参数align=0时表示不需要对齐
|
||||
// 分配器实例的allocate函数。当无法分配空间时返回nullptr。在size参数为0时,
|
||||
// 保证不可以分配空间,但是如果空间已满依然返回nullptr。
|
||||
memm_allocate_t allocate;
|
||||
|
||||
// 分配器实例的free函数
|
||||
// 若不是allocate得到的地址则什么都不做
|
||||
// 分配器实例的free函数。若不是allocate得到的地址则什么都不做。
|
||||
memm_free_t free;
|
||||
|
||||
// 分配器实例
|
||||
// 对应`type`类型使用
|
||||
// 在kernel/memm/allocator/中是所有的内存分配器
|
||||
// 分配器实例。
|
||||
u64 allocator_instance[0];
|
||||
} allocator_t;
|
||||
|
||||
typedef struct __allocator_iterator_t
|
||||
{
|
||||
allocator_t *allocator;
|
||||
struct __allocator_iterator_t *left, *right;
|
||||
} allocator_iterator_t;
|
||||
|
||||
/*
|
||||
内存管理器
|
||||
内存分配分成两个阶段:映射和分配
|
||||
映射后的页进入allocator记录中,具体的分配工作由allocator完成
|
||||
|
||||
在page_map中置位、在map_with_allocator中复位、在map_with_destructed_allocator中复位
|
||||
且不在available_pages_table中的页,是页表、程序代码段、内核代码等使用的页
|
||||
*/
|
||||
/**
|
||||
* @name 内存管理器
|
||||
*
|
||||
* @internal alloc_only_memory
|
||||
*
|
||||
* 在进入内核主程序之前,有些不在内核中的虚拟内存空间已经被页表映射,这部分内存不可以再映射到物理页框。
|
||||
*/
|
||||
typedef struct __mem_manager_t
|
||||
{
|
||||
usize memory_size;
|
||||
usize page_amount;
|
||||
|
||||
// 这里记录的数量为最小的页的数量
|
||||
usize mapped_page_amount;
|
||||
|
||||
// 在进入内核主程序之前,有些不在内核中的虚拟内存空间已经被
|
||||
// 页表映射,这部分内存不可以再映射到物理页框
|
||||
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;
|
||||
|
||||
// 空闲页线段搜索表
|
||||
lst_iterator_t *available_pages_table;
|
||||
allocator_t *kernel_base_allocator;
|
||||
|
||||
// 分配器树
|
||||
// 为方便查找,以二叉树的形式存储
|
||||
// index=0为无效项
|
||||
allocator_iterator_t *allocators;
|
||||
} mem_manager_t;
|
||||
usize page_table_area;
|
||||
} memory_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`的内存分配器
|
||||
当`pid`为0时,表示这个分配器只给内核使用
|
||||
/**
|
||||
* @name memm_get_manager
|
||||
*
|
||||
* ```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);
|
||||
|
||||
/*
|
||||
释放分配器对象
|
||||
|
||||
只能被内存回收模块调用
|
||||
/**
|
||||
* @name memm_allocator_destruct
|
||||
*
|
||||
* ```c
|
||||
* void memm_allocator_destruct(allocator_t *allocator);
|
||||
* ```
|
||||
*
|
||||
* 释放分配器对象。
|
||||
*
|
||||
* 只能被**内存回收模块**调用。
|
||||
*/
|
||||
void memm_allocator_destruct(allocator_t *allocator);
|
||||
|
||||
/*
|
||||
申请内存
|
||||
第三个参数也是返回值,表示申请内存使用的分配器
|
||||
pid=0时为内核分配
|
||||
所有内存在内核空间都有对物理内存空间的直接映射,也就是线性地址与物理地址相同,称为内核地址
|
||||
|
||||
allocator对象在进程与内核之间传递时一律使用内核空间的映射地址
|
||||
|
||||
## 要求在返回的地址前16字节处保留8字节空间作为它所在的allocator地址,并且不需要分配器的具体实现做这个事
|
||||
/**
|
||||
* @name memm_kernel_allocate
|
||||
*
|
||||
* ```c
|
||||
* void *memm_kernel_allocate(usize size);
|
||||
* ```
|
||||
*
|
||||
* 为内核空间申请内存。
|
||||
*/
|
||||
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_user_allocate(usize size, usize pid);
|
||||
|
||||
/*
|
||||
释放内存
|
||||
/**
|
||||
* @name memm_free
|
||||
*
|
||||
* ```c
|
||||
* void memm_free(void *mem);
|
||||
* ```
|
||||
*
|
||||
* 释放内存。
|
||||
*/
|
||||
void memm_free(void *mem);
|
||||
|
||||
/*
|
||||
寻找大小合适的一组页
|
||||
*/
|
||||
usize find_fitable_pages(usize page_count);
|
||||
void *memm_allcate_pagetable();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,20 +10,25 @@ typedef struct __raw_allocator_cell
|
|||
{
|
||||
usize capacity; // 是content的长度
|
||||
usize length; // 是实际使用的长度
|
||||
allocator_t *allocator; // 所在的分配器
|
||||
usize reserved;
|
||||
u8 content[0];
|
||||
} raw_allocator_cell;
|
||||
#define raw_allocator_next_cell(cell) (raw_allocator_cell *)((void *)((cell)->content) + (cell)->capacity)
|
||||
|
||||
// 原始分配器
|
||||
//
|
||||
// 包括至少一个cell,分配时像cell的分裂一样将空白的一段分成两段,
|
||||
// 释放时,只把length归零,并不将cell合并。
|
||||
// length=0的cell称为空cell
|
||||
//
|
||||
// 统计从上次细胞合并以来free的调用次数,当调用次数很多或可用空间不足时
|
||||
// 触发细胞合并。
|
||||
/**
|
||||
* @name raw_allocator_t
|
||||
*
|
||||
* 原始分配器。包括至少一个cell,分配时像cell的分裂一样将空白的一段分成两段,释放时,只把length归零,并不将cell合并。
|
||||
*
|
||||
* `length`为0的cell称为空cell。
|
||||
*
|
||||
* 统计从上次细胞合并以来free的调用次数,当调用次数达到`RAW_ALLOCATOR_FREE_MAX`或无可用空间时触发细胞合并。
|
||||
*
|
||||
* 使用建议:只在少量allocate和free的情况下使用。使用大量allocate时效率低下并难以得到内存安全保证。
|
||||
*
|
||||
* @internal free_count
|
||||
*
|
||||
* free方法的调用次数,达到`RAW_ALLOCATOR_FREE_MAX`时归零。
|
||||
*/
|
||||
typedef struct __raw_allocator_t
|
||||
{
|
||||
usize size;
|
||||
|
@ -34,9 +39,23 @@ typedef struct __raw_allocator_t
|
|||
} raw_allocator_t;
|
||||
#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_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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
|
@ -121,6 +121,16 @@ void tty_set_framebuffer(tty *ttyx, framebuffer *fb);
|
|||
void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor);
|
||||
|
||||
#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_height(tty *ttyx);
|
||||
|
|
|
@ -33,7 +33,7 @@ bool lst_remove(lst_iterator_t *lst, usize left, usize right, bool force);
|
|||
/*
|
||||
在`lst`中添加一个线段[left,right)
|
||||
force=true时忽略已经存在于`lst`中的线段
|
||||
force=false时若有存在于`lst`中的线段,只添加这些部分之外的线段,返回false,否则返回true
|
||||
force=false时若有存在于`lst`中的线段,不添加任何线段,返回false,否则返回true
|
||||
*/
|
||||
bool lst_add(lst_iterator_t *lst, usize left, usize right, bool force);
|
||||
|
||||
|
|
|
@ -3,14 +3,25 @@
|
|||
|
||||
#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 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
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "stable"
|
2
rustlib
2
rustlib
|
@ -1 +1 @@
|
|||
Subproject commit 087c4795bbc23cd0baee060bda8c1159a971a542
|
||||
Subproject commit 6a2ca2afcd651e46f1c19f8d8a3f685fd982d824
|
|
@ -49,15 +49,17 @@ for mod in kernel_modules:
|
|||
print(" " + color['lpink'] + f"{mod}" + color['reset'] + " exists.")
|
||||
else:
|
||||
print(" " + color['lred'] + f"{mod}" + color['reset'] + " not found.")
|
||||
print("Kernel module " +
|
||||
color['lred'] + f"{mod}" + color['reset'] + " is not installed.")
|
||||
print(
|
||||
"Kernel module " +
|
||||
color['lred'] + f"{mod}" + color['reset'] + " is not installed.")
|
||||
exit(-1)
|
||||
|
||||
# 检查软件依赖
|
||||
pathsenv = os.environ.get("PATH").split(":")
|
||||
for software, progs in softwares.items():
|
||||
print("Checking " + color['lcyan'] +
|
||||
f"{software}" + color['reset'] + " ...")
|
||||
print(
|
||||
"Checking " + color['lcyan'] +
|
||||
f"{software}" + color['reset'] + " ...")
|
||||
for program in progs:
|
||||
exists = False
|
||||
for path in pathsenv:
|
||||
|
@ -65,15 +67,19 @@ for software, progs in softwares.items():
|
|||
exists = True
|
||||
break
|
||||
if exists:
|
||||
print(" " + color['lyellow'] +
|
||||
f"{program}" + color['reset'] + " existed.")
|
||||
print(
|
||||
" " + color['lyellow'] +
|
||||
f"{program}" + color['reset'] + " existed.")
|
||||
else:
|
||||
print(" " + color['lred'] +
|
||||
f"{program}" + color['reset'] + " not found.")
|
||||
print(
|
||||
" " + color['lred'] +
|
||||
f"{program}" + color['reset'] + " not found.")
|
||||
|
||||
print("Software " + color['lred'] + f"{software}" +
|
||||
color['reset'] + " is not installed or completed.")
|
||||
print(
|
||||
"Software " + color['lred'] + f"{software}" +
|
||||
color['reset'] + " is not installed or completed.")
|
||||
exit(-2)
|
||||
|
||||
print("All dependencies are " +
|
||||
color['lgreen'] + "satisfied." + color['reset'])
|
||||
print(
|
||||
"All dependencies are " +
|
||||
color['lgreen'] + "satisfied." + color['reset'])
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import time
|
||||
|
||||
curtime = str(int(time.time() * 1000))
|
||||
|
||||
print(curtime)
|
44
src/Makefile
44
src/Makefile
|
@ -2,7 +2,7 @@
|
|||
|
||||
ARCH := $(shell uname -m)
|
||||
PWD := $(shell pwd)
|
||||
SOURCE := ${PWD}/scripts
|
||||
SOURCE := ${PWD}/../scripts
|
||||
ifeq (${ARCH},x86_64)
|
||||
ASM = nasm
|
||||
ASMFLAGS = -f elf64
|
||||
|
@ -12,9 +12,14 @@ ifdef release
|
|||
release = 1
|
||||
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
|
||||
|
||||
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
|
||||
DEFINES := ${DEFINES} release=1
|
||||
endif
|
||||
|
@ -25,24 +30,21 @@ endif
|
|||
RSCFLAGS = --emit obj --crate-type staticlib --verbose \
|
||||
--crate-name=metaverse \
|
||||
--edition 2021 \
|
||||
-L crate="${PWD}/../rustlib/${ARCH}/src/" \
|
||||
-L crate="${PWD}/../rustlib/src/" \
|
||||
-C code-model=large \
|
||||
-C relocation-model=static \
|
||||
-C embed-bitcode=no
|
||||
|
||||
ifeq (${ARCH},x86_64)
|
||||
RSCFLAGS := ${RSCFLAGS} --target x86_64-unknown-none
|
||||
endif
|
||||
|
||||
ifdef release
|
||||
RSCFLAGS := -O
|
||||
endif
|
||||
|
||||
ifeq (${ARCH},x86_64)
|
||||
RSCFLAGS := ${RSCFLAGS} -C target-feature=-sse
|
||||
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" \
|
||||
"${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
|
||||
|
||||
all: postproc metaverse.elf
|
||||
@echo -e "Build \e[1;32msucceeded\e[0m."
|
||||
@echo -e "Build ID \e[1;31m${BUILD_ID}\e[0m."
|
||||
|
||||
postproc:
|
||||
@echo -n -e "\e[36m"
|
||||
|
@ -67,16 +71,24 @@ postproc:
|
|||
@echo -e "\e[0m"
|
||||
|
||||
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}
|
||||
@echo -e "\e[33m-------------------------\e[0m"
|
||||
@if [ ! ${release} ]; then \
|
||||
echo -e "\e[33m-------------------------\e[0m"; \
|
||||
fi
|
||||
|
||||
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}
|
||||
@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"
|
||||
@rustc ${RSCFLAGS} lib.rs -o rust.o
|
||||
|
||||
|
|
|
@ -6,12 +6,15 @@
|
|||
CC = gcc
|
||||
CCFLAGS = -m64 -mcmodel=large -I ../../include \
|
||||
-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
|
||||
CCFLAGS := ${CCFLAGS} -O2
|
||||
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}
|
||||
|
||||
################################
|
||||
|
@ -26,7 +29,8 @@ endif
|
|||
ASMFLAGS := ${ASMFLAGS}
|
||||
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}
|
||||
|
||||
################################
|
||||
|
|
|
@ -1,13 +1,32 @@
|
|||
section .entry align=8
|
||||
extern kmain
|
||||
extern systemcall_procedure
|
||||
global init64
|
||||
init64:
|
||||
endbr64
|
||||
cli
|
||||
|
||||
mov rax, 0x1000000
|
||||
mov rbp, rax
|
||||
mov rsp, rax
|
||||
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
|
||||
|
||||
section .multiboot2 align=8
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
section .entry
|
||||
extern init64
|
||||
; 寄存器ebx是multiboot2 information,不可以使用
|
||||
;
|
||||
; 由于这个代码是32位环境的代码,而链接器链接时会把它当作64位代码链接
|
||||
; 所以这里所有的使用了常数的位置都要通过指令写入
|
||||
init32:
|
||||
cli
|
||||
|
||||
|
@ -37,18 +34,17 @@ init32:
|
|||
add edi, 4
|
||||
loop init32_loop0
|
||||
|
||||
; 设置gdt_ptr
|
||||
mov eax, 0x10402a ; gdt_ptr + 2
|
||||
mov dword [eax], 0x104000 ; gdt
|
||||
; 加载GDTR和段寄存器
|
||||
; 加载GDTR、段寄存器和TR寄存器
|
||||
db 0x66
|
||||
lgdt [0x104028] ; gdt_ptr
|
||||
lgdt [0x104000] ; gdt_ptr
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov ss, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ax, 0x30
|
||||
ltr ax
|
||||
|
||||
; 打开PAE
|
||||
mov eax, cr4
|
||||
|
@ -77,7 +73,6 @@ init32:
|
|||
section .cpumeta align=4096
|
||||
global PML4
|
||||
; 分页
|
||||
; 链接器会把这些数据替换掉所以要在代码中重新设置
|
||||
PML4:
|
||||
dq 0x003 + PDPT0
|
||||
resq 511
|
||||
|
@ -89,15 +84,43 @@ PDPT0:
|
|||
PD0:
|
||||
resq 512
|
||||
|
||||
; 分段
|
||||
gdt:
|
||||
dq 0
|
||||
dq 0x0020980000000000 ; 内核态代码段
|
||||
dq 0x0000920000000000 ; 内核态数据段
|
||||
dq 0x0020f80000000000 ; 用户态代码段
|
||||
dq 0x0000f20000000000 ; 用户态数据段
|
||||
gdt_end:
|
||||
section .cpumeta.tblptrs
|
||||
|
||||
gdt_ptr:
|
||||
gdt_ptr: ; 0x104000
|
||||
dw gdt_end - gdt - 1
|
||||
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)
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
section .text
|
||||
|
||||
global interrupt_open
|
||||
interrupt_open:
|
||||
sti
|
||||
ret
|
||||
|
||||
global interrupt_close
|
||||
interrupt_close:
|
||||
cli
|
||||
ret
|
|
@ -9,8 +9,9 @@
|
|||
map_pageframe_to((u64)addr, (u64)addr, false, true, MEMM_PAGE_SIZE_4K);
|
||||
|
||||
// 这里的physical必须保证根据ps对齐
|
||||
static void map_pageframe_to(u64 target, u64 physical,
|
||||
bool user, bool write, memm_page_size ps)
|
||||
static void map_pageframe_to(
|
||||
u64 target, u64 physical,
|
||||
bool user, bool write, memm_page_size ps)
|
||||
{
|
||||
if (!is_cannonical(target))
|
||||
return;
|
||||
|
@ -22,7 +23,7 @@ static void map_pageframe_to(u64 target, u64 physical,
|
|||
PDPT = (u64 *)memm_entry_get_address(pml4e);
|
||||
else
|
||||
{
|
||||
PDPT = (u64 *)(find_fitable_pages(1) * MEMM_PAGE_SIZE);
|
||||
PDPT = memm_allcate_pagetable();
|
||||
map_pagemap(PDPT);
|
||||
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);
|
||||
else
|
||||
{
|
||||
PDT = (u64 *)(find_fitable_pages(1) * MEMM_PAGE_SIZE);
|
||||
PDT = memm_allcate_pagetable();
|
||||
map_pagemap(PDT);
|
||||
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);
|
||||
else
|
||||
{
|
||||
PT = (u64 *)(find_fitable_pages(1) * MEMM_PAGE_SIZE);
|
||||
PT = memm_allcate_pagetable();
|
||||
map_pagemap(PT);
|
||||
memset(PT, 0, MEMM_PAGE_SIZE);
|
||||
|
||||
|
@ -110,7 +111,6 @@ bool memm_map_pageframes_to(
|
|||
return false;
|
||||
while (size != 0)
|
||||
{
|
||||
// 这是当前需要映射的页的内存对齐(或者说是当前映射的页的大小)
|
||||
memm_page_size align = memm_get_page_align(physical);
|
||||
if (align == MEMM_PAGE_SIZE_1G)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#include <kernel/syscall.h>
|
||||
|
||||
#include <libk/string.h>
|
||||
|
||||
void syscall_init()
|
||||
{
|
||||
memset(&system_calls_table, 0, sizeof(system_calls_table));
|
||||
}
|
|
@ -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
|
|
@ -1,4 +1,3 @@
|
|||
use alloc::string::ToString;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
|
@ -140,7 +139,7 @@ impl KernelLogger {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
true
|
||||
};
|
||||
while !all_end(&indeces, &logs) {
|
||||
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() {
|
||||
Some(
|
||||
MessageBuilder::new()
|
||||
.message(&time.to_string())
|
||||
.message(time)
|
||||
.append(MessageBuilder::from_message(msg.clone()))
|
||||
.build(),
|
||||
)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <kernel/kernel.h>
|
||||
#include <kernel/tty.h>
|
||||
#include <kernel/memm.h>
|
||||
#include <kernel/interrupt.h>
|
||||
#include <kernel/syscall.h>
|
||||
|
||||
#include <libk/multiboot2.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_controller_t *tty_controler = tty_controller_new();
|
||||
|
@ -41,6 +43,13 @@ void kmain(void *mb2_bootinfo)
|
|||
get_frame_buffer_with_bootinfo(&fb, &bootinfo);
|
||||
tty *tty0 = tty_new(tty_type_raw_framebuffer, tty_mode_text);
|
||||
tty_set_framebuffer(tty0, &fb);
|
||||
tty_enable(tty0);
|
||||
|
||||
// 初始化中断管理
|
||||
interrupt_init();
|
||||
|
||||
// 初始化系统调用
|
||||
syscall_init();
|
||||
|
||||
// 为rust准备正确对齐的栈
|
||||
prepare_stack();
|
||||
|
|
|
@ -8,7 +8,6 @@ use super::{
|
|||
#[no_mangle]
|
||||
extern "C" fn kmain_rust() -> ! {
|
||||
let tty = Tty::from_id(0).unwrap();
|
||||
tty.enable();
|
||||
let mut logger = KernelLogger::new();
|
||||
logger.info(message!(
|
||||
Msg("Hello, "),
|
||||
|
|
|
@ -13,7 +13,7 @@ void raw_allocator_new(raw_allocator_t *allocator, usize size)
|
|||
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;
|
||||
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;
|
||||
while ((void *)cell < raw_allocator_end(allocator))
|
||||
{
|
||||
{ // TODO 内存错误
|
||||
if (mem == cell->content)
|
||||
{
|
||||
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->free_count++;
|
||||
if ( // 可用内存不超过当前allocator的 5% 或调用free次数很多时
|
||||
allocator->size / allocator->rest_memory > 20 &&
|
||||
allocator->size / allocator->rest_memory > 20 ||
|
||||
allocator->free_count > RAW_ALLOCATOR_FREE_MAX)
|
||||
{
|
||||
raw_allocator_cellmerge(allocator);
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
#include <libk/string.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));
|
||||
memory_manager.memory_size = mem_size;
|
||||
|
@ -17,62 +17,25 @@ mem_manager_t *memm_new(usize mem_size)
|
|||
usize kernel_initial_size = (usize)&kend;
|
||||
align_to(kernel_initial_size, MEMM_PAGE_SIZE);
|
||||
|
||||
// 配置分配器树
|
||||
allocator_t *allocator0 = memm_allocator_new(
|
||||
(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);
|
||||
|
||||
allocator_iterator_t *alcatr_ind = allocator0->allocate(
|
||||
&allocator0->allocator_instance, sizeof(allocator_iterator_t), 0);
|
||||
memory_manager.kernel_base_allocator = allocator0;
|
||||
|
||||
alcatr_ind->allocator = allocator0;
|
||||
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);
|
||||
return &memory_manager;
|
||||
}
|
||||
|
||||
memory_manager_t *memm_get_manager()
|
||||
{
|
||||
return &memory_manager;
|
||||
}
|
||||
|
||||
allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid)
|
||||
{
|
||||
allocator_t *allocator = start;
|
||||
allocator->initialized = true;
|
||||
allocator->magic = MEMM_ALLOCATOR_MAGIC;
|
||||
allocator->full = false;
|
||||
allocator->pid = 0;
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
allocator->initialized = false;
|
||||
allocator->magic = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void memm_allocator_destruct(allocator_t *allocator)
|
||||
{
|
||||
allocator->initialized = false;
|
||||
allocator->magic = 0;
|
||||
// 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)
|
||||
{
|
||||
return memm_allocate(size, 0);
|
||||
}
|
||||
|
||||
void *memm_user_allocate(usize size, usize pid)
|
||||
{
|
||||
void *res = memm_allocate(size, pid);
|
||||
// TODO 将内存空间映射到用户空间
|
||||
return res;
|
||||
allocator_t *allocator = memory_manager.kernel_base_allocator;
|
||||
return allocator->allocate(allocator->allocator_instance, size);
|
||||
}
|
||||
|
||||
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))
|
||||
{ // TODO 对于用户空间的地址需要先转换到内核地址后释放
|
||||
{
|
||||
mem = mem - allocator->userspace + (void *)allocator;
|
||||
}
|
||||
allocator->free(allocator->allocator_instance, mem);
|
||||
if (allocator->full)
|
||||
allocator->full = false;
|
||||
}
|
||||
|
||||
usize find_fitable_pages(usize page_count)
|
||||
void *memm_allcate_pagetable()
|
||||
{
|
||||
usize res = 0;
|
||||
lst_iterator_t *iter = memory_manager.available_pages_table;
|
||||
do
|
||||
if (memory_manager.page_table_area < MEMM_PAGE_TABLE_AREA_MAX)
|
||||
{
|
||||
if (iter->line.right - iter->line.left > page_count)
|
||||
{
|
||||
res = iter->line.left;
|
||||
lst_remove(iter, res, res + page_count, false);
|
||||
for (usize i = res; i < res + page_count; i++)
|
||||
{
|
||||
bitmap_set(memory_manager.page_map, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while ((iter = lst_next(iter)) != nullptr);
|
||||
memory_manager.mapped_page_amount += page_count;
|
||||
return res;
|
||||
memory_manager.page_table_area += MEMM_PAGE_TABLE_SIZE;
|
||||
return memory_manager.alloc_only_memory - memory_manager.page_table_area;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,8 +58,8 @@ void tty_set_framebuffer(tty *ttyx, framebuffer *fb)
|
|||
ttyx->height = ttyx->typeinfo.raw_framebuffer.height;
|
||||
if (ttyx->mode == tty_mode_text)
|
||||
{
|
||||
ttyx->text.width = fb->width / tty_get_font()->char_width;
|
||||
ttyx->text.height = fb->height / tty_get_font()->char_height;
|
||||
ttyx->text.width = fb->width / (TTY_FONT_SCALE * tty_get_font()->char_width);
|
||||
ttyx->text.height = fb->height / (TTY_FONT_SCALE * tty_get_font()->char_height);
|
||||
ttyx->text.line = 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')
|
||||
{ // 水平制表符
|
||||
putchar(ttyx, ' ', 0, 0);
|
||||
ttyx->text.column += 8;
|
||||
ttyx->text.column -= ttyx->text.column % 8;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\r')
|
||||
{ // 回到行首
|
||||
putchar(ttyx, ' ', 0, 0);
|
||||
ttyx->text.column = 0;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\v')
|
||||
{ // 垂直制表符
|
||||
putchar(ttyx, ' ', 0, 0);
|
||||
ttyx->text.line++;
|
||||
if (ttyx->text.line == ttyx->text.height)
|
||||
{
|
||||
|
|
|
@ -150,10 +150,11 @@ impl Color {
|
|||
pub const RED: Color = Color(0xee, 0x22, 0x22);
|
||||
pub const GREEN: Color = Color(0x22, 0xee, 0x22);
|
||||
pub const BLUE: Color = Color(0x22, 0x22, 0xee);
|
||||
pub const YELLOW: Color = Color(0xee, 0x22, 0x22);
|
||||
pub const ORANGE: Color = Color(0xee, 0xee, 0x22);
|
||||
pub const PURPLE: Color = Color(0xee, 0, 0xee);
|
||||
pub const YELLOW: Color = Color(0xee, 0xee, 0x22);
|
||||
pub const ORANGE: Color = Color(0xee, 0xaa, 0x22);
|
||||
pub const PURPLE: Color = Color(0xee, 0x22, 0xee);
|
||||
pub const PINK: Color = Color(0xee, 0x44, 0x66);
|
||||
pub const GRAY: Color = Color(0xaa, 0xaa, 0xaa);
|
||||
}
|
||||
|
||||
impl From<Color> for u32 {
|
||||
|
@ -181,6 +182,16 @@ pub struct MessageSection {
|
|||
#[derive(Clone)]
|
||||
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
|
||||
///
|
||||
/// 使用链式调用模式构造一个消息.
|
||||
|
@ -196,6 +207,19 @@ pub struct Message(Vec<MessageSection>);
|
|||
/// .build();
|
||||
/// ```
|
||||
///
|
||||
/// 定义了`message!`宏,简化构造消息的代码:
|
||||
///
|
||||
/// ```rust
|
||||
/// use crate::kernel::tty::tty::BuilderFunctions::*;
|
||||
///
|
||||
/// message!(
|
||||
/// Msg("Hello, "),
|
||||
/// Msg("Metaverse"),
|
||||
/// FgColor(Color::GREEN),
|
||||
/// Msg("!\n"),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// 对于特殊情况可以使用非链式调用:
|
||||
/// ```rust
|
||||
/// let mut msg = MessageBuilder::new();
|
||||
|
@ -226,7 +250,7 @@ impl MessageBuilder {
|
|||
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 {
|
||||
msg: msg.to_string(),
|
||||
fgcolor: Color(0xee, 0xee, 0xee),
|
||||
|
@ -235,7 +259,7 @@ impl MessageBuilder {
|
|||
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 {
|
||||
msg: msg.to_string(),
|
||||
fgcolor: Color(0xee, 0xee, 0xee),
|
||||
|
|
|
@ -11,7 +11,7 @@ ifdef release
|
|||
CCFLAGS := ${CCFLAGS} -O2
|
||||
endif
|
||||
|
||||
C_SRCS = bootinfo.c lst.c
|
||||
C_SRCS = bootinfo.c lst.c utils.c
|
||||
C_OBJS = ${C_SRCS:.c=.c.o}
|
||||
|
||||
################################
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -13,10 +13,26 @@ SECTIONS {
|
|||
{
|
||||
*(.multiboot2)
|
||||
}
|
||||
.cpumeta :
|
||||
.cpumeta ALIGN(4096) :
|
||||
{
|
||||
*(.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;
|
||||
.text :
|
||||
{
|
||||
|
|
Reference in New Issue