Browse Source

进入用户模式(系统调用存在page fault的bug)

fslongjin 3 years ago
parent
commit
dacc29310f

+ 2 - 2
kernel/driver/timers/rtc/rtc.c

@@ -22,7 +22,7 @@ enum CMOSTimeSelector
 int rtc_get_cmos_time(struct rtc_time_t *t)
 {
     // 为防止中断请求打断该过程,需要先关中断
-    cli();
+    //cli();
 
     uint8_t status_register_B = read_cmos(0x0B);                  // 读取状态寄存器B
     bool is_24h = ((status_register_B & 0x02) ? true : false);    // 判断是否启用24小时模式
@@ -53,6 +53,6 @@ int rtc_get_cmos_time(struct rtc_time_t *t)
 
     if ((!is_24h) && t->hour & 0x80) // 将十二小时制转为24小时
         t->hour = ((t->hour & 0x7f) + 12) % 24;
-    sti();
+    //sti();
     return 0;
 }

+ 28 - 29
kernel/exception/entry.S

@@ -104,13 +104,15 @@ Err_Code:
 // 系统调用入口
 // 保存寄存器
 ENTRY(system_call)
+    
     // 由于sysenter指令会禁用中断,因此要在这里手动开启中断
     sti;
-    hlt
+
+    
     subq $0x38, %rsp
     
     cld;
-
+    
     pushq %rax
     movq %es, %rax
     pushq %rax
@@ -137,6 +139,7 @@ ENTRY(system_call)
     // 将rsp作为参数传递给system_call_function
     movq %rsp, %rdi
 
+    
     callq system_call_function
 
 
@@ -145,33 +148,29 @@ ENTRY(system_call)
 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
+	 
+	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				 	
+	movq	%rax,	%ds			 
+	popq	%rax				 
+	movq	%rax,	%es			 
+	popq	%rax				 
+	addq	$0x38,	%rsp	
+	.byte	0x48		 
+	sysexit		
 
 
 // 0 #DE 除法错误

+ 2 - 2
kernel/exception/trap.c

@@ -168,7 +168,7 @@ void do_stack_segment_fault(struct pt_regs *regs, unsigned long error_code)
 // 13 #GP 通用保护性异常
 void do_general_protection(struct pt_regs *regs, unsigned long error_code)
 {
-    hlt();
+    
     kerror("do_general_protection(13),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip);
     if (error_code & 0x01)
         printk_color(RED, BLACK, "The exception occurred during delivery of an event external to the program,such as an interrupt or an earlier exception.\n");
@@ -192,7 +192,7 @@ void do_general_protection(struct pt_regs *regs, unsigned long error_code)
 // 14 #PF 页故障
 void do_page_fault(struct pt_regs *regs, unsigned long error_code)
 {
-    hlt();
+   
     unsigned long cr2 = 0;
 
 	__asm__	__volatile__("movq	%%cr2,	%0":"=r"(cr2)::"memory");

+ 6 - 6
kernel/mm/mm.c

@@ -164,7 +164,7 @@ void mm_init()
         if (z->zone_addr_start >= 0x100000000 && (!ZONE_UNMAPPED_INDEX))
             ZONE_UNMAPPED_INDEX = i;
     }
-    kdebug("ZONE_DMA_INDEX=%d\tZONE_NORMAL_INDEX=%d\tZONE_UNMAPPED_INDEX=%d", ZONE_DMA_INDEX, ZONE_NORMAL_INDEX, ZONE_UNMAPPED_INDEX);
+    //kdebug("ZONE_DMA_INDEX=%d\tZONE_NORMAL_INDEX=%d\tZONE_UNMAPPED_INDEX=%d", ZONE_DMA_INDEX, ZONE_NORMAL_INDEX, ZONE_UNMAPPED_INDEX);
     // 设置内存页管理结构的地址,预留了一段空间,防止内存越界。
     memory_management_struct.end_of_struct = (ul)((ul)memory_management_struct.zones_struct + memory_management_struct.zones_struct_len + sizeof(long) * 32) & (~(sizeof(long) - 1));
 
@@ -174,7 +174,7 @@ void mm_init()
     // 初始化内存管理单元结构所占的物理页的结构体
 
     ul mms_max_page = (virt_2_phys(memory_management_struct.end_of_struct) >> PAGE_2M_SHIFT); // 内存管理单元所占据的序号最大的物理页
-    kdebug("mms_max_page=%ld", mms_max_page);
+    //kdebug("mms_max_page=%ld", mms_max_page);
 
     struct Page *tmp_page = NULL;
     ul page_num;
@@ -191,11 +191,11 @@ void mm_init()
 
     global_CR3 = get_CR3();
     // root_page_table_phys_addr = global_CR3;
-    kdebug("global_CR3\t:%#018lx", global_CR3);
-    kdebug("*global_CR3\t:%#018lx", *phys_2_virt(global_CR3) & (~0xff));
-    kdebug("**global_CR3\t:%#018lx", *phys_2_virt(*phys_2_virt(global_CR3) & (~0xff)) & (~0xff));
+    //kdebug("global_CR3\t:%#018lx", global_CR3);
+    //kdebug("*global_CR3\t:%#018lx", *phys_2_virt(global_CR3) & (~0xff));
+    //kdebug("**global_CR3\t:%#018lx", *phys_2_virt(*phys_2_virt(global_CR3) & (~0xff)) & (~0xff));
 
-    kdebug("1.memory_management_struct.bmp:%#018lx\tzone->count_pages_using:%d\tzone_struct->count_pages_free:%d", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free);
+    //kdebug("1.memory_management_struct.bmp:%#018lx\tzone->count_pages_using:%d\tzone_struct->count_pages_free:%d", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free);
     //kinfo("Cleaning page table remapping at 0x0000");
 
     kinfo("Memory management unit initialize complete!");

+ 2 - 2
kernel/mm/slab.c

@@ -374,7 +374,7 @@ ul slab_init()
         page_init(page, PAGE_KERNEL_INIT | PAGE_KERNEL | PAGE_PGT_MAPPED);
     }
 
-    kdebug("2.memory_management_struct.bmp:%#018lx\tzone_struct->count_pages_using:%d\tzone_struct->count_pages_free:%d", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free);
+    //kdebug("2.memory_management_struct.bmp:%#018lx\tzone_struct->count_pages_using:%d\tzone_struct->count_pages_free:%d", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free);
 
     // 为slab内存池对象分配内存空间
     ul *virt = NULL;
@@ -395,7 +395,7 @@ ul slab_init()
 
         kmalloc_cache_group[i].cache_pool_entry->vaddr = virt;
     }
-    kdebug("3.memory_management_struct.bmp:%#018lx\tzone_struct->count_pages_using:%d\tzone_struct->count_pages_free:%d", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free);
+    //kdebug("3.memory_management_struct.bmp:%#018lx\tzone_struct->count_pages_using:%d\tzone_struct->count_pages_free:%d", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free);
 
     kinfo("SLAB initialized successfully!");
 

+ 44 - 29
kernel/process/process.c

@@ -8,6 +8,7 @@
 #include <mm/slab.h>
 #include <sched/sched.h>
 
+extern void system_call(void);
 /**
  * @brief 切换进程
  *
@@ -20,24 +21,20 @@
 void __switch_to(struct process_control_block *prev, struct process_control_block *next)
 {
     initial_tss[0].rsp0 = next->thread->rbp;
-    kdebug("phys_2_virt(TSS64_Table)=%#018lx", phys_2_virt(TSS64_Table));
     set_tss64((uint *)phys_2_virt(TSS64_Table), initial_tss[0].rsp0, 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);
 
-    kdebug("prev->thread=%#018lx", prev->thread);
-    kdebug("next->thread=%#018lx", next->thread);
-
     __asm__ __volatile__("movq	%%fs,	%0 \n\t"
                          : "=a"(prev->thread->fs)::"memory");
     __asm__ __volatile__("movq	%%gs,	%0 \n\t"
                          : "=a"(prev->thread->gs)::"memory");
-    kdebug("&next->thread->fs=%#018lx", &(next->thread->fs));
 
     __asm__ __volatile__("movq	%0, %%fs \n\t" ::"a"(next->thread->fs)
                          : "memory");
 
     __asm__ __volatile__("movq	%0,	%%gs \n\t" ::"a"(next->thread->gs)
                          : "memory");
+    wrmsr(0x175, next->thread->rbp);
     kdebug("prev->thread->rsp0:%#018lx\n", prev->thread->rbp);
     kdebug("next->thread->rsp0:%#018lx\n", next->thread->rbp);
 }
@@ -51,18 +48,21 @@ void user_level_function()
     // kinfo("Program (user_level_function) is runing...");
     // kinfo("Try to enter syscall id 15...");
     // enter_syscall(15, 0, 0, 0, 0, 0, 0, 0, 0);
-    
-    //enter_syscall(SYS_PRINTF, (ul) "test_sys_printf\n", 0, 0, 0, 0, 0, 0, 0);
-long ret = 0;
-//	color_printk(RED,BLACK,"user_level_function task is running\n");
-	char string[]="Hello World!\n";
-
-	__asm__	__volatile__	(	"leaq	sysexit_return_address(%%rip),	%%rdx	\n\t"
-					"movq	%%rsp,	%%rcx		\n\t"
-					"sysenter			\n\t"
-					"sysexit_return_address:	\n\t"
-					:"=a"(ret):"0"(1),"D"(string):"memory");
-    //kinfo("Return from syscall id 15...");
+
+    // enter_syscall(SYS_PRINTF, (ul) "test_sys_printf\n", 0, 0, 0, 0, 0, 0, 0);
+    long ret = 0;
+    //	color_printk(RED,BLACK,"user_level_function task is running\n");
+
+    char string[] = "Hello World!\n";
+
+    __asm__ __volatile__("leaq	sysexit_return_address(%%rip),	%%rdx	\n\t"
+                         "movq	%%rsp,	%%rcx		\n\t"
+                         "sysenter			\n\t"
+                         "sysexit_return_address:	\n\t"
+                         : "=a"(ret)
+                         : "0"(1), "D"(string)
+                         : "memory", "rcx", "rdx", "r14");
+    // kinfo("Return from syscall id 15...");
 
     while (1)
         ;
@@ -89,10 +89,10 @@ ul do_execve(struct pt_regs *regs)
     // mm_map_proc_page_table(get_CR3(), true, 0x800000, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true);
 
     uint64_t addr = 0x800000UL;
-    
-    unsigned long * tmp = phys_2_virt((unsigned long *)((unsigned long)get_CR3() & (~0xfffUL)) + (( addr>> PAGE_GDT_SHIFT) & 0x1ff));
-    
-    unsigned long * virtual = kmalloc(PAGE_4K_SIZE, 0);
+
+    unsigned long *tmp = phys_2_virt((unsigned long *)((unsigned long)get_CR3() & (~0xfffUL)) + ((addr >> PAGE_GDT_SHIFT) & 0x1ff));
+
+    unsigned long *virtual = kmalloc(PAGE_4K_SIZE, 0);
     set_pml4t(tmp, mk_pml4t(virt_2_phys(virtual), PAGE_USER_PGT));
 
     tmp = phys_2_virt((unsigned long *)(*tmp & (~0xfffUL)) + ((addr >> PAGE_1G_SHIFT) & 0x1ff));
@@ -105,9 +105,10 @@ ul do_execve(struct pt_regs *regs)
 
     flush_tlb();
 
-/*
-    mm_map_phys_addr_user(addr, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE);
- */   if (!(current_pcb->flags & PF_KTHREAD))
+    /*
+        mm_map_phys_addr_user(addr, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE);
+     */
+    if (!(current_pcb->flags & PF_KTHREAD))
         current_pcb->addr_limit = KERNEL_BASE_LINEAR_ADDR;
     // 将程序代码拷贝到对应的内存中
     memcpy((void *)0x800000, user_level_function, 1024);
@@ -247,29 +248,36 @@ void process_init()
     initial_mm.brk_start = 0;
     initial_mm.brk_end = memory_management_struct.kernel_end;
 
-
     initial_mm.stack_start = *(ul *)phys_2_virt(&_stack_start);
 
+    // 向MSR寄存器组中的 IA32_SYSENTER_CS寄存器写入内核的代码段的地址
+    wrmsr(0x174, KERNEL_CS);
+    // 向MSR寄存器组中的 IA32_SYSENTER_ESP寄存器写入内核进程的rbp(在syscall入口中会将rsp减去相应的数值)
+    wrmsr(0x175, current_pcb->thread->rbp);
+
+    // 向MSR寄存器组中的 IA32_SYSENTER_EIP寄存器写入系统调用入口的地址。
+    wrmsr(0x176, (ul)system_call);
     // 初始化进程和tss
     set_tss64((uint *)phys_2_virt(TSS64_Table), 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;
+    /*
     kdebug("initial_thread.rbp=%#018lx", initial_thread.rbp);
     kdebug("initial_tss[0].rsp1=%#018lx", initial_tss[0].rsp1);
     kdebug("initial_tss[0].ist1=%#018lx", initial_tss[0].ist1);
-
+*/
     // 初始化进程的循环链表
     list_init(&initial_proc_union.pcb.list);
-
+    current_pcb->flags=0;
     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(&current_pcb->list), struct process_control_block, list);
+    // struct process_control_block *p = container_of(list_next(&current_pcb->list), struct process_control_block, list);
 
     kdebug("Ready to switch...");
     // 切换到新的内核线程
-    switch_proc(current_pcb, p);
+    // switch_proc(current_pcb, p);
 }
 
 /**
@@ -296,6 +304,8 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
     // 将当前进程的pcb复制到新的pcb内
     *tsk = *current_pcb;
 
+    kdebug("current_pcb->flags=%#010lx", current_pcb->flags);
+
     // 将进程加入循环链表
     list_init(&tsk->list);
 
@@ -306,6 +316,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
 
     // 将线程结构体放置在pcb的后面
     struct thread_struct *thd = (struct thread_struct *)(tsk + 1);
+    memset(thd, 0, sizeof(struct thread_struct));
     tsk->thread = thd;
 
     // 将寄存器信息存储到进程的内核栈空间的顶部
@@ -321,6 +332,10 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
     // 若进程不是内核层的进程,则跳转到ret from system call
     if (!(tsk->flags & PF_KTHREAD))
         thd->rip = regs->rip = (ul)ret_from_system_call;
+    else
+        kdebug("is kernel proc.");
+
+    kdebug("ret_from_system_call=%#018lx", (ul)ret_from_system_call);
 
     tsk->state = PROC_RUNNING;
 

+ 5 - 5
kernel/smp/smp.c

@@ -24,7 +24,7 @@ void smp_init()
 
     apic_get_ics(ACPI_ICS_TYPE_PROCESSOR_LOCAL_APIC, tmp_vaddr, &total_processor_num);
 
-    kdebug("processor num=%d", total_processor_num);
+    //kdebug("processor num=%d", total_processor_num);
     for (int i = 0; i < total_processor_num; ++i)
         proc_local_apic_structs[i] = (struct acpi_Processor_Local_APIC_Structure_t *)(tmp_vaddr[i]);
 
@@ -56,10 +56,10 @@ void smp_init()
         set_tss_descriptor(10 + (i * 2), (void *)virt_2_phys(cpu_core_info[i].tss_vaddr));
 
         set_tss64((uint *)cpu_core_info[i].tss_vaddr, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start);
-        kdebug("phys_2_virt(GDT_Table)=%#018lx",phys_2_virt(GDT_Table));
-        kdebug("GDT Table %#018lx, \t %#018lx", *(ul *)(phys_2_virt(GDT_Table) + 10 + i * 2), *(ul *)(phys_2_virt(GDT_Table) + 10 + i * 2 + 1));
+        //kdebug("phys_2_virt(GDT_Table)=%#018lx",phys_2_virt(GDT_Table));
+        //kdebug("GDT Table %#018lx, \t %#018lx", *(ul *)(phys_2_virt(GDT_Table) + 10 + i * 2), *(ul *)(phys_2_virt(GDT_Table) + 10 + i * 2 + 1));
         // kdebug("(cpu_core_info[i].tss_vaddr)=%#018lx", (cpu_core_info[i].tss_vaddr));
-        kdebug("(cpu_core_info[i].stack_start)=%#018lx", (cpu_core_info[i].stack_start));
+        //kdebug("(cpu_core_info[i].stack_start)=%#018lx", (cpu_core_info[i].stack_start));
         // 连续发送两次start-up IPI
         ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand, true, proc_local_apic_structs[i]->ACPI_ID);
         ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand, true, proc_local_apic_structs[i]->ACPI_ID);
@@ -111,7 +111,7 @@ void smp_ap_start()
     load_TR(10 + current_starting_cpu * 2);
 
     sti();
-    kdebug("IDT_addr = %#018lx", phys_2_virt(IDT_Table));
+    //kdebug("IDT_addr = %#018lx", phys_2_virt(IDT_Table));
     memset(current_pcb, 0, sizeof(struct process_control_block));
     spin_unlock(&multi_core_starting_lock);
     while (1) // 这里要循环hlt,原因是当收到中断后,核心会被唤醒,处理完中断之后不会自动hlt

+ 7 - 4
kernel/syscall/syscall.c

@@ -26,9 +26,11 @@ void syscall_init()
     wrmsr(0x174, KERNEL_CS);
     // 向MSR寄存器组中的 IA32_SYSENTER_ESP寄存器写入内核进程的rbp(在syscall入口中会将rsp减去相应的数值)
     wrmsr(0x175, current_pcb->thread->rbp);
+    
 
     // 向MSR寄存器组中的 IA32_SYSENTER_EIP寄存器写入系统调用入口的地址。
     wrmsr(0x176, (ul)system_call);
+    
 }
 
 long enter_syscall(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg4, ul arg5, ul arg6, ul arg7)
@@ -65,10 +67,11 @@ long enter_syscall(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg4, u
  */
 ul sys_printf(struct pt_regs *regs)
 {
-    while(1);
-    if(regs->r9 == 0 &&regs->r10 == 0)
-        printk((char*)regs->r8);
-    else printk_color(regs->r9, regs->r10, (char*)regs->r8);
+    
+    //if(regs->r9 == 0 &&regs->r10 == 0)
+    //    printk((char*)regs->r8);
+    //else printk_color(regs->r9, regs->r10, (char*)regs->r8);
+    printk_color(BLACK,WHITE,(char *)regs->rdi);
 
     return 0;
 }

+ 1 - 1
run.sh

@@ -12,7 +12,7 @@ if [ ! "$1" == "--nobuild" ]; then
     make clean
 fi
 
-IA32_USE_QEMU=0
+IA32_USE_QEMU=1
 bochsrc="./bochsrc"
 ARCH="x86_64"