将内核定位到高地址(存在bug,中断时会访问低地址)

This commit is contained in:
fslongjin 2022-04-10 21:30:16 +08:00
parent 3063a340e2
commit f5f36aafd8
23 changed files with 689 additions and 238 deletions

View File

@ -19,7 +19,7 @@ ata1-master: type=cdrom, path="DragonOS.iso", status=inserted
ata2: enabled=0 ata2: enabled=0
ata3: enabled=0 ata3: enabled=0
pci: enabled=1, chipset=i440fx 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" 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"

View File

@ -6,8 +6,8 @@ struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES];
uint32_t count_ahci_devices = 0; uint32_t count_ahci_devices = 0;
uint64_t ahci_port_base_vaddr; // 端口映射base addr uint64_t ahci_port_base_vaddr; // 端口映射base addr
uint64_t ahci_port_base_phys_addr; // 端口映射的物理基地址ahci控制器的参数的地址都是物理地址 uint64_t ahci_port_base_phys_addr; // 端口映射的物理基地址ahci控制器的参数的地址都是物理地址
static void start_cmd(HBA_PORT *port); static void start_cmd(HBA_PORT *port);
static void stop_cmd(HBA_PORT *port); static void stop_cmd(HBA_PORT *port);
@ -27,12 +27,20 @@ void ahci_init()
{ {
kinfo("Initializing AHCI..."); kinfo("Initializing AHCI...");
pci_get_device_structure(0x1, 0x6, ahci_devs, &count_ahci_devices); 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 // 映射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("phys_2_virt(ahci_devs[0])= %#018lx",(ahci_devs[0]));
// kdebug("ABAR mapped!"); 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); // 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结构体 // 赋值HBA_MEM结构体
@ -40,16 +48,18 @@ void ahci_init()
ahci_devices[i].hba_mem = (HBA_MEM *)(cal_HBA_MEM_VIRT_ADDR(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); kdebug("ahci_devices[i].hba_mem = %#018lx", (ul)ahci_devices[i].hba_mem);
} }
// todo: 支持多个ahci控制器。 // todo: 支持多个ahci控制器。
ahci_port_base_vaddr = (uint64_t)kmalloc(1048576, 0); ahci_port_base_vaddr = (uint64_t)kmalloc(1048576, 0);
kdebug("ahci_port_base_vaddr=%#018lx", ahci_port_base_vaddr); kdebug("ahci_port_base_vaddr=%#018lx", ahci_port_base_vaddr);
ahci_probe_port(0); ahci_probe_port(0);
port_rebase(&ahci_devices[0].hba_mem->ports[0], 0); port_rebase(&ahci_devices[0].hba_mem->ports[0], 0);
// 初始化请求队列 // 初始化请求队列
ahci_req_queue.in_service = NULL; ahci_req_queue.in_service = NULL;
list_init(&(ahci_req_queue.queue_list)); list_init(&(ahci_req_queue.queue_list));
ahci_req_queue.request_count = 0; ahci_req_queue.request_count = 0;
kinfo("AHCI initialized.");
} }
// Check device type // 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); memset((void *)phys_2_virt(cmdheader[i].ctba), 0, 256);
} }
start_cmd(port); // Start command engine start_cmd(port); // Start command engine
} }

View File

@ -425,6 +425,19 @@ void apic_init()
apic_io_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(); sti();
} }
/** /**

View File

@ -73,6 +73,8 @@
// 分频配置寄存器(定时器专用) // 分频配置寄存器(定时器专用)
#define LOCAL_APIC_OFFSET_Local_APIC_CLKDIV 0x3e0 #define LOCAL_APIC_OFFSET_Local_APIC_CLKDIV 0x3e0
uint32_t RCBA_vaddr = 0;// RCBA寄存器的虚拟地址
/* /*
1: LVT CMCI 1: LVT CMCI

View File

@ -447,7 +447,7 @@ void pci_init()
{ {
if (ptr->Status & 0x10) 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); uint32_t tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer);
} }
else 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)) 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; res[*count_res] = ptr;
++(*count_res); ++(*count_res);
} }

View File

@ -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) if (container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list)->expire_jiffies <= timer_jiffies)
set_softirq_status(TIMER_SIRQ); set_softirq_status(TIMER_SIRQ);
/*
switch (current_pcb->priority) switch (current_pcb->priority)
{ {
case 0: 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) if (sched_cfs_ready_queue.cpu_exec_proc_jiffies <= 0)
current_pcb->flags |= PROC_NEED_SCHED; current_pcb->flags |= PROC_NEED_SCHED;
*/
break; break;
default: default:
@ -85,32 +85,72 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
int HPET_init() int HPET_init()
{ {
kinfo("Initializing HPET...");
// 从acpi获取hpet结构体 // 从acpi获取hpet结构体
ul hpet_table_addr = 0; ul hpet_table_addr = 0;
acpi_iter_SDT(acpi_get_HPET, &hpet_table_addr); acpi_iter_SDT(acpi_get_HPET, &hpet_table_addr);
// ACPI表没有HPET尝试读HPTC
if (hpet_table_addr == 0) if (hpet_table_addr == 0)
{ {
kerror("HPET Not Found On This Computer!"); kwarn("ACPI: HPET Table Not Found On This Computer!");
return E_HPET_INIT_FAILED;
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; else // ACPI表中有HPET表
// 由于这段内存与io/apic的映射在同一物理页内因此不需要重复映射 {
HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + hpet_table->address; 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; uint64_t tmp;
tmp = *(uint64_t *)(HPET_REG_BASE + GCAP_ID); tmp = *(uint64_t *)(HPET_REG_BASE + GCAP_ID);
HPET_COUNTER_CLK_PERIOD = (tmp >> 32) & 0xffffffff; HPET_COUNTER_CLK_PERIOD = (tmp >> 32) & 0xffffffff;
HPET_freq = 1.0 * 1e15 / HPET_COUNTER_CLK_PERIOD; HPET_freq = 1.0 * 1e15 / HPET_COUNTER_CLK_PERIOD;
HPET_NUM_TIM_CAP = (tmp >> 8) & 0x1f; // 读取计时器数量 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; struct apic_IO_APIC_RTE_entry entry;
// 使用I/O APIC 的IRQ2接收hpet定时器0的中断 // 使用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); 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; // 置位旧设备中断路由兼容标志位、定时器组使能标志位 *(uint64_t *)(HPET_REG_BASE + GEN_CONF) = 3; // 置位旧设备中断路由兼容标志位、定时器组使能标志位
io_mfence(); io_mfence();
@ -123,4 +163,7 @@ int HPET_init()
rtc_get_cmos_time(&rtc_now); rtc_get_cmos_time(&rtc_now);
*(uint64_t *)(HPET_REG_BASE + MAIN_CNT) = 0; *(uint64_t *)(HPET_REG_BASE + MAIN_CNT) = 0;
io_mfence(); io_mfence();
// 注册中断
irq_register(34, &entry, &HPET_handler, 0, &HPET_intr_controller, "HPET0");
kinfo("HPET Initialized.");
} }

View File

@ -1,4 +1,6 @@
#include"../common/asm.h" #include"../common/asm.h"
.code64
.section .text
R15 = 0x00 R15 = 0x00
R14 = 0x08 R14 = 0x08
@ -54,6 +56,7 @@ Restore_all:
ret_from_exception: ret_from_exception:
// === === // === ===
.code64
ENTRY(ret_from_intr) ENTRY(ret_from_intr)
jmp Restore_all jmp Restore_all
@ -85,18 +88,18 @@ Err_Code:
pushq %r15 pushq %r15
cld cld
movq ERRCODE(%rsp), %rsi // rsi movq ERRCODE(%rsp), %rsi // rsi
movq FUNC(%rsp), %rdx movq FUNC(%rsp), %rdx
movq $0x10, %rdi // movq $0x10, %rdi //
movq %rdi, %ds movq %rdi, %ds
movq %rdi, %es movq %rdi, %es
movq %rsp, %rdi // rdi movq %rsp, %rdi // rdi
callq *%rdx // *
callq %rdx // *
jmp ret_from_exception jmp ret_from_exception
// //
@ -174,6 +177,7 @@ ENTRY(ret_from_system_call)
// 0 #DE // 0 #DE
ENTRY(divide_error) ENTRY(divide_error)
pushq $0 //#DE0 pushq $0 //#DE0
pushq %rax // rax pushq %rax // rax
leaq do_divide_error(%rip), %rax // leaq do_divide_error(%rip), %rax //
@ -333,3 +337,7 @@ ENTRY(virtualization_exception)
leaq do_virtualization_exception(%rip), %rax // leaq do_virtualization_exception(%rip), %rax //
xchgq %rax, (%rsp) // FUNC xchgq %rax, (%rsp) // FUNC
jmp Err_Code jmp Err_Code
ENTRY(_stack_start)
.quad initial_proc_union + 32768

View File

@ -10,6 +10,7 @@
#define __GATE_H__ #define __GATE_H__
#include "../common/kprint.h" #include "../common/kprint.h"
#include <mm/mm.h>
//描述符表的结构体 //描述符表的结构体
struct desc_struct 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 struct gate_struct IDT_Table[]; // IDT_Table是head.S中的IDT_Table
extern unsigned int TSS64_Table[26]; 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 * @brief 16B
* @param gate_selector_addr IDT表项的地址 * @param gate_selector_addr IDT表项的地址
@ -86,8 +99,10 @@ void set_tss_descriptor(unsigned int n, void *addr)
{ {
unsigned long limit = 103; 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) void set_intr_gate(unsigned int n, unsigned char ist, void *addr)
{ {
_set_gate((IDT_Table + n), 0x8E, ist, addr); // p=1DPL=0, type=E _set_gate(phys_2_virt(IDT_Table + n), 0x8E, ist, addr); // p=1DPL=0, type=E
// set_gate((ul *)(IDT_Table + n), 0x8E, ist, (ul *)(addr)); // p=1DPL=0, type=E
//set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8E, ist, (ul *)(addr)); // p=1DPL=0, type=E
} }
/** /**
@ -125,8 +141,8 @@ void set_trap_gate(unsigned int n, unsigned char ist, void *addr)
{ {
// kdebug("addr=%#018lx", (ul)(addr)); // kdebug("addr=%#018lx", (ul)(addr));
// set_gate((ul *)(IDT_Table + n), 0x8F, ist, (ul *)(addr)); // p=1DPL=0, type=F //set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8F, ist, (ul *)(addr)); // p=1DPL=0, type=F
_set_gate((IDT_Table + n), 0x8F, ist, addr); // p=1DPL=0, type=F _set_gate(phys_2_virt(IDT_Table + n), 0x8F, ist, addr); // p=1DPL=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)); // kdebug("addr=%#018lx", (ul)(addr));
// set_gate((ul *)(IDT_Table + n), 0xEF, ist, (ul *)(addr)); // p=1DPL=3, type=F //set_gate((ul *)phys_2_virt(IDT_Table + n), 0xEF, ist, (ul *)(addr)); // p=1DPL=3, type=F
_set_gate((IDT_Table + n), 0xEF, ist, addr); // p=1DPL=3, type=F _set_gate(phys_2_virt(IDT_Table + n), 0xEF, ist, addr); // p=1DPL=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, 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 ist4, unsigned long ist5, unsigned long ist6, unsigned long ist7)
{ {
*(unsigned long *)(Table+1) = rsp0; *(unsigned long *)(Table + 1) = rsp0;
*(unsigned long *)(Table+3) = rsp1; *(unsigned long *)(Table + 3) = rsp1;
*(unsigned long *)(Table+5) = rsp2; *(unsigned long *)(Table + 5) = rsp2;
*(unsigned long *)(Table+9) = ist1; *(unsigned long *)(Table + 9) = ist1;
*(unsigned long *)(Table+11) = ist2; *(unsigned long *)(Table + 11) = ist2;
*(unsigned long *)(Table+13) = ist3; *(unsigned long *)(Table + 13) = ist3;
*(unsigned long *)(Table+15) = ist4; *(unsigned long *)(Table + 15) = ist4;
*(unsigned long *)(Table+17) = ist5; *(unsigned long *)(Table + 17) = ist5;
*(unsigned long *)(Table+19) = ist6; *(unsigned long *)(Table + 19) = ist6;
*(unsigned long *)(Table+21) = ist7; *(unsigned long *)(Table + 21) = ist7;
} }
#endif #endif

View File

@ -203,6 +203,10 @@ void irq_init()
#else #else
apic_init(); 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 #endif
} }

View File

@ -58,7 +58,6 @@ void sys_vector_init()
// 0 #DE 除法错误 // 0 #DE 除法错误
void do_divide_error(struct pt_regs *regs, unsigned long error_code) void do_divide_error(struct pt_regs *regs, unsigned long error_code)
{ {
kerror("do_divide_error(0)"); kerror("do_divide_error(0)");
//kerror("do_divide_error(0),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); //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 页故障 // 14 #PF 页故障
void do_page_fault(struct pt_regs *regs, unsigned long error_code) void do_page_fault(struct pt_regs *regs, unsigned long error_code)
{ {
hlt();
unsigned long cr2 = 0; 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))
if (!(error_code & 0x01)) printk_color(RED,BLACK,"Page Not-Present,\t");
printk("Page does not exist.\n");
if (error_code & 0x02) if(error_code & 0x02)
printk("Fault occurred during operation: writing\n"); printk_color(RED,BLACK,"Write Cause Fault,\t");
else else
printk("Fault occurred during operation: reading\n"); printk_color(RED,BLACK,"Read Cause Fault,\t");
if (error_code & 0x04) if(error_code & 0x04)
printk("Fault in user level(3).\n"); printk_color(RED,BLACK,"Fault in user(3)\t");
else else
printk("Fault in supervisor level(0,1,2).\n"); printk_color(RED,BLACK,"Fault in supervisor(0,1,2)\t");
if (error_code & 0x08) if(error_code & 0x08)
printk("Reserved bit caused the fault.\n"); printk_color(RED,BLACK,",Reserved Bit Cause Fault\t");
if (error_code & 0x10) if(error_code & 0x10)
printk("Fault occurred during fetching instruction.\n"); printk_color(RED,BLACK,",Instruction fetch Cause Fault");
printk_color(RED,BLACK,"\n");
printk_color(RED,BLACK,"CR2:%#018lx\n",cr2);
while (1) while (1)
; ;

View File

@ -269,8 +269,17 @@ enter_head_from_ap_boot:
hlt hlt
ret ret
.code64 .code64
.global ready_to_start_64
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 //6. start64
movq switch_to_start64(%rip), %rax movq switch_to_start64(%rip), %rax
pushq $0x08 // pushq $0x08 //
@ -281,19 +290,23 @@ switch_to_start64:
.quad _start64 .quad _start64
.code64 .code64
is_from_ap:
hlt
.global _start64 .global _start64
.type _start64, @function .type _start64, @function
.extern Start_Kernel .extern Start_Kernel
ENTRY(_start64) ENTRY(_start64)
// //
mov $0x10, %ax mov $0x10, %ax
mov %ax, %ds mov %ax, %ds
mov %ax, %es mov %ax, %es
mov %ax, %fs mov %ax, %fs
mov %ax, %ss mov %ax, %ss
mov $0x7e00, %esp mov $0x7e00, %esp
// === GDTR ==== // === GDTR ====
@ -302,13 +315,7 @@ ENTRY(_start64)
// === IDTR ==== // === IDTR ====
lidt IDT_POINTER(%rip) lidt IDT_POINTER(%rip)
//lidt $IDT_POINTER //lidt $IDT_POINTER
mov $0x10, %ax movq GDT_POINTER(%rip), %r12
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %ss
mov %ax, %gs
movq _stack_start(%rip), %rsp movq _stack_start(%rip), %rsp
// apu // apu
@ -333,10 +340,13 @@ ENTRY(_start64)
// ==== CR3 // ==== CR3
load_cr3:
movq $__PML4E, %rax //
movq %rax, %cr3
load_cr3:
// apu
movq $__PML4E, %rax //
movq %rax, %cr3
movq switch_seg(%rip), %rax movq switch_seg(%rip), %rax
// ljmplcallGASlretcs // ljmplcallGASlretcs
// Amazing // Amazing
@ -360,6 +370,21 @@ entry64:
movq _stack_start(%rip), %rsp //rsp movq _stack_start(%rip), %rsp //rsp
// GDTIDT
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 // apu
movq $0x1b, %rcx // IA32_APIC_BASE.BSP[8]apu movq $0x1b, %rcx // IA32_APIC_BASE.BSP[8]apu
@ -399,6 +424,10 @@ SetUp_TSS64:
// == 64 === // == 64 ===
//rdx8B rax8B //rdx8B rax8B
leaq TSS64_Table(%rip), %rdx leaq TSS64_Table(%rip), %rdx
movq $0xffff800000000000, %r8
addq %r8, %rdx
xorq %rax, %rax xorq %rax, %rax
xorq %rcx, %rcx xorq %rcx, %rcx
@ -440,23 +469,57 @@ SetUp_TSS64:
or $(3 << 9), %ax //set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time or $(3 << 9), %ax //set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
movq %rax, %cr4 movq %rax, %cr4
//call Start_Kernel
movq go_to_kernel(%rip), %rax /* movq address */ movq go_to_kernel(%rip), %rax /* movq address */
pushq $0x08 pushq $0x08
pushq %rax pushq %rax
movq mb2_info, %r15
movq mb2_info, %r15
movq mb2_magic, %r14 movq mb2_magic, %r14
lretq lretq
go_to_kernel: go_to_kernel:
.quad Start_Kernel .quad Start_Kernel
start_smp: 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 */ movq go_to_smp_kernel(%rip), %rax /* movq address */
pushq $0x08 pushq $0x08
pushq %rax pushq %rax
/*
// GDTIDT
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 lretq
go_to_smp_kernel: go_to_smp_kernel:
@ -484,10 +547,10 @@ ENTRY(_stack_start)
// //
.align 0x1000 //4k .align 0x1000 //4k
.org 0x1000 //0x1000 //.org 0x1000 //0x1000
__PML4E: __PML4E:
.quad 0x103003 // 访 31~12 .quad 0x103007 // 访 31~12
.fill 255,8,0 .fill 255,8,0
.quad 0x103003 .quad 0x103003
.fill 255,8,0 .fill 255,8,0
@ -575,6 +638,11 @@ GDT_POINTER:
GDT_LIMIT: .word GDT_END - GDT_Table - 1 // GDT GDT_LIMIT: .word GDT_END - GDT_Table - 1 // GDT
GDT_BASE: .quad GDT_Table 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 // IDT
.global IDT_Table .global IDT_Table
@ -587,6 +655,11 @@ IDT_POINTER:
IDT_LIMIT: .word IDT_END - IDT_Table - 1 IDT_LIMIT: .word IDT_END - IDT_Table - 1
IDT_BASE: .quad IDT_Table IDT_BASE: .quad IDT_Table
.global IDT_POINTER64
IDT_POINTER64:
IDT_LIMIT64: .word IDT_END - IDT_Table - 1
IDT_BASE64: .quad IDT_Table + 0xffff800000000000
// 64TSS // 64TSS
.global TSS64_Table .global TSS64_Table

View File

@ -20,7 +20,8 @@ SECTIONS
} }
. += KERNEL_VMA; . += KERNEL_VMA;
.text : AT(ADDR(.text) - KERNEL_VMA) text_start_pa = .;
.text (text_start_pa): AT(text_start_pa - KERNEL_VMA)
{ {
_text = .; _text = .;
@ -28,14 +29,16 @@ SECTIONS
_etext = .; _etext = .;
} }
. = ALIGN(8); . = ALIGN(8);
.data : AT(ADDR(.data) - KERNEL_VMA) data_start_pa = .;
.data (data_start_pa): AT(data_start_pa - KERNEL_VMA)
{ {
_data = .; _data = .;
*(.data) *(.data)
_edata = .; _edata = .;
} }
.rodata : AT(ADDR(.rodata) - KERNEL_VMA) rodata_start_pa = .;
.rodata (rodata_start_pa): AT(rodata_start_pa - KERNEL_VMA)
{ {
_rodata = .; _rodata = .;
*(.rodata) *(.rodata)
@ -43,9 +46,13 @@ SECTIONS
} }
. = ALIGN(32768); . = 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) } { *(.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 = .;
*(.bss) *(.bss)

View File

@ -29,6 +29,7 @@
#include <driver/timers/timer.h> #include <driver/timers/timer.h>
unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址 unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址
ul bsp_idt_size, bsp_gdt_size;
struct memory_desc memory_management_struct = {{0}, 0}; struct memory_desc memory_management_struct = {{0}, 0};
// struct Global_Memory_Descriptor 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!"); 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() void system_initialize()
{ {
// 初始化printk // 初始化printk
printk_init(8, 16); printk_init(8, 16);
kinfo("Kernel Starting..."); 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寄存器 load_TR(10); // 加载TR寄存器
ul tss_item_addr = 0x7c00; set_tss64((uint *)phys_2_virt(TSS64_Table), _stack_start, _stack_start, _stack_start, tss_item_addr,
set_tss64(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); 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].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(); sys_vector_init();
// 初始化内存管理单元 // 初始化内存管理单元
mm_init(); mm_init();
acpi_init(); acpi_init();
for (int i = 0; i < 1e7; ++i)
;
// 初始化中断模块 // 初始化中断模块
sched_init();
irq_init(); irq_init();
softirq_init(); softirq_init();
timer_init();
HPET_init();
smp_init();
// 先初始化系统调用模块 // 先初始化系统调用模块
syscall_init(); syscall_init();
// 再初始化进程模块。顺序不能调转
sched_init();
timer_init();
smp_init();
cpu_init(); cpu_init();
// ps2_keyboard_init(); // ps2_keyboard_init();
// ps2_mouse_init(); // ps2_mouse_init();
@ -189,10 +223,10 @@ void system_initialize()
ahci_init(); ahci_init();
// test_slab(); // test_slab();
// test_mm(); // test_mm();
process_init();
// 再初始化进程模块。顺序不能调转 cli();
// sched_init(); HPET_init();
// process_init(); sti();
} }
//操作系统内核从这里开始执行 //操作系统内核从这里开始执行
@ -203,12 +237,20 @@ void Start_Kernel(void)
uint64_t mb2_info, mb2_magic; uint64_t mb2_info, mb2_magic;
__asm__ __volatile__("movq %%r15, %0 \n\t" __asm__ __volatile__("movq %%r15, %0 \n\t"
"movq %%r14, %1 \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_info &= 0xffffffff;
mb2_magic &= 0xffffffff; mb2_magic &= 0xffffffff;
multiboot2_magic = mb2_magic; multiboot2_magic = mb2_magic;
multiboot2_boot_info_addr = mb2_info+PAGE_OFFSET; multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET;
system_initialize(); system_initialize();
/* /*

View File

@ -6,7 +6,7 @@
ul Total_Memory = 0; ul Total_Memory = 0;
ul total_2M_pages = 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() void mm_init()
{ {
kinfo("Initializing memory management unit..."); kinfo("Initializing memory management unit...");
@ -190,22 +190,16 @@ void mm_init()
} }
global_CR3 = get_CR3(); 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", global_CR3);
kdebug("*global_CR3\t:%#018lx", *phys_2_virt(global_CR3) & (~0xff)); kdebug("*global_CR3\t:%#018lx", *phys_2_virt(global_CR3) & (~0xff));
kdebug("**global_CR3\t:%#018lx", *phys_2_virt(*phys_2_virt(global_CR3) & (~0xff)) & (~0xff)); kdebug("**global_CR3\t:%#018lx", *phys_2_virt(*phys_2_virt(global_CR3) & (~0xff)) & (~0xff));
kdebug("1.memory_management_struct.bmp:%#018lx\tzone->count_pages_using:%d\tzone_struct->count_pages_free:%d", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free); kdebug("1.memory_management_struct.bmp:%#018lx\tzone->count_pages_using:%d\tzone_struct->count_pages_free:%d", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free);
//kinfo("Cleaning page table remapping at 0x0000");
kinfo("Memory management unit initialize complete!"); 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(); flush_tlb();
// 初始化slab内存池 // 初始化slab内存池
slab_init(); slab_init();
@ -424,8 +418,9 @@ void free_pages(struct Page *page, int number)
*/ */
void page_table_init() void page_table_init()
{ {
kinfo("Initializing page table..."); kinfo("Re-Initializing page table...");
global_CR3 = get_CR3(); global_CR3 = get_CR3();
/*
// 由于CR3寄存器的[11..0]位是PCID标志位因此将低12位置0后就是PML4页表的基地址 // 由于CR3寄存器的[11..0]位是PCID标志位因此将低12位置0后就是PML4页表的基地址
ul *pml4_addr = (ul *)((ul)phys_2_virt((ul)global_CR3 & (~0xfffUL))); ul *pml4_addr = (ul *)((ul)phys_2_virt((ul)global_CR3 & (~0xfffUL)));
kdebug("PML4 addr=%#018lx *pml4=%#018lx", pml4_addr, *pml4_addr); 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)); ul *pd_addr = phys_2_virt(*pdpt_addr & (~0xfffUL));
kdebug("pd addr=%#018lx *pd=%#018lx", pd_addr, *pd_addr); kdebug("pd addr=%#018lx *pd=%#018lx", pd_addr, *pd_addr);
*/
ul *tmp_addr; ul *tmp_addr;
for (int i = 0; i < memory_management_struct.count_zones; ++i) 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) 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页表中的页表项的地址 // 计算出PML4页表中的页表项的地址
tmp_addr = (ul *)((ul)pml4_addr + ((((ul)phys_2_virt(p->addr_phys)) >> PAGE_GDT_SHIFT) & 0x1ff) * 8); 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物理页 // 填入pd页表的页表项映射2MB物理页
set_pdt(tmp_addr, mk_pdt(virt_2_phys(p->addr_phys), PAGE_KERNEL_PAGE)); set_pdt(tmp_addr, mk_pdt(virt_2_phys(p->addr_phys), PAGE_KERNEL_PAGE));
*/
// 测试 // 测试
if (j % 50 == 0) if (j % 50 == 0)
kdebug("pd_addr=%#018lx, *pd_addr=%#018lx", tmp_addr, *tmp_addr); 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(); 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 * @brief
* *
* @param proc_page_table_addr * @param proc_page_table_addr
* @param is_phys
* @param virt_addr_start * @param virt_addr_start
* @param phys_addr_start * @param phys_addr_start
* @param length * @param length
* @param user 访 * @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页表项的地址 // 计算线性地址对应的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) if (*tmp == 0)
{ {
ul *virt_addr = kmalloc(PAGE_4K_SIZE, 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))); 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) 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) for (ul i = 0; i < (length); i += PAGE_2M_SIZE)
{ {
// 计算当前2M物理页对应的pdt的页表项的物理地址 // 计算当前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))); set_pdt(tmp1, mk_pdt((ul)phys_addr_start + i, flags | (user ? PAGE_USER_PAGE : PAGE_KERNEL_PAGE)));

View File

@ -8,7 +8,7 @@
// 内核层的起始地址 // 内核层的起始地址
#define PAGE_OFFSET ((unsigned long)0xffff800000000000) #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_4K_SHIFT 12
#define PAGE_2M_SHIFT 21 #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 * @brief
* *
* @param proc_page_table_addr * @param proc_page_table_addr
* @param is_phys
* @param virt_addr_start * @param virt_addr_start
* @param phys_addr_start * @param phys_addr_start
* @param length * @param length
* @param user 访 * @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);
void mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags);

View File

@ -5,6 +5,8 @@
#include "../common/kprint.h" #include "../common/kprint.h"
#include "../syscall/syscall.h" #include "../syscall/syscall.h"
#include "../syscall/syscall_num.h" #include "../syscall/syscall_num.h"
#include <mm/slab.h>
#include <sched/sched.h>
/** /**
* @brief * @brief
@ -18,16 +20,26 @@
void __switch_to(struct process_control_block *prev, struct process_control_block *next) void __switch_to(struct process_control_block *prev, struct process_control_block *next)
{ {
initial_tss[0].rsp0 = next->thread->rbp; 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); 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" kdebug("prev->thread=%#018lx", prev->thread);
: "=a"(prev->thread->fs)); kdebug("next->thread=%#018lx", next->thread);
__asm__ __volatile__("movq %%gs, %0 \n\t"
: "=a"(prev->thread->gs));
__asm__ __volatile__("movq %0, %%fs \n\t" ::"a"(next->thread->fs)); __asm__ __volatile__("movq %%fs, %0 \n\t"
__asm__ __volatile__("movq %0, %%gs \n\t" ::"a"(next->thread->gs)); : "=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() void user_level_function()
{ {
kinfo("Program (user_level_function) is runing..."); // kinfo("Program (user_level_function) is runing...");
kinfo("Try to enter syscall id 15..."); // kinfo("Try to enter syscall id 15...");
enter_syscall(15, 0, 0, 0, 0, 0, 0, 0, 0); // 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); enter_syscall(SYS_PRINTF, (ul) "test_sys_printf\n", 0, 0, 0, 0, 0, 0, 0);
kinfo("Return from syscall id 15..."); kinfo("Return from syscall id 15...");
@ -63,8 +76,34 @@ ul do_execve(struct pt_regs *regs)
regs->es = 0; regs->es = 0;
kdebug("do_execve is running..."); 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); memcpy((void *)0x800000, user_level_function, 1024);
kdebug("program copied!");
return 0; return 0;
} }
@ -82,9 +121,11 @@ ul initial_kernel_thread(ul arg)
current_pcb->thread->rip = (ul)ret_from_system_call; current_pcb->thread->rip = (ul)ret_from_system_call;
current_pcb->thread->rsp = (ul)current_pcb + STACK_SIZE - sizeof(struct pt_regs); 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; regs = (struct pt_regs *)current_pcb->thread->rsp;
current_pcb->flags = 0;
// 将返回用户层的代码压入堆栈向rdx传入regs的地址然后jmp到do_execve这个系统调用api的处理函数 这里的设计思路和switch_proc类似 // 将返回用户层的代码压入堆栈向rdx传入regs的地址然后jmp到do_execve这个系统调用api的处理函数 这里的设计思路和switch_proc类似
__asm__ __volatile__("movq %1, %%rsp \n\t" __asm__ __volatile__("movq %1, %%rsp \n\t"
"pushq %2 \n\t" "pushq %2 \n\t"
@ -101,7 +142,7 @@ ul initial_kernel_thread(ul arg)
* @param code * @param code
* @return ul * @return ul
*/ */
ul do_exit(ul code) ul process_thread_do_exit(ul code)
{ {
kinfo("thread_exiting..., code is %#018lx.", code); kinfo("thread_exiting..., code is %#018lx.", code);
while (1) while (1)
@ -142,7 +183,7 @@ __asm__(
" movq %rdx, %rdi \n\t" " movq %rdx, %rdi \n\t"
" callq *%rbx \n\t" " callq *%rbx \n\t"
" movq %rax, %rdi \n\t" " movq %rax, %rdi \n\t"
" callq do_exit \n\t"); " callq process_thread_do_exit \n\t");
/** /**
* @brief * @brief
@ -183,7 +224,7 @@ int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigne
*/ */
void process_init() void process_init()
{ {
kinfo("Initializing process...");
initial_mm.pgd = (pml4t_t *)global_CR3; initial_mm.pgd = (pml4t_t *)global_CR3;
initial_mm.code_addr_start = memory_management_struct.kernel_code_start; 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_start = 0;
initial_mm.brk_end = memory_management_struct.kernel_end; 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 // 初始化进程和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; 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); list_init(&initial_proc_union.pcb.list);
@ -214,6 +259,7 @@ void process_init()
// 获取新的进程的pcb // 获取新的进程的pcb
struct process_control_block *p = container_of(list_next(&current_pcb->list), struct process_control_block, list); struct process_control_block *p = container_of(list_next(&current_pcb->list), struct process_control_block, list);
kdebug("Ready to switch...");
// 切换到新的内核线程 // 切换到新的内核线程
switch_proc(current_pcb, p); switch_proc(current_pcb, p);
} }
@ -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); 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内 // 将当前进程的pcb复制到新的pcb内
*tsk = *current_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_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->pid);
tsk->state = PROC_UNINTERRUPTIBLE; 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; tsk->state = PROC_RUNNING;
sched_cfs_enqueue(tsk);
return 0; return 0;
} }

View File

@ -17,8 +17,7 @@
#include "ptrace.h" #include "ptrace.h"
extern unsigned long _stack_start; // 导出内核层栈基地址定义在head.S extern unsigned long _stack_start; // 导出内核层栈基地址定义在head.S
extern void ret_from_intr(void); // 导出从中断返回的函数定义在entry.S extern void ret_from_intr(void); // 导出从中断返回的函数定义在entry.S
// 进程的内核栈大小 32K // 进程的内核栈大小 32K
#define STACK_SIZE 32768 #define STACK_SIZE 32768
@ -86,45 +85,38 @@ struct thread_struct
ul err_code; ul err_code;
}; };
// ========= pcb->flags =========
// 进程标志位 // 进程标志位
#define PF_KTHREAD (1 << 0) #define PF_KTHREAD (1UL << 0)
#define PROC_NEED_SCHED (1UL << 1) // 进程需要被调度
/** /**
* @brief * @brief
* *
*/ */
struct process_control_block struct process_control_block
{ {
// 连接各个pcb的双向链表
struct List list;
// 进程的状态 // 进程的状态
volatile long state; volatile long state;
// 进程标志:进程、线程、内核线程 // 进程标志:进程、线程、内核线程
unsigned long flags; unsigned long flags;
long signal;
// 内存空间分布结构体, 记录内存页表和程序段信息 // 内存空间分布结构体, 记录内存页表和程序段信息
struct mm_struct *mm; struct mm_struct *mm;
// 进程切换时保存的状态信息 // 进程切换时保存的状态信息
struct thread_struct *thread; struct thread_struct *thread;
// 连接各个pcb的双向链表
struct List list;
// 地址空间范围 // 地址空间范围
// 用户空间: 0x0000 0000 0000 0000 ~ 0x0000 7fff ffff ffff // 用户空间: 0x0000 0000 0000 0000 ~ 0x0000 7fff ffff ffff
// 内核空间: 0xffff 8000 0000 0000 ~ 0xffff ffff ffff ffff // 内核空间: 0xffff 8000 0000 0000 ~ 0xffff ffff ffff ffff
ul addr_limit; uint64_t addr_limit;
// 进程id
long pid; long pid;
long priority; // 优先级
// 可用时间片 long virtual_runtime; // 虚拟运行时间
long counter;
// 信号
long signal;
// 优先级
long priority;
}; };
// 将进程的pcb和内核栈融合到一起,8字节对齐 // 将进程的pcb和内核栈融合到一起,8字节对齐
@ -146,9 +138,9 @@ struct thread_struct initial_thread;
.thread = &initial_thread, \ .thread = &initial_thread, \
.addr_limit = 0xffff800000000000, \ .addr_limit = 0xffff800000000000, \
.pid = 0, \ .pid = 0, \
.counter = 1, \ .virtual_runtime = 0, \
.signal = 0, \ .signal = 0, \
.priority = 0 \ .priority = 2 \
} }
// 初始化 初始进程的union ,并将其链接到.data.init_proc段内 // 初始化 初始进程的union ,并将其链接到.data.init_proc段内
@ -224,18 +216,17 @@ struct process_control_block *get_current_pcb()
return current; return current;
}; };
#define current_pcb get_current_pcb() #define current_pcb get_current_pcb()
#define GET_CURRENT_PCB \ #define GET_CURRENT_PCB \
"movq %rsp, %rbx \n\t" \ "movq %rsp, %rbx \n\t" \
"andq $-32768, %rbx\n\t" "andq $-32768, %rbx\n\t"
/** /**
* @brief * @brief
* rbp和rax保存到栈中rsp和rip保存到prev的thread结构体中 * rbp和rax保存到栈中rsp和rip保存到prev的thread结构体中
* __switch_to切换栈rax rbp * __switch_to切换栈rax rbp
*/ */
#define switch_proc(prev, next) \ #define switch_proc(prev, next) \
do \ do \

112
kernel/sched/sched.c Normal file
View File

@ -0,0 +1,112 @@
#include "sched.h"
#include <common/kprint.h>
/**
* @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;
}

41
kernel/sched/sched.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include <common/glib.h>
#include <process/process.h>
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();

View File

@ -3,7 +3,7 @@
.align 0x1000 // 4k .align 0x1000 // 4k
.text .section .text
.code16 .code16
ENTRY(_apu_boot_start) ENTRY(_apu_boot_start)
@ -72,58 +72,16 @@ _apu_code32:
mov %cr4, %eax mov %cr4, %eax
or $(1<<5), %eax or $(1<<5), %eax
mov %eax, %cr4 mov %eax, %cr4
/*
movl $enter_head_from_ap_boot, %eax movl $enter_head_from_ap_boot, %eax
jmpl *%eax jmpl *%eax
hlt hlt
*/
//
movl $pml4, %eax // bsp32
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 .code64
.align 0x1000 .align 0x1000
_apu_code64: _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 hlt

View File

@ -15,10 +15,11 @@ static struct acpi_Processor_Local_APIC_Structure_t *proc_local_apic_structs[MAX
static uint32_t total_processor_num = 0; static uint32_t total_processor_num = 0;
int current_starting_cpu = 0; int current_starting_cpu = 0;
int num_cpu_started = 1;
void smp_init() void smp_init()
{ {
spin_init(&multi_core_starting_lock); // 初始化多核启动锁 spin_init(&multi_core_starting_lock); // 初始化多核启动锁
ul tmp_vaddr[MAX_SUPPORTED_PROCESSOR_NUM] = {0}; ul tmp_vaddr[MAX_SUPPORTED_PROCESSOR_NUM] = {0};
apic_get_ics(ACPI_ICS_TYPE_PROCESSOR_LOCAL_APIC, tmp_vaddr, &total_processor_num); 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的代码) //*(uchar *)0x20000 = 0xf4; // 在内存的0x20000处写入HLT指令(AP处理器会执行物理地址0x20000的代码)
// 将引导程序复制到物理地址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中断门 // 设置多核IPI中断门
for (int i = 200; i < 210; ++i) for (int i = 200; i < 210; ++i)
set_intr_gate(i, 2, SMP_interrupt_table[i - 200]); 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); 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 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); spin_lock(&multi_core_starting_lock);
current_starting_cpu = i; current_starting_cpu = i;
@ -49,15 +53,34 @@ void smp_init()
cpu_core_info[i].tss_vaddr = (uint64_t)kmalloc(128, 0); 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); 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].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 // 连续发送两次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);
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() 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) __asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start)
: "memory"); : "memory");
__asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) __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) __asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(stack_start)
: "memory");*/ : "memory");*/
ksuccess("AP core successfully started!"); 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); load_TR(10 + current_starting_cpu * 2);
spin_unlock(&multi_core_starting_lock);
sti(); sti();
kdebug("IDT_addr = %#018lx", &IDT_Table); kdebug("IDT_addr = %#018lx", phys_2_virt(IDT_Table));
spin_unlock(&multi_core_starting_lock);
while (1) // 这里要循环hlt原因是当收到中断后核心会被唤醒处理完中断之后不会自动hlt while (1) // 这里要循环hlt原因是当收到中断后核心会被唤醒处理完中断之后不会自动hlt
hlt(); hlt();
} }

View File

@ -21,6 +21,7 @@ ul system_call_function(struct pt_regs *regs)
*/ */
void syscall_init() void syscall_init()
{ {
kinfo("Initializing syscall...");
// 向MSR寄存器组中的 IA32_SYSENTER_CS寄存器写入内核的代码段的地址 // 向MSR寄存器组中的 IA32_SYSENTER_CS寄存器写入内核的代码段的地址
wrmsr(0x174, KERNEL_CS); wrmsr(0x174, KERNEL_CS);
// 向MSR寄存器组中的 IA32_SYSENTER_ESP寄存器写入内核进程的rbp在syscall入口中会将rsp减去相应的数值 // 向MSR寄存器组中的 IA32_SYSENTER_ESP寄存器写入内核进程的rbp在syscall入口中会将rsp减去相应的数值

2
run.sh
View File

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