Browse Source

将内核层空间移动到0xffff800000000000

fslongjin 3 years ago
parent
commit
05dc7ac73b

+ 2 - 2
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
 

+ 7 - 3
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

+ 14 - 14
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;
 }

+ 8 - 6
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)
     {

+ 23 - 19
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();
 }
 

+ 7 - 0
kernel/driver/interrupt/apic/apic.c

@@ -7,6 +7,8 @@
 #include "../../acpi/acpi.h"
 
 #include <exception/softirq.h>
+#include <process/process.h>
+#include <sched/sched.h>
 
 // 导出定义在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();
 }
 
 /**

+ 7 - 7
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)))
     {

+ 1 - 0
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;

+ 26 - 4
kernel/driver/timers/HPET/HPET.c

@@ -4,6 +4,8 @@
 #include <driver/interrupt/apic/apic.h>
 #include <exception/softirq.h>
 #include <driver/timers/timer.h>
+#include <process/process.h>
+#include <sched/sched.h>
 
 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);

+ 99 - 70
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
+

+ 20 - 10
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 = .;
-}
+}

+ 14 - 1
kernel/main.c

@@ -15,6 +15,7 @@
 #include "syscall/syscall.h"
 #include "smp/smp.h"
 #include <smp/ipi.h>
+#include <sched/sched.h>
 
 #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();
 
     /*

+ 45 - 3
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();
 }

+ 48 - 36
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);
+
+/**
+ * @brief 将将物理地址填写到进程的页表的函数
+ *
+ * @param proc_page_table_addr 进程的页表的虚拟基地址
  * @param virt_addr_start 要映射到的虚拟地址的起始位置
  * @param phys_addr_start 物理地址的起始位置
  * @param length 要映射的区域的长度(字节)
+ * @param user 用户态是否可访问
  */
-void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags);
+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);