浏览代码

fix: fix some problem

simon 8 月之前
父节点
当前提交
29a110d40d
共有 14 个文件被更改,包括 177 次插入141 次删除
  1. 8 2
      bochsrc
  2. 16 7
      kernel/global.h
  3. 1 1
      kernel/init.c
  4. 1 1
      kernel/interrupt.c
  5. 14 13
      kernel/kernel.S
  6. 27 24
      kernel/main.c
  7. 16 14
      kernel/memory.c
  8. 1 1
      lib/kernel/list.h
  9. 1 9
      lib/stdint.h
  10. 1 1
      makefile
  11. 8 1
      thread/thread.c
  12. 14 6
      userprog/process.c
  13. 68 21
      userprog/tss.c
  14. 1 40
      userprog/tss.h

+ 8 - 2
bochsrc

@@ -1,9 +1,10 @@
 display_library: sdl2
 
-romimage: file=$BXSHARE/BIOS-bochs-latest, options=fastboot
+romimage: file=$BXSHARE/BIOS-bochs-latest
 
 vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
 
+
 mouse: enabled=0
 
 # floppya: 1_44=a.img, status=inserted
@@ -23,4 +24,9 @@ debug_symbols: file="build/bin/kernel.sym"
 print_timestamps: enabled=0
 
 
-memory: guest=32, host=32, block_size=512
+memory: guest=32, host=32, block_size=512
+
+# gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0
+
+# error: action=report
+# debug: action=report

+ 16 - 7
kernel/global.h

@@ -21,9 +21,9 @@
 #define DESC_S_DATA DESC_S_CODE // 存储段
 #define DESC_S_SYS 0            // 系统段
 
-#define DESC_TYPE_CODE 0x8 // 代码段(x=1,c=0,r=0,a=0) 可执行、非依从、不可读、已访问位 a 清 0
-#define DESC_TYPE_DATA 0x2 // 数据段(x=0,e=0,w=1,a=0) 不可执行、向上扩展、可写、已访问位 a 清 0
-#define DESC_TYPE_TSS 0x9  // 任务状态段 B 位为 0, 不忙
+#define DESC_TYPE_CODE 8 // 代码段(x=1,c=0,r=0,a=0) 可执行、非依从、不可读、已访问位 a 清 0
+#define DESC_TYPE_DATA 2 // 数据段(x=0,e=0,w=1,a=0) 不可执行、向上扩展、可写、已访问位 a 清 0
+#define DESC_TYPE_TSS 9  // 任务状态段 B 位为 0, 不忙
 
 #define RPL0 0
 #define RPL1 1
@@ -40,7 +40,7 @@
 #define SELECTOR_K_STACK SELECTOR_K_DATA
 #define SELECTOR_K_GS ((3 << 3) + (TI_GDT << 2) + RPL0)
 /* 第 3 个段描述符是显存,第 4 个是 tss */
-#define SELECTOR_TSS ((4 << 3) + (TI_GDT << 2) + RPL0) // GDT 中第 4 个
+
 #define SELECTOR_U_CODE ((5 << 3) + (TI_GDT << 2) + RPL3)
 #define SELECTOR_U_DATA ((6 << 3) + (TI_GDT << 2) + RPL3)
 #define SELECTOR_U_STACK SELECTOR_U_DATA
@@ -54,7 +54,8 @@
 
 #define TSS_ATTR_HIGH ((DESC_G_4K << 7) + (TSS_DESC_D << 6) + (DESC_L << 5) + (DESC_AVL << 4) + 0x0)
 #define TSS_ATTR_LOW ((DESC_P << 7) + (DESC_DPL_0 << 5) + (DESC_S_SYS << 4) + DESC_TYPE_TSS)
-//! 上面已经定义 #define SELECTOR_TSS ((4 << 3) + (TI_GDT << 2) + RPL0)
+
+#define SELECTOR_TSS ((4 << 3) + (TI_GDT << 2) + RPL0)
 
 /*---------------------- IDT 描述符属性 -----------------------------------------*/
 #define IDT_DESC_P 1
@@ -79,6 +80,14 @@
 #define EFLAGES_AC (1 << 18)  // 累加器状态位,0 表示在 32 位模式下运行
 #define EFLAGES_VIF (1 << 19) // 中断标志位
 
+#define NULL ((void *)0)
+#define DIV_ROUND_UP(X, SETUP) ((X + SETUP - 1) / (SETUP))
+#define true 1
+#define false 0
+#define bool int
+
+#define PG_SIZE 4096 // 1 页 = 4KB = 4096 字节
+
 /*---------------------- 定义 GDT 中描述符的结构 -----------------------------------------*/
 //   段描述符格式
 //   31~24  23  22  21  20  19~16   15  14~13 12  11~8   7~0
@@ -90,7 +99,7 @@
 //   ----------------------------------------------------------
 //  |         Base                |        Limit              |
 //   ----------------------------------------------------------
-typedef struct gdt_desc
+struct gdt_desc
 {
     uint16_t limit_low_word; // 低 16 位
     uint16_t base_low_word;
@@ -98,6 +107,6 @@ typedef struct gdt_desc
     uint8_t attr_low_byte;
     uint8_t limit_high_attr_high;
     uint8_t base_high_byte;
-} __attribute__((packed)) GdtDesc;
+};
 
 #endif // __KERNEL_GLOBAL_H

+ 1 - 1
kernel/init.c

@@ -19,5 +19,5 @@ void init_all(void)
     console_init();  // 初始化 console
     keyboard_init(); // 键盘初始化
     tss_init();      // tss_init
-    syscall_init();  // syscall_init
+    // syscall_init();  // syscall_init
 }

+ 1 - 1
kernel/interrupt.c

@@ -161,7 +161,7 @@ void idt_init(void)
     pic_init();       // 初始化可编程中断控制器8259A
 
     /* 加载 idt */
-    uint64_t idt_operand = ((sizeof(idt) - 1) | ((uint64_t)((uintptr_t)idt << 16)));
+    uint64_t idt_operand = (sizeof(idt) - 1) | ((uint64_t)((uint32_t)idt << 16));
     asm volatile("lidt %0" ::"m"(idt_operand));
     put_str("idt_init done\n");
 }

+ 14 - 13
kernel/kernel.S

@@ -39,18 +39,6 @@ section .data
 
 %endmacro
 
-section .text
-global intr_exit
-intr_exit:
-    add esp, 4  ; 跳过中断向量号
-    popad       ; 恢复通用寄存器的值
-    pop gs
-    pop fs
-    pop es
-    pop ds
-    add esp, 4  ; 由于中断发生时,CPU 会自动压入错误码,所以在中断退出时,需要将错误码弹出
-    iretd       ; 从中断返回
-
 VECTOR 0x00, ZERO
 VECTOR 0x01, ZERO
 VECTOR 0x02, ZERO
@@ -125,4 +113,17 @@ syscall_handle:
 
     ; 将 call 调用后的返回值存入当前内核栈中 eax 的位置
     mov [esp + 8 *4], eax
-    jmp intr_exit    ; 返回,恢复上下文
+    jmp intr_exit    ; 返回,恢复上下文
+
+[bits 32]
+section .text
+global intr_exit
+intr_exit:
+    add esp, 4  ; 跳过中断向量号
+    popad       ; 恢复通用寄存器的值
+    pop gs
+    pop fs
+    pop es
+    pop ds
+    add esp, 4  ; 由于中断发生时,CPU 会自动压入错误码,所以在中断退出时,需要将错误码弹出
+    iretd       ; 从中断返回

+ 27 - 24
kernel/main.c

@@ -31,17 +31,19 @@ int main(void)
     // put_int((uintptr_t)addr);
     // put_str("\n");
 
-    process_execute(user_prog_a, "user_prog_a");
-    // process_execute(user_prog_b, "user_prog_b");
-
-    intr_enable(); // 打开中断,使中断起作用
-    console_put_str(" main_pid:0x");
-    console_put_int(sys_getpid());
-    console_put_str("\n");
+    // console_put_str(" main_pid:0x");
+    // console_put_int(sys_getpid());
+    // console_put_str("\n");
 
     thread_start("kernel_thread_a_func", 31, kernel_thread_a_func, "argA ");
     thread_start("kernel_thread_a_func", 31, kernel_thread_b_func, "argB ");
-    // 主线程会一直执行, 直到被中断或被其他线程强制结束
+
+    process_execute(user_prog_a, "user_prog_a");
+    process_execute(user_prog_b, "user_prog_b");
+
+    intr_enable(); // 打开中断,使中断起作用
+    // intr_disable(); // 关闭中断,使中断不起作用
+    //  主线程会一直执行, 直到被中断或被其他线程强制结束
     while (1)
         ;
     return 0;
@@ -52,34 +54,35 @@ void kernel_thread_a_func(void *arg)
 {
     // 用 void 来表示通用类型,这样就可以传递任意类型的参数
     char *para = arg;
-    console_put_str(" thread_a_pid:0x");
-    console_put_int(sys_getpid());
-    console_put_char('\n');
-    console_put_str(" prog_a_pid:0x");
-    console_put_int(prog_a_pid);
-    console_put_char('\n');
+    while (1)
+    {
+        console_put_str(" v_a:0x");
+        console_put_int(test_var_a);
+    }
 }
 void kernel_thread_b_func(void *arg)
 {
     char *para = arg;
-    console_put_str(" thread_b_pid:0x");
-    console_put_int(sys_getpid());
-    console_put_char('\n');
-    console_put_str(" prog_b_pid:0x");
-    console_put_int(prog_b_pid);
-    console_put_char('\n');
+    while (1)
+    {
+        console_put_str(" v_b:0x");
+        console_put_int(test_var_b);
+    }
 }
 
 /*测试用户进程*/
 void user_prog_a(void *UNUSED(arg))
 {
-    prog_a_pid = getpid();
+
     while (1)
-        ;
+    {
+        test_var_a++;
+    }
 }
 void user_prog_b(void *UNUSED(arg))
 {
-    prog_b_pid = getpid();
     while (1)
-        ;
+    {
+        test_var_b++;
+    }
 }

+ 16 - 14
kernel/memory.c

@@ -6,6 +6,10 @@
 #include "../thread/sync.h"
 #include "../thread/thread.h"
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
+
 /************************ 位图地址 ****************************************
  * 0xc009f000 是内核主线程栈顶,0xc009e000 是内核主线程的pcb
  * 一个页框大小的位图可表示128MB内存,位图位置安排在地址0xc009a000
@@ -89,12 +93,12 @@ static void mem_pool_init(uint32_t all_mem)
 
     /********************** 输出内存池信息 ******************************/
     put_str("    kernel_pool_bitmap_start: ");
-    put_int((uintptr_t)kernel_pool.pool_bitmap.bits);
+    put_int((uint32_t)kernel_pool.pool_bitmap.bits);
     put_str(", kernel_pool_phy_addr_start: ");
     put_int(kernel_pool.phy_addr_start);
     put_str("\n");
     put_str("    user_pool_bitmap_start: ");
-    put_int((uintptr_t)user_pool.pool_bitmap.bits);
+    put_int((uint32_t)user_pool.pool_bitmap.bits);
     put_str(", user_pool_phy_addr_start: ");
     put_int(user_pool.phy_addr_start);
     put_str("\n");
@@ -105,7 +109,7 @@ static void mem_pool_init(uint32_t all_mem)
     /*********************** 初始化虚拟内存池 ********************************/
     kernel_vaddr.vaddr_bitmap.btmp_bytes_len = kbm_length; // 虚拟地址位图的长度,按实际物理内存大小生成数组
     /*位图的数组指向一块未使用的内存,目前定位在内核内存池和用户内存池之后*/
-    kernel_vaddr.vaddr_bitmap.bits = (void *)((uintptr_t)MEM_BITMAP_BASE + kbm_length + ubm_length);
+    kernel_vaddr.vaddr_bitmap.bits = (void *)(MEM_BITMAP_BASE + kbm_length + ubm_length);
     kernel_vaddr.vaddr_start = K_HEAP_START;
     bitmap_init(&kernel_vaddr.vaddr_bitmap);
 
@@ -124,8 +128,7 @@ void mem_init(void)
 // 从内核内存池中申请 pg_cnt 个页空间,成功则返回其虚拟地址,失败则返回 NULL
 static void *vaddr_get(enum pool_flags pf, uint32_t pg_cnt)
 {
-    uintptr_t vaddr_start = 0;
-    int bit_idx_start = -1;
+    int vaddr_start = 0, bit_idx_start = -1;
     uint32_t cnt = 0;
     if (PF_KERNEL == pf)
     { // 内核内存池
@@ -277,7 +280,7 @@ void *malloc_page(enum pool_flags pf, uint32_t pg_cnt)
             // 失败时要将曾经已申请的虚拟地址和物理页全部回滚
             return NULL;
         }
-        page_table_add((void *)(uintptr_t)vaddr, page_phyaddr);
+        page_table_add((void *)vaddr, page_phyaddr);
         vaddr += PG_SIZE; // 下一个虚拟页
     }
 
@@ -301,11 +304,8 @@ void *get_user_pages(uint32_t pg_cnt)
 {
     lock_acquire(&user_pool.lock);
     void *vaddr = malloc_page(PF_USER, pg_cnt);
-    if (NULL != vaddr)
-    {
-        // 若分配的地址不为空,则将页内存清 0 后返回
-        _memset(vaddr, 0, pg_cnt * PG_SIZE);
-    }
+    // 将页内存清 0
+    _memset(vaddr, 0, pg_cnt * PG_SIZE);
     lock_release(&user_pool.lock);
     return vaddr;
 }
@@ -341,10 +341,10 @@ void *get_a_page(enum pool_flags pf, uint32_t vaddr)
     void *page_phyaddr = palloc(mem_pool);
     if (page_phyaddr == NULL)
         return NULL;
-    page_table_add((void *)(uintptr_t)vaddr, page_phyaddr);
+    page_table_add((void *)vaddr, page_phyaddr);
 
     lock_release(&mem_pool->lock);
-    return (void *)(uintptr_t)vaddr;
+    return (void *)vaddr;
 }
 
 // 得到虚拟地址映射到的物理地址
@@ -353,4 +353,6 @@ uint32_t addr_vaddr2phy(uint32_t vaddr)
     uint32_t *pte = pte_ptr(vaddr);
     /* (*pte)是值是页表所在的物理页框地址,去掉其低 12 位的页表项属性+虚拟地址 vaddr 的低 12 位 */
     return ((*pte & 0xfffff000) + (vaddr & 0xfff));
-}
+}
+
+#pragma GCC diagnostic pop

+ 1 - 1
lib/kernel/list.h

@@ -1,7 +1,7 @@
 // 双向链表结构
 #ifndef __LIB_KERNEL_LIST_H
 #define __LIB_KERNEL_LIST_H
-#include "../stdint.h"
+#include "../../kernel/global.h"
 
 // 获取结构体中成员的偏移量, 并将其转换为 void* 类型
 #define offset(struct_type, member) (uintptr_t)(&((struct_type *)0)->member)

+ 1 - 9
lib/stdint.h

@@ -1,13 +1,6 @@
 #ifndef __LIB_STDINT_H
 #define __LIB_STDINT_H
 
-#define NULL ((void *)0)
-#define DIV_ROUND_UP(X, SETUP) ((X + SETUP - 1) / (SETUP))
-#define true 1
-#define false 0
-
-#define PG_SIZE 4096 // 1 页 = 4KB = 4096 字节
-
 typedef signed char int8_t;
 typedef signed short int16_t;
 typedef signed int int32_t;
@@ -18,7 +11,6 @@ typedef unsigned short uint16_t;
 typedef unsigned int uint32_t;
 typedef unsigned long long uint64_t;
 
-typedef uint8_t bool;
-typedef unsigned long uintptr_t;
+typedef uint32_t uintptr_t;
 
 #endif // __LIB_STDINT_H

+ 1 - 1
makefile

@@ -127,7 +127,7 @@ mbr: mk_dir $(BUILD_BIN_DIR)/mbr.bin
 
 loader: mk_dir $(BUILD_BIN_DIR)/loader.bin 
 
-run: hd
+run: all hd
 	bochs -f bochsrc -q
 
 all: mk_dir mbr loader K sym

+ 8 - 1
thread/thread.c

@@ -17,6 +17,10 @@ struct lock pid_lock;
 
 extern void switch_to(struct task_struct *cur, struct task_struct *next);
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
+#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
+
 // 获取当前线程的 PCB 指针
 struct task_struct *running_thread(void)
 {
@@ -142,6 +146,7 @@ void schedule(void)
     // 方法 2: PCB 在自然页的起始地址, 所以 pcb 地址=0xfffff000&(&(PCB.general_tag))
 
     next->status = TASK_RUNNING;
+
     // 激活任务页表等
     process_activate(next);
 
@@ -189,4 +194,6 @@ void thread_init(void)
     lock_init(&pid_lock);
     make_main_thread(); // 将当前 main 函数创建为线程
     put_str("thread_init end\n");
-}
+}
+
+#pragma GCC diagnostic pop

+ 14 - 6
userprog/process.c

@@ -5,6 +5,10 @@
 #include "../kernel/memory.h"
 #include "../kernel/interrupt.h"
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
+
 /// @brief 内核中断函数 intr_exit
 /// 实现见 kernel/kernel.S
 /// @param None
@@ -25,14 +29,16 @@ void start_process(void *filename_)
     struct intr_stack *proc_stack = (struct intr_stack *)cur->self_kstack;
 
     proc_stack->edi = proc_stack->esi = proc_stack->ebp = proc_stack->esp_dummy = 0;
-    proc_stack->ebx = proc_stack->edx = proc_stack->ecx = proc_stack->eax = proc_stack->gs = 0;
+    proc_stack->ebx = proc_stack->edx = proc_stack->ecx = proc_stack->eax = 0;
+
+    proc_stack->gs = 0; // 用户态用不上,直接初始为 0
 
     // 为通过中断返回的方式进入 3 特权级做准备
     proc_stack->ds = proc_stack->es = proc_stack->fs = SELECTOR_U_DATA;
     proc_stack->eip = function; // 待执行的用户程序地址
     proc_stack->cs = SELECTOR_U_CODE;
-    proc_stack->eflags = (EFLAGES_IOPL_0 | EFLAGES_MBS | EFLAGES_IF_1);
-    proc_stack->esp = (void *)(get_a_page(PF_USER, USER_STACK3_VADDR) + PG_SIZE);
+    proc_stack->eflags = (EFLAGES_IOPL_0 | EFLAGES_MBS | EFLAGES_IF_1); // Intel 8086 Eflags Register
+    proc_stack->esp = (void *)((uintptr_t)get_a_page(PF_USER, USER_STACK3_VADDR) + PG_SIZE);
     proc_stack->ss = SELECTOR_U_DATA;
     asm volatile("movl %0, %%esp; jmp intr_exit" ::"g"(proc_stack) : "memory");
 }
@@ -50,7 +56,7 @@ void page_dir_activate(struct task_struct *p_thread)
     uint32_t pagedir_pyh_addr = 0x100000;
     if (p_thread->pgdir != NULL)
     { // 用户态进程有自己的页目录表
-        pagedir_pyh_addr = addr_vaddr2phy((uintptr_t)p_thread->pgdir);
+        pagedir_pyh_addr = addr_vaddr2phy((uint32_t)p_thread->pgdir);
     }
     /* 更新页目录寄存器 cr3,使新页表生效 */
     asm volatile("movl %0, %%cr3" ::"r"(pagedir_pyh_addr) : "memory");
@@ -89,7 +95,7 @@ uint32_t *create_page_dir(void)
     // 用户进程页目录的第 768~1023 个页目录项 = 内核页目录表的 768~1023 页目录项
     // (uint32_t *)(page_dir_vaddr + 0x768*4) 是进程页目录表基地址 768 个页目录项的地方
     // 用户进程的创建是在内核中完成的,因此当前是在内核的页表中,其中 0xfffff000 便是用来访问内核页目录表基地址(也是第 0 个页目录项)
-    _memcpy((uint32_t *)(page_dir_vaddr + 768 * 4), (uint32_t *)(0xfffff000 + 768 * 4), 1024); // 1024/4=256 个页目录项大小
+    _memcpy((uint32_t *)((uint32_t)page_dir_vaddr + 768 * 4), (uint32_t *)(0xfffff000 + 768 * 4), 1024); // 1024/4=256 个页目录项大小
 
     /* 2. 更新页目录地址,把最后一个页目录项更新为用户进程自己的页目录表的物理地址 */
     uint32_t new_page_dir_phy_addr = addr_vaddr2phy((uintptr_t)page_dir_vaddr);
@@ -133,4 +139,6 @@ void process_execute(void *filename, char *name)
     list_append(&thread_all_list, &pcb->all_list_tag);
 
     intr_set_status(old_status);
-}
+}
+
+#pragma GCC diagnostic push

+ 68 - 21
userprog/tss.c

@@ -1,44 +1,89 @@
 /**
  * @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
+ *       <bochs:6> info 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 0xc0006b40, 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
+ *       You can list individual entries with 'info gdt [NUM]' or groups with 'info gdt [NUM] [NUM]'
  */
 #include "tss.h"
 #include "../kernel/global.h"
 #include "../lib/kernel/print.h"
 #include "../lib/string.h"
 
-/// @brief TSS implementation
-static Tss tss;
+/**
+ * @file tss.c
+ * @brief Header file for the Task State Segment (TSS) structure.
+ *
+ * This file contains the definition of the TSS structure used in the
+ * operating system kernel's user program module. The TSS is used to
+ * store information about a task, such as stack pointers and segment
+ * selectors, which are essential for task switching in protected mode.
+ */
+struct tss
+{
+    uint32_t backlink; // 上一个任务的 TSS 指针
+    uint32_t *esp0;
+    uint32_t ss0;
+    uint32_t *esp1;
+    uint32_t ss1;
+    uint32_t *esp2;
+    uint32_t ss2;
+    uint32_t cr3;
+    uint32_t (*eip)(void);
+    uint32_t eflags;
+    uint32_t eax;
+    uint32_t ecx;
+    uint32_t edx;
+    uint32_t ebx;
+    uint32_t esp;
+    uint32_t ebp;
+    uint32_t esi;
+    uint32_t edi;
+    uint32_t es;
+    uint32_t cs;
+    uint32_t ss;
+    uint32_t ds;
+    uint32_t fs;
+    uint32_t gs;
+    uint32_t ldt;
+    uint32_t trace;
+    uint32_t io_base;
+};
+static struct tss tss;
+
 /// @brief 创建 GDT 描述符
 /// @param desc_addr 基址
 /// @param limit 界限
 /// @param attr_low 属性(低位)
-/// @param attr_high 属性(低位)
+/// @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);
+static struct gdt_desc make_gdt_desc(uint32_t *desc_addr, uint32_t limit, uint8_t attr_low, uint8_t attr_high);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
 
 void update_tss_esp(struct task_struct *pthread)
 {
-    tss.esp0 = (uint32_t *)((uintptr_t)pthread + PG_SIZE); // 0 级线程的 esp0 指向 pthread 的 0 级线程的 ESP
+    tss.esp0 = (uint32_t *)((uint32_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)
+static struct gdt_desc 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;
+    uint32_t desc_base = (uint32_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.limit_high_attr_high = (((limit & 0x000f0000) >> 16) + (uint8_t)(attr_high));
     desc.base_high_byte = desc_base >> 24;
 
     return desc;
@@ -51,15 +96,15 @@ void tss_init(void)
     _memset(&tss, 0, tss_size);
 
     tss.ss0 = SELECTOR_K_STACK;
-    tss.iomap = tss_size;
+    tss.io_base = 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);
+    *((struct gdt_desc *)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);
+    *((struct gdt_desc *)0xc0000928) = make_gdt_desc((uint32_t *)0, 0xfffff, GDT_CODE_ATTR_LOW_DPL3, GDT_ATTR_HIGH);
+    *((struct gdt_desc *)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 个描述符大小
@@ -68,4 +113,6 @@ void tss_init(void)
     asm volatile("ltr %w0" ::"r"(SELECTOR_TSS));
 
     put_str("tss_init and ltr done\n");
-}
+}
+
+#pragma GCC diagnostic pop

+ 1 - 40
userprog/tss.h

@@ -2,46 +2,7 @@
 #define __USERPROG_TSS_H__
 #include "../thread/thread.h"
 #include "../lib/stdint.h"
-
-/**
- * @file tss.h
- * @brief Header file for the Task State Segment (TSS) structure.
- *
- * This file contains the definition of the TSS structure used in the
- * operating system kernel's user program module. The TSS is used to
- * store information about a task, such as stack pointers and segment
- * selectors, which are essential for task switching in protected mode.
- */
-typedef struct tss
-{
-    uint32_t backlink;
-    uint32_t *esp0;
-    uint32_t ss0;
-    uint32_t *esp1;
-    uint32_t ss1;
-    uint32_t *esp2;
-    uint32_t ss2;
-    uint32_t cr3;
-    uint32_t (*eip)(void);
-    uint32_t eflags;
-    uint32_t eax;
-    uint32_t ecx;
-    uint32_t edx;
-    uint32_t ebx;
-    uint32_t esp;
-    uint32_t ebp;
-    uint32_t esi;
-    uint32_t edi;
-    uint32_t es;
-    uint32_t cs;
-    uint32_t ss;
-    uint32_t ds;
-    uint32_t fs;
-    uint32_t gs;
-    uint32_t ldt;
-    uint32_t trap;
-    uint32_t iomap;
-} Tss;
+#include "../thread/thread.h" // Include the header file for struct task_struct
 
 /// @brief 更新 tss 中 esp0 字段的值为 pthread 的 0 级线程
 /// @param pthread