xv6

链接脚本

OUTPUT_ARCH( "riscv" )
ENTRY( _entry )

SECTIONS
{
/*
* ensure that entry.S / _entry is at 0x80000000,
* where qemu's -kernel jumps.
*/
. = 0x80000000;

.text : {
*(.text .text.*)
. = ALIGN(0x1000);
_trampoline = .;
*(trampsec)
. = ALIGN(0x1000); // trampoline不超过一页
ASSERT(. - _trampoline == 0x1000, "error: trampoline larger than one page");
PROVIDE(etext = .); // 可以在c中进行引用,text段的结尾
}

.rodata : {
. = ALIGN(16);
*(.srodata .srodata.*) /* do not need to distinguish this from .rodata */
. = ALIGN(16);
*(.rodata .rodata.*)
}

.data : {
. = ALIGN(16);
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
. = ALIGN(16);
*(.data .data.*)
}

.bss : {
. = ALIGN(16);
*(.sbss .sbss.*) /* do not need to distinguish this from .bss */
. = ALIGN(16);
*(.bss .bss.*)
}

PROVIDE(end = .);
}

设置内核页表

void
kvminithart() {
w_satp(MAKE_SATP(kernel_pagetable));
sfence_vma();
}
  • 内核告诉MMU来使用刚刚设置好的page table

  • 在这条指令之前,我们使用的都是物理内存地址,这条指令之后page table开始生效,所有的内存地址都变成了另一个含义,也就是虚拟内存地址

  • 内核设置了虚拟地址等于物理地址的映射关系

  • 每个proc结构体,里面有一个指向page table的指针,这对应了进程的根page table物理内存地址。

trapframe