head.S 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. // 这是内核执行头程序
  2. // Created by longjin.
  3. // 2022/01/20
  4. #include "common/asm.h"
  5. // 以下是来自 multiboot2 规范的定义
  6. // How many bytes from the start of the file we search for the header.
  7. #define MULTIBOOT_SEARCH 32768
  8. #define MULTIBOOT_HEADER_ALIGN 8
  9. // The magic field should contain this.
  10. #define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
  11. // This should be in %eax.
  12. #define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
  13. // Alignment of multiboot modules.
  14. #define MULTIBOOT_MOD_ALIGN 0x00001000
  15. // Alignment of the multiboot info structure.
  16. #define MULTIBOOT_INFO_ALIGN 0x00000008
  17. // Flags set in the 'flags' member of the multiboot header.
  18. #define MULTIBOOT_TAG_ALIGN 8
  19. #define MULTIBOOT_TAG_TYPE_END 0
  20. #define MULTIBOOT_TAG_TYPE_CMDLINE 1
  21. #define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
  22. #define MULTIBOOT_TAG_TYPE_MODULE 3
  23. #define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
  24. #define MULTIBOOT_TAG_TYPE_BOOTDEV 5
  25. #define MULTIBOOT_TAG_TYPE_MMAP 6
  26. #define MULTIBOOT_TAG_TYPE_VBE 7
  27. #define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
  28. #define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
  29. #define MULTIBOOT_TAG_TYPE_APM 10
  30. #define MULTIBOOT_TAG_TYPE_EFI32 11
  31. #define MULTIBOOT_TAG_TYPE_EFI64 12
  32. #define MULTIBOOT_TAG_TYPE_SMBIOS 13
  33. #define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
  34. #define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
  35. #define MULTIBOOT_TAG_TYPE_NETWORK 16
  36. #define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
  37. #define MULTIBOOT_TAG_TYPE_EFI_BS 18
  38. #define MULTIBOOT_TAG_TYPE_EFI32_IH 19
  39. #define MULTIBOOT_TAG_TYPE_EFI64_IH 20
  40. #define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
  41. #define MULTIBOOT_HEADER_TAG_END 0
  42. #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
  43. #define MULTIBOOT_HEADER_TAG_ADDRESS 2
  44. #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
  45. #define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
  46. #define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
  47. #define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
  48. #define MULTIBOOT_HEADER_TAG_EFI_BS 7
  49. #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
  50. #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
  51. #define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
  52. #define MULTIBOOT_ARCHITECTURE_I386 0
  53. #define MULTIBOOT_ARCHITECTURE_MIPS32 4
  54. #define MULTIBOOT_HEADER_TAG_OPTIONAL 1
  55. #define MULTIBOOT_LOAD_PREFERENCE_NONE 0
  56. #define MULTIBOOT_LOAD_PREFERENCE_LOW 1
  57. #define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
  58. #define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
  59. #define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
  60. // 以下是来自 multiboot2 规范的定义
  61. // How many bytes from the start of the file we search for the header.
  62. #define MULTIBOOT_SEARCH 32768
  63. #define MULTIBOOT_HEADER_ALIGN 8
  64. // The magic field should contain this.
  65. #define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
  66. // This should be in %eax.
  67. #define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
  68. // Alignment of multiboot modules.
  69. #define MULTIBOOT_MOD_ALIGN 0x00001000
  70. // Alignment of the multiboot info structure.
  71. #define MULTIBOOT_INFO_ALIGN 0x00000008
  72. // Flags set in the 'flags' member of the multiboot header.
  73. #define MULTIBOOT_TAG_ALIGN 8
  74. #define MULTIBOOT_TAG_TYPE_END 0
  75. #define MULTIBOOT_TAG_TYPE_CMDLINE 1
  76. #define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
  77. #define MULTIBOOT_TAG_TYPE_MODULE 3
  78. #define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
  79. #define MULTIBOOT_TAG_TYPE_BOOTDEV 5
  80. #define MULTIBOOT_TAG_TYPE_MMAP 6
  81. #define MULTIBOOT_TAG_TYPE_VBE 7
  82. #define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
  83. #define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
  84. #define MULTIBOOT_TAG_TYPE_APM 10
  85. #define MULTIBOOT_TAG_TYPE_EFI32 11
  86. #define MULTIBOOT_TAG_TYPE_EFI64 12
  87. #define MULTIBOOT_TAG_TYPE_SMBIOS 13
  88. #define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
  89. #define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
  90. #define MULTIBOOT_TAG_TYPE_NETWORK 16
  91. #define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
  92. #define MULTIBOOT_TAG_TYPE_EFI_BS 18
  93. #define MULTIBOOT_TAG_TYPE_EFI32_IH 19
  94. #define MULTIBOOT_TAG_TYPE_EFI64_IH 20
  95. #define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
  96. #define MULTIBOOT_HEADER_TAG_END 0
  97. #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
  98. #define MULTIBOOT_HEADER_TAG_ADDRESS 2
  99. #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
  100. #define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
  101. #define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
  102. #define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
  103. #define MULTIBOOT_HEADER_TAG_EFI_BS 7
  104. #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
  105. #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
  106. #define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
  107. #define MULTIBOOT_ARCHITECTURE_I386 0
  108. #define MULTIBOOT_ARCHITECTURE_MIPS32 4
  109. #define MULTIBOOT_HEADER_TAG_OPTIONAL 1
  110. #define MULTIBOOT_LOAD_PREFERENCE_NONE 0
  111. #define MULTIBOOT_LOAD_PREFERENCE_LOW 1
  112. #define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
  113. #define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
  114. #define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
  115. // 直接用 -m64 编译出来的是 64 位代码,
  116. // 但是启动后的机器是 32 位的,相当于在 32 位机器上跑 64 位程序。
  117. // 得加一层跳转到 64 位的 -m32 代码,开启 long 模式后再跳转到以 -m64 编译的代码中
  118. // 对于 x86_64,需要在启动阶段进入长模式(IA32E),这意味着需要一个临时页表
  119. // See https://wiki.osdev.org/Creating_a_64-bit_kernel:
  120. // With a 32-bit bootstrap in your kernel
  121. // 这部分是从保护模式启动 long 模式的代码
  122. // 工作在 32bit
  123. // 声明这一段代码以 32 位模式编译
  124. .code32
  125. // multiboot2 文件头
  126. // 计算头长度
  127. .SET HEADER_LENGTH, multiboot_header_end - multiboot_header
  128. // 计算校验和
  129. .SET CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADER_LENGTH)
  130. // 8 字节对齐
  131. .section .multiboot_header
  132. .align MULTIBOOT_HEADER_ALIGN
  133. // 声明所属段
  134. multiboot_header:
  135. // 魔数
  136. .long MULTIBOOT2_HEADER_MAGIC
  137. // 架构
  138. .long MULTIBOOT_ARCHITECTURE_I386
  139. // 头长度
  140. .long HEADER_LENGTH
  141. // 校验和
  142. .long CHECKSUM
  143. // 添加其它内容在此,详细信息见 Multiboot2 Specification version 2.0.pdf
  144. // 设置帧缓冲区
  145. .align 8
  146. framebuffer_tag_start:
  147. .short MULTIBOOT_HEADER_TAG_FRAMEBUFFER
  148. .short MULTIBOOT_HEADER_TAG_OPTIONAL
  149. .long framebuffer_tag_end - framebuffer_tag_start
  150. .long 1440
  151. .long 900
  152. .long 32
  153. framebuffer_tag_end:
  154. .align 8
  155. .short MULTIBOOT_HEADER_TAG_END
  156. // 结束标记
  157. .short 0
  158. .long 8
  159. multiboot_header_end:
  160. .section .bootstrap
  161. .global _start
  162. .type _start, @function
  163. # 在 multiboot2.cpp 中定义
  164. .extern _start64
  165. .extern boot_info_addr
  166. .extern multiboot2_magic
  167. ENTRY(_start)
  168. // 关中断
  169. cli
  170. // multiboot2_info 结构体指针
  171. mov %ebx, mb2_info
  172. //mov %ebx, %e8
  173. // 魔数
  174. mov %eax, mb2_magic
  175. //mov %eax, %e9
  176. / 从保护模式跳转到长模式
  177. // 1. 允许 PAE
  178. mov %cr4, %eax
  179. or $(1<<5), %eax
  180. mov %eax, %cr4
  181. // 2. 设置临时页表
  182. // 最高级
  183. mov $pml4, %eax
  184. mov $pdpt, %ebx
  185. or $0x3, %ebx
  186. mov %ebx, 0(%eax)
  187. // 次级
  188. mov $pdpt, %eax
  189. mov $pd, %ebx
  190. or $0x3, %ebx
  191. mov %ebx, 0(%eax)
  192. // 次低级
  193. mov $pd, %eax
  194. mov $pt, %ebx
  195. or $0x3, %ebx
  196. mov %ebx, 0(%eax)
  197. // 最低级
  198. // 循环 512 次,填满一页
  199. mov $512, %ecx
  200. mov $pt, %eax
  201. mov $0x3, %ebx
  202. .fill_pt:
  203. mov %ebx, 0(%eax)
  204. add $0x1000, %ebx
  205. add $8, %eax
  206. loop .fill_pt
  207. .global enter_head_from_ap_boot
  208. enter_head_from_ap_boot:
  209. // 填写 CR3
  210. mov $pml4, %eax
  211. mov %eax, %cr3
  212. // 3. 切换到 long 模式
  213. mov $0xC0000080, %ecx
  214. rdmsr
  215. or $(1<<8), %eax
  216. wrmsr
  217. // 4. 开启分页
  218. mov %cr0, %eax
  219. or $(1<<31), %eax
  220. mov %eax, %cr0
  221. // 5. 重新设置 GDT
  222. mov $gdt64_pointer, %eax
  223. lgdt 0(%eax)
  224. jmp $0x8, $ready_to_start_64
  225. hlt
  226. ret
  227. .code64
  228. .global ready_to_start_64
  229. ready_to_start_64:
  230. mov $0x10, %ax
  231. mov %ax, %ds
  232. mov %ax, %es
  233. mov %ax, %fs
  234. mov %ax, %ss
  235. mov $0x7e00, %esp
  236. //6. 跳转到start64
  237. movq switch_to_start64(%rip), %rax
  238. pushq $0x08 //段选择子
  239. pushq %rax
  240. lretq
  241. switch_to_start64:
  242. .quad _start64
  243. .code64
  244. is_from_ap:
  245. hlt
  246. .global _start64
  247. .type _start64, @function
  248. .extern Start_Kernel
  249. ENTRY(_start64)
  250. // 初始化寄存器
  251. mov $0x10, %ax
  252. mov %ax, %ds
  253. mov %ax, %es
  254. mov %ax, %fs
  255. mov %ax, %ss
  256. mov $0x7e00, %esp
  257. // === 加载GDTR ====
  258. lgdt GDT_POINTER(%rip) //这里我没搞明白rip相对寻址, 看了文档,大概是用来实现PIC的(position independent code)
  259. //lgdt $GDT_POINTER
  260. // === 加载IDTR ====
  261. lidt IDT_POINTER(%rip)
  262. //lidt $IDT_POINTER
  263. movq GDT_POINTER(%rip), %r12
  264. movq head_stack_start(%rip), %rsp
  265. // 分支,判断是否为apu
  266. movq $0x1b, %rcx // 根据IA32_APIC_BASE.BSP[8]标志位判断处理器是否为apu
  267. rdmsr
  268. bt $8, %rax
  269. jnc load_cr3
  270. // 2. 设置临时页表
  271. // 最高级
  272. mov $__PML4E, %eax
  273. mov $__PDPTE, %ebx
  274. or $0x3, %ebx
  275. mov %ebx, 0(%eax)
  276. mov %ebx, 256(%eax)
  277. // 次级
  278. mov $__PDPTE, %eax
  279. mov $__PDE, %ebx
  280. or $0x3, %ebx
  281. mov %ebx, 0(%eax)
  282. // ==== 加载CR3寄存器
  283. load_cr3:
  284. // 分支,判断是否为apu
  285. movq $__PML4E, %rax //设置页目录基地址
  286. movq %rax, %cr3
  287. movq switch_seg(%rip), %rax
  288. // 由于ljmp和lcall在GAS中不受支持,因此我们需要先伪造函数调用现场,通过lret的方式,给它跳转过去。才能更新cs寄存器
  289. // 实在是太妙了!Amazing!
  290. pushq $0x08 //段选择子
  291. pushq %rax
  292. lretq
  293. // 64位模式的代码
  294. switch_seg:
  295. .quad entry64
  296. entry64:
  297. movq $0x10, %rax
  298. movq %rax, %ds
  299. movq %rax, %es
  300. movq %rax, %gs
  301. movq %rax, %ss
  302. movq head_stack_start(%rip), %rsp //rsp的地址
  303. // 重新加载GDT和IDT,加载到高地址
  304. leaq GDT_Table(%rip), %r8
  305. leaq GDT_END(%rip), %r9
  306. subq %r8, %r9
  307. movq %r9, %r13 // GDT size
  308. leaq IDT_Table(%rip), %r8
  309. leaq IDT_END(%rip), %r9
  310. subq %r8, %r9
  311. movq %r9, %r12 // IDT size
  312. lgdt GDT_POINTER64(%rip)
  313. lidt IDT_POINTER64(%rip)
  314. // 分支,判断是否为apu
  315. movq $0x1b, %rcx // 根据IA32_APIC_BASE.BSP[8]标志位判断处理器是否为apu
  316. rdmsr
  317. bt $8, %rax
  318. jnc start_smp
  319. setup_IDT:
  320. leaq m_ignore_int(%rip), %rdx // 将ignore_int的地址暂时存到中段描述符的高8B
  321. movq $(0x08 << 16), %rax // 设置段选择子。由IDT结构和段选择子结构可知,本行设置段基地址为0x100000,TI=0,RPL=0
  322. movw %dx, %ax
  323. movq $ (0x8e00 << 32), %rcx // 设置Type=1110 P=1 DPL=00 0=0
  324. addq %rcx, %rax
  325. // 把ignore_int的地址填写到正确位置, rax存低8B, rdx存高8B
  326. movl %edx, %ecx
  327. shrl $16, %ecx // 去除低16位
  328. shlq $48, %rcx
  329. addq %rcx, %rax // 填写段内偏移31:16
  330. shrq $32, %rdx // (已经填写了32位,故右移32)
  331. leaq IDT_Table(%rip), %rdi // 获取中断描述符表的首地址,存储到rdi
  332. mov $256, %rcx // 初始化每个中断描述符
  333. repeat_set_idt:
  334. // ====== 循环,初始化总共256个中断描述符 ===
  335. movq %rax, (%rdi) // 保存低8B
  336. movq %rdx, 8(%rdi) // 保存高8B
  337. addq $0x10, %rdi // 转到下一个IDT表项
  338. dec %rcx
  339. jne repeat_set_idt
  340. SetUp_TSS64:
  341. // == 设置64位的任务状态段表 ===
  342. //rdx保存高8B, rax保存低8B
  343. leaq TSS64_Table(%rip), %rdx // 获取定义在process.c中的initial_tss[0]的地址
  344. movq $0xffff800000000000, %r8
  345. addq %r8, %rdx
  346. xorq %rax, %rax
  347. xorq %rcx, %rcx
  348. // 设置TSS描述符的47:40位为1000 1001
  349. movq $0x89, %rax
  350. shlq $40, %rax
  351. // 设置段基地址31:24
  352. movl %edx, %ecx
  353. shrl $24, %ecx
  354. shlq $56, %rcx
  355. addq %rcx, %rax
  356. xorq %rcx, %rcx
  357. // 设置段基地址23:00
  358. movl %edx, %ecx
  359. andl $0xffffff, %ecx // 清空ecx的中有效值的高8位(也就是上面已经赋值了的)
  360. shlq $16, %rcx
  361. addq %rcx, %rax
  362. addq $103, %rax // 设置段长度
  363. leaq GDT_Table(%rip), %rdi
  364. movq %rax, 80(%rdi) // 把低八B存储到GDT第10项
  365. shrq $32, %rdx
  366. movq %rdx, 88(%rdi) // 高8B存到GDT第11项
  367. // 装载任务状态段寄存器(已改为在main.c中使用load_TR宏进行装载)
  368. // mov $0x50, %ax // 设置起始地址为80
  369. // ltr %ax
  370. //now enable SSE and the like
  371. movq %cr0, %rax
  372. and $0xFFFB, %ax //clear coprocessor emulation CR0.EM
  373. or $0x2, %ax //set coprocessor monitoring CR0.MP
  374. movq %rax, %cr0
  375. movq %cr4, %rax
  376. or $(3 << 9), %ax //set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
  377. movq %rax, %cr4
  378. movq go_to_kernel(%rip), %rax /* movq address */
  379. pushq $0x08
  380. pushq %rax
  381. movq mb2_info, %r15
  382. movq mb2_magic, %r14
  383. lretq
  384. go_to_kernel:
  385. .quad Start_Kernel
  386. start_smp:
  387. //now enable SSE and the like
  388. movq %cr0, %rax
  389. and $0xFFFB, %ax //clear coprocessor emulation CR0.EM
  390. or $0x2, %ax //set coprocessor monitoring CR0.MP
  391. movq %rax, %cr0
  392. movq %cr4, %rax
  393. or $(3 << 9), %ax //set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
  394. movq %rax, %cr4
  395. movq go_to_smp_kernel(%rip), %rax /* movq address */
  396. pushq $0x08
  397. pushq %rax
  398. /*
  399. // 重新加载GDT和IDT,加载到高地址
  400. leaq GDT_Table(%rip), %r8
  401. leaq GDT_END(%rip), %r9
  402. subq %r8, %r9
  403. movq %r9, %r13 // GDT size
  404. leaq IDT_Table(%rip), %r8
  405. leaq IDT_END(%rip), %r9
  406. subq %r8, %r9
  407. movq %r9, %r12 // IDT size
  408. lgdt GDT_POINTER64(%rip)
  409. lidt IDT_POINTER64(%rip)
  410. */
  411. lretq
  412. go_to_smp_kernel:
  413. .quad smp_ap_start
  414. // ==== 异常/中断处理模块 ignore int: 忽略中断
  415. m_ignore_int:
  416. // 切换到c语言的ignore_int
  417. movq go_to_ignore_int(%rip), %rax
  418. pushq $0x08
  419. pushq %rax
  420. lretq
  421. lretq
  422. go_to_ignore_int:
  423. .quad ignore_int
  424. ENTRY(head_stack_start)
  425. .quad initial_proc_union + 32768
  426. // 初始化页表
  427. .align 0x1000 //设置为4k对齐
  428. //.org 0x1000 //设置页表位置为内核执行头程序的0x1000处
  429. __PML4E:
  430. .quad 0x103007 // 用户访问,可读写,已存在, 地址在31~12位
  431. .fill 255,8,0
  432. .quad 0x103003
  433. .fill 255,8,0
  434. .org 0x2000
  435. __PDPTE:
  436. .quad 0x104003 // 用户访问,可读写,已存在
  437. .fill 511,8,0
  438. .org 0x3000
  439. __PDE:
  440. .quad 0x000083 // 用户访问,可读写,已存在
  441. .quad 0x200083
  442. .quad 0x400083
  443. .quad 0x600083
  444. .quad 0x800083
  445. .quad 0xa00083
  446. .quad 0xc00083
  447. .quad 0xe00083
  448. .quad 0x1000083
  449. .quad 0x1200083
  450. .quad 0x1400083
  451. .quad 0x1600083
  452. .quad 0x1800083
  453. .quad 0x1a00083
  454. .quad 0x1c00083
  455. .quad 0x1e00083
  456. .quad 0x2000083
  457. .quad 0x2200083
  458. .quad 0x2400083
  459. .quad 0x2600083
  460. .quad 0x2800083
  461. .quad 0x2a00083
  462. .quad 0x2c00083
  463. .quad 0x2e00083
  464. .quad 0x3000083
  465. .quad 0x3200083
  466. .quad 0x3400083
  467. .quad 0x3600083
  468. .quad 0xe0000083 /*虚拟地址0x 3000000 初始情况下,帧缓冲区映射到这里*/
  469. .quad 0xe0200083
  470. .quad 0xe0400083
  471. .quad 0xe0600083 /*0x1000000*/
  472. .quad 0xe0800083
  473. .quad 0xe0a00083
  474. .quad 0xe0c00083
  475. .quad 0xe0e00083
  476. .quad 0xe1000083
  477. .quad 0xe1200083
  478. .quad 0xe1400083
  479. .quad 0xe1600083
  480. .quad 0xe1800083
  481. .quad 0xe1a00083
  482. .quad 0xe1c00083
  483. .quad 0xe1e00083
  484. .fill 468,8,0
  485. // GDT表
  486. .align 16
  487. .global GDT_Table // 使得GDT可以被外部程序引用或者访问
  488. GDT_Table:
  489. .quad 0x0000000000000000 // 0 空描述符 0x00
  490. .quad 0x0020980000000000 // 1 内核64位代码段描述符 0x08
  491. .quad 0x0000920000000000 // 2 内核64位数据段描述符 0x10
  492. .quad 0x0000000000000000 // 3 用户32位代码段描述符 0x18
  493. .quad 0x0000000000000000 // 4 用户32位数据段描述符 0x20
  494. .quad 0x0020f80000000000 // 5 用户64位代码段描述符 0x28
  495. .quad 0x0000f20000000000 // 6 用户64位数据段描述符 0x30
  496. .quad 0x00cf9a000000ffff // 7 内核32位代码段描述符 0x38
  497. .quad 0x00cf92000000ffff // 8 内核32位数据段描述符 0x40
  498. .fill 100, 8, 0 // 10-11 TSS(跳过了第9段) 重复十次填充8字节的空间,赋值为0 长模式下,每个TSS长度为128bit
  499. GDT_END:
  500. .global GDT_POINTER
  501. GDT_POINTER:
  502. GDT_LIMIT: .word GDT_END - GDT_Table - 1 // GDT的大小
  503. GDT_BASE: .quad GDT_Table
  504. .global GDT_POINTER64
  505. GDT_POINTER64:
  506. GDT_LIMIT64: .word GDT_END - GDT_Table - 1 // GDT的大小
  507. GDT_BASE64: .quad GDT_Table + 0xffff800000000000
  508. // IDT 表
  509. .global IDT_Table
  510. IDT_Table:
  511. .fill 512, 8, 0 // 设置512*8字节的IDT表的空间
  512. IDT_END:
  513. .global IDT_POINTER
  514. IDT_POINTER:
  515. IDT_LIMIT: .word IDT_END - IDT_Table - 1
  516. IDT_BASE: .quad IDT_Table
  517. .global IDT_POINTER64
  518. IDT_POINTER64:
  519. IDT_LIMIT64: .word IDT_END - IDT_Table - 1
  520. IDT_BASE64: .quad IDT_Table + 0xffff800000000000
  521. // 64位的TSS表
  522. .global TSS64_Table
  523. TSS64_Table:
  524. .fill 13, 8, 0
  525. TSS64_END:
  526. .section .bootstrap.data
  527. mb2_magic: .quad 0
  528. mb2_info: .quad 0
  529. .code32
  530. // 临时页表 4KB/页
  531. .align 0x1000
  532. .global pml4
  533. pml4:
  534. .skip 0x1000
  535. pdpt:
  536. .skip 0x1000
  537. pd:
  538. .skip 0x1000
  539. pt:
  540. .skip 0x1000
  541. // 临时 GDT
  542. .align 16
  543. gdt64:
  544. null_desc:
  545. .short 0xFFFF
  546. .short 0
  547. .byte 0
  548. .byte 0
  549. .byte 0
  550. .byte 0
  551. code_desc:
  552. .short 0
  553. .short 0
  554. .byte 0
  555. .byte 0x9A
  556. .byte 0x20
  557. .byte 0
  558. data_desc:
  559. .short 0
  560. .short 0
  561. .byte 0
  562. .byte 0x92
  563. .byte 0
  564. .byte 0
  565. user_code_desc:
  566. .short 0
  567. .short 0
  568. .byte 0
  569. .byte 0xFA
  570. .byte 0x20
  571. .byte 0
  572. user_data_desc:
  573. .short 0
  574. .short 0
  575. .byte 0
  576. .byte 0xF2
  577. .byte 0
  578. .byte 0
  579. gdt64_pointer:
  580. .short gdt64_pointer-gdt64-1
  581. .quad gdt64
  582. gdt64_pointer64:
  583. .short gdt64_pointer-gdt64-1
  584. .quad gdt64