Skip to content

Commit

Permalink
Merge pull request #190 from MRNIU/memory
Browse files Browse the repository at this point in the history
Memory
  • Loading branch information
MRNIU authored Sep 18, 2024
2 parents ec74b1b + 77d443e commit 24feb00
Show file tree
Hide file tree
Showing 22 changed files with 2,664 additions and 41 deletions.
53 changes: 17 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

# SimpleKernel

intr branch
memory branch

## 关键词

Expand Down Expand Up @@ -113,27 +113,15 @@ intr branch

- riscv64

1. 对 CSR 寄存器的抽象
2. 寄存器状态打印
3. 基于 Direct 的中断处理
4. 中断注册函数
5. 时钟中断

1.

- X86_64

1. cpu 抽象
2. 8259A pic 控制器抽象
3. 8253/8254 timer 控制器抽象
4. gdt 初始化
5. 中断处理流程
6. 中断注册函数
7. 时钟中断
1.

- TODO

riscv64 PLIC

x86_64 APIC


- 全局对象

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

- [x] [BUILD] 使用 CMake 的构建系统

- [x] [BUILD] 使用 gdb remote 调试

- [x] [BUILD] 第三方资源集成

- [x] [COMMON] C++ 全局对象的构造

- [x] [COMMON] C++ 静态局部对象构造

- [x] [COMMON] C 栈保护支持

- [x] [COMMON] printf 支持

- [x] [COMMON] 简单的 C++ 异常支持

- [x] [COMMON] 带颜色的字符串输出

- [x] [x86_64] 基于 gnuefi 的 bootloader

- [x] [x86_64] 基于 serial 的基本输出

- [x] [x86_64] 物理内存信息探测

- [x] [x86_64] 显示缓冲区探测

- [x] [x86_64] 调用栈回溯

- [x] [riscv64] gp 寄存器的初始化

- [x] [riscv64] 基于 opensbi 的基本输出

- [x] [riscv64] device tree 硬件信息解析

- [x] [riscv64] ns16550a 串口驱动

- [x] [riscv64] 调用栈回溯(仅打印地址)

- [ ] [aarch64] 基于 gnuefi 的 bootloader(调试中)
- [x] [riscv64] 对 CSR 寄存器的抽象
- [x] [riscv64] 寄存器状态打印
- [x] [riscv64] 基于 Direct 的中断处理
- [x] [riscv64] 中断注册函数
- [x] [riscv64] 时钟中断
- [x] [x86_64] cpu 抽象
- [x] [x86_64] 8259A pic 控制器抽象
- [x] [x86_64] 8253/8254 timer 控制器抽象
- [x] [x86_64] gdt 初始化
- [x] [x86_64] 中断处理流程
- [x] [x86_64] 中断注册函数
- [x] [x86_64] 时钟中断

## 使用的第三方资源

Expand Down
4 changes: 3 additions & 1 deletion src/kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ add_subdirectory(${PROJECT_SOURCE_DIR}/driver)

add_executable(${PROJECT_NAME}
main.cpp
physical_memory_manager.cpp
virtual_memory_manager.cpp
)

# 添加头文件
target_include_directories(kernel PRIVATE
include
../
)

# 添加要链接的库
Expand Down
8 changes: 8 additions & 0 deletions src/kernel/arch/aarch64/interrupt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
#include "kernel_log.hpp"
#include "sk_cstdio"

<<<<<<< HEAD
Interrupt::Interrupt() { log::Info("Interrupt init.\n"); }
=======
Interrupt::Interrupt() { klog::Info("Interrupt init.\n"); }
>>>>>>> new_intr

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

uint32_t InterruptInit(uint32_t, uint8_t *) {
<<<<<<< HEAD
log::Info("Hello InterruptInit\n");
=======
klog::Info("Hello InterruptInit\n");
>>>>>>> new_intr

return 0;
}
80 changes: 80 additions & 0 deletions src/kernel/arch/riscv64/include/cpu/cpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,84 @@
#include "sk_cstdio"
#include "sk_iostream"

namespace cpu {
namespace vmm {
enum {
VALID_OFFSET = 0,
READ_OFFSET = 1,
WRITE_OFFSET = 2,
EXEC_OFFSET = 3,
USER_OFFSET = 4,
GLOBAL_OFFSET = 5,
ACCESSED_OFFSET = 6,
DIRTY_OFFSET = 7,
VALID = 1 << VALID_OFFSET,
READ = 1 << READ_OFFSET,
WRITE = 1 << WRITE_OFFSET,
EXEC = 1 << EXEC_OFFSET,
USER = 1 << USER_OFFSET,
GLOBAL = 1 << GLOBAL_OFFSET,
ACCESSED = 1 << ACCESSED_OFFSET,
DIRTY = 1 << DIRTY_OFFSET,
};
/// 有效位
static constexpr const uint8_t VMM_PAGE_VALID = VALID;
/// 可读位
static constexpr const uint8_t VMM_PAGE_READABLE = READ;
/// 可写位s
static constexpr const uint8_t VMM_PAGE_WRITABLE = WRITE;
/// 可执行位
static constexpr const uint8_t VMM_PAGE_EXECUTABLE = EXEC;
/// 用户位
static constexpr const uint8_t VMM_PAGE_USER = USER;
/// 全局位,我们不会使用
static constexpr const uint8_t VMM_PAGE_GLOBAL = GLOBAL;
/// 已使用位,用于替换算法
static constexpr const uint8_t VMM_PAGE_ACCESSED = ACCESSED;
/// 已修改位,用于替换算法
static constexpr const uint8_t VMM_PAGE_DIRTY = DIRTY;
/// 内核虚拟地址相对物理地址的偏移
static constexpr const size_t KERNEL_OFFSET = 0x0;
/// PTE 属性位数
static constexpr const size_t VMM_PTE_PROP_BITS = 10;
/// PTE 页内偏移位数
static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
/// VPN 位数
static constexpr const size_t VMM_VPN_BITS = 9;
/// VPN 位数掩码,9 位 VPN
static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
/// riscv64 使用了三级页表
static constexpr const size_t VMM_PT_LEVEL = 3;

// 开启 PG
inline void EnablePage() {
kAllCsr.satp.asid.Write(0);
kAllCsr.satp.mode.Write(register_info::csr::SatpInfo::kSv39);
}
inline void DisablePage() {
kAllCsr.satp.mode.Write(register_info::csr::SatpInfo::kBare);
}

/**
* @brief 设置 页目录
* @param _pgd 要设置的页表
* @return true 成功
* @return false 失败
*/
inline void SetPageDirectory(uint64_t pgd) { kAllCsr.satp.ppn.Write(pgd); }

/**
* @brief 获取页目录
* @return uint64_t 页目录值
*/
inline uint64_t GetPageDirectory() { return kAllCsr.satp.ppn.Get(); }

inline void FlushPage(uint64_t addr) {
(void)addr;
__asm__ volatile("sfence.vma zero, zero");
}

} // namespace vmm
} // namespace cpu

#endif // SIMPLEKERNEL_SRC_KERNEL_ARCH_RISCV64_INCLUDE_CPU_CPU_HPP_
31 changes: 31 additions & 0 deletions src/kernel/arch/riscv64/include/cpu/regs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,37 @@
*/
namespace cpu {

// namespace vmm_info {
// /// 有效位
// static constexpr const uint8_t VMM_PAGE_VALID = CPU::pte_t::VALID;
// /// 可读位
// static constexpr const uint8_t VMM_PAGE_READABLE = CPU::pte_t::READ;
// /// 可写位s
// static constexpr const uint8_t VMM_PAGE_WRITABLE = CPU::pte_t::WRITE;
// /// 可执行位
// static constexpr const uint8_t VMM_PAGE_EXECUTABLE = CPU::pte_t::EXEC;
// /// 用户位
// static constexpr const uint8_t VMM_PAGE_USER = CPU::pte_t::USER;
// /// 全局位,我们不会使用
// static constexpr const uint8_t VMM_PAGE_GLOBAL = CPU::pte_t::GLOBAL;
// /// 已使用位,用于替换算法
// static constexpr const uint8_t VMM_PAGE_ACCESSED = CPU::pte_t::ACCESSED;
// /// 已修改位,用于替换算法
// static constexpr const uint8_t VMM_PAGE_DIRTY = CPU::pte_t::DIRTY;
// /// 内核虚拟地址相对物理地址的偏移
// static constexpr const size_t KERNEL_OFFSET = 0x0;
// /// PTE 属性位数
// static constexpr const size_t VMM_PTE_PROP_BITS = 10;
// /// PTE 页内偏移位数
// static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
// /// VPN 位数
// static constexpr const size_t VMM_VPN_BITS = 9;
// /// VPN 位数掩码,9 位 VPN
// static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
// /// riscv64 使用了三级页表
// static constexpr const size_t VMM_PT_LEVEL = 3;
// }; // namespace vmm_info

// 第一部分:寄存器定义
namespace register_info {

Expand Down
47 changes: 47 additions & 0 deletions src/kernel/arch/x86_64/include/cpu/cpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,53 @@ struct InterruptContextErrorCode {
}
};

namespace vmm {
/// P = 1 表示有效; P = 0 表示无效。
static constexpr const uint8_t VMM_PAGE_VALID = 1 << 0;
/// 如果为 0 表示页面只读或可执行。
static constexpr const uint8_t VMM_PAGE_READABLE = 0;
static constexpr const uint8_t VMM_PAGE_WRITABLE = 1 << 1;
static constexpr const uint8_t VMM_PAGE_EXECUTABLE = 0;
/// U/S-- 位 2 是用户 / 超级用户 (User/Supervisor) 标志。
/// 如果为 1 那么运行在任何特权级上的程序都可以访问该页面。
static constexpr const uint8_t VMM_PAGE_USER = 1 << 2;
/// 内核虚拟地址相对物理地址的偏移
static constexpr const size_t KERNEL_OFFSET = 0x0;
/// PTE 属性位数
static constexpr const size_t VMM_PTE_PROP_BITS = 12;
/// PTE 页内偏移位数
static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
/// VPN 位数
static constexpr const size_t VMM_VPN_BITS = 9;
/// VPN 位数掩码,9 位 VPN
static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
/// x86_64 使用了四级页表
static constexpr const size_t VMM_PT_LEVEL = 4;

// 开启 PG
inline void EnablePage() { kAllCr.cr0.pg.Set(); }
inline void DisablePage() { kAllCr.cr0.pg.Clear(); }

/**
* @brief 设置 页目录
* @param _pgd 要设置的页表
* @return true 成功
* @return false 失败
*/
inline void SetPageDirectory(uint64_t pgd) { kAllCr.cr3.Write(pgd); }

/**
* @brief 获取页目录 CR3
* @return uint64_t CR3 值
*/
inline uint64_t GetPageDirectory() { return kAllCr.cr3.Read(); }

inline void FlushPage(uint64_t addr) {
__asm__ volatile("invlpg (%0)" : : "r"(addr) : "memory");
}

}; // namespace vmm

}; // namespace cpu

#endif // SIMPLEKERNEL_SRC_KERNEL_ARCH_X86_64_INCLUDE_CPU_CPU_HPP_
21 changes: 19 additions & 2 deletions src/kernel/arch/x86_64/include/cpu/regs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,15 @@ class WriteOnlyRegBase {
klog::Err("TODO\n");
} else if constexpr (std::is_same<RegInfo,
register_info::cr::Cr0Info>::value) {
__asm__ volatile("bts %%cr0, %0" : : "r"(offset) :);
// __asm__ volatile("bts %%cr0, %0" : : "r"(offset) :);
uint64_t value;
__asm__ volatile(
"mov %%cr0, %0\n\t"
"bts %1, %0\n\t"
"mov %0, %%cr0"
: "=r"(value)
: "r"(offset)
: "memory");
} else if constexpr (std::is_same<RegInfo,
register_info::cr::Cr2Info>::value) {
__asm__ volatile("bts %%cr2, %0" : : "r"(offset) :);
Expand Down Expand Up @@ -1059,7 +1067,16 @@ class WriteOnlyRegBase {
klog::Err("TODO\n");
} else if constexpr (std::is_same<RegInfo,
register_info::cr::Cr0Info>::value) {
__asm__ volatile("btr %%cr0, %0" : : "r"(offset) :);
// __asm__ volatile("btr %%cr0, %0" : : "r"(offset) :);
// __asm__ volatile("bts %%cr0, %0" : : "r"(offset) :);
uint64_t value;
__asm__ volatile(
"mov %%cr0, %0\n\t"
"btr %1, %0\n\t"
"mov %0, %%cr0"
: "=r"(value)
: "r"(offset)
: "memory");
} else if constexpr (std::is_same<RegInfo,
register_info::cr::Cr2Info>::value) {
__asm__ volatile("btr %%cr2, %0" : : "r"(offset) :);
Expand Down
4 changes: 4 additions & 0 deletions src/kernel/include/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ uint32_t main(uint32_t argc, uint8_t* argv);

uint32_t InterruptInit(uint32_t argc, uint8_t* argv);

uint32_t PhysicalMemoryInit(uint32_t argc, uint8_t* argv);

uint32_t VirtualMemoryInit(uint32_t argc, uint8_t* argv);

#endif /* SIMPLEKERNEL_SRC_KERNEL_INCLUDE_KERNEL_H_ */
Loading

0 comments on commit 24feb00

Please sign in to comment.