kernel space 目前完成

ch4
zhangxinyu 2 years ago
parent bb03c2e3e2
commit 8f8b06e3bf

@ -10,6 +10,18 @@ pub const USER_STACK_SIZE: usize = 4096 * 2; // 每个应用用户态的栈大
pub const KERNEL_STACK_SIZE: usize = 4096 * 2; // 每个应用的内核栈
pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1; // __alltraps对齐到了这里, (内核空间和用户空间这里虚拟地址都用这个)虚拟地址最高页 存放跳板, 跳板那一页, 被映射到 strampoline段(trap) 实际的物理地址, 即陷入时 cpu需要跳转的地址
pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE; // 用户 trap context开始的位置 在次高页
pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE; // 用户 trap context开始的位置 在 每个用户程序 它本身地址空间 的次高页
pub use crate::board::*;
pub use crate::board::*;
/// 得到 "用户程序的内核栈" 的在 内核本身栈中的虚拟位置
/// 这个在 次高页的下面的某个位置
/// 每个用户除了分配 KERNEL_STACK_SIZE 大小外, 还额外 增加 一个PAGE_SIZE 放在比栈底要高的地址 用来隔离每个用户内核栈
pub fn kernel_stack_position(app_id: usize) -> (usize, usize) {
let top = TRAMPOLINE - app_id * (KERNEL_STACK_SIZE + PAGE_SIZE);
// 栈底只需要 KERNEL_STACK_SIZE 即可,
let bottom = top - KERNEL_STACK_SIZE;
(bottom, top)
}

@ -10,6 +10,10 @@ SECTIONS
stext = .; /* .text段的开始位置 */
.text : { /* 表示生成一个为 .text的段, 花括号内按照防止顺序表示将输入文件中的哪些段放在 当前.text段中 */
*(.text.entry) /* entry.asm中, 我们自己定义的.text.entry段, 被放在顶部*/
. = ALIGN(4K); /*4k对齐*/
strampoline = .;
/* strampoline 段, 将来会被 memory set 导入, 当做跳板最高页vpn的实际物理帧 ppn*/
*(.text.trampoline);
*(.text .text.*)
}
@ -31,6 +35,7 @@ SECTIONS
. = ALIGN(4K);
edata = .;
sbss_with_stack = .;
.bss : {
*(.bss.stack) /* 全局符号 sbss 和 ebss 分别指向 .bss 段除 .bss.stack 以外的起始和终止地址(.bss.stack是我们在entry.asm中定义的栈) */
sbss = .;

@ -1,6 +1,11 @@
use alloc::collections::BTreeMap;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::arch::asm;
use bitflags::bitflags;
use lazy_static::lazy_static;
use riscv::register::satp;
use crate::sync::UPSafeCell;
use crate::config::{MEMORY_END, PAGE_SIZE, TRAMPOLINE};
use crate::mm::address::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum, VPNRange};
use crate::mm::frame_allocator::{frame_alloc, FrameTracker};
@ -20,6 +25,11 @@ extern "C" {
fn ekernel();
fn strampoline(); // 这个符号 在linker.ld 中定义
}
lazy_static! {
/// a memory set instance through lazy_static! managing kernel space
pub static ref KERNEL_SPACE: Arc<UPSafeCell<MemorySet>> =
Arc::new(unsafe { UPSafeCell::new(MemorySet::new_kernel()) });
}
// 某逻辑段的映射方式
#[derive(Copy, Clone, PartialEq, Debug)]
@ -164,6 +174,21 @@ impl MemorySet {
self.page_table.token()
}
// 激活当前地址空间
pub fn activate(&self) {
// let satp = self.page_table.token();
// 得到当前地址空间的 页表 的规定格式
let satp = self.token();;
unsafe {
// 设置satp CSR寄存器为我们
satp::write(satp);
// 刷新快表缓存TLB, 这个指令最简单的作用就是清空旧的快表
// 更深层次其实是一个内存屏障
asm!("sfence.vma");
}
}
// 根据 start va 和end va 创建一个 逻辑段类型为逻辑映射, 插入到 当前地址空间
pub fn insert_framed_area(&mut self, start_va: VirtAddr, end_va: VirtAddr, permission: MapPermission) {
self.push(MapArea::from(start_va, end_va, MapType::Framed, permission), None);

@ -1,3 +1,5 @@
use crate::mm::memory_set::KERNEL_SPACE;
pub mod heap_allocator;
pub mod address;
pub mod frame_allocator;
@ -9,6 +11,8 @@ pub mod memory_set;
pub fn init(){
// 开启 内核的内存分配器
heap_allocator::init_heap();
// 初始化bin测试 物理页帧管理器
// 初始化测试 物理页帧管理器
frame_allocator::frame_allocator_test();
// 激活内核的地址空间
KERNEL_SPACE.exclusive_access().activate();
}
Loading…
Cancel
Save