FreeBSD 4.0 Kernel Hacking Guide--i386/i386/l

  •   2009-07-28/15:33

  • 这介绍 FreeBSD 的 kernel, 目前暂不包含 SMP 的部分. 我是以我个人的想法去记录下, 当我看到 code 时脑中的想法. 如果你有什麽建议, 能让你更容易看懂, 请 mail 给我. 谢谢! 
    i386/i386/locore.s 
       boot loader 将 kernel binary 读入 memory 後, kernel 的进入点. 
    i386/i386/machdep.c 
       和机器相关之 function. 
    i386/i386/pmap.c 
       physcial mapping module. 
    kern/init_main.c 
       执行 sub-system 的初始. 
    vm/vm_init.c 
       vm sub-system 初始. 
    vm/vm_page.c 
       vm_page module. 
    vm/vm_object.c 
       vm_object module. 

    -----------------------------------------------
    i386/i386/locore.s

    当 boot loader load kernel 之後, i386/i386/locore.s
    为 kernel 的进入点. 第一个被执行的 code 为 label btext 所标
    示的 assembly code.

    boot manager (bootstrap) 会从 stack 传入. 最主要的的参数是
    bootinfo, 开机时使用者所下的参数和 bios 资料. 248 行 call
    recover_bootinfo, recover_bootinfo 即从 stack 取得 bootinfo,
    即之存入变数 _bootinfo, 让以後的 C code 可以直接以 global
    变数(bootinfo)读使.

    256 行, 设立之一个新的 stack 供之後的 instruction 使用. stack
    之所以在此设立, 是因为我们必需先从旧的 stack 取得 bootinfo 的
    内容, 然後才可以设立新的 stack, 丢弃旧的 stack.

    258 行, call identify_cpu 以辨别 CPU 的型号. identify_cpu 会设
    定几个 global 变数.
    _cpu CPU 的种类, 为 32 bits 的整数, 所有的 constant
    都定义在 i386/include/cputypes.h, 45行-60行.
    相对应的文字和 CPU 分类, 定义在 i386/i386/identcpu.c
    , 89行, i386_cpus.
    _cpu_vendor CPU 造商.
    _cpu_id CPU 的 ID. 也许就是 Intel 所提的序号.
    _cpu_feature unknow ???

    303-309 行, 清除 bss.

    311 行, call create_pagetable. 设定进行入 protected mode 之後,
    enable paging 所需的 page table. create_pagetable 的说明请见
    後面的说明.

    316-336行, enable paging mechanical. 在此, IP register 的 value
    为 kernel 的 physical address, 因此会使用到 create_pagetable
    920-923行, 重 mapping 的 page table.

    347-348行, 以 ret 的方式跳到 begin 执行. 在执行完 ret 後, IP register
    将指到我们所期望的 KERNBASE virtual address.

    353-359行, 重新设立 stack 和 PCB.

    363行, call _init386, i386/i386/machdep.c, 1802行, function init386.
    传入 physfree, 尚未使用的 free memory. init386 设定各种
    cpu 会使用到的 table, 如 gdt, ldt, idt, tss. 并进行 proc0
    的资料设定. init386 所进行的工作为杂, 主要是进行初始化
    的动作, 以让机器(CPU+内部装置)可以顺利的在 protected mode 运作.
    详细动作, 请见专篇报导.

    377行, call _mi_startup, 执行 mi_startup 函数, kern/init_main.c, 171行.
    从此开始, 正式进入 kernel 的核心部分.


    create_pagetable: 744行,
    746-778行, 计算出 kernel 结束的位址, 并设立两个 global 变数,
    _KERNend kernel 的结束位址.
    physfree 尚未使用的记忆. 在初使阶段, physical
    address 的配置是从 kernel 之後的空间,
    依序配置. 在此设立此变数, 以记录目前
    可用空间的开始位置.
    781-814行, 为各种系统资料配置记忆空间.
    _KPTphys kernel 所使用的 page table. 共 NKPT 个
    page. (physical address)
    _IdlePTD page table directory. 有关 page table
    架构, 请参考 Intel 所出的 programming
    guide. (physical address)
    p0upa UPAGE (physical address)
    _proc0paddr (virtual address)
    vm86phystk
    _vm86pa
    _vm86paddr (virtual address)
    831-935行, 设定 page table. 将所有上面配置的空间和 kernel 所占之间空
    依 physical addr 顺序, map 到 virtual address 的 KERNBASE 位址.
    831-834行, 将 kernel 的 text section map 成为 read only page.
    837-851行, 将 kernel 的 data, bss 和symbols map 成为 read-write
    page.
    ..........
    920-923行, 将第一个 page table map 到 page directory 的第一个
    entry. 这一个 page table 将会"暂时"在 page directory
    map 两次. 主要是因为目前的指令实际执行的 address
    为 physical address, 当一开始 enable paging 时, 将会
    产生一个模糊地带, 使的我们 address 依然是以 physcial
    address 的值进行 map, 而不是我们所希望的 KERNBASE
    为其 base. 因此, 我们做此 map, 以便在 enable paging
    之後, 可以顺利的执行正确的 code.
    926-929行, 将 _KPTphys 安装在 page table directory(PDE) 正确的位置,
    使 kernel map 到 KERNBASE.
    932-935行, 将 PDE 安装在 PDE 上, 这是一个 recursive 的做法, 如
    此会使的 PDE 在第二层 mapping 时, 转而成为 page table,
    使的原本 PDE 所 mapping 的 page table 反而成为最後的
    destination memory. 我们可以直接透过 mapping 直接读每
    一个 page table.

    评论 {{userinfo.comments}}

    {{money}}

    {{question.question}}

    A {{question.A}}
    B {{question.B}}
    C {{question.C}}
    D {{question.D}}
    提交

    驱动号 更多