From f5f36aafd813d6d96c29ad1628d3f3db9b780b93 Mon Sep 17 00:00:00 2001 From: fslongjin Date: Sun, 10 Apr 2022 21:30:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E5=86=85=E6=A0=B8=E5=AE=9A=E4=BD=8D?= =?UTF-8?q?=E5=88=B0=E9=AB=98=E5=9C=B0=E5=9D=80=EF=BC=88=E5=AD=98=E5=9C=A8?= =?UTF-8?q?bug=EF=BC=8C=E4=B8=AD=E6=96=AD=E6=97=B6=E4=BC=9A=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E4=BD=8E=E5=9C=B0=E5=9D=80=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bochsrc | 2 +- kernel/driver/disk/ahci/ahci.c | 26 +++++-- kernel/driver/interrupt/apic/apic.c | 13 ++++ kernel/driver/interrupt/apic/apic.h | 2 + kernel/driver/pci/pci.c | 6 +- kernel/driver/timers/HPET/HPET.c | 69 +++++++++++++---- kernel/exception/entry.S | 16 +++- kernel/exception/gate.h | 56 +++++++++----- kernel/exception/irq.c | 6 +- kernel/exception/trap.c | 43 +++++------ kernel/head.S | 105 ++++++++++++++++++++++---- kernel/link.lds | 17 +++-- kernel/main.c | 78 ++++++++++++++----- kernel/mm/mm.c | 84 ++++++++++++++++----- kernel/mm/mm.h | 10 ++- kernel/process/process.c | 86 ++++++++++++++++----- kernel/process/process.h | 45 +++++------ kernel/sched/sched.c | 112 ++++++++++++++++++++++++++++ kernel/sched/sched.h | 41 ++++++++++ kernel/smp/apu_boot.S | 48 +----------- kernel/smp/smp.c | 59 +++++++++++---- kernel/syscall/syscall.c | 1 + run.sh | 2 +- 23 files changed, 689 insertions(+), 238 deletions(-) create mode 100644 kernel/sched/sched.c create mode 100644 kernel/sched/sched.h diff --git a/bochsrc b/bochsrc index aba91f47..f4e59008 100644 --- a/bochsrc +++ b/bochsrc @@ -19,7 +19,7 @@ ata1-master: type=cdrom, path="DragonOS.iso", status=inserted ata2: enabled=0 ata3: enabled=0 pci: enabled=1, chipset=i440fx -vga: extension=vbe, update_freq=5 +vga: extension=vbe, update_freq=30 cpu: count=1:2:1, ips=4000000, quantum=16, model=corei7_haswell_4770, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0, msrs="msrs.def" diff --git a/kernel/driver/disk/ahci/ahci.c b/kernel/driver/disk/ahci/ahci.c index 77da7380..af32d93e 100644 --- a/kernel/driver/disk/ahci/ahci.c +++ b/kernel/driver/disk/ahci/ahci.c @@ -6,8 +6,8 @@ struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES]; uint32_t count_ahci_devices = 0; -uint64_t ahci_port_base_vaddr; // 端口映射base addr -uint64_t ahci_port_base_phys_addr; // 端口映射的物理基地址(ahci控制器的参数的地址都是物理地址) +uint64_t ahci_port_base_vaddr; // 端口映射base addr +uint64_t ahci_port_base_phys_addr; // 端口映射的物理基地址(ahci控制器的参数的地址都是物理地址) static void start_cmd(HBA_PORT *port); static void stop_cmd(HBA_PORT *port); @@ -27,12 +27,20 @@ void ahci_init() { kinfo("Initializing AHCI..."); pci_get_device_structure(0x1, 0x6, ahci_devs, &count_ahci_devices); - + + if (count_ahci_devices == 0) + { + kwarn("There is no AHCI device found on this computer!"); + return; + } // 映射ABAR - mm_map_phys_addr(AHCI_MAPPING_BASE, ((ul)(((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); - // kdebug("ABAR mapped!"); + kdebug("phys_2_virt(ahci_devs[0])= %#018lx",(ahci_devs[0])); + kdebug("((struct pci_device_structure_general_device_t *)phys_2_virt(ahci_devs[0])))->BAR5= %#018lx",((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5); + uint32_t bar5 = ((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5; - for (int i = 0; i < count_ahci_devices; ++i) + mm_map_phys_addr(AHCI_MAPPING_BASE, (ul)(bar5) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + kdebug("ABAR mapped!"); + for (int i = 0; i < count_ahci_devices; ++i) { // kdebug("[%d] class_code=%d, sub_class=%d, progIF=%d, ABAR=%#010lx", i, ahci_devs[i]->Class_code, ahci_devs[i]->SubClass, ahci_devs[i]->ProgIF, ((struct pci_device_structure_general_device_t *)(ahci_devs[i]))->BAR5); // 赋值HBA_MEM结构体 @@ -40,16 +48,18 @@ void ahci_init() ahci_devices[i].hba_mem = (HBA_MEM *)(cal_HBA_MEM_VIRT_ADDR(i)); kdebug("ahci_devices[i].hba_mem = %#018lx", (ul)ahci_devices[i].hba_mem); } + // todo: 支持多个ahci控制器。 ahci_port_base_vaddr = (uint64_t)kmalloc(1048576, 0); kdebug("ahci_port_base_vaddr=%#018lx", ahci_port_base_vaddr); ahci_probe_port(0); port_rebase(&ahci_devices[0].hba_mem->ports[0], 0); - + // 初始化请求队列 ahci_req_queue.in_service = NULL; list_init(&(ahci_req_queue.queue_list)); ahci_req_queue.request_count = 0; + kinfo("AHCI initialized."); } // Check device type @@ -186,7 +196,7 @@ static void port_rebase(HBA_PORT *port, int portno) memset((void *)phys_2_virt(cmdheader[i].ctba), 0, 256); } - + start_cmd(port); // Start command engine } diff --git a/kernel/driver/interrupt/apic/apic.c b/kernel/driver/interrupt/apic/apic.c index 422cd30c..7397a338 100644 --- a/kernel/driver/interrupt/apic/apic.c +++ b/kernel/driver/interrupt/apic/apic.c @@ -425,6 +425,19 @@ void apic_init() apic_io_apic_init(); + // get RCBA address + io_out32(0xcf8, 0x8000f8f0); + uint32_t RCBA_phys = io_in32(0xcfc); + + // 获取RCBA寄存器的地址 + if (RCBA_phys > 0xfec00000 && RCBA_phys < 0xfee00000) + RCBA_vaddr = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + RCBA_phys; + else + { + RCBA_vaddr = 0; + kwarn("Cannot get RCBA address. RCBA_phys=%#010lx", RCBA_phys); + + } sti(); } /** diff --git a/kernel/driver/interrupt/apic/apic.h b/kernel/driver/interrupt/apic/apic.h index 8df6b0b3..82e6ab99 100644 --- a/kernel/driver/interrupt/apic/apic.h +++ b/kernel/driver/interrupt/apic/apic.h @@ -73,6 +73,8 @@ // 分频配置寄存器(定时器专用) #define LOCAL_APIC_OFFSET_Local_APIC_CLKDIV 0x3e0 +uint32_t RCBA_vaddr = 0;// RCBA寄存器的虚拟地址 + /* 1: LVT CMCI diff --git a/kernel/driver/pci/pci.c b/kernel/driver/pci/pci.c index 0668e04a..a6ac1dd2 100644 --- a/kernel/driver/pci/pci.c +++ b/kernel/driver/pci/pci.c @@ -447,7 +447,7 @@ void pci_init() { if (ptr->Status & 0x10) { - kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\tcap_pointer=%#010lx", i, ptr->Class_code, ptr->SubClass, ptr->Status, ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer); + kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\tcap_pointer=%#010lx\tbar5=%#010lx", i, ptr->Class_code, ptr->SubClass, ptr->Status, ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer, ((struct pci_device_structure_general_device_t *)ptr)->BAR5); uint32_t tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer); } else @@ -592,8 +592,8 @@ void pci_get_device_structure(uint8_t class_code, uint8_t sub_class, struct pci_ { if ((ptr->Class_code == 1) && (ptr->SubClass == 6)) { - kdebug("[%d] class_code=%d, sub_class=%d, progIF=%d", i, ptr->Class_code, ptr->SubClass, ptr->ProgIF); - + kdebug("[%d] class_code=%d, sub_class=%d, progIF=%d, bar5=%#010lx", i, ptr->Class_code, ptr->SubClass, ptr->ProgIF,((struct pci_device_structure_general_device_t *)ptr)->BAR5); + res[*count_res] = ptr; ++(*count_res); } diff --git a/kernel/driver/timers/HPET/HPET.c b/kernel/driver/timers/HPET/HPET.c index e7b4a228..719e3f85 100644 --- a/kernel/driver/timers/HPET/HPET.c +++ b/kernel/driver/timers/HPET/HPET.c @@ -57,7 +57,7 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs) // 若当前时间比定时任务的时间间隔大,则进入中断下半部 if (container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list)->expire_jiffies <= timer_jiffies) set_softirq_status(TIMER_SIRQ); -/* + switch (current_pcb->priority) { case 0: @@ -74,7 +74,7 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs) if (sched_cfs_ready_queue.cpu_exec_proc_jiffies <= 0) current_pcb->flags |= PROC_NEED_SCHED; -*/ + break; default: @@ -85,32 +85,72 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs) int HPET_init() { + kinfo("Initializing HPET..."); // 从acpi获取hpet结构体 ul hpet_table_addr = 0; acpi_iter_SDT(acpi_get_HPET, &hpet_table_addr); + + // ACPI表没有HPET,尝试读HPTC if (hpet_table_addr == 0) { - kerror("HPET Not Found On This Computer!"); - return E_HPET_INIT_FAILED; + kwarn("ACPI: HPET Table Not Found On This Computer!"); + + if (RCBA_vaddr != 0) + { + kerror("NO HPET found on this computer!"); + uint32_t *hptc = (uint32_t *)(RCBA_vaddr + 0x3404UL); + // enable HPET + io_mfence(); + // 读取HPET配置寄存器地址 + switch ((*hptc) & 0x3) + { + case 0: + HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed00000; + break; + case 1: + HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed01000; + break; + case 2: + HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed02000; + break; + case 3: + HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed03000; + break; + default: + break; + } + // enable HPET + *hptc = 0x80; + io_mfence(); + } + else + { + // 没有RCBA寄存器,采用默认值 + HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + 0xfed00000; + kwarn("There is no RCBA register on this computer, and HPET regs base use default value."); + } } - hpet_table = (struct acpi_HPET_description_table_t *)hpet_table_addr; - // 由于这段内存与io/apic的映射在同一物理页内,因此不需要重复映射 - HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + hpet_table->address; + else // ACPI表中有HPET表 + { + hpet_table = (struct acpi_HPET_description_table_t *)hpet_table_addr; + kdebug("hpet_table_addr=%#018lx", hpet_table_addr); + + // 由于这段内存与io/apic的映射在同一物理页内,因此不需要重复映射 + HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + hpet_table->address; + } + // 读取计时精度并计算频率 uint64_t tmp; tmp = *(uint64_t *)(HPET_REG_BASE + GCAP_ID); HPET_COUNTER_CLK_PERIOD = (tmp >> 32) & 0xffffffff; HPET_freq = 1.0 * 1e15 / HPET_COUNTER_CLK_PERIOD; HPET_NUM_TIM_CAP = (tmp >> 8) & 0x1f; // 读取计时器数量 - double x = 1*2; - x = 1.0*3.65; - //kinfo("HPET CLK_PERIOD=%#03lx Frequency=%f", HPET_COUNTER_CLK_PERIOD, (double)HPET_freq); - + + // kinfo("HPET CLK_PERIOD=%#03lx Frequency=%f", HPET_COUNTER_CLK_PERIOD, (double)HPET_freq); + struct apic_IO_APIC_RTE_entry entry; // 使用I/O APIC 的IRQ2接收hpet定时器0的中断 apic_make_rte_entry(&entry, 34, IO_APIC_FIXED, DEST_PHYSICAL, IDLE, POLARITY_HIGH, IRR_RESET, EDGE_TRIGGER, MASKED, 0); - // 注册中断 - irq_register(34, &entry, &HPET_handler, 0, &HPET_intr_controller, "HPET0"); *(uint64_t *)(HPET_REG_BASE + GEN_CONF) = 3; // 置位旧设备中断路由兼容标志位、定时器组使能标志位 io_mfence(); @@ -123,4 +163,7 @@ int HPET_init() rtc_get_cmos_time(&rtc_now); *(uint64_t *)(HPET_REG_BASE + MAIN_CNT) = 0; io_mfence(); + // 注册中断 + irq_register(34, &entry, &HPET_handler, 0, &HPET_intr_controller, "HPET0"); + kinfo("HPET Initialized."); } \ No newline at end of file diff --git a/kernel/exception/entry.S b/kernel/exception/entry.S index c3938d0c..e7013ad2 100644 --- a/kernel/exception/entry.S +++ b/kernel/exception/entry.S @@ -1,4 +1,6 @@ #include"../common/asm.h" +.code64 +.section .text R15 = 0x00 R14 = 0x08 @@ -54,6 +56,7 @@ Restore_all: ret_from_exception: // === 从中断中返回 === + .code64 ENTRY(ret_from_intr) jmp Restore_all @@ -85,18 +88,18 @@ Err_Code: pushq %r15 cld - + movq ERRCODE(%rsp), %rsi // 把错误码装进rsi,作为函数的第二个参数 movq FUNC(%rsp), %rdx - + movq $0x10, %rdi // 加载内核段的地址 movq %rdi, %ds movq %rdi, %es movq %rsp, %rdi // 把栈指针装入rdi,作为函数的第一个的参数 - callq *%rdx //调用服务程序 带*号表示调用的是绝对地址 - + + callq %rdx //调用服务程序 带*号表示调用的是绝对地址 jmp ret_from_exception // 系统调用入口 @@ -174,6 +177,7 @@ ENTRY(ret_from_system_call) // 0 #DE 除法错误 ENTRY(divide_error) + pushq $0 //由于#DE不会产生错误码,但是为了保持弹出结构的一致性,故也压入一个错误码0 pushq %rax // 先将rax入栈 leaq do_divide_error(%rip), %rax // 获取中断服务程序的地址 @@ -333,3 +337,7 @@ ENTRY(virtualization_exception) leaq do_virtualization_exception(%rip), %rax // 获取中断服务程序的地址 xchgq %rax, (%rsp) // 把FUNC的地址换入栈中 jmp Err_Code + + +ENTRY(_stack_start) + .quad initial_proc_union + 32768 \ No newline at end of file diff --git a/kernel/exception/gate.h b/kernel/exception/gate.h index af234850..5d519496 100644 --- a/kernel/exception/gate.h +++ b/kernel/exception/gate.h @@ -10,6 +10,7 @@ #define __GATE_H__ #include "../common/kprint.h" +#include //描述符表的结构体 struct desc_struct @@ -27,6 +28,18 @@ extern struct desc_struct GDT_Table[]; // GDT_Table是head.S中的GDT_Table extern struct gate_struct IDT_Table[]; // IDT_Table是head.S中的IDT_Table extern unsigned int TSS64_Table[26]; +struct gdtr +{ + uint16_t size; + uint64_t gdt_vaddr; +}__attribute__((packed)); + +struct idtr +{ + uint16_t size; + uint64_t idt_vaddr; +}__attribute__((packed)); + /** * @brief 初始化中段描述符表内的门描述符(每个16B) * @param gate_selector_addr IDT表项的地址 @@ -86,8 +99,10 @@ void set_tss_descriptor(unsigned int n, void *addr) { unsigned long limit = 103; - *(unsigned long *)(&GDT_Table[n]) = (limit & 0xffff) | (((unsigned long)addr & 0xffff) << 16) | ((((unsigned long)addr >> 16) & 0xff) << 32) | ((unsigned long)0x89 << 40) | ((limit >> 16 & 0xf) << 48) | (((unsigned long)addr >> 24 & 0xff) << 56); /////89 is attribute - *(unsigned long *)(&GDT_Table[n + 1]) = (((unsigned long)addr >> 32) & 0xffffffff) | 0; + + *(unsigned long *)(phys_2_virt(GDT_Table) + n) = (limit & 0xffff) | (((unsigned long)addr & 0xffff) << 16) | ((((unsigned long)addr >> 16) & 0xff) << 32) | ((unsigned long)0x89 << 40) | ((limit >> 16 & 0xf) << 48) | (((unsigned long)addr >> 24 & 0xff) << 56); /////89 is attribute + kdebug("1212"); + *(unsigned long *)(phys_2_virt(GDT_Table) + n + 1) = (((unsigned long)addr >> 32) & 0xffffffff) | 0; } /** @@ -110,8 +125,9 @@ void set_tss_descriptor(unsigned int n, void *addr) */ void set_intr_gate(unsigned int n, unsigned char ist, void *addr) { - _set_gate((IDT_Table + n), 0x8E, ist, addr); // p=1,DPL=0, type=E - // set_gate((ul *)(IDT_Table + n), 0x8E, ist, (ul *)(addr)); // p=1,DPL=0, type=E + _set_gate(phys_2_virt(IDT_Table + n), 0x8E, ist, addr); // p=1,DPL=0, type=E + + //set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8E, ist, (ul *)(addr)); // p=1,DPL=0, type=E } /** @@ -125,8 +141,8 @@ void set_trap_gate(unsigned int n, unsigned char ist, void *addr) { // kdebug("addr=%#018lx", (ul)(addr)); - // set_gate((ul *)(IDT_Table + n), 0x8F, ist, (ul *)(addr)); // p=1,DPL=0, type=F - _set_gate((IDT_Table + n), 0x8F, ist, addr); // p=1,DPL=0, type=F + //set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8F, ist, (ul *)(addr)); // p=1,DPL=0, type=F + _set_gate(phys_2_virt(IDT_Table + n), 0x8F, ist, addr); // p=1,DPL=0, type=F } /** @@ -140,8 +156,8 @@ void set_system_trap_gate(unsigned int n, unsigned char ist, void *addr) { // kdebug("addr=%#018lx", (ul)(addr)); - // set_gate((ul *)(IDT_Table + n), 0xEF, ist, (ul *)(addr)); // p=1,DPL=3, type=F - _set_gate((IDT_Table + n), 0xEF, ist, addr); // p=1,DPL=3, type=F + //set_gate((ul *)phys_2_virt(IDT_Table + n), 0xEF, ist, (ul *)(addr)); // p=1,DPL=3, type=F + _set_gate(phys_2_virt(IDT_Table + n), 0xEF, ist, addr); // p=1,DPL=3, type=F } /** @@ -149,19 +165,19 @@ void set_system_trap_gate(unsigned int n, unsigned char ist, void *addr) * */ -void set_tss64(unsigned int * Table,unsigned long rsp0,unsigned long rsp1,unsigned long rsp2,unsigned long ist1,unsigned long ist2,unsigned long ist3, -unsigned long ist4,unsigned long ist5,unsigned long ist6,unsigned long ist7) +void set_tss64(unsigned int *Table, unsigned long rsp0, unsigned long rsp1, unsigned long rsp2, unsigned long ist1, unsigned long ist2, unsigned long ist3, + unsigned long ist4, unsigned long ist5, unsigned long ist6, unsigned long ist7) { - *(unsigned long *)(Table+1) = rsp0; - *(unsigned long *)(Table+3) = rsp1; - *(unsigned long *)(Table+5) = rsp2; + *(unsigned long *)(Table + 1) = rsp0; + *(unsigned long *)(Table + 3) = rsp1; + *(unsigned long *)(Table + 5) = rsp2; - *(unsigned long *)(Table+9) = ist1; - *(unsigned long *)(Table+11) = ist2; - *(unsigned long *)(Table+13) = ist3; - *(unsigned long *)(Table+15) = ist4; - *(unsigned long *)(Table+17) = ist5; - *(unsigned long *)(Table+19) = ist6; - *(unsigned long *)(Table+21) = ist7; + *(unsigned long *)(Table + 9) = ist1; + *(unsigned long *)(Table + 11) = ist2; + *(unsigned long *)(Table + 13) = ist3; + *(unsigned long *)(Table + 15) = ist4; + *(unsigned long *)(Table + 17) = ist5; + *(unsigned long *)(Table + 19) = ist6; + *(unsigned long *)(Table + 21) = ist7; } #endif \ No newline at end of file diff --git a/kernel/exception/irq.c b/kernel/exception/irq.c index 4e9c3054..68eb6052 100644 --- a/kernel/exception/irq.c +++ b/kernel/exception/irq.c @@ -203,6 +203,10 @@ void irq_init() #else apic_init(); - memset(interrupt_desc, 0, sizeof(irq_desc_t) * IRQ_NUM); + kdebug("interrupt_desc=%#018lx",(void*)interrupt_desc); + kdebug("irq_init()=%#018lx",(void*)irq_init); + + memset((void*)interrupt_desc, 0, sizeof(irq_desc_t) * IRQ_NUM); + #endif } diff --git a/kernel/exception/trap.c b/kernel/exception/trap.c index b7562029..83efd6ba 100644 --- a/kernel/exception/trap.c +++ b/kernel/exception/trap.c @@ -58,7 +58,6 @@ void sys_vector_init() // 0 #DE 除法错误 void do_divide_error(struct pt_regs *regs, unsigned long error_code) { - kerror("do_divide_error(0)"); //kerror("do_divide_error(0),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); @@ -243,33 +242,35 @@ 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; - // 先保存cr2寄存器的值,避免由于再次触发页故障而丢失值 - // cr2存储着触发异常的线性地址 - __asm__ __volatile__("movq %%cr2, %0" - : "=r"(cr2)::"memory"); - kerror("do_page_fault(14),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\tCR2:%#18lx\n", error_code, regs->rsp, regs->rip, cr2); + __asm__ __volatile__("movq %%cr2, %0":"=r"(cr2)::"memory"); + + kerror("do_page_fault(14),Error code :%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - printk_color(YELLOW, BLACK, "Information:\n"); - if (!(error_code & 0x01)) - printk("Page does not exist.\n"); + if(!(error_code & 0x01)) + printk_color(RED,BLACK,"Page Not-Present,\t"); - if (error_code & 0x02) - printk("Fault occurred during operation: writing\n"); - else - printk("Fault occurred during operation: reading\n"); + if(error_code & 0x02) + printk_color(RED,BLACK,"Write Cause Fault,\t"); + else + printk_color(RED,BLACK,"Read Cause Fault,\t"); - if (error_code & 0x04) - printk("Fault in user level(3).\n"); - else - printk("Fault in supervisor level(0,1,2).\n"); + if(error_code & 0x04) + printk_color(RED,BLACK,"Fault in user(3)\t"); + else + printk_color(RED,BLACK,"Fault in supervisor(0,1,2)\t"); - if (error_code & 0x08) - printk("Reserved bit caused the fault.\n"); + if(error_code & 0x08) + printk_color(RED,BLACK,",Reserved Bit Cause Fault\t"); - if (error_code & 0x10) - printk("Fault occurred during fetching instruction.\n"); + if(error_code & 0x10) + printk_color(RED,BLACK,",Instruction fetch Cause Fault"); + + printk_color(RED,BLACK,"\n"); + + printk_color(RED,BLACK,"CR2:%#018lx\n",cr2); while (1) ; diff --git a/kernel/head.S b/kernel/head.S index 10e0757c..f413eac8 100644 --- a/kernel/head.S +++ b/kernel/head.S @@ -269,8 +269,17 @@ enter_head_from_ap_boot: hlt ret .code64 +.global ready_to_start_64 ready_to_start_64: + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %ss + mov $0x7e00, %esp + + //6. 跳转到start64 movq switch_to_start64(%rip), %rax pushq $0x08 //段选择子 @@ -281,19 +290,23 @@ switch_to_start64: .quad _start64 - .code64 +is_from_ap: + + hlt + .global _start64 .type _start64, @function .extern Start_Kernel ENTRY(_start64) + + // 初始化寄存器 mov $0x10, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %ss - mov $0x7e00, %esp // === 加载GDTR ==== @@ -302,13 +315,7 @@ ENTRY(_start64) // === 加载IDTR ==== lidt IDT_POINTER(%rip) //lidt $IDT_POINTER - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %ss - mov %ax, %gs - + movq GDT_POINTER(%rip), %r12 movq _stack_start(%rip), %rsp // 分支,判断是否为apu @@ -333,10 +340,13 @@ ENTRY(_start64) // ==== 加载CR3寄存器 -load_cr3: - movq $__PML4E, %rax //设置页目录基地址 - movq %rax, %cr3 +load_cr3: + // 分支,判断是否为apu + movq $__PML4E, %rax //设置页目录基地址 + + movq %rax, %cr3 + movq switch_seg(%rip), %rax // 由于ljmp和lcall在GAS中不受支持,因此我们需要先伪造函数调用现场,通过lret的方式,给它跳转过去。才能更新cs寄存器 // 实在是太妙了!Amazing! @@ -360,6 +370,21 @@ entry64: movq _stack_start(%rip), %rsp //rsp的地址 + // 重新加载GDT和IDT,加载到高地址 + leaq GDT_Table(%rip), %r8 + leaq GDT_END(%rip), %r9 + + subq %r8, %r9 + movq %r9, %r13 // GDT size + + leaq IDT_Table(%rip), %r8 + leaq IDT_END(%rip), %r9 + + subq %r8, %r9 + movq %r9, %r12 // IDT size + + lgdt GDT_POINTER64(%rip) + lidt IDT_POINTER64(%rip) // 分支,判断是否为apu movq $0x1b, %rcx // 根据IA32_APIC_BASE.BSP[8]标志位判断处理器是否为apu @@ -399,6 +424,10 @@ SetUp_TSS64: // == 设置64位的任务状态段表 === //rdx保存高8B, rax保存低8B leaq TSS64_Table(%rip), %rdx + + movq $0xffff800000000000, %r8 + addq %r8, %rdx + xorq %rax, %rax xorq %rcx, %rcx @@ -440,23 +469,57 @@ SetUp_TSS64: or $(3 << 9), %ax //set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time movq %rax, %cr4 - //call Start_Kernel + + movq go_to_kernel(%rip), %rax /* movq address */ pushq $0x08 pushq %rax - movq mb2_info, %r15 + + movq mb2_info, %r15 movq mb2_magic, %r14 + + lretq go_to_kernel: .quad Start_Kernel start_smp: + + + //now enable SSE and the like + movq %cr0, %rax + and $0xFFFB, %ax //clear coprocessor emulation CR0.EM + or $0x2, %ax //set coprocessor monitoring CR0.MP + movq %rax, %cr0 + movq %cr4, %rax + or $(3 << 9), %ax //set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time + movq %rax, %cr4 + + movq go_to_smp_kernel(%rip), %rax /* movq address */ pushq $0x08 pushq %rax + +/* + // 重新加载GDT和IDT,加载到高地址 + leaq GDT_Table(%rip), %r8 + leaq GDT_END(%rip), %r9 + + subq %r8, %r9 + movq %r9, %r13 // GDT size + + leaq IDT_Table(%rip), %r8 + leaq IDT_END(%rip), %r9 + + subq %r8, %r9 + movq %r9, %r12 // IDT size + + lgdt GDT_POINTER64(%rip) + lidt IDT_POINTER64(%rip) +*/ lretq go_to_smp_kernel: @@ -484,10 +547,10 @@ ENTRY(_stack_start) // 初始化页表 .align 0x1000 //设置为4k对齐 -.org 0x1000 //设置页表位置为内核执行头程序的0x1000处 +//.org 0x1000 //设置页表位置为内核执行头程序的0x1000处 __PML4E: - .quad 0x103003 // 用户访问,可读写,已存在, 地址在31~12位 + .quad 0x103007 // 用户访问,可读写,已存在, 地址在31~12位 .fill 255,8,0 .quad 0x103003 .fill 255,8,0 @@ -575,6 +638,11 @@ GDT_POINTER: GDT_LIMIT: .word GDT_END - GDT_Table - 1 // GDT的大小 GDT_BASE: .quad GDT_Table +.global GDT_POINTER64 +GDT_POINTER64: +GDT_LIMIT64: .word GDT_END - GDT_Table - 1 // GDT的大小 +GDT_BASE64: .quad GDT_Table + 0xffff800000000000 + // IDT 表 .global IDT_Table @@ -587,6 +655,11 @@ IDT_POINTER: IDT_LIMIT: .word IDT_END - IDT_Table - 1 IDT_BASE: .quad IDT_Table +.global IDT_POINTER64 +IDT_POINTER64: +IDT_LIMIT64: .word IDT_END - IDT_Table - 1 +IDT_BASE64: .quad IDT_Table + 0xffff800000000000 + // 64位的TSS表 .global TSS64_Table diff --git a/kernel/link.lds b/kernel/link.lds index db1684db..42127d3c 100644 --- a/kernel/link.lds +++ b/kernel/link.lds @@ -20,7 +20,8 @@ SECTIONS } . += KERNEL_VMA; - .text : AT(ADDR(.text) - KERNEL_VMA) + text_start_pa = .; + .text (text_start_pa): AT(text_start_pa - KERNEL_VMA) { _text = .; @@ -28,14 +29,16 @@ SECTIONS _etext = .; } . = ALIGN(8); - .data : AT(ADDR(.data) - KERNEL_VMA) + data_start_pa = .; + .data (data_start_pa): AT(data_start_pa - KERNEL_VMA) { _data = .; *(.data) _edata = .; } - .rodata : AT(ADDR(.rodata) - KERNEL_VMA) + rodata_start_pa = .; + .rodata (rodata_start_pa): AT(rodata_start_pa - KERNEL_VMA) { _rodata = .; *(.rodata) @@ -43,9 +46,13 @@ SECTIONS } . = ALIGN(32768); - .data.init_proc_union : AT(ADDR(.data.init_proc_union) - KERNEL_VMA) + + init_proc_union_start_pa = .; + .data.init_proc_union (init_proc_union_start_pa): AT(init_proc_union_start_pa - KERNEL_VMA) { *(.data.init_proc_union) } - .bss : AT(ADDR(.bss) - KERNEL_VMA) + + bss_start_pa = .; + .bss (bss_start_pa): AT(bss_start_pa - KERNEL_VMA) { _bss = .; *(.bss) diff --git a/kernel/main.c b/kernel/main.c index e1e2ae93..69fef6fb 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -29,6 +29,7 @@ #include unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址 +ul bsp_idt_size, bsp_gdt_size; struct memory_desc memory_management_struct = {{0}, 0}; // struct Global_Memory_Descriptor memory_management_struct = {{0}, 0}; @@ -143,44 +144,77 @@ void test_slab() kinfo("SLAB test completed!"); } +struct gdtr gdtp; +struct idtr idtp; +void reload_gdt() +{ + + gdtp.size = bsp_gdt_size-1; + gdtp.gdt_vaddr = (ul)phys_2_virt((ul)&GDT_Table); + //kdebug("gdtvaddr=%#018lx", p.gdt_vaddr); + //kdebug("gdt size=%d", p.size); + + asm volatile("lgdt (%0) \n\t" ::"r"(&gdtp) + : "memory"); +} + +void reload_idt() +{ + + idtp.size = bsp_idt_size-1; + idtp.idt_vaddr = (ul)phys_2_virt((ul)&IDT_Table); + //kdebug("gdtvaddr=%#018lx", p.gdt_vaddr); + //kdebug("gdt size=%d", p.size); + + asm volatile("lidt (%0) \n\t" ::"r"(&idtp) + : "memory"); +} + // 初始化系统各模块 void system_initialize() { // 初始化printk - + printk_init(8, 16); kinfo("Kernel Starting..."); + // 重新加载gdt和idt + ul tss_item_addr = (ul)phys_2_virt(0x7c00); + kdebug("TSS64_Table=%#018lx", (void *)TSS64_Table); + kdebug("&TSS64_Table=%#018lx", (void *)&TSS64_Table); + kdebug("_stack_start=%#018lx", _stack_start); load_TR(10); // 加载TR寄存器 - ul tss_item_addr = 0x7c00; - - set_tss64(TSS64_Table, _stack_start, _stack_start, _stack_start, tss_item_addr, + set_tss64((uint *)phys_2_virt(TSS64_Table), _stack_start, _stack_start, _stack_start, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr); cpu_core_info[0].stack_start = _stack_start; - cpu_core_info[0].tss_vaddr = &TSS64_Table; - + cpu_core_info[0].tss_vaddr = (uint64_t)phys_2_virt((uint64_t)TSS64_Table); + kdebug("cpu_core_info[0].tss_vaddr=%#018lx", cpu_core_info[0].tss_vaddr); + kdebug("cpu_core_info[0].stack_start%#018lx", cpu_core_info[0].stack_start); + + // 初始化中断描述符表 sys_vector_init(); // 初始化内存管理单元 mm_init(); - + acpi_init(); - for (int i = 0; i < 1e7; ++i) - ; // 初始化中断模块 + sched_init(); irq_init(); + softirq_init(); - timer_init(); - HPET_init(); - smp_init(); // 先初始化系统调用模块 syscall_init(); + // 再初始化进程模块。顺序不能调转 + sched_init(); + timer_init(); + smp_init(); cpu_init(); // ps2_keyboard_init(); // ps2_mouse_init(); @@ -189,10 +223,10 @@ void system_initialize() ahci_init(); // test_slab(); // test_mm(); - - // 再初始化进程模块。顺序不能调转 - // sched_init(); - // process_init(); + process_init(); + cli(); + HPET_init(); + sti(); } //操作系统内核从这里开始执行 @@ -203,12 +237,20 @@ void Start_Kernel(void) uint64_t mb2_info, mb2_magic; __asm__ __volatile__("movq %%r15, %0 \n\t" "movq %%r14, %1 \n\t" - : "=r"(mb2_info), "=r"(mb2_magic)::"memory"); + "movq %%r13, %2 \n\t" + "movq %%r12, %3 \n\t" + : "=r"(mb2_info), "=r"(mb2_magic), "=r"(bsp_gdt_size), "=r"(bsp_idt_size)::"memory"); + reload_gdt(); + reload_idt(); + + mb2_info &= 0xffffffff; mb2_magic &= 0xffffffff; multiboot2_magic = mb2_magic; - multiboot2_boot_info_addr = mb2_info+PAGE_OFFSET; + multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET; + + system_initialize(); /* diff --git a/kernel/mm/mm.c b/kernel/mm/mm.c index df484465..a45af772 100644 --- a/kernel/mm/mm.c +++ b/kernel/mm/mm.c @@ -6,7 +6,7 @@ ul Total_Memory = 0; ul total_2M_pages = 0; -static ul root_page_table_phys_addr=0; // 内核层根页表的物理地址 +static ul root_page_table_phys_addr = 0; // 内核层根页表的物理地址 void mm_init() { kinfo("Initializing memory management unit..."); @@ -190,22 +190,16 @@ void mm_init() } global_CR3 = get_CR3(); - //root_page_table_phys_addr = global_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("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!"); - /* - kinfo("Cleaning page table remapping at 0x0000"); - for (int i = 0; i < 10; ++i) - *(phys_2_virt(global_CR3) + i) = 0UL; - kinfo("Successfully cleaned page table remapping!\n"); - */ - flush_tlb(); // 初始化slab内存池 slab_init(); @@ -424,8 +418,9 @@ void free_pages(struct Page *page, int number) */ void page_table_init() { - kinfo("Initializing page table..."); + kinfo("Re-Initializing page table..."); global_CR3 = get_CR3(); + /* // 由于CR3寄存器的[11..0]位是PCID标志位,因此将低12位置0后,就是PML4页表的基地址 ul *pml4_addr = (ul *)((ul)phys_2_virt((ul)global_CR3 & (~0xfffUL))); kdebug("PML4 addr=%#018lx *pml4=%#018lx", pml4_addr, *pml4_addr); @@ -435,7 +430,7 @@ void page_table_init() ul *pd_addr = phys_2_virt(*pdpt_addr & (~0xfffUL)); kdebug("pd addr=%#018lx *pd=%#018lx", pd_addr, *pd_addr); - +*/ ul *tmp_addr; for (int i = 0; i < memory_management_struct.count_zones; ++i) { @@ -447,6 +442,8 @@ void page_table_init() for (int j = 0; j < z->count_pages; ++j) { + mm_map_phys_addr((ul)phys_2_virt(p->addr_phys), p->addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE); + /* // 计算出PML4页表中的页表项的地址 tmp_addr = (ul *)((ul)pml4_addr + ((((ul)phys_2_virt(p->addr_phys)) >> PAGE_GDT_SHIFT) & 0x1ff) * 8); @@ -472,7 +469,7 @@ void page_table_init() // 填入pd页表的页表项,映射2MB物理页 set_pdt(tmp_addr, mk_pdt(virt_2_phys(p->addr_phys), PAGE_KERNEL_PAGE)); - + */ // 测试 if (j % 50 == 0) kdebug("pd_addr=%#018lx, *pd_addr=%#018lx", tmp_addr, *tmp_addr); @@ -569,27 +566,77 @@ void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flag flush_tlb(); } +void mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags) +{ + global_CR3 = get_CR3(); + + // 计算线性地址对应的pml4页表项的地址 + ul *tmp = phys_2_virt((ul *)((ul)global_CR3 & (~0xfffUL)) + ((virt_addr_start >> PAGE_GDT_SHIFT) & 0x1ff)); + if (*tmp == 0) + { + ul *virt_addr = kmalloc(PAGE_4K_SIZE, 0); + set_pml4t(tmp, mk_pml4t(virt_2_phys(virt_addr), PAGE_USER_PGT)); + } + else + kdebug("*tmp != 0!!! \t tmp = %#018lx\t *tmp = %#018lx",tmp, *tmp); + + tmp = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + ((virt_addr_start >> PAGE_1G_SHIFT) & 0x1ff)); + + if (*tmp == 0) + { + ul *virt_addr = kmalloc(PAGE_4K_SIZE, 0); + set_pdpt(tmp, mk_pdpt(virt_2_phys(virt_addr), PAGE_USER_DIR)); + } + else + kdebug("*tmp != 0!!! \t tmp = %#018lx\t *tmp = %#018lx",tmp, *tmp); + + ul *tmp1; + // 初始化2M物理页 + for (ul i = 0; i < (length); i += PAGE_2M_SIZE) + { + // 计算当前2M物理页对应的pdt的页表项的物理地址 + tmp1 = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr_start + i) >> PAGE_2M_SHIFT) & 0x1ff)); + + // 页面写穿,禁止缓存 + set_pdt(tmp1, mk_pdt((ul)phys_addr_start + i, flags | PAGE_USER_PAGE)); + kdebug("mk_pdt((ul)phys_addr_start + i, flags | PAGE_USER_PAGE) = %#018lx",mk_pdt((ul)phys_addr_start + i, flags | PAGE_USER_PAGE)); + } + + flush_tlb(); +} + /** * @brief 将将物理地址填写到进程的页表的函数 * - * @param proc_page_table_addr 进程的页表的虚拟基地址 + * @param proc_page_table_addr 页表的基地址 + * @param is_phys 页表的基地址是否为物理地址 * @param virt_addr_start 要映射到的虚拟地址的起始位置 * @param phys_addr_start 物理地址的起始位置 * @param length 要映射的区域的长度(字节) * @param user 用户态是否可访问 */ -void mm_map_proc_page_table(ul *proc_page_table_addr, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user) +void mm_map_proc_page_table(ul *proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user) { // 计算线性地址对应的pml4页表项的地址 - ul *tmp = (ul *)((ul)proc_page_table_addr & (~0xfffUL)) + ((virt_addr_start >> PAGE_GDT_SHIFT) & 0x1ff); + ul *tmp; + if (is_phys) + tmp = phys_2_virt((ul *)((ul)proc_page_table_addr & (~0xfffUL)) + ((virt_addr_start >> PAGE_GDT_SHIFT) & 0x1ff)); + else + tmp = (ul *)((ul)proc_page_table_addr & (~0xfffUL)) + ((virt_addr_start >> PAGE_GDT_SHIFT) & 0x1ff); + + kdebug("tmp = %#018lx", tmp); if (*tmp == 0) { ul *virt_addr = kmalloc(PAGE_4K_SIZE, 0); set_pml4t(tmp, mk_pml4t(virt_2_phys(virt_addr), (user ? PAGE_USER_PGT : PAGE_KERNEL_PGT))); } + kdebug("*tmp = %#018lx", *tmp); - tmp = (ul *)(*tmp & (~0xfffUL)) + ((virt_addr_start >> PAGE_1G_SHIFT) & 0x1ff); + if (is_phys) + tmp = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + ((virt_addr_start >> PAGE_1G_SHIFT) & 0x1ff)); + else + tmp = (ul *)(*tmp & (~0xfffUL)) + ((virt_addr_start >> PAGE_1G_SHIFT) & 0x1ff); if (*tmp == 0) { @@ -602,7 +649,10 @@ void mm_map_proc_page_table(ul *proc_page_table_addr, ul virt_addr_start, ul phy for (ul i = 0; i < (length); i += PAGE_2M_SIZE) { // 计算当前2M物理页对应的pdt的页表项的物理地址 - tmp1 = ((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr_start + i) >> PAGE_2M_SHIFT) & 0x1ff)); + if (is_phys) + tmp1 = phys_2_virt(((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr_start + i) >> PAGE_2M_SHIFT) & 0x1ff))); + else + tmp1 = ((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr_start + i) >> PAGE_2M_SHIFT) & 0x1ff)); // 页面写穿,禁止缓存 set_pdt(tmp1, mk_pdt((ul)phys_addr_start + i, flags | (user ? PAGE_USER_PAGE : PAGE_KERNEL_PAGE))); diff --git a/kernel/mm/mm.h b/kernel/mm/mm.h index 2e3f7e57..d2b27e5f 100644 --- a/kernel/mm/mm.h +++ b/kernel/mm/mm.h @@ -8,7 +8,7 @@ // 内核层的起始地址 #define PAGE_OFFSET ((unsigned long)0xffff800000000000) -#define KERNEL_BASE_PHYS_ADDR ((unsigned long)0xffff800000000000) +#define KERNEL_BASE_LINEAR_ADDR ((unsigned long)0xffff800000000000) #define PAGE_4K_SHIFT 12 #define PAGE_2M_SHIFT 21 @@ -365,10 +365,14 @@ void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flag /** * @brief 将将物理地址填写到进程的页表的函数 * - * @param proc_page_table_addr 进程的页表的虚拟基地址 + * @param proc_page_table_addr 页表的基地址 + * @param is_phys 页表的基地址是否为物理地址 * @param virt_addr_start 要映射到的虚拟地址的起始位置 * @param phys_addr_start 物理地址的起始位置 * @param length 要映射的区域的长度(字节) * @param user 用户态是否可访问 */ -void mm_map_proc_page_table(ul *proc_page_table_addr, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user); \ No newline at end of file +void mm_map_proc_page_table(ul *proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user); + + +void mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags); \ No newline at end of file diff --git a/kernel/process/process.c b/kernel/process/process.c index 7e19a07b..a8c219b2 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -5,6 +5,8 @@ #include "../common/kprint.h" #include "../syscall/syscall.h" #include "../syscall/syscall_num.h" +#include +#include /** * @brief 切换进程 @@ -18,16 +20,26 @@ void __switch_to(struct process_control_block *prev, struct process_control_block *next) { initial_tss[0].rsp0 = next->thread->rbp; - set_tss64(TSS64_Table, initial_tss[0].rsp0, initial_tss[0].rsp1, initial_tss[0].rsp2, initial_tss[0].ist1, + 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); - __asm__ __volatile__("movq %%fs, %0 \n\t" - : "=a"(prev->thread->fs)); - __asm__ __volatile__("movq %%gs, %0 \n\t" - : "=a"(prev->thread->gs)); + kdebug("prev->thread=%#018lx", prev->thread); + kdebug("next->thread=%#018lx", next->thread); - __asm__ __volatile__("movq %0, %%fs \n\t" ::"a"(next->thread->fs)); - __asm__ __volatile__("movq %0, %%gs \n\t" ::"a"(next->thread->gs)); + __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"); + kdebug("prev->thread->rsp0:%#018lx\n", prev->thread->rbp); + kdebug("next->thread->rsp0:%#018lx\n", next->thread->rbp); } /** @@ -36,9 +48,10 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc */ 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); + // 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); + hlt(); enter_syscall(SYS_PRINTF, (ul) "test_sys_printf\n", 0, 0, 0, 0, 0, 0, 0); kinfo("Return from syscall id 15..."); @@ -63,8 +76,34 @@ ul do_execve(struct pt_regs *regs) regs->es = 0; kdebug("do_execve is running..."); + + // 映射起始页面 + // 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); + 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)); + virtual = kmalloc(PAGE_4K_SIZE, 0); + set_pdpt(tmp, mk_pdpt(virt_2_phys(virtual), PAGE_USER_DIR)); + + tmp = phys_2_virt((unsigned long *)(*tmp & (~0xfffUL)) + ((addr >> PAGE_2M_SHIFT) & 0x1ff)); + struct Page *p = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED); + set_pdt(tmp, mk_pdt(p->addr_phys, PAGE_USER_PAGE)); + + 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)) + current_pcb->addr_limit = KERNEL_BASE_LINEAR_ADDR; // 将程序代码拷贝到对应的内存中 memcpy((void *)0x800000, user_level_function, 1024); + kdebug("program copied!"); return 0; } @@ -82,9 +121,11 @@ ul initial_kernel_thread(ul arg) current_pcb->thread->rip = (ul)ret_from_system_call; current_pcb->thread->rsp = (ul)current_pcb + STACK_SIZE - sizeof(struct pt_regs); + // current_pcb->mm->pgd = kmalloc(PAGE_4K_SIZE, 0); + // memset((void*)current_pcb->mm->pgd, 0, PAGE_4K_SIZE); regs = (struct pt_regs *)current_pcb->thread->rsp; - + current_pcb->flags = 0; // 将返回用户层的代码压入堆栈,向rdx传入regs的地址,然后jmp到do_execve这个系统调用api的处理函数 这里的设计思路和switch_proc类似 __asm__ __volatile__("movq %1, %%rsp \n\t" "pushq %2 \n\t" @@ -101,7 +142,7 @@ ul initial_kernel_thread(ul arg) * @param code 返回码 * @return ul */ -ul do_exit(ul code) +ul process_thread_do_exit(ul code) { kinfo("thread_exiting..., code is %#018lx.", code); while (1) @@ -142,7 +183,7 @@ __asm__( " movq %rdx, %rdi \n\t" " callq *%rbx \n\t" " movq %rax, %rdi \n\t" - " callq do_exit \n\t"); + " callq process_thread_do_exit \n\t"); /** * @brief 初始化内核进程 @@ -183,7 +224,7 @@ int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigne */ void process_init() { - + kinfo("Initializing process..."); initial_mm.pgd = (pml4t_t *)global_CR3; initial_mm.code_addr_start = memory_management_struct.kernel_code_start; @@ -198,12 +239,16 @@ void process_init() initial_mm.brk_start = 0; initial_mm.brk_end = memory_management_struct.kernel_end; - initial_mm.stack_start = _stack_start; + + initial_mm.stack_start = *(ul *)phys_2_virt(&_stack_start); // 初始化进程和tss - set_tss64(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); + 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); @@ -214,6 +259,7 @@ void process_init() // 获取新的进程的pcb struct process_control_block *p = container_of(list_next(¤t_pcb->list), struct process_control_block, list); + kdebug("Ready to switch..."); // 切换到新的内核线程 switch_proc(current_pcb, p); } @@ -237,7 +283,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned tsk = (struct process_control_block *)phys_2_virt(pp->addr_phys); - memset(tsk, 0, sizeof(*tsk)); + memset(tsk, 0, sizeof(struct process_control_block)); // 将当前进程的pcb复制到新的pcb内 *tsk = *current_pcb; @@ -245,8 +291,8 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned // 将进程加入循环链表 list_init(&tsk->list); - list_add(&initial_proc_union.pcb.list, &tsk->list); - + // list_add(&initial_proc_union.pcb.list, &tsk->list); + tsk->priority = 2; ++(tsk->pid); tsk->state = PROC_UNINTERRUPTIBLE; @@ -270,5 +316,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned tsk->state = PROC_RUNNING; + sched_cfs_enqueue(tsk); + return 0; } diff --git a/kernel/process/process.h b/kernel/process/process.h index 7a388d39..8ca0036e 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -17,8 +17,7 @@ #include "ptrace.h" extern unsigned long _stack_start; // 导出内核层栈基地址(定义在head.S) -extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S) - +extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S) // 进程的内核栈大小 32K #define STACK_SIZE 32768 @@ -86,45 +85,38 @@ struct thread_struct ul err_code; }; +// ========= pcb->flags ========= // 进程标志位 -#define PF_KTHREAD (1 << 0) - +#define PF_KTHREAD (1UL << 0) +#define PROC_NEED_SCHED (1UL << 1) // 进程需要被调度 /** * @brief 进程控制块 * */ struct process_control_block { - // 连接各个pcb的双向链表 - struct List list; - // 进程的状态 volatile long state; // 进程标志:进程、线程、内核线程 unsigned long flags; - + long signal; // 内存空间分布结构体, 记录内存页表和程序段信息 struct mm_struct *mm; // 进程切换时保存的状态信息 struct thread_struct *thread; + // 连接各个pcb的双向链表 + struct List list; + // 地址空间范围 // 用户空间: 0x0000 0000 0000 0000 ~ 0x0000 7fff ffff ffff // 内核空间: 0xffff 8000 0000 0000 ~ 0xffff ffff ffff ffff - ul addr_limit; + uint64_t addr_limit; - // 进程id long pid; - - // 可用时间片 - long counter; - - // 信号 - long signal; - - // 优先级 - long priority; + long priority; // 优先级 + long virtual_runtime; // 虚拟运行时间 }; // 将进程的pcb和内核栈融合到一起,8字节对齐 @@ -146,9 +138,9 @@ struct thread_struct initial_thread; .thread = &initial_thread, \ .addr_limit = 0xffff800000000000, \ .pid = 0, \ - .counter = 1, \ + .virtual_runtime = 0, \ .signal = 0, \ - .priority = 0 \ + .priority = 2 \ } // 初始化 初始进程的union ,并将其链接到.data.init_proc段内 @@ -224,18 +216,17 @@ struct process_control_block *get_current_pcb() return current; }; - #define current_pcb get_current_pcb() #define GET_CURRENT_PCB \ "movq %rsp, %rbx \n\t" \ "andq $-32768, %rbx\n\t" -/** - * @brief 切换进程上下文 - * 先把rbp和rax保存到栈中,然后将rsp和rip保存到prev的thread结构体中 - * 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。 - */ + /** + * @brief 切换进程上下文 + * 先把rbp和rax保存到栈中,然后将rsp和rip保存到prev的thread结构体中 + * 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。 + */ #define switch_proc(prev, next) \ do \ diff --git a/kernel/sched/sched.c b/kernel/sched/sched.c new file mode 100644 index 00000000..da5e4eea --- /dev/null +++ b/kernel/sched/sched.c @@ -0,0 +1,112 @@ +#include "sched.h" +#include + +/** + * @brief 从就绪队列中取出PCB + * + * @return struct process_control_block* + */ +struct process_control_block *sched_cfs_dequeue() +{ + if (list_empty(&sched_cfs_ready_queue.proc_queue.list)) + { + return &initial_proc_union.pcb; + } + + struct process_control_block *proc = container_of(list_next(&sched_cfs_ready_queue.proc_queue.list), struct process_control_block, list); + + list_del(&proc->list); + --sched_cfs_ready_queue.count; + return proc; +} + +/** + * @brief 将PCB加入就绪队列 + * + * @param pcb + */ +void sched_cfs_enqueue(struct process_control_block *pcb) +{ + struct process_control_block *proc = container_of(list_next(&sched_cfs_ready_queue.proc_queue.list), struct process_control_block, list); + if (proc == &initial_proc_union.pcb) + return; + if (!(list_empty(&sched_cfs_ready_queue.proc_queue.list))) + { + while (proc->virtual_runtime < pcb->virtual_runtime) + { + proc = container_of(list_next(&proc->list), struct process_control_block, list); + } + } + list_append(&proc->list, &pcb->list); + ++sched_cfs_ready_queue.count; +} + +/** + * @brief 调度函数 + * + */ +void sched_cfs() +{ + + current_pcb->flags &= ~PROC_NEED_SCHED; + struct process_control_block *proc = sched_cfs_dequeue(); + + if (current_pcb->virtual_runtime >= proc->virtual_runtime) // 当前进程运行时间大于了下一进程的运行时间,进行切换 + { + + if (current_pcb->state = PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理 + sched_cfs_enqueue(current_pcb); + + if (!sched_cfs_ready_queue.cpu_exec_proc_jiffies) + { + switch (proc->priority) + { + case 0: + case 1: + sched_cfs_ready_queue.cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue.count; + break; + case 2: + default: + + sched_cfs_ready_queue.cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue.count) << 2; + break; + } + } + + switch_proc(current_pcb, proc); + } + else // 不进行切换 + { + kdebug("not switch."); + sched_cfs_enqueue(current_pcb); + + if (!sched_cfs_ready_queue.cpu_exec_proc_jiffies) + { + switch (proc->priority) + { + case 0: + case 1: + sched_cfs_ready_queue.cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue.cpu_exec_proc_jiffies; + break; + case 2: + default: + sched_cfs_ready_queue.cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue.cpu_exec_proc_jiffies) << 2; + break; + } + } + kdebug("hhhh"); + } +} + +/** + * @brief 初始化进程调度器 + * + */ +void sched_init() +{ + memset(&sched_cfs_ready_queue, 0, sizeof(struct sched_queue_t)); + list_init(&sched_cfs_ready_queue.proc_queue.list); + sched_cfs_ready_queue.count = 1; // 因为存在IDLE进程,因此为1 + sched_cfs_ready_queue.cpu_exec_proc_jiffies = 4; + sched_cfs_ready_queue.proc_queue.virtual_runtime = 0x7fffffffffffffff; +} \ No newline at end of file diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h new file mode 100644 index 00000000..31a836e6 --- /dev/null +++ b/kernel/sched/sched.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +struct sched_queue_t +{ + long count; // 当前队列中的数量 + long cpu_exec_proc_jiffies; // 进程可执行的时间片数量 + struct process_control_block proc_queue; +}; + +// @todo: 用红黑树重写cfs的队列 +struct sched_queue_t sched_cfs_ready_queue; // 就绪队列 + +/** + * @brief 调度函数 + * + */ +void sched_cfs(); + +/** + * @brief 将PCB加入就绪队列 + * + * @param pcb + */ +void sched_cfs_enqueue(struct process_control_block *pcb); + + +/** + * @brief 从就绪队列中取出PCB + * + * @return struct process_control_block* + */ +struct process_control_block *sched_cfs_dequeue(); + +/** + * @brief 初始化进程调度器 + * + */ +void sched_init(); \ No newline at end of file diff --git a/kernel/smp/apu_boot.S b/kernel/smp/apu_boot.S index 12c8308c..a00fafb1 100644 --- a/kernel/smp/apu_boot.S +++ b/kernel/smp/apu_boot.S @@ -3,7 +3,7 @@ .align 0x1000 // 按照4k对齐 -.text +.section .text .code16 ENTRY(_apu_boot_start) @@ -72,58 +72,16 @@ _apu_code32: mov %cr4, %eax or $(1<<5), %eax mov %eax, %cr4 -/* + movl $enter_head_from_ap_boot, %eax jmpl *%eax hlt -*/ + - // 设置页表 - - movl $pml4, %eax // 复用bsp处理器初始化时的32位页表 - movl %eax, %cr3 - - // enable long mode - movl $0xC0000080, %ecx - rdmsr - - bts $8, %eax - wrmsr - - // enable PE and paging - mov %cr0, %eax - bts $0, %eax - bts $31, %eax - mov %eax, %cr0 - - // 跳转到64位代码 - ljmp *(_apu_code64_vector - _apu_boot_base)(%esi) - - .code64 .align 0x1000 _apu_code64: - movq $0x20, %rax - movq %rax, %ds - movq %rax, %es - movq %rax, %ss - movq %rax, %fs - movq %rax, %gs - - - //now enable SSE and the like - movq %cr0, %rax - and $0xFFFB, %ax //clear coprocessor emulation CR0.EM - or $0x2, %ax //set coprocessor monitoring CR0.MP - movq %rax, %cr0 - movq %cr4, %rax - or $(3 << 9), %ax //set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time - movq %rax, %cr4 - - // 跳转到地址1MB处执行 - movq $_start64, %rax - jmpq *%rax hlt diff --git a/kernel/smp/smp.c b/kernel/smp/smp.c index e66b393e..f803ef07 100644 --- a/kernel/smp/smp.c +++ b/kernel/smp/smp.c @@ -15,10 +15,11 @@ static struct acpi_Processor_Local_APIC_Structure_t *proc_local_apic_structs[MAX static uint32_t total_processor_num = 0; int current_starting_cpu = 0; +int num_cpu_started = 1; + void smp_init() { spin_init(&multi_core_starting_lock); // 初始化多核启动锁 - ul tmp_vaddr[MAX_SUPPORTED_PROCESSOR_NUM] = {0}; apic_get_ics(ACPI_ICS_TYPE_PROCESSOR_LOCAL_APIC, tmp_vaddr, &total_processor_num); @@ -29,17 +30,20 @@ void smp_init() //*(uchar *)0x20000 = 0xf4; // 在内存的0x20000处写入HLT指令(AP处理器会执行物理地址0x20000的代码) // 将引导程序复制到物理地址0x20000处 - memcpy((unsigned char *)0x20000, _apu_boot_start, (unsigned long)&_apu_boot_end - (unsigned long)&_apu_boot_start); - + memcpy((unsigned char *)phys_2_virt(0x20000), _apu_boot_start, (unsigned long)&_apu_boot_end - (unsigned long)&_apu_boot_start); + // 设置多核IPI中断门 for (int i = 200; i < 210; ++i) set_intr_gate(i, 2, SMP_interrupt_table[i - 200]); - memset(SMP_IPI_desc, 0, sizeof(irq_desc_t) * SMP_IRQ_NUM); + + memset((void *)SMP_IPI_desc, 0, sizeof(irq_desc_t) * SMP_IRQ_NUM); ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x00, ICR_INIT, ICR_ALL_EXCLUDE_Self, true, 0x00); for (int i = 1; i < total_processor_num; ++i) // i从1开始,不初始化bsp { + if (proc_local_apic_structs[i]->ACPI_Processor_UID == 0) + --total_processor_num; spin_lock(&multi_core_starting_lock); current_starting_cpu = i; @@ -49,15 +53,34 @@ void smp_init() cpu_core_info[i].tss_vaddr = (uint64_t)kmalloc(128, 0); - set_tss_descriptor(10 + (i * 2), (void *)(cpu_core_info[i].tss_vaddr)); + 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("GDT Table %#018lx, \t %#018lx", GDT_Table[10 + i * 2], 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); } + + while (num_cpu_started != total_processor_num) + __asm__ __volatile__("pause" :: + : "memory"); + + kinfo("Cleaning page table remapping...\n"); + + // 由于ap处理器初始化过程需要用到0x00处的地址,因此初始化完毕后才取消内存地址的重映射 + //todo: 取消低0-2M的地址映射 + for (int i = 1; i < 128; ++i) + { + + *(ul *)(phys_2_virt(global_CR3) + i) = 0UL; + } + + kinfo("Successfully cleaned page table remapping!\n"); + } /** @@ -66,8 +89,9 @@ void smp_init() */ void smp_ap_start() { - // 切换栈基地址 - // uint64_t stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE; + + // 切换栈基地址 + // uint64_t stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE; __asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) : "memory"); __asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) @@ -78,15 +102,18 @@ void smp_ap_start() __asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(stack_start) : "memory");*/ ksuccess("AP core successfully started!"); - kdebug("current cpu = %d", current_starting_cpu); - apic_init_ap_core_local_apic(); + ++num_cpu_started; + + kdebug("current cpu = %d", current_starting_cpu); + + apic_init_ap_core_local_apic(); load_TR(10 + current_starting_cpu * 2); - spin_unlock(&multi_core_starting_lock); + sti(); - kdebug("IDT_addr = %#018lx", &IDT_Table); - - - while (1) // 这里要循环hlt,原因是当收到中断后,核心会被唤醒,处理完中断之后不会自动hlt + kdebug("IDT_addr = %#018lx", phys_2_virt(IDT_Table)); + + spin_unlock(&multi_core_starting_lock); + while (1) // 这里要循环hlt,原因是当收到中断后,核心会被唤醒,处理完中断之后不会自动hlt hlt(); } \ No newline at end of file diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 22ec0331..d2d12a45 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -21,6 +21,7 @@ ul system_call_function(struct pt_regs *regs) */ void syscall_init() { + kinfo("Initializing syscall..."); // 向MSR寄存器组中的 IA32_SYSENTER_CS寄存器写入内核的代码段的地址 wrmsr(0x174, KERNEL_CS); // 向MSR寄存器组中的 IA32_SYSENTER_ESP寄存器写入内核进程的rbp(在syscall入口中会将rsp减去相应的数值) diff --git a/run.sh b/run.sh index 4274c7c1..db61c57f 100644 --- a/run.sh +++ b/run.sh @@ -12,7 +12,7 @@ if [ ! "$1" == "--nobuild" ]; then make clean fi -IA32_USE_QEMU=1 +IA32_USE_QEMU=0 bochsrc="./bochsrc" ARCH="x86_64"