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