高地址
+--------------------------------------------------+ 0xFFFFFFFF_FFFFFFFF
|                                                  |
|                  高位内存区域                      |
|                                                  |
+--------------------------------------------------+ 0xFFFFFFFF_FFFFF000 (usize::MAX - PAGE_SIZE + 1)                       |
|                跳板代码 (Trampoline Code)         |          
|                                                  |
+--------------------------------------------------+ 0xFFFFFFFF_FFFFF000 (TRAMPOLINE - PAGE_SIZE)
|               陷阱上下文 (Trap Context)            |
|                                                  |
+--------------------------------------------------+ 0xFFFFFFFF_FFFF8000
|                  应用 1 的内核栈 (8KB)            |
|               底部 = 0xFFFFFFFF_FFFF6000          |
|               顶部 = 0xFFFFFFFF_FFFF8000          |
+--------------------------------------------------+ 0xFFFFFFFF_FFFF6000
|                    守卫页 (4KB)                   |
+--------------------------------------------------+ 0xFFFFFFFF_FFFF5000
|                  应用 2 的内核栈 (8KB)            |
|               底部 = 0xFFFFFFFF_FFFF3000          |
|               顶部 = 0xFFFFFFFF_FFFF5000          |
+--------------------------------------------------+ 0xFFFFFFFF_FFFF3000
|                    守卫页 (4KB)                   |
+--------------------------------------------------+ 0xFFFFFFFF_FFFF2000
低地址

上面只是一个示意图,下面用代码描述一下

  1. 全局的初始化

    pub fn init() {
     //全局的堆空间管理, 利用一个伙伴系统,稍后我会分析一下源码
     heap_allocator::init_heap();
     //配置可利用总的空间,根据自己的硬件情况来配置
     frame_allocator::init_frame_allocator();
     //会先调用KERNEL_SPACE初始化,然后在, 设置satp 开启内存的分页
     KERNEL_SPACE.exclusive_access().activate();
    }

    KERNEL_SPACE初始化,主要是各个段的映射, 恒等映射的方式

    pub fn new_kernel() -> Self {
         let mut memory_set = Self::new_bare();
         memory_set.map_trampoline();
         memory_set.push(
             MapArea::new(
                 (stext as usize).into(),
                 (etext as usize).into(),
                 MapType::Identical,
                 MapPermission::R | MapPermission::X,
             ),
             None,
         );
         memory_set.push(
             MapArea::new(
                 (srodata as usize).into(),
                 (erodata as usize).into(),
                 MapType::Identical,
                 MapPermission::R,
             ),
             None,
         );
         memory_set.push(
             MapArea::new(
                 (sdata as usize).into(),
                 (edata as usize).into(),
                 MapType::Identical,
                 MapPermission::R | MapPermission::W,
             ),
             None,
         );
         memory_set.push(
             MapArea::new(
                 (sbss_with_stack as usize).into(),
                 (ebss as usize).into(),
                 MapType::Identical,
                 MapPermission::R | MapPermission::W,
             ),
             None,
         );
         memory_set.push(
             MapArea::new(
                 (ekernel as usize).into(),
                 MEMORY_END.into(),
                 MapType::Identical,
                 MapPermission::R | MapPermission::W,
             ),
             None,
         );
         println!("mapping memory-mapped registers");
         for pair in MMIO {
             memory_set.push(
                 MapArea::new(
                     (*pair).0.into(),
                     ((*pair).0 + (*pair).1).into(),
                     MapType::Identical,
                     MapPermission::R | MapPermission::W,
                 ),
                 None,
             );
         }
         memory_set
     }

    map_trampoline 映射稍微有些特殊:

    fn map_trampoline(&mut self) {
         self.page_table.map(
             VirtAddr::from(TRAMPOLINE).into(),
             PhysAddr::from(strampoline as usize).into(),
             PTEFlags::R | PTEFlags::X,
         );
     }

    TRAMPOLINE:一个虚拟地址

    pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1;
    pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE;

    strampoline 是内核结束之后的一个物理地址

     stext = .;
     .text : {
         *(.text.entry)
         . = ALIGN(4K);
         strampoline = .;
         *(.text.trampoline);
         . = ALIGN(4K);
         *(.text .text.*)
     }

putao
8 声望1 粉丝

推动世界向前发展,改善民生。