[OS64位][017]源码阅读:程序4-1 内核执行头程序head.S->内核主程序 main.c

学习笔记

使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171

源码结构

  • 配书代码包:第4章\程序\程序4-1
[OS64位][017]源码阅读:程序4-1 内核执行头程序head.S->内核主程序 main.c_第1张图片
程序4-1 源码结构

命令行操作

[anno@localhost bootloader]$ make
nasm boot.asm -o boot.bin
nasm loader.asm -o loader.bin

[anno@localhost kernel]$ make
gcc -E  head.S > head.s
as --64 -o head.o head.s
gcc  -mcmodel=large -fno-builtin -m64 -c main.c
ld -b elf64-x86-64 -o system head.o main.o -T Kernel.lds 
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary system kernel.bin


[anno@localhost 4-1]$ sudo mount boot.img media -t vfat -o loop
[anno@localhost 4-1]$ sudo cp bootloader/loader.bin media
[anno@localhost 4-1]$ sync
[anno@localhost 4-1]$ sudo cp bootloader/boot.bin media
[anno@localhost 4-1]$ sync
[anno@localhost 4-1]$ sudo cp kernel/kernel.bin media
[anno@localhost 4-1]$ sync

[anno@localhost 4-1]$  bochs -f ./bochsrc

调试过程

[OS64位][017]源码阅读:程序4-1 内核执行头程序head.S->内核主程序 main.c_第2张图片
内存示意图

[OS64位][017]源码阅读:程序4-1 内核执行头程序head.S->内核主程序 main.c_第3张图片
死循环 rip 停住不变

源码阅读

内核执行头程序 head.S

  • 内核执行头程序head.S: 设置寄存器、GDTR、IDTR、CR3,跳转到内核主程序;

线性地址 与 物理地址

  • 内核层的起始线性地址0x ffff 8000 0000 0000对应着物理地址0
  • 内核程序的起始线性地址位于0x ffff 8000 0000 0000 + 0x 10 0000

设置 四级页表 PML4 - PDPT - PDT - PT

//=======   init page
.align 8

.org    0x1000

__PML4E:

    .quad   0x102007
    .fill   255,8,0
    .quad   0x102007
    .fill   255,8,0

.org    0x2000

__PDPTE:
    
    .quad   0x103003
    .fill   511,8,0

.org    0x3000

__PDE:

    .quad   0x000083    
    .quad   0x200083
    .quad   0x400083
    .quad   0x600083
    .quad   0x800083
    .quad   0xe0000083      /*0x a00000*/
    .quad   0xe0200083
    .quad   0xe0400083
    .quad   0xe0600083      /*0x1000000*/
    .quad   0xe0800083
    .quad   0xe0a00083
    .quad   0xe0c00083
    .quad   0xe0e00083
    .fill   499,8,0
  • 使用2MB大小的物理页,页表结构参考Linear-Address Translation to a 2-MByte Page using 4-Level Paging

设置CR3

//=======   load    cr3

    movq    $0x101000,  %rax
    movq    %rax,       %cr3
    movq    switch_seg(%rip),   %rax
    pushq   $0x08
    pushq   %rax
    lretq
  • CR3寄存器 存放 PML4物理基地址 0x101000

GDT

//=======   GDT_Table

.section .data

.globl GDT_Table

GDT_Table:
    .quad   0x0000000000000000          /*0 NULL descriptor             00*/
    .quad   0x0020980000000000          /*1 KERNEL  Code    64-bit  Segment 08*/
    .quad   0x0000920000000000          /*2 KERNEL  Data    64-bit  Segment 10*/
    .quad   0x0020f80000000000          /*3 USER    Code    64-bit  Segment 18*/
    .quad   0x0000f20000000000          /*4 USER    Data    64-bit  Segment 20*/
    .quad   0x00cf9a000000ffff          /*5 KERNEL  Code    32-bit  Segment 28*/
    .quad   0x00cf92000000ffff          /*6 KERNEL  Data    32-bit  Segment 30*/
    .fill   10,8,0                  /*8 ~ 9 TSS (jmp one segment <7>) in long-mode 128-bit 40*/
GDT_END:

GDT_POINTER:
GDT_LIMIT:  .word   GDT_END - GDT_Table - 1
GDT_BASE:   .quad   GDT_Table

.quad 0x0020980000000000 /*1 KERNEL Code 64-bit Segment 08*/
这一串是代码段描述符 单个描述符长度是八字节
位于第二项即内核代码段选择子 0x08

跳转到内核主程序

//=======   64-bit mode code

switch_seg:
    .quad   entry64

entry64:
    movq    $0x10,  %rax
    movq    %rax,   %ds
    movq    %rax,   %es
    movq    %rax,   %gs
    movq    %rax,   %ss
    movq    $0xffff800000007E00,    %rsp        /* rsp address */

    movq    go_to_kernel(%rip), %rax        /* movq address */
    pushq   $0x08
    pushq   %rax
    lretq

go_to_kernel:
    .quad   Start_Kernel

movq go_to_kernel(%rip), %rax
Rip relative addressing RIP相对寻址

pushq $0x08 pushq %rax lretq
相当于 jmp 0x08 : rax
0x08内核代码段选择子

内核主程序 main.c

  • 内核主程序main.c:目前只有一个死循环,目前只是提供一个内核主程序的入口;
void Start_Kernel(void)
{
    while(1)
        ;
}

参考资料

  • 四级页表结构

Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4
Volume 3 / CHAPTER 4 PAGING / 4.5 4-LEVEL PAGING
https://software.intel.com/en-us/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4

[OS64位][017]源码阅读:程序4-1 内核执行头程序head.S->内核主程序 main.c_第4张图片
Figure 4-9. Linear-Address Translation to a 2-MByte Page using 4-Level Paging

  • Rip relative addressing

从机器码理解RIP 相对寻址https://www.cnblogs.com/papertree/p/6298763.html

你可能感兴趣的:([OS64位][017]源码阅读:程序4-1 内核执行头程序head.S->内核主程序 main.c)