Skip to content

Commit 24feb00

Browse files
authored
Merge pull request #190 from MRNIU/memory
Memory
2 parents ec74b1b + 77d443e commit 24feb00

22 files changed

+2664
-41
lines changed

README.md

+17-36
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
# SimpleKernel
1212

13-
intr branch
13+
memory branch
1414

1515
## 关键词
1616

@@ -113,27 +113,15 @@ intr branch
113113

114114
- riscv64
115115

116-
1. 对 CSR 寄存器的抽象
117-
2. 寄存器状态打印
118-
3. 基于 Direct 的中断处理
119-
4. 中断注册函数
120-
5. 时钟中断
121-
116+
1.
117+
122118
- X86_64
123119

124-
1. cpu 抽象
125-
2. 8259A pic 控制器抽象
126-
3. 8253/8254 timer 控制器抽象
127-
4. gdt 初始化
128-
5. 中断处理流程
129-
6. 中断注册函数
130-
7. 时钟中断
120+
1.
131121

132122
- TODO
133123

134-
riscv64 PLIC
135-
136-
x86_64 APIC
124+
137125

138126
- 全局对象
139127

@@ -150,44 +138,37 @@ intr branch
150138
## 已支持特性
151139

152140
- [x] [BUILD] 使用 CMake 的构建系统
153-
154141
- [x] [BUILD] 使用 gdb remote 调试
155-
156142
- [x] [BUILD] 第三方资源集成
157-
158143
- [x] [COMMON] C++ 全局对象的构造
159-
160144
- [x] [COMMON] C++ 静态局部对象构造
161-
162145
- [x] [COMMON] C 栈保护支持
163-
164146
- [x] [COMMON] printf 支持
165-
166147
- [x] [COMMON] 简单的 C++ 异常支持
167-
168148
- [x] [COMMON] 带颜色的字符串输出
169-
170149
- [x] [x86_64] 基于 gnuefi 的 bootloader
171-
172150
- [x] [x86_64] 基于 serial 的基本输出
173-
174151
- [x] [x86_64] 物理内存信息探测
175-
176152
- [x] [x86_64] 显示缓冲区探测
177-
178153
- [x] [x86_64] 调用栈回溯
179-
180154
- [x] [riscv64] gp 寄存器的初始化
181-
182155
- [x] [riscv64] 基于 opensbi 的基本输出
183-
184156
- [x] [riscv64] device tree 硬件信息解析
185-
186157
- [x] [riscv64] ns16550a 串口驱动
187-
188158
- [x] [riscv64] 调用栈回溯(仅打印地址)
189-
190159
- [ ] [aarch64] 基于 gnuefi 的 bootloader(调试中)
160+
- [x] [riscv64] 对 CSR 寄存器的抽象
161+
- [x] [riscv64] 寄存器状态打印
162+
- [x] [riscv64] 基于 Direct 的中断处理
163+
- [x] [riscv64] 中断注册函数
164+
- [x] [riscv64] 时钟中断
165+
- [x] [x86_64] cpu 抽象
166+
- [x] [x86_64] 8259A pic 控制器抽象
167+
- [x] [x86_64] 8253/8254 timer 控制器抽象
168+
- [x] [x86_64] gdt 初始化
169+
- [x] [x86_64] 中断处理流程
170+
- [x] [x86_64] 中断注册函数
171+
- [x] [x86_64] 时钟中断
191172

192173
## 使用的第三方资源
193174

src/kernel/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ add_subdirectory(${PROJECT_SOURCE_DIR}/driver)
2121

2222
add_executable(${PROJECT_NAME}
2323
main.cpp
24+
physical_memory_manager.cpp
25+
virtual_memory_manager.cpp
2426
)
2527

26-
# 添加头文件
2728
target_include_directories(kernel PRIVATE
2829
include
30+
../
2931
)
3032

3133
# 添加要链接的库

src/kernel/arch/aarch64/interrupt.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
#include "kernel_log.hpp"
1919
#include "sk_cstdio"
2020

21+
<<<<<<< HEAD
22+
Interrupt::Interrupt() { log::Info("Interrupt init.\n"); }
23+
=======
2124
Interrupt::Interrupt() { klog::Info("Interrupt init.\n"); }
25+
>>>>>>> new_intr
2226

2327
void Interrupt::Do(uint64_t cause, uint8_t *context) {
2428
(void)cause;
@@ -31,7 +35,11 @@ void Interrupt::RegisterInterruptFunc(uint64_t cause, InterruptFunc func) {
3135
}
3236

3337
uint32_t InterruptInit(uint32_t, uint8_t *) {
38+
<<<<<<< HEAD
39+
log::Info("Hello InterruptInit\n");
40+
=======
3441
klog::Info("Hello InterruptInit\n");
42+
>>>>>>> new_intr
3543

3644
return 0;
3745
}

src/kernel/arch/riscv64/include/cpu/cpu.hpp

+80
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,84 @@
2727
#include "sk_cstdio"
2828
#include "sk_iostream"
2929

30+
namespace cpu {
31+
namespace vmm {
32+
enum {
33+
VALID_OFFSET = 0,
34+
READ_OFFSET = 1,
35+
WRITE_OFFSET = 2,
36+
EXEC_OFFSET = 3,
37+
USER_OFFSET = 4,
38+
GLOBAL_OFFSET = 5,
39+
ACCESSED_OFFSET = 6,
40+
DIRTY_OFFSET = 7,
41+
VALID = 1 << VALID_OFFSET,
42+
READ = 1 << READ_OFFSET,
43+
WRITE = 1 << WRITE_OFFSET,
44+
EXEC = 1 << EXEC_OFFSET,
45+
USER = 1 << USER_OFFSET,
46+
GLOBAL = 1 << GLOBAL_OFFSET,
47+
ACCESSED = 1 << ACCESSED_OFFSET,
48+
DIRTY = 1 << DIRTY_OFFSET,
49+
};
50+
/// 有效位
51+
static constexpr const uint8_t VMM_PAGE_VALID = VALID;
52+
/// 可读位
53+
static constexpr const uint8_t VMM_PAGE_READABLE = READ;
54+
/// 可写位s
55+
static constexpr const uint8_t VMM_PAGE_WRITABLE = WRITE;
56+
/// 可执行位
57+
static constexpr const uint8_t VMM_PAGE_EXECUTABLE = EXEC;
58+
/// 用户位
59+
static constexpr const uint8_t VMM_PAGE_USER = USER;
60+
/// 全局位,我们不会使用
61+
static constexpr const uint8_t VMM_PAGE_GLOBAL = GLOBAL;
62+
/// 已使用位,用于替换算法
63+
static constexpr const uint8_t VMM_PAGE_ACCESSED = ACCESSED;
64+
/// 已修改位,用于替换算法
65+
static constexpr const uint8_t VMM_PAGE_DIRTY = DIRTY;
66+
/// 内核虚拟地址相对物理地址的偏移
67+
static constexpr const size_t KERNEL_OFFSET = 0x0;
68+
/// PTE 属性位数
69+
static constexpr const size_t VMM_PTE_PROP_BITS = 10;
70+
/// PTE 页内偏移位数
71+
static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
72+
/// VPN 位数
73+
static constexpr const size_t VMM_VPN_BITS = 9;
74+
/// VPN 位数掩码,9 位 VPN
75+
static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
76+
/// riscv64 使用了三级页表
77+
static constexpr const size_t VMM_PT_LEVEL = 3;
78+
79+
// 开启 PG
80+
inline void EnablePage() {
81+
kAllCsr.satp.asid.Write(0);
82+
kAllCsr.satp.mode.Write(register_info::csr::SatpInfo::kSv39);
83+
}
84+
inline void DisablePage() {
85+
kAllCsr.satp.mode.Write(register_info::csr::SatpInfo::kBare);
86+
}
87+
88+
/**
89+
* @brief 设置 页目录
90+
* @param _pgd 要设置的页表
91+
* @return true 成功
92+
* @return false 失败
93+
*/
94+
inline void SetPageDirectory(uint64_t pgd) { kAllCsr.satp.ppn.Write(pgd); }
95+
96+
/**
97+
* @brief 获取页目录
98+
* @return uint64_t 页目录值
99+
*/
100+
inline uint64_t GetPageDirectory() { return kAllCsr.satp.ppn.Get(); }
101+
102+
inline void FlushPage(uint64_t addr) {
103+
(void)addr;
104+
__asm__ volatile("sfence.vma zero, zero");
105+
}
106+
107+
} // namespace vmm
108+
} // namespace cpu
109+
30110
#endif // SIMPLEKERNEL_SRC_KERNEL_ARCH_RISCV64_INCLUDE_CPU_CPU_HPP_

src/kernel/arch/riscv64/include/cpu/regs.hpp

+31
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,37 @@
3838
*/
3939
namespace cpu {
4040

41+
// namespace vmm_info {
42+
// /// 有效位
43+
// static constexpr const uint8_t VMM_PAGE_VALID = CPU::pte_t::VALID;
44+
// /// 可读位
45+
// static constexpr const uint8_t VMM_PAGE_READABLE = CPU::pte_t::READ;
46+
// /// 可写位s
47+
// static constexpr const uint8_t VMM_PAGE_WRITABLE = CPU::pte_t::WRITE;
48+
// /// 可执行位
49+
// static constexpr const uint8_t VMM_PAGE_EXECUTABLE = CPU::pte_t::EXEC;
50+
// /// 用户位
51+
// static constexpr const uint8_t VMM_PAGE_USER = CPU::pte_t::USER;
52+
// /// 全局位,我们不会使用
53+
// static constexpr const uint8_t VMM_PAGE_GLOBAL = CPU::pte_t::GLOBAL;
54+
// /// 已使用位,用于替换算法
55+
// static constexpr const uint8_t VMM_PAGE_ACCESSED = CPU::pte_t::ACCESSED;
56+
// /// 已修改位,用于替换算法
57+
// static constexpr const uint8_t VMM_PAGE_DIRTY = CPU::pte_t::DIRTY;
58+
// /// 内核虚拟地址相对物理地址的偏移
59+
// static constexpr const size_t KERNEL_OFFSET = 0x0;
60+
// /// PTE 属性位数
61+
// static constexpr const size_t VMM_PTE_PROP_BITS = 10;
62+
// /// PTE 页内偏移位数
63+
// static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
64+
// /// VPN 位数
65+
// static constexpr const size_t VMM_VPN_BITS = 9;
66+
// /// VPN 位数掩码,9 位 VPN
67+
// static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
68+
// /// riscv64 使用了三级页表
69+
// static constexpr const size_t VMM_PT_LEVEL = 3;
70+
// }; // namespace vmm_info
71+
4172
// 第一部分:寄存器定义
4273
namespace register_info {
4374

src/kernel/arch/x86_64/include/cpu/cpu.hpp

+47
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,53 @@ struct InterruptContextErrorCode {
512512
}
513513
};
514514

515+
namespace vmm {
516+
/// P = 1 表示有效; P = 0 表示无效。
517+
static constexpr const uint8_t VMM_PAGE_VALID = 1 << 0;
518+
/// 如果为 0 表示页面只读或可执行。
519+
static constexpr const uint8_t VMM_PAGE_READABLE = 0;
520+
static constexpr const uint8_t VMM_PAGE_WRITABLE = 1 << 1;
521+
static constexpr const uint8_t VMM_PAGE_EXECUTABLE = 0;
522+
/// U/S-- 位 2 是用户 / 超级用户 (User/Supervisor) 标志。
523+
/// 如果为 1 那么运行在任何特权级上的程序都可以访问该页面。
524+
static constexpr const uint8_t VMM_PAGE_USER = 1 << 2;
525+
/// 内核虚拟地址相对物理地址的偏移
526+
static constexpr const size_t KERNEL_OFFSET = 0x0;
527+
/// PTE 属性位数
528+
static constexpr const size_t VMM_PTE_PROP_BITS = 12;
529+
/// PTE 页内偏移位数
530+
static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
531+
/// VPN 位数
532+
static constexpr const size_t VMM_VPN_BITS = 9;
533+
/// VPN 位数掩码,9 位 VPN
534+
static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
535+
/// x86_64 使用了四级页表
536+
static constexpr const size_t VMM_PT_LEVEL = 4;
537+
538+
// 开启 PG
539+
inline void EnablePage() { kAllCr.cr0.pg.Set(); }
540+
inline void DisablePage() { kAllCr.cr0.pg.Clear(); }
541+
542+
/**
543+
* @brief 设置 页目录
544+
* @param _pgd 要设置的页表
545+
* @return true 成功
546+
* @return false 失败
547+
*/
548+
inline void SetPageDirectory(uint64_t pgd) { kAllCr.cr3.Write(pgd); }
549+
550+
/**
551+
* @brief 获取页目录 CR3
552+
* @return uint64_t CR3 值
553+
*/
554+
inline uint64_t GetPageDirectory() { return kAllCr.cr3.Read(); }
555+
556+
inline void FlushPage(uint64_t addr) {
557+
__asm__ volatile("invlpg (%0)" : : "r"(addr) : "memory");
558+
}
559+
560+
}; // namespace vmm
561+
515562
}; // namespace cpu
516563

517564
#endif // SIMPLEKERNEL_SRC_KERNEL_ARCH_X86_64_INCLUDE_CPU_CPU_HPP_

src/kernel/arch/x86_64/include/cpu/regs.hpp

+19-2
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,15 @@ class WriteOnlyRegBase {
999999
klog::Err("TODO\n");
10001000
} else if constexpr (std::is_same<RegInfo,
10011001
register_info::cr::Cr0Info>::value) {
1002-
__asm__ volatile("bts %%cr0, %0" : : "r"(offset) :);
1002+
// __asm__ volatile("bts %%cr0, %0" : : "r"(offset) :);
1003+
uint64_t value;
1004+
__asm__ volatile(
1005+
"mov %%cr0, %0\n\t"
1006+
"bts %1, %0\n\t"
1007+
"mov %0, %%cr0"
1008+
: "=r"(value)
1009+
: "r"(offset)
1010+
: "memory");
10031011
} else if constexpr (std::is_same<RegInfo,
10041012
register_info::cr::Cr2Info>::value) {
10051013
__asm__ volatile("bts %%cr2, %0" : : "r"(offset) :);
@@ -1059,7 +1067,16 @@ class WriteOnlyRegBase {
10591067
klog::Err("TODO\n");
10601068
} else if constexpr (std::is_same<RegInfo,
10611069
register_info::cr::Cr0Info>::value) {
1062-
__asm__ volatile("btr %%cr0, %0" : : "r"(offset) :);
1070+
// __asm__ volatile("btr %%cr0, %0" : : "r"(offset) :);
1071+
// __asm__ volatile("bts %%cr0, %0" : : "r"(offset) :);
1072+
uint64_t value;
1073+
__asm__ volatile(
1074+
"mov %%cr0, %0\n\t"
1075+
"btr %1, %0\n\t"
1076+
"mov %0, %%cr0"
1077+
: "=r"(value)
1078+
: "r"(offset)
1079+
: "memory");
10631080
} else if constexpr (std::is_same<RegInfo,
10641081
register_info::cr::Cr2Info>::value) {
10651082
__asm__ volatile("btr %%cr2, %0" : : "r"(offset) :);

src/kernel/include/kernel.h

+4
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,8 @@ uint32_t main(uint32_t argc, uint8_t* argv);
4343

4444
uint32_t InterruptInit(uint32_t argc, uint8_t* argv);
4545

46+
uint32_t PhysicalMemoryInit(uint32_t argc, uint8_t* argv);
47+
48+
uint32_t VirtualMemoryInit(uint32_t argc, uint8_t* argv);
49+
4650
#endif /* SIMPLEKERNEL_SRC_KERNEL_INCLUDE_KERNEL_H_ */

0 commit comments

Comments
 (0)