Skip to content

Latest commit

 

History

History
173 lines (129 loc) · 3.46 KB

物理内存管理.md

File metadata and controls

173 lines (129 loc) · 3.46 KB

一、 初始化物理内存管理

核心是进行 gdt 的初始化。

void
pmm_init(void) {
    gdt_init();
}

TSS (task segment selector):任务段选择子。

1.1 设置 TSS

设置 1 个 TSS,这样从用户态切换到内核态时可以获取正确的堆栈。

ts.ts_esp0 = (uint32_t)&stack0 + sizeof(stack0);

这里的 stack0 是 1 个临时的内核堆栈。

uint8_t stack0[1024];

查看一下其具体的数值如下。

(gdb) p &stack0
$2 = (uint8_t (*)[1024]) 0x10f980 <stack0>

即,将 ts_esp0 的值设为 stack0 数组的尾部。

ts.ts_ss0 = KERNEL_DS;

ts_ss0 设为内核的数据段。

设置好之后的数据如下。

ts_esp0 = 1113472, 
ts_ss0 = 16, 
  • ts_esp0:栈指针和段选择子;
  • ts_ss0:在特权级中会有 1 个增量。

1.2 初始化 GDT 中的 TSS

gdt[SEG_TSS] = SEG16(STS_T32A, (uint32_t)&ts, sizeof(ts), DPL_KERNEL);
gdt[SEG_TSS].sd_s = 0;

运行结果如下。

(gdb) p gdt[5]
$5 = {
    sd_lim_15_0 = 104, 
    sd_base_15_0 = 63648, 
    sd_base_23_16 = 16, 
    sd_type = 9, 
    sd_s = 0, 
    sd_dpl = 0, 
    sd_p = 1, 
    sd_lim_19_16 = 0, 
    sd_avl = 0, 
    sd_rsv1 = 0, 
    sd_db = 1, 
    sd_g = 0, 
    sd_base_31_24 = 0
}

1.3 加载全局描述符表并复位内核的数据、代码段寄存器的数值

// reload all segment registers
lgdt(&gdt_pd);

即使用内联汇编来加载全局描述符表,并复位内核的数据、代码段寄存器的数值。

/* *
 * lgdt - load the global descriptor table register and reset the
 * data/code segement registers for kernel.
 * */
static inline void
lgdt(struct pseudodesc *pd) {
    asm volatile ("lgdt (%0)" :: "r" (pd));
    asm volatile ("movw %%ax, %%gs" :: "a" (USER_DS));
    asm volatile ("movw %%ax, %%fs" :: "a" (USER_DS));
    asm volatile ("movw %%ax, %%es" :: "a" (KERNEL_DS));
    asm volatile ("movw %%ax, %%ds" :: "a" (KERNEL_DS));
    asm volatile ("movw %%ax, %%ss" :: "a" (KERNEL_DS));
    // reload cs
    asm volatile ("ljmp %0, $1f\n 1:\n" :: "i" (KERNEL_CS));
}

反汇编的代码如下。

(gdb) b kern/mm/pmm.c:63
Breakpoint 3 at 0x10290a: file kern/mm/pmm.c, line 63.
(gdb) c
Continuing.
Breakpoint 3, lgdt (pd=0x10ea10 <gdt_pd>) at kern/mm/pmm.c:63
63	    asm volatile ("movw %%ax, %%fs" :: "a" (USER_DS));
(gdb) disassemble lgdt
Dump of assembler code for function lgdt:
   0x001028fa <+ 0>:	push   %bp
   0x001028fb <+ 1>:	mov    %sp,%bp
   0x001028fd <+ 3>:	mov    0x8(%di),%ax
   0x00102900 <+ 6>:	lgdtw  (%bx,%si)
   0x00102903 <+ 9>:	mov    $0x23,%ax
   0x00102906 <+12>:	add    %al,(%bx,%si)
   0x00102908 <+14>:	mov    %ax,%gs
=> 0x0010290a <+16>:	mov    $0x23,%ax
   0x0010290d <+19>:	add    %al,(%bx,%si)
   0x0010290f <+21>:	mov    %ax,%fs
   0x00102911 <+23>:	mov    $0x10,%ax
   0x00102914 <+26>:	add    %al,(%bx,%si)
   0x00102916 <+28>:	mov    %ax,%es
   0x00102918 <+30>:	mov    $0x10,%ax
   0x0010291b <+33>:	add    %al,(%bx,%si)
   0x0010291d <+35>:	mov    %ax,%ds
   0x0010291f <+37>:	mov    $0x10,%ax
   0x00102922 <+40>:	add    %al,(%bx,%si)
   0x00102924 <+42>:	mov    %ax,%ss
   0x00102926 <+44>:	ljmp   $0x10,$0x292d
   0x0010292b <+49>:	or     %al,(%bx,%si)
   0x0010292d <+51>:	pop    %bp
   0x0010292e <+52>:	ret    
End of assembler dump.

1.4 加载 TSS

// load the TSS
ltr(GD_TSS);

ltr 的实现如下。

static inline void
ltr(uint16_t sel) {
    asm volatile ("ltr %0" :: "r" (sel));
}