| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- /**
- * @brief 安装 TSS 到 GDT,安装用户代码段、数据段到 GDT
- * @note 安装后系统 GDT 显示如下:
- * gdt (base=0x00000000c0000900, limit=55):
- * gdt[0x0000]=<null entry>
- * gdt[0x0008]=Code segment, base=0x00000000, limit=0xffffffff, Execute-Only, Non-Conforming, Accessed, 32-bit
- * gdt[0x0010]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
- * gdt[0x0018]=Data segment, base=0xc00b8000, limit=0x00007fff, Read/Write, Accessed
- * gdt[0x0020]=32-Bit TSS (Busy) at 0xc0005560, length 0x0006b
- * gdt[0x0028]=Code segment, base=0x00000000, limit=0xffffffff, Execute-Only, Non-Conforming, 32-bit
- * gdt[0x0030]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write
- */
- #include "tss.h"
- #include "../kernel/global.h"
- #include "../lib/kernel/print.h"
- #include "../lib/string.h"
- /// @brief TSS implementation
- static Tss tss;
- /// @brief 创建 GDT 描述符
- /// @param desc_addr 基址
- /// @param limit 界限
- /// @param attr_low 属性(低位)
- /// @param attr_high 属性(低位)
- /// @return GdtDescriptor
- static GdtDesc make_gdt_desc(uint32_t *desc_addr, uint32_t limit, uint8_t attr_low, uint8_t attr_high);
- void update_tss_esp(struct task_struct *pthread)
- {
- tss.esp0 = (uint32_t *)((uintptr_t)pthread + PG_SIZE); // 0 级线程的 esp0 指向 pthread 的 0 级线程的 ESP
- }
- static GdtDesc make_gdt_desc(uint32_t *desc_addr, uint32_t limit, uint8_t attr_low, uint8_t attr_high)
- {
- uint32_t desc_base = (uint32_t)(uintptr_t)desc_addr;
- struct gdt_desc desc;
- desc.limit_low_word = limit & 0xFFFF;
- desc.base_low_word = desc_base & 0xFFFF;
- desc.base_middle_byte = ((desc_base & 0x00ff0000) >> 16);
- desc.attr_low_byte = (uint8_t)attr_low;
- desc.limit_high_attr_high = ((uint8_t)(attr_high) + ((limit & 0x000f0000) >> 16));
- desc.base_high_byte = desc_base >> 24;
- return desc;
- }
- /* 在 GDT 中创建 tss 并加载 gdt */
- void tss_init(void)
- {
- put_str("tss_init start\n");
- uint32_t tss_size = sizeof(tss);
- _memset(&tss, 0, tss_size);
- tss.ss0 = SELECTOR_K_STACK;
- tss.iomap = tss_size;
- /* gdt 段基址为 0x900,把 tss 放到第 4 个位置,也就是 0x900+0x20 的位置 */
- // 在 gdt 中添加 dpl 为 0 的 TSS 描述符
- *((GdtDesc *)0xc0000920) = make_gdt_desc((uint32_t *)&tss, tss_size - 1, TSS_ATTR_LOW, TSS_ATTR_HIGH);
- // 在 gdt 中添加 dpl 为 3 的数据段和代码段描述符
- *((GdtDesc *)0xc0000928) = make_gdt_desc((uint32_t *)0, 0xfffff, GDT_CODE_ATTR_LOW_DPL3, GDT_ATTR_HIGH);
- *((GdtDesc *)0xc0000930) = make_gdt_desc((uint32_t *)0, 0xfffff, GDT_DATA_ATTR_LOW_DPL3, GDT_ATTR_HIGH);
- // gdt 的指针,前 2 个字节(16 位)是 gdt 界限 limit,后 4 字节(32位)是 gdt 起始地址 Base
- uint64_t gdt_operand_ptr = (8 * 7 - 1) | ((uint64_t)(uint32_t)0xc0000900 << 16); // 7 个描述符大小
- asm volatile("lgdt %0" ::"m"(gdt_operand_ptr));
- asm volatile("ltr %w0" ::"r"(SELECTOR_TSS));
- put_str("tss_init and ltr done\n");
- }
|