diff --git a/README.md b/README.md index 72ad9f38..a8c2ab2d 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ # DragonOS +**Languages** 中文|[English](README_EN.md) +   这是一个运行于x86_64平台的64位操作系统。目前正在开发之中! ## 开发环境 -GCC==8.0 +GCC>=8.0 bochs==2.7 @@ -48,7 +50,7 @@ bximage - [ ] 图形驱动 -- [ ] 第一个进程 +- [x] 第一个进程 - [ ] 进程管理 @@ -101,7 +103,3 @@ fslongjin ## 赞赏者列表 暂无 - - - - diff --git a/kernel/common/glib.h b/kernel/common/glib.h index fb203bca..478b7e62 100644 --- a/kernel/common/glib.h +++ b/kernel/common/glib.h @@ -90,22 +90,6 @@ static inline void list_append(struct List *entry, struct List *node) list_add(tail, node); } - void list_add_to_behind(struct List * entry,struct List * new) ////add to entry behind -{ - new->next = entry->next; - new->prev = entry; - new->next->prev = new; - entry->next = new; -} - - void list_add_to_before(struct List * entry,struct List * new) ////add to entry behind -{ - new->next = entry; - entry->prev->next = new; - new->prev = entry->prev; - entry->prev = new; -} - static inline void list_del(struct List *entry) { /** @@ -274,7 +258,6 @@ void io_out32(unsigned short port, unsigned int value) : "memory"); } - /** * @brief 读取rsp寄存器的值(存储了页目录的基地址) * @@ -342,4 +325,33 @@ unsigned long *get_rbx() "movq %%rbx, %0\n\t" : "=r"(tmp)::"memory"); return tmp; -} \ No newline at end of file +} + +// ========= MSR寄存器组操作 ============= +/** + * @brief 向msr寄存器组的address处的寄存器写入值value + * + * @param address 地址 + * @param value 要写入的值 + */ +void wrmsr(ul address, ul value) +{ + __asm__ __volatile__("wrmsr \n\t" ::"d"(value >> 32), "a"(value & 0xffffffff), "c"(address) + : "memory"); +} + +/** + * @brief 从msr寄存器组的address地址处读取值 + * + * @param address 地址 + * @return ul address处的寄存器的值 + */ +ul rdmsr(ul address) +{ + unsigned int tmp0, tmp1; + __asm__ __volatile__("rdmsr \n\t" + : "=d"(tmp0), "=a"(tmp1) + : "c"(address) + : "memory"); + return ((ul)tmp0 << 32) | tmp1; +} diff --git a/kernel/exception/entry.S b/kernel/exception/entry.S index baf29f62..88e1d4be 100644 --- a/kernel/exception/entry.S +++ b/kernel/exception/entry.S @@ -99,6 +99,38 @@ Err_Code: jmp ret_from_exception +// 从系统调用中返回 +ENTRY(ret_from_system_call) + movq %rax, 0x80(%rsp) // 将当前rax的值先存到栈中rax的位置 + + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %r11 + popq %r10 + popq %r9 + popq %r8 + popq %rbx + popq %rcx + popq %rdx + popq %rsi + popq %rdi + popq %rbp + + popq %rax // 不允许直接pop到ds + movq %rax, %ds + + popq %rax + movq %rax, %es + + popq %rax + + addq $0x38, %rsp + + .byte 0x48 + sysexit + // 0 #DE 除法错误 ENTRY(divide_error) diff --git a/kernel/head.S b/kernel/head.S index 0cdf4e69..f6d2f84e 100644 --- a/kernel/head.S +++ b/kernel/head.S @@ -111,12 +111,12 @@ SetUp_TSS64: addq $103, %rax // 设置段长度 leaq GDT_Table(%rip), %rdi - movq %rax, 64(%rdi) // 把低八B存储到GDT第8项 + movq %rax, 80(%rdi) // 把低八B存储到GDT第10项 shrq $32, %rdx - movq %rdx, 72(%rdi) // 高8B存到GDT低9项 + movq %rdx, 88(%rdi) // 高8B存到GDT第11项 // 装载任务状态段寄存器(已改为在main.c中使用load_TR宏进行装载) - // mov $0x40, %ax // 设置起始地址为64 + // mov $0x50, %ax // 设置起始地址为80 // ltr %ax // 切换到内核主程序 @@ -152,7 +152,7 @@ ENTRY(_stack_start) .org 0x1000 //设置页表位置为内核执行头程序的0x1000处 __PML4E: - .quad 0x102007 // 系统访问,可读写,已存在, 地址在31~12位 + .quad 0x102007 // 用户访问,可读写,已存在, 地址在31~12位 .fill 255,8,0 .quad 0x102007 .fill 255,8,0 @@ -161,26 +161,26 @@ __PML4E: __PDPTE: - .quad 0x103003 // 用户访问,可读写,已存在 + .quad 0x103007 // 用户访问,可读写,已存在 .fill 511,8,0 .org 0x3000 __PDE: - .quad 0x000083 // 用户访问,可读写,已存在 - .quad 0x200083 - .quad 0x400083 - .quad 0x600083 - .quad 0x800083 - .quad 0xe0000083 /*0x a00000*/ - .quad 0xe0200083 - .quad 0xe0400083 - .quad 0xe0600083 /*0x1000000*/ - .quad 0xe0800083 - .quad 0xe0a00083 - .quad 0xe0c00083 - .quad 0xe0e00083 + .quad 0x000087 // 用户访问,可读写,已存在 + .quad 0x200087 + .quad 0x400087 + .quad 0x600087 + .quad 0x800087 + .quad 0xe0000087 /*0x a00000*/ + .quad 0xe0200087 + .quad 0xe0400087 + .quad 0xe0600087 /*0x1000000*/ + .quad 0xe0800087 + .quad 0xe0a00087 + .quad 0xe0c00087 + .quad 0xe0e00087 .fill 499,8,0 // GDT表 @@ -188,14 +188,16 @@ __PDE: .global GDT_Table // 使得GDT可以被外部程序引用或者访问 GDT_Table: - .quad 0x0000000000000000 // 0 空描述符 00 - .quad 0x0020980000000000 // 1 内核64位代码段描述符 08 - .quad 0x0000920000000000 // 2 内核64位数据段描述符 10 - .quad 0x0020f80000000000 // 3 用户64位代码段描述符 18 - .quad 0x0000f20000000000 // 4 用户64位数据段描述符 20 - .quad 0x00cf9a000000ffff // 5 内核32位代码段描述符 28 - .quad 0x00cf92000000ffff // 6 内核32位数据段描述符 30 - .fill 10, 8, 0 // 8~9 TSS(跳过了第七段) 重复十次填充8字节的空间,赋值为0 + .quad 0x0000000000000000 // 0 空描述符 0x00 + .quad 0x0020980000000000 // 1 内核64位代码段描述符 0x08 + .quad 0x0000920000000000 // 2 内核64位数据段描述符 0x10 + .quad 0x0000000000000000 // 3 用户32位代码段描述符 0x18 + .quad 0x0000000000000000 // 4 用户32位数据段描述符 0x20 + .quad 0x0020f80000000000 // 5 用户64位代码段描述符 0x28 + .quad 0x0000f20000000000 // 6 用户64位数据段描述符 0x30 + .quad 0x00cf9a000000ffff // 7 内核32位代码段描述符 0x38 + .quad 0x00cf92000000ffff // 8 内核32位数据段描述符 0x40 + .fill 10, 8, 0 // 10-11 TSS(跳过了第9段) 重复十次填充8字节的空间,赋值为0 GDT_END: GDT_POINTER: diff --git a/kernel/main.c b/kernel/main.c index a81e35bc..5d6ee558 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -65,7 +65,7 @@ void system_initialize() // 初始化printk init_printk(1440, 900, FR_address, 1440 * 900 * 4, 8, 16); - load_TR(8); // 加载TR寄存器 + load_TR(10); // 加载TR寄存器 // 初始化任务状态段表 ul tss_item_addr = 0xffff800000007c00; diff --git a/kernel/mm/mm.c b/kernel/mm/mm.c index fd5702d6..34809cea 100644 --- a/kernel/mm/mm.c +++ b/kernel/mm/mm.c @@ -191,10 +191,11 @@ void mm_init() */ + /* // 消除一致性页表映射,将页目录(PML4E)的前10项清空 for (int i = 0; i < 10; ++i) *(phys_2_virt(global_CR3) + i) = 0UL; - + */ flush_tlb(); diff --git a/kernel/process/process.c b/kernel/process/process.c index 16928825..75ca57ee 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -26,7 +26,38 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc __asm__ __volatile__("movq %0, %%fs \n\t" ::"a"(next->thread->fs)); __asm__ __volatile__("movq %0, %%gs \n\t" ::"a"(next->thread->gs)); +} +/** + * @brief 这是一个用户态的程序 + * + */ +void user_level_function() +{ + kinfo("Program (user_level_function) is runing..."); + + while(1); +} +/** + * @brief 使当前进程去执行新的代码 + * + * @param regs 当前进程的寄存器 + * @return ul 错误码 + */ +ul do_execve(struct pt_regs *regs) +{ + // 选择这两个寄存器是对应了sysexit指令的需要 + regs->rdx = 0x800000; // rip 应用层程序的入口地址 这里的地址选择没有特殊要求,只要是未使用的内存区域即可。 + regs->rcx = 0xa00000; // rsp 应用层程序的栈顶地址 + + regs->rax = 1; + regs->ds = 0; + regs->es = 0; + + kdebug("do_execve is running..."); + // 将程序代码拷贝到对应的内存中 + memcpy((void *)0x800000, user_level_function, 1024); + return 0; } /** @@ -38,6 +69,21 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc ul initial_kernel_thread(ul arg) { kinfo("initial proc running...\targ:%#018lx", arg); + + struct pt_regs *regs; + + current_pcb->thread->rip = (ul)ret_from_system_call; + current_pcb->thread->rsp = (ul)current_pcb + STACK_SIZE - sizeof(struct pt_regs); + + regs = (struct pt_regs *)current_pcb->thread->rsp; + + // 将返回用户层的代码压入堆栈,向rdx传入regs的地址,然后jmp到do_execve这个系统调用api的处理函数 这里的设计思路和switch_proc类似 + __asm__ __volatile__("movq %1, %%rsp \n\t" + "pushq %2 \n\t" + "jmp do_execve \n\t" ::"D"(regs), + "m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip) + : "memory"); + return 1; } @@ -62,35 +108,33 @@ ul do_exit(ul code) */ extern void kernel_thread_func(void); -__asm__ ( -"kernel_thread_func: \n\t" -" popq %r15 \n\t" -" popq %r14 \n\t" -" popq %r13 \n\t" -" popq %r12 \n\t" -" popq %r11 \n\t" -" popq %r10 \n\t" -" popq %r9 \n\t" -" popq %r8 \n\t" -" popq %rbx \n\t" -" popq %rcx \n\t" -" popq %rdx \n\t" -" popq %rsi \n\t" -" popq %rdi \n\t" -" popq %rbp \n\t" -" popq %rax \n\t" -" movq %rax, %ds \n\t" -" popq %rax \n\t" -" movq %rax, %es \n\t" -" popq %rax \n\t" -" addq $0x38, %rsp \n\t" -///////////////////////////////// -" movq %rdx, %rdi \n\t" -" callq *%rbx \n\t" -" movq %rax, %rdi \n\t" -" callq do_exit \n\t" -); - +__asm__( + "kernel_thread_func: \n\t" + " popq %r15 \n\t" + " popq %r14 \n\t" + " popq %r13 \n\t" + " popq %r12 \n\t" + " popq %r11 \n\t" + " popq %r10 \n\t" + " popq %r9 \n\t" + " popq %r8 \n\t" + " popq %rbx \n\t" + " popq %rcx \n\t" + " popq %rdx \n\t" + " popq %rsi \n\t" + " popq %rdi \n\t" + " popq %rbp \n\t" + " popq %rax \n\t" + " movq %rax, %ds \n\t" + " popq %rax \n\t" + " movq %rax, %es \n\t" + " popq %rax \n\t" + " addq $0x38, %rsp \n\t" + ///////////////////////////////// + " movq %rdx, %rdi \n\t" + " callq *%rbx \n\t" + " movq %rax, %rdi \n\t" + " callq do_exit \n\t"); /** * @brief 初始化内核进程 @@ -116,7 +160,6 @@ int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigne regs.cs = KERNEL_CS; regs.ss = KERNEL_DS; - // 置位中断使能标志位 regs.rflags = (1 << 9); @@ -129,7 +172,6 @@ int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigne void process_init() { - initial_mm.pgd = (pml4t_t *)global_CR3; initial_mm.code_addr_start = memory_management_struct.kernel_code_start; @@ -146,23 +188,24 @@ void process_init() initial_mm.stack_start = _stack_start; + // 向MSR寄存器组中的 IA32_SYSENTER_CS寄存器写入内核的代码段的地址 + wrmsr(0x174, KERNEL_CS); + // 初始化进程和tss set_TSS64(initial_thread.rbp, initial_tss[0].rsp1, initial_tss[0].rsp2, initial_tss[0].ist1, initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5, initial_tss[0].ist6, initial_tss[0].ist7); initial_tss[0].rsp0 = initial_thread.rbp; - // 初始化进程的循环链表 list_init(&initial_proc_union.pcb.list); - kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); // 初始化内核进程 initial_proc_union.pcb.state = PROC_RUNNING; // 获取新的进程的pcb struct process_control_block *p = container_of(list_next(¤t_pcb->list), struct process_control_block, list); - // 切换到新的内核线程 + // 切换到新的内核线程 switch_proc(current_pcb, p); } @@ -180,14 +223,11 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned { struct process_control_block *tsk = NULL; - // 获取一个物理页并在这个物理页内初始化pcb struct Page *pp = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED | PAGE_ACTIVE | PAGE_KERNEL); - tsk = (struct process_control_block *)phys_2_virt(pp->addr_phys); - memset(tsk, 0, sizeof(*tsk)); // 将当前进程的pcb复制到新的pcb内 @@ -198,7 +238,6 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned list_add(&initial_proc_union.pcb.list, &tsk->list); - ++(tsk->pid); tsk->state = PROC_UNINTERRUPTIBLE; @@ -214,9 +253,9 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned thd->rip = regs->rip; thd->rsp = (ul)tsk + STACK_SIZE - sizeof(struct pt_regs); - // 若进程不是内核层的进程,则跳转到ret from intr + // 若进程不是内核层的进程,则跳转到ret from system call if (!(tsk->flags & PF_KTHREAD)) - thd->rip = regs->rip = (ul)ret_from_intr; + thd->rip = regs->rip = (ul)ret_from_system_call; tsk->state = PROC_RUNNING; diff --git a/kernel/process/process.h b/kernel/process/process.h index 224c0813..eeb90e11 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -16,7 +16,8 @@ #include "ptrace.h" extern unsigned long _stack_start; // 导出内核层栈基地址(定义在head.S) -extern void ret_from_intr(); // 导出从中断返回的函数(定义在entry.S) +extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S) +extern void ret_from_system_call(void); // 导出从中断返回的函数(定义在entry.S) // 进程的内核栈大小 32K #define STACK_SIZE 32768