diff --git a/Makefile b/Makefile index b00ac762..789a951c 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ all: @list='$(SUBDIRS)'; for subdir in $$list; do \ echo "make all in $$subdir";\ cd $$subdir;\ - make all;\ + $(MAKE) all;\ cd ..;\ done @@ -14,7 +14,7 @@ all: clean: @list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Clean in dir: $$subdir";\ - cd $$subdir && make clean;\ + cd $$subdir && $(MAKE) clean;\ cd .. ;\ done diff --git a/kernel/Makefile b/kernel/Makefile index 88835477..1bb86e27 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -11,7 +11,7 @@ CFLAGS := -mcmodel=large -fno-builtin -m64 -g -O0 -I . ARCH=x86_64 # 控制操作系统使用的中断控制器 _INTR_8259A_ _INTR_APIC_ PIC := _INTR_APIC_ -CFLAGS += -D $(PIC) -D $(ARCH) +CFLAGS += -D $(PIC) -D $(ARCH) ASFLAGS := --64 @@ -56,6 +56,10 @@ slab.o: mm/slab.c process.o: process/process.c gcc $(CFLAGS) -c process/process.c -o process/process.o + +sched.o: sched/sched.c + gcc $(CFLAGS) -c sched/sched.c -o sched/sched.o + syscall.o: syscall/syscall.c gcc $(CFLAGS) -c syscall/syscall.c -o syscall/syscall.o @@ -127,9 +131,9 @@ all: kernel objcopy -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../bin/kernel/kernel.elf # -kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o rtc.o HPET.o softirq.o timer.o $(OBJ_LIST) +kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o sched.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o rtc.o HPET.o softirq.o timer.o $(OBJ_LIST) ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o mm/mm.o mm/slab.o process/process.o syscall/syscall.o driver/multiboot2/multiboot2.o \ - common/cpu.o smp/smp.o smp/apu_boot.o exception/softirq.o \ + common/cpu.o smp/smp.o smp/apu_boot.o exception/softirq.o sched/sched.o \ driver/acpi/acpi.o driver/interrupt/pic.o driver/keyboard/ps2_keyboard.o driver/mouse/ps2_mouse.o driver/disk/ata.o driver/pci/pci.o driver/disk/ahci/ahci.o driver/timers/rtc/rtc.o driver/timers/HPET/HPET.o driver/timers/timer.o \ $(LD_LIST) \ -T link.lds diff --git a/kernel/common/cpu.c b/kernel/common/cpu.c index 482c3c48..8a0f0f52 100644 --- a/kernel/common/cpu.c +++ b/kernel/common/cpu.c @@ -7,7 +7,7 @@ void cpu_init(void) // 获取处理器制造商信息 uint tmp_info[4] = {0}; cpu_cpuid(0, 0, &tmp_info[0], &tmp_info[1], &tmp_info[2], &tmp_info[3]); - + // 保存CPU支持的最大cpuid指令主功能号 Cpu_cpuid_max_Basic_mop = tmp_info[0]; // 保存制造商名称 @@ -37,28 +37,28 @@ void cpu_init(void) // EAX中包含 Version Informatin Type,Family,Model,and Stepping ID Cpu_Stepping_ID = tmp_info[0] & 0xf; - Cpu_Model_ID = (tmp_info[0]>>4) & 0xf; - Cpu_Family_ID = (tmp_info[0]>>8) & 0xf; - Cpu_Processor_Type = (tmp_info[0]>>12)& 0x3; + Cpu_Model_ID = (tmp_info[0] >> 4) & 0xf; + Cpu_Family_ID = (tmp_info[0] >> 8) & 0xf; + Cpu_Processor_Type = (tmp_info[0] >> 12) & 0x3; // 14-15位保留 - Cpu_Extended_Model_ID = (tmp_info[0]>>16)&0xf; - Cpu_Extended_Family_ID = (tmp_info[0]>>20)&0xff; - //31-25位保留 - kinfo("Family ID=%#03lx\t Extended Family ID=%#03lx\t Processor Type=%#03lx\t",Cpu_Family_ID, Cpu_Extended_Family_ID, Cpu_Processor_Type); - kinfo("Model ID=%#03lx\t Extended Model ID=%#03lx\tStepping ID=%#03lx\t",Cpu_Model_ID, Cpu_Extended_Model_ID,Cpu_Stepping_ID); + Cpu_Extended_Model_ID = (tmp_info[0] >> 16) & 0xf; + Cpu_Extended_Family_ID = (tmp_info[0] >> 20) & 0xff; + // 31-25位保留 + kinfo("Family ID=%#03lx\t Extended Family ID=%#03lx\t Processor Type=%#03lx\t", Cpu_Family_ID, Cpu_Extended_Family_ID, Cpu_Processor_Type); + kinfo("Model ID=%#03lx\t Extended Model ID=%#03lx\tStepping ID=%#03lx\t", Cpu_Model_ID, Cpu_Extended_Model_ID, Cpu_Stepping_ID); // 使用0x80000008主功能号,查询处理器支持的最大可寻址地址线宽度 cpu_cpuid(0x80000008, 0, &tmp_info[0], &tmp_info[1], &tmp_info[2], &tmp_info[3]); - Cpu_max_phys_addrline_size = tmp_info[0]&0xff; - Cpu_max_linear_addrline_size = (tmp_info[0]>>8)&0xff; + Cpu_max_phys_addrline_size = tmp_info[0] & 0xff; + Cpu_max_linear_addrline_size = (tmp_info[0] >> 8) & 0xff; kinfo("Cpu_max_phys_addrline_size = %d", Cpu_max_phys_addrline_size); kinfo("Cpu_max_linear_addrline_size = %d", Cpu_max_linear_addrline_size); - + cpu_cpuid(0x80000000, 0, &tmp_info[0], &tmp_info[1], &tmp_info[2], &tmp_info[3]); Cpu_cpuid_max_Extended_mop = tmp_info[0]; - kinfo("Max basic mop=%#05lx",Cpu_cpuid_max_Basic_mop); - kinfo("Max extended mop=%#05lx",Cpu_cpuid_max_Extended_mop); + kinfo("Max basic mop=%#05lx", Cpu_cpuid_max_Basic_mop); + kinfo("Max extended mop=%#05lx", Cpu_cpuid_max_Extended_mop); return; } \ No newline at end of file diff --git a/kernel/common/printk.c b/kernel/common/printk.c index fe100507..c06dc95a 100644 --- a/kernel/common/printk.c +++ b/kernel/common/printk.c @@ -28,16 +28,19 @@ int printk_init(const int char_size_x, const int char_size_y) struct multiboot_tag_framebuffer_info_t info; int reserved; multiboot2_iter(multiboot2_get_Framebuffer_info, &info, &reserved); - + + pos.width = info.framebuffer_width; pos.height = info.framebuffer_height; + pos.char_size_x = char_size_x; pos.char_size_y = char_size_y; pos.max_x = calculate_max_charNum(pos.width, char_size_x); pos.max_y = calculate_max_charNum(pos.height, char_size_y); - + VBE_FB_phys_addr = (ul)info.framebuffer_addr; - pos.FB_address = (uint *)0x0000000003000000; + + pos.FB_address = (uint *)0xffff800003000000; pos.FB_length = 1UL * pos.width * pos.height; // 初始化自旋锁 @@ -69,11 +72,11 @@ int printk_init(const int char_size_x, const int char_size_y) pos.x = 0; pos.y = 0; - + cls(); kdebug("width=%d\theight=%d", pos.width, pos.height); - + return 0; } @@ -532,7 +535,6 @@ static char *write_float_point_num(char *str, double num, int field_width, int p // 设置填充元素 pad = (flags & PAD_ZERO) ? '0' : ' '; - sign = 0; if (flags & SIGN && num < 0) { diff --git a/kernel/driver/disk/ahci/ahci.c b/kernel/driver/disk/ahci/ahci.c index a8aae72c..14fd1e0e 100644 --- a/kernel/driver/disk/ahci/ahci.c +++ b/kernel/driver/disk/ahci/ahci.c @@ -7,6 +7,7 @@ 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控制器的参数的地址都是物理地址) static void start_cmd(HBA_PORT *port); static void stop_cmd(HBA_PORT *port); @@ -24,21 +25,24 @@ static int ahci_find_cmdslot(HBA_PORT *port); */ void ahci_init() { + kinfo("Initializing AHCI..."); pci_get_device_structure(0x1, 0x6, ahci_devs, &count_ahci_devices); // 映射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("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结构体 + // 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结构体 ahci_devices[i].dev_struct = ahci_devs[i]; 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); @@ -118,7 +122,7 @@ static void ahci_probe_port(const uint32_t device_num) static void start_cmd(HBA_PORT *port) { // Wait until CR (bit15) is cleared - while (port->cmd & HBA_PxCMD_CR) + while ((port->cmd) & HBA_PxCMD_CR) ; // Set FRE (bit4) and ST (bit0) @@ -160,29 +164,29 @@ static void port_rebase(HBA_PORT *port, int portno) // Command list entry maxim count = 32 // Command list maxim size = 32*32 = 1K per port - port->clb = ahci_port_base_vaddr + (portno << 10); + port->clb = virt_2_phys(ahci_port_base_vaddr + (portno << 10)); - memset((void *)(port->clb), 0, 1024); + memset((void *)(phys_2_virt(port->clb)), 0, 1024); // FIS offset: 32K+256*portno // FIS entry size = 256 bytes per port - port->fb = ahci_port_base_vaddr + (32 << 10) + (portno << 8); + port->fb = virt_2_phys(ahci_port_base_vaddr + (32 << 10) + (portno << 8)); - memset((void *)(port->fb), 0, 256); + memset((void *)(phys_2_virt(port->fb)), 0, 256); // Command table offset: 40K + 8K*portno // Command table size = 256*32 = 8K per port - HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)(port->clb); + HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)(phys_2_virt(port->clb)); for (int i = 0; i < 32; ++i) { cmdheader[i].prdtl = 8; // 8 prdt entries per command table // 256 bytes per command table, 64+16+48+16*8 // Command table offset: 40K + 8K*portno + cmdheader_index*256 - cmdheader[i].ctba = ahci_port_base_vaddr + (40 << 10) + (portno << 13) + (i << 8); + cmdheader[i].ctba = virt_2_phys((ahci_port_base_vaddr + (40 << 10) + (portno << 13) + (i << 8))); - memset((void *)cmdheader[i].ctba, 0, 256); + memset((void *)phys_2_virt(cmdheader[i].ctba), 0, 256); } - + start_cmd(port); // Start command engine } @@ -206,20 +210,20 @@ static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t if (slot == -1) return E_NOEMPTYSLOT; - HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)port->clb; + HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb); cmdheader += slot; cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32_t); // Command FIS size cmdheader->w = 0; // Read from device cmdheader->prdtl = (uint16_t)((count - 1) >> 4) + 1; // PRDT entries count - HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)(cmdheader->ctba); + HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)phys_2_virt(cmdheader->ctba); memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) + (cmdheader->prdtl - 1) * sizeof(HBA_PRDT_ENTRY)); // 8K bytes (16 sectors) per PRDT int i; for (i = 0; i < cmdheader->prdtl - 1; ++i) { - cmdtbl->prdt_entry[i].dba = buf; + cmdtbl->prdt_entry[i].dba = virt_2_phys(buf); cmdtbl->prdt_entry[i].dbc = 8 * 1024 - 1; // 8K bytes (this value should always be set to 1 less than the actual value) cmdtbl->prdt_entry[i].i = 1; buf += 4 * 1024; // 4K uint16_ts @@ -227,7 +231,7 @@ static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t } // Last entry - cmdtbl->prdt_entry[i].dba = buf; + cmdtbl->prdt_entry[i].dba = virt_2_phys(buf); cmdtbl->prdt_entry[i].dbc = (count << 9) - 1; // 512 bytes per sector cmdtbl->prdt_entry[i].i = 1; @@ -296,7 +300,7 @@ static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_ if (slot == -1) return E_NOEMPTYSLOT; - HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)port->clb; + HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb); cmdheader += slot; cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32_t); // Command FIS size @@ -305,7 +309,7 @@ static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_ cmdheader->p = 1; cmdheader->prdtl = (uint16_t)((count - 1) >> 4) + 1; // PRDT entries count - HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)(cmdheader->ctba); + HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)phys_2_virt(cmdheader->ctba); memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) + (cmdheader->prdtl - 1) * sizeof(HBA_PRDT_ENTRY)); int i = 0; @@ -438,7 +442,7 @@ static void ahci_end_request() ahci_req_queue.in_service = NULL; // 进行下一轮的磁盘请求 (由于未实现单独的io调度器,这里会造成长时间的io等待) - if (ahci_req_queue.request_count>0) + if (ahci_req_queue.request_count > 0) ahci_query_disk(); } diff --git a/kernel/driver/interrupt/apic/apic.c b/kernel/driver/interrupt/apic/apic.c index 096575c2..422cd30c 100644 --- a/kernel/driver/interrupt/apic/apic.c +++ b/kernel/driver/interrupt/apic/apic.c @@ -7,6 +7,8 @@ #include "../../acpi/acpi.h" #include +#include +#include // 导出定义在irq.c中的中段门表 extern void (*interrupt_table[24])(void); @@ -472,6 +474,11 @@ void do_IRQ(struct pt_regs *rsp, ul number) // 检测是否有未处理的软中断 if (softirq_status != 0) do_softirq(); + + // 检测当前进程是否可被调度 + struct process_control_block *current_proc = get_current_pcb(); + if (current_proc->flags & PROC_NEED_SCHED) + sched_cfs(); } /** diff --git a/kernel/driver/multiboot2/multiboot2.c b/kernel/driver/multiboot2/multiboot2.c index 969ea123..2681a87a 100644 --- a/kernel/driver/multiboot2/multiboot2.c +++ b/kernel/driver/multiboot2/multiboot2.c @@ -3,18 +3,18 @@ #include "../../common/glib.h" #include "../../common/kprint.h" -uintptr_t boot_info_addr; +uintptr_t multiboot2_boot_info_addr; unsigned int multiboot2_magic; -unsigned int boot_info_size; +unsigned int multiboot2_boot_info_size; bool multiboot2_init(void) { - uintptr_t *addr = (uintptr_t *)boot_info_addr; + uintptr_t *addr = (uintptr_t *)multiboot2_boot_info_addr; if (multiboot2_magic != MULTIBOOT2_BOOTLOADER_MAGIC) ; return false; // addr+0 处保存了大小 - boot_info_size = *(unsigned int *)addr; + multiboot2_boot_info_size = *(unsigned int *)addr; return true; } @@ -22,9 +22,9 @@ void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned i void *data, unsigned int *count) { - uintptr_t addr = boot_info_addr; - // 下一字节开始为 tag 信息 - struct iter_data_t *tag = (struct iter_data_t *)(addr + 8); + uintptr_t addr = multiboot2_boot_info_addr; + // 接下来的第8字节开始,为 tag 信息 + struct iter_data_t *tag = (struct iter_data_t *)((void*)addr + 8); for (; tag->type != MULTIBOOT_TAG_TYPE_END; tag = (struct iter_data_t *)((uint8_t *)tag + ALIGN(tag->size, 8))) { diff --git a/kernel/driver/multiboot2/multiboot2.h b/kernel/driver/multiboot2/multiboot2.h index 776724ea..ccfee2b8 100644 --- a/kernel/driver/multiboot2/multiboot2.h +++ b/kernel/driver/multiboot2/multiboot2.h @@ -27,6 +27,7 @@ */ extern unsigned int multiboot2_magic; +extern uintptr_t multiboot2_boot_info_addr; /* How many bytes from the start of the file we search for the header. */ static const unsigned int MULTIBOOT_SEARCH = 32768; diff --git a/kernel/driver/timers/HPET/HPET.c b/kernel/driver/timers/HPET/HPET.c index dd987f54..e7b4a228 100644 --- a/kernel/driver/timers/HPET/HPET.c +++ b/kernel/driver/timers/HPET/HPET.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include static struct acpi_HPET_description_table_t *hpet_table; static uint64_t HPET_REG_BASE = 0; @@ -52,8 +54,27 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs) { case 0: // 定时器0中断 ++timer_jiffies; - if (container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list)->expire_jiffies <= timer_jiffies) // 若当前时间比定时任务的时间间隔大,则进入中断下半部 + // 若当前时间比定时任务的时间间隔大,则进入中断下半部 + 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: + case 1: + --sched_cfs_ready_queue.cpu_exec_proc_jiffies; + ++current_pcb->virtual_runtime; + break; + case 2: + default: + sched_cfs_ready_queue.cpu_exec_proc_jiffies -= 2; + current_pcb->virtual_runtime += 2; + break; + } + + if (sched_cfs_ready_queue.cpu_exec_proc_jiffies <= 0) + current_pcb->flags |= PROC_NEED_SCHED; +*/ break; default: @@ -75,15 +96,16 @@ int HPET_init() 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; - // 读取计时精度并计算频率 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; // 读取计时器数量 - - kinfo("HPET CLK_PERIOD=%#03lx Frequency=%f", HPET_COUNTER_CLK_PERIOD, HPET_freq); + double x = 1*2; + x = 1.0*3.65; + //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); diff --git a/kernel/head.S b/kernel/head.S index 6b5a343b..10e0757c 100644 --- a/kernel/head.S +++ b/kernel/head.S @@ -158,9 +158,10 @@ // 计算校验和 .SET CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADER_LENGTH) // 8 字节对齐 +.section .multiboot_header .align MULTIBOOT_HEADER_ALIGN // 声明所属段 -.section .multiboot_header + multiboot_header: // 魔数 .long MULTIBOOT2_HEADER_MAGIC @@ -189,79 +190,25 @@ framebuffer_tag_end: .long 8 multiboot_header_end: +.section .bootstrap -// 临时页表 4KB/页 -.section .data -.align 0x1000 -.global pml4 -pml4: - .skip 0x1000 -pdpt: - .skip 0x1000 -pd: - .skip 0x1000 -pt: - .skip 0x1000 - -// 临时 GDT -.align 16 -gdt64: -null_desc: - .short 0xFFFF - .short 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 -code_desc: - .short 0 - .short 0 - .byte 0 - .byte 0x9A - .byte 0x20 - .byte 0 -data_desc: - .short 0 - .short 0 - .byte 0 - .byte 0x92 - .byte 0 - .byte 0 -user_code_desc: - .short 0 - .short 0 - .byte 0 - .byte 0xFA - .byte 0x20 - .byte 0 -user_data_desc: - .short 0 - .short 0 - .byte 0 - .byte 0xF2 - .byte 0 - .byte 0 -gdt64_pointer: - .short gdt64_pointer-gdt64-1 - .quad gdt64 -gdt64_pointer64: - .short gdt64_pointer-gdt64-1 - .quad gdt64 - -.section .text .global _start .type _start, @function # 在 multiboot2.cpp 中定义 + +.extern _start64 .extern boot_info_addr .extern multiboot2_magic -.extern _start64 -_start: +ENTRY(_start) // 关中断 cli // multiboot2_info 结构体指针 - mov %ebx, boot_info_addr + mov %ebx, mb2_info + //mov %ebx, %e8 // 魔数 - mov %eax, multiboot2_magic + mov %eax, mb2_magic + + //mov %eax, %e9 / 从保护模式跳转到长模式 // 1. 允许 PAE mov %cr4, %eax @@ -318,13 +265,22 @@ enter_head_from_ap_boot: mov $gdt64_pointer, %eax lgdt 0(%eax) - // 6. 跳转到 64 位代码执行 - jmp $0x8, $_start64 + jmp $0x8, $ready_to_start_64 hlt ret +.code64 +ready_to_start_64: + + //6. 跳转到start64 + movq switch_to_start64(%rip), %rax + pushq $0x08 //段选择子 + pushq %rax + lretq + +switch_to_start64: + .quad _start64 -.section .text .code64 .global _start64 @@ -367,6 +323,7 @@ ENTRY(_start64) mov $__PDPTE, %ebx or $0x3, %ebx mov %ebx, 0(%eax) + mov %ebx, 256(%eax) // 次级 mov $__PDPTE, %eax @@ -402,6 +359,7 @@ entry64: movq %rax, %ss movq _stack_start(%rip), %rsp //rsp的地址 + // 分支,判断是否为apu movq $0x1b, %rcx // 根据IA32_APIC_BASE.BSP[8]标志位判断处理器是否为apu @@ -482,7 +440,15 @@ SetUp_TSS64: or $(3 << 9), %ax //set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time movq %rax, %cr4 - call Start_Kernel + //call Start_Kernel + movq go_to_kernel(%rip), %rax /* movq address */ + pushq $0x08 + pushq %rax + + movq mb2_info, %r15 + + movq mb2_magic, %r14 + lretq go_to_kernel: .quad Start_Kernel @@ -517,7 +483,6 @@ ENTRY(_stack_start) // 初始化页表 - .align 0x1000 //设置为4k对齐 .org 0x1000 //设置页表位置为内核执行头程序的0x1000处 @@ -586,8 +551,9 @@ __PDE: .quad 0xe1e00083 .fill 468,8,0 + // GDT表 -.section .data + .align 16 .global GDT_Table // 使得GDT可以被外部程序引用或者访问 @@ -627,3 +593,66 @@ IDT_BASE: .quad IDT_Table TSS64_Table: .fill 13, 8, 0 TSS64_END: + +.section .bootstrap.data +mb2_magic: .quad 0 +mb2_info: .quad 0 + +.code32 +// 临时页表 4KB/页 +.align 0x1000 +.global pml4 +pml4: + .skip 0x1000 +pdpt: + .skip 0x1000 +pd: + .skip 0x1000 +pt: + .skip 0x1000 + +// 临时 GDT +.align 16 +gdt64: +null_desc: + .short 0xFFFF + .short 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 +code_desc: + .short 0 + .short 0 + .byte 0 + .byte 0x9A + .byte 0x20 + .byte 0 +data_desc: + .short 0 + .short 0 + .byte 0 + .byte 0x92 + .byte 0 + .byte 0 +user_code_desc: + .short 0 + .short 0 + .byte 0 + .byte 0xFA + .byte 0x20 + .byte 0 +user_data_desc: + .short 0 + .short 0 + .byte 0 + .byte 0xF2 + .byte 0 + .byte 0 +gdt64_pointer: + .short gdt64_pointer-gdt64-1 + .quad gdt64 +gdt64_pointer64: + .short gdt64_pointer-gdt64-1 + .quad gdt64 + diff --git a/kernel/link.lds b/kernel/link.lds index 2056e808..db1684db 100644 --- a/kernel/link.lds +++ b/kernel/link.lds @@ -5,27 +5,37 @@ ENTRY(_start) SECTIONS { + KERNEL_VMA = 0xffff800000000000; + //KERNEL_VMA = 0; . = 0; . = 0x100000; - .text : + .boot.text : + { + KEEP(*(.multiboot_header)) + head.o(.bootstrap) + head.o(.bootstrap.code64) + head.o(.bootstrap.data) + . = ALIGN(4096); + } + + . += KERNEL_VMA; + .text : AT(ADDR(.text) - KERNEL_VMA) { - _text = .; - *(.multiboot_header) + *(.text) - _etext = .; } . = ALIGN(8); - .data : + .data : AT(ADDR(.data) - KERNEL_VMA) { _data = .; *(.data) _edata = .; } - .rodata : + .rodata : AT(ADDR(.rodata) - KERNEL_VMA) { _rodata = .; *(.rodata) @@ -33,14 +43,14 @@ SECTIONS } . = ALIGN(32768); - .data.init_proc_union : { *(.data.init_proc_union) } - .bss : + .data.init_proc_union : AT(ADDR(.data.init_proc_union) - KERNEL_VMA) + { *(.data.init_proc_union) } + .bss : AT(ADDR(.bss) - KERNEL_VMA) { _bss = .; *(.bss) _ebss = .; } - _end = .; -} +} \ No newline at end of file diff --git a/kernel/main.c b/kernel/main.c index 5011d4f1..e1e2ae93 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -15,6 +15,7 @@ #include "syscall/syscall.h" #include "smp/smp.h" #include +#include #include "driver/multiboot2/multiboot2.h" #include "driver/acpi/acpi.h" @@ -147,8 +148,8 @@ void system_initialize() { // 初始化printk + printk_init(8, 16); - kinfo("Kernel Starting..."); load_TR(10); // 加载TR寄存器 @@ -190,12 +191,24 @@ void system_initialize() // test_mm(); // 再初始化进程模块。顺序不能调转 + // sched_init(); // process_init(); } //操作系统内核从这里开始执行 void Start_Kernel(void) { + + // 获取multiboot2的信息 + 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"); + mb2_info &= 0xffffffff; + mb2_magic &= 0xffffffff; + + multiboot2_magic = mb2_magic; + multiboot2_boot_info_addr = mb2_info+PAGE_OFFSET; system_initialize(); /* diff --git a/kernel/mm/mm.c b/kernel/mm/mm.c index d0e5bcc4..df484465 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; // 内核层根页表的物理地址 void mm_init() { kinfo("Initializing memory management unit..."); @@ -190,7 +190,7 @@ 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)); @@ -539,7 +539,7 @@ void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flag { global_CR3 = get_CR3(); - // 计算帧缓冲区的线性地址对应的pml4页表项的地址 + // 计算线性地址对应的pml4页表项的地址 ul *tmp = phys_2_virt((ul *)((ul)global_CR3 & (~0xfffUL)) + ((virt_addr_start >> PAGE_GDT_SHIFT) & 0x1ff)); if (*tmp == 0) { @@ -566,5 +566,47 @@ void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flag set_pdt(tmp1, mk_pdt((ul)phys_addr_start + i, flags)); } + flush_tlb(); +} + +/** + * @brief 将将物理地址填写到进程的页表的函数 + * + * @param proc_page_table_addr 进程的页表的虚拟基地址 + * @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) +{ + + // 计算线性地址对应的pml4页表项的地址 + ul *tmp = (ul *)((ul)proc_page_table_addr & (~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), (user ? PAGE_USER_PGT : PAGE_KERNEL_PGT))); + } + + tmp = (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), (user ? PAGE_USER_DIR : PAGE_KERNEL_DIR))); + } + + ul *tmp1; + // 初始化2M物理页 + 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)); + + // 页面写穿,禁止缓存 + set_pdt(tmp1, mk_pdt((ul)phys_addr_start + i, flags | (user ? PAGE_USER_PAGE : PAGE_KERNEL_PAGE))); + } + flush_tlb(); } \ No newline at end of file diff --git a/kernel/mm/mm.h b/kernel/mm/mm.h index bbe4792e..2e3f7e57 100644 --- a/kernel/mm/mm.h +++ b/kernel/mm/mm.h @@ -7,13 +7,13 @@ #define PTRS_PER_PGT 512 // 内核层的起始地址 -#define PAGE_OFFSET ((unsigned long)0x000000) -#define KERNEL_BASE_PHYS_ADDR ((unsigned long)0x100000) +#define PAGE_OFFSET ((unsigned long)0xffff800000000000) +#define KERNEL_BASE_PHYS_ADDR ((unsigned long)0xffff800000000000) #define PAGE_4K_SHIFT 12 #define PAGE_2M_SHIFT 21 #define PAGE_1G_SHIFT 30 -#define PAGE_GDT_SHIFT 39 +#define PAGE_GDT_SHIFT 39 // 不同大小的页的容量 #define PAGE_4K_SIZE (1UL << PAGE_4K_SHIFT) @@ -36,13 +36,13 @@ #define Phy_to_2M_Page(kaddr) (memory_management_struct.pages_struct + ((unsigned long)(kaddr) >> PAGE_2M_SHIFT)) // 在这个地址以上的虚拟空间,用来进行特殊的映射 -#define SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE 0xffff800000000000UL +#define SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE 0xffffa00000000000UL #define FRAME_BUFFER_MAPPING_OFFSET 0x3000000UL #define ACPI_RSDT_MAPPING_OFFSET 0x7000000UL #define ACPI_XSDT_MAPPING_OFFSET 0x9000000UL #define IO_APIC_MAPPING_OFFSET 0xfec00000UL #define LOCAL_APIC_MAPPING_OFFSET 0xfee00000UL -#define AHCI_MAPPING_OFFSET 0xff200000UL // AHCI 映射偏移量,之后使用了4M的地址 +#define AHCI_MAPPING_OFFSET 0xff200000UL // AHCI 映射偏移量,之后使用了4M的地址 // ===== 内存区域属性 ===== // DMA区域 @@ -66,58 +66,59 @@ #define PAGE_KERNEL (1 << 3) // 共享的页 shared=1 single-use=0 -#define PAGE_SHARED (1<<4) +#define PAGE_SHARED (1 << 4) // =========== 页表项权限 ======== // bit 63 Execution Disable: -#define PAGE_XD (1UL << 63) +#define PAGE_XD (1UL << 63) // bit 12 Page Attribute Table -#define PAGE_PAT (1UL << 12) +#define PAGE_PAT (1UL << 12) // bit 8 Global Page:1,global;0,part -#define PAGE_GLOBAL (1UL << 8) +#define PAGE_GLOBAL (1UL << 8) // bit 7 Page Size:1,big page;0,small page; -#define PAGE_PS (1UL << 7) +#define PAGE_PS (1UL << 7) // bit 6 Dirty:1,dirty;0,clean; -#define PAGE_DIRTY (1UL << 6) +#define PAGE_DIRTY (1UL << 6) // bit 5 Accessed:1,visited;0,unvisited; -#define PAGE_ACCESSED (1UL << 5) +#define PAGE_ACCESSED (1UL << 5) // bit 4 Page Level Cache Disable -#define PAGE_PCD (1UL << 4) +#define PAGE_PCD (1UL << 4) // bit 3 Page Level Write Through -#define PAGE_PWT (1UL << 3) +#define PAGE_PWT (1UL << 3) // bit 2 User Supervisor:1,user and supervisor;0,supervisor; -#define PAGE_U_S (1UL << 2) +#define PAGE_U_S (1UL << 2) // bit 1 Read Write:1,read and write;0,read; -#define PAGE_R_W (1UL << 1) +#define PAGE_R_W (1UL << 1) // bit 0 Present:1,present;0,no present; -#define PAGE_PRESENT (1UL << 0) +#define PAGE_PRESENT (1UL << 0) -//1,0 -#define PAGE_KERNEL_PGT (PAGE_R_W | PAGE_PRESENT) +// 1,0 +#define PAGE_KERNEL_PGT (PAGE_R_W | PAGE_PRESENT) -//1,0 -#define PAGE_KERNEL_DIR (PAGE_R_W | PAGE_PRESENT) +// 1,0 +#define PAGE_KERNEL_DIR (PAGE_R_W | PAGE_PRESENT) -//7,1,0 -#define PAGE_KERNEL_PAGE (PAGE_PS | PAGE_R_W | PAGE_PRESENT) +// 7,1,0 +#define PAGE_KERNEL_PAGE (PAGE_PS | PAGE_R_W | PAGE_PRESENT) -//2,1,0 -#define PAGE_USER_DIR (PAGE_U_S | PAGE_R_W | PAGE_PRESENT) +#define PAGE_USER_PGT (PAGE_U_S | PAGE_R_W | PAGE_PRESENT) -//7,2,1,0 -#define PAGE_USER_PAGE (PAGE_PS | PAGE_U_S | PAGE_R_W | PAGE_PRESENT) +// 2,1,0 +#define PAGE_USER_DIR (PAGE_U_S | PAGE_R_W | PAGE_PRESENT) +// 7,2,1,0 +#define PAGE_USER_PAGE (PAGE_PS | PAGE_U_S | PAGE_R_W | PAGE_PRESENT) // ===== 错误码定义 ==== // 物理页结构体为空 @@ -227,7 +228,7 @@ extern char _end; // 每个区域的索引 int ZONE_DMA_INDEX = 0; -int ZONE_NORMAL_INDEX = 0; // low 1GB RAM ,was mapped in pagetable +int ZONE_NORMAL_INDEX = 0; // low 1GB RAM ,was mapped in pagetable int ZONE_UNMAPPED_INDEX = 0; // above 1GB RAM,unmapped in pagetable ul *global_CR3 = NULL; @@ -272,9 +273,9 @@ struct Page *alloc_pages(unsigned int zone_select, int num, ul flags); /** * @brief 清除页面的引用计数, 计数为0时清空除页表已映射以外的所有属性 - * + * * @param p 物理页结构体 - * @return unsigned long + * @return unsigned long */ unsigned long page_clean(struct Page *page); @@ -288,20 +289,20 @@ void free_pages(struct Page *page, int number); /** * @brief Get the page's attr - * + * * @param page 内存页结构体 * @return ul 属性 */ -ul get_page_attr(struct Page* page); +ul get_page_attr(struct Page *page); /** * @brief Set the page's attr - * + * * @param page 内存页结构体 * @param flags 属性 * @return ul 错误码 */ -ul set_page_attr(struct Page* page, ul flags); +ul set_page_attr(struct Page *page, ul flags); /** * @brief 内存页表结构体 @@ -354,9 +355,20 @@ void init_frame_buffer(); /** * @brief 将物理地址映射到页表的函数 - * + * * @param virt_addr_start 要映射到的虚拟地址的起始位置 * @param phys_addr_start 物理地址的起始位置 * @param length 要映射的区域的长度(字节) */ -void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags); \ No newline at end of file +void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags); + +/** + * @brief 将将物理地址填写到进程的页表的函数 + * + * @param proc_page_table_addr 进程的页表的虚拟基地址 + * @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