mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 19:36: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
|
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"
|
||||||
|
|
||||||
|
@ -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);
|
||||||
@ -28,11 +28,19 @@ 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,6 +48,7 @@ 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);
|
||||||
@ -50,6 +59,7 @@ void ahci_init()
|
|||||||
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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
||||||
|
@ -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,7 +592,7 @@ 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);
|
||||||
|
@ -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.");
|
||||||
}
|
}
|
@ -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
|
||||||
|
|
||||||
@ -95,8 +98,8 @@ Err_Code:
|
|||||||
|
|
||||||
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 //由于#DE不会产生错误码,但是为了保持弹出结构的一致性,故也压入一个错误码0
|
pushq $0 //由于#DE不会产生错误码,但是为了保持弹出结构的一致性,故也压入一个错误码0
|
||||||
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
|
@ -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=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 *)(IDT_Table + n), 0x8E, ist, (ul *)(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));
|
// kdebug("addr=%#018lx", (ul)(addr));
|
||||||
|
|
||||||
// set_gate((ul *)(IDT_Table + n), 0x8F, ist, (ul *)(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((IDT_Table + n), 0x8F, ist, 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));
|
// kdebug("addr=%#018lx", (ul)(addr));
|
||||||
|
|
||||||
// set_gate((ul *)(IDT_Table + n), 0xEF, ist, (ul *)(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((IDT_Table + n), 0xEF, ist, 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,
|
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
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
|
||||||
printk_color(YELLOW, BLACK, "Information:\n");
|
kerror("do_page_fault(14),Error code :%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip);
|
||||||
if (!(error_code & 0x01))
|
|
||||||
printk("Page does not exist.\n");
|
|
||||||
|
|
||||||
if (error_code & 0x02)
|
if(!(error_code & 0x01))
|
||||||
printk("Fault occurred during operation: writing\n");
|
printk_color(RED,BLACK,"Page Not-Present,\t");
|
||||||
else
|
|
||||||
printk("Fault occurred during operation: reading\n");
|
|
||||||
|
|
||||||
if (error_code & 0x04)
|
if(error_code & 0x02)
|
||||||
printk("Fault in user level(3).\n");
|
printk_color(RED,BLACK,"Write Cause Fault,\t");
|
||||||
else
|
else
|
||||||
printk("Fault in supervisor level(0,1,2).\n");
|
printk_color(RED,BLACK,"Read Cause Fault,\t");
|
||||||
|
|
||||||
if (error_code & 0x08)
|
if(error_code & 0x04)
|
||||||
printk("Reserved bit caused the fault.\n");
|
printk_color(RED,BLACK,"Fault in user(3)\t");
|
||||||
|
else
|
||||||
|
printk_color(RED,BLACK,"Fault in supervisor(0,1,2)\t");
|
||||||
|
|
||||||
if (error_code & 0x10)
|
if(error_code & 0x08)
|
||||||
printk("Fault occurred during fetching instruction.\n");
|
printk_color(RED,BLACK,",Reserved Bit Cause Fault\t");
|
||||||
|
|
||||||
|
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)
|
while (1)
|
||||||
;
|
;
|
||||||
|
@ -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,8 +340,11 @@ ENTRY(_start64)
|
|||||||
|
|
||||||
|
|
||||||
// ==== 加载CR3寄存器
|
// ==== 加载CR3寄存器
|
||||||
|
|
||||||
load_cr3:
|
load_cr3:
|
||||||
|
// 分支,判断是否为apu
|
||||||
movq $__PML4E, %rax //设置页目录基地址
|
movq $__PML4E, %rax //设置页目录基地址
|
||||||
|
|
||||||
movq %rax, %cr3
|
movq %rax, %cr3
|
||||||
|
|
||||||
movq switch_seg(%rip), %rax
|
movq switch_seg(%rip), %rax
|
||||||
@ -360,6 +370,21 @@ entry64:
|
|||||||
|
|
||||||
movq _stack_start(%rip), %rsp //rsp的地址
|
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
|
// 分支,判断是否为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位的任务状态段表 ===
|
||||||
//rdx保存高8B, rax保存低8B
|
//rdx保存高8B, rax保存低8B
|
||||||
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
|
||||||
|
|
||||||
|
/*
|
||||||
|
// 重新加载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
|
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
|
||||||
|
|
||||||
// 64位的TSS表
|
// 64位的TSS表
|
||||||
.global TSS64_Table
|
.global TSS64_Table
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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,6 +144,32 @@ 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()
|
||||||
{
|
{
|
||||||
@ -151,15 +178,21 @@ void system_initialize()
|
|||||||
|
|
||||||
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();
|
||||||
@ -169,18 +202,19 @@ void system_initialize()
|
|||||||
|
|
||||||
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();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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)));
|
||||||
|
@ -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);
|
@ -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(¤t_pcb->list), struct process_control_block, list);
|
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);
|
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;
|
||||||
}
|
}
|
||||||
|
@ -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
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对齐
|
.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 // 复用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
|
.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
|
||||||
|
|
||||||
|
@ -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!");
|
||||||
|
|
||||||
|
++num_cpu_started;
|
||||||
|
|
||||||
kdebug("current cpu = %d", current_starting_cpu);
|
kdebug("current cpu = %d", current_starting_cpu);
|
||||||
|
|
||||||
apic_init_ap_core_local_apic();
|
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();
|
||||||
}
|
}
|
@ -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减去相应的数值)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user