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

This commit is contained in:
fslongjin 2022-04-11 10:32:39 +08:00
parent c09c6d4e66
commit dacc29310f
9 changed files with 96 additions and 79 deletions

View File

@ -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;
}

View File

@ -104,9 +104,11 @@ Err_Code:
//
//
ENTRY(system_call)
// sysenter
sti;
hlt
subq $0x38, %rsp
cld;
@ -137,6 +139,7 @@ ENTRY(system_call)
// rspsystem_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) // raxrax
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 // popds
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

View File

@ -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");

View File

@ -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!");

View File

@ -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!");

View File

@ -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);
}
@ -52,17 +49,20 @@ void user_level_function()
// 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";
// 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");
__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...");
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)
;
@ -90,9 +90,9 @@ ul do_execve(struct pt_regs *regs)
uint64_t addr = 0x800000UL;
unsigned long * tmp = phys_2_virt((unsigned long *)((unsigned long)get_CR3() & (~0xfffUL)) + (( addr>> PAGE_GDT_SHIFT) & 0x1ff));
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 *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;

View File

@ -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

View File

@ -27,8 +27,10 @@ void syscall_init()
// 向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;
}

2
run.sh
View File

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