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

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

View File

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

View File

@ -28,10 +28,18 @@ 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;
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);
@ -40,6 +48,7 @@ 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);
@ -50,6 +59,7 @@ void ahci_init()
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

View File

@ -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();
}
/**

View File

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

View File

@ -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,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))
{
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);

View File

@ -57,7 +57,7 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
// 若当前时间比定时任务的时间间隔大,则进入中断下半部
if (container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list)->expire_jiffies <= timer_jiffies)
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.");
}
}
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);
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.");
}

View File

@ -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
@ -95,8 +98,8 @@ Err_Code:
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 //#DE0
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

View File

@ -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=1DPL=0, type=E
// set_gate((ul *)(IDT_Table + n), 0x8E, ist, (ul *)(addr)); // p=1DPL=0, type=E
_set_gate(phys_2_virt(IDT_Table + n), 0x8E, ist, addr); // p=1DPL=0, type=E
//set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8E, ist, (ul *)(addr)); // p=1DPL=0, type=E
}
/**
@ -125,8 +141,8 @@ void set_trap_gate(unsigned int n, unsigned char ist, void *addr)
{
// kdebug("addr=%#018lx", (ul)(addr));
// set_gate((ul *)(IDT_Table + n), 0x8F, ist, (ul *)(addr)); // p=1DPL=0, type=F
_set_gate((IDT_Table + n), 0x8F, ist, addr); // p=1DPL=0, type=F
//set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8F, ist, (ul *)(addr)); // p=1DPL=0, type=F
_set_gate(phys_2_virt(IDT_Table + n), 0x8F, ist, addr); // p=1DPL=0, type=F
}
/**
@ -140,8 +156,8 @@ void set_system_trap_gate(unsigned int n, unsigned char ist, void *addr)
{
// kdebug("addr=%#018lx", (ul)(addr));
// set_gate((ul *)(IDT_Table + n), 0xEF, ist, (ul *)(addr)); // p=1DPL=3, type=F
_set_gate((IDT_Table + n), 0xEF, ist, addr); // p=1DPL=3, type=F
//set_gate((ul *)phys_2_virt(IDT_Table + n), 0xEF, ist, (ul *)(addr)); // p=1DPL=3, type=F
_set_gate(phys_2_virt(IDT_Table + n), 0xEF, ist, addr); // p=1DPL=3, type=F
}
/**

View File

@ -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
}

View File

@ -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");
printk_color(RED,BLACK,"Page Not-Present,\t");
if(error_code & 0x02)
printk("Fault occurred during operation: writing\n");
printk_color(RED,BLACK,"Write Cause Fault,\t");
else
printk("Fault occurred during operation: reading\n");
printk_color(RED,BLACK,"Read Cause Fault,\t");
if(error_code & 0x04)
printk("Fault in user level(3).\n");
printk_color(RED,BLACK,"Fault in user(3)\t");
else
printk("Fault in supervisor level(0,1,2).\n");
printk_color(RED,BLACK,"Fault in supervisor(0,1,2)\t");
if(error_code & 0x08)
printk("Reserved bit caused the fault.\n");
printk_color(RED,BLACK,",Reserved Bit Cause Fault\t");
if(error_code & 0x10)
printk("Fault occurred during fetching instruction.\n");
printk_color(RED,BLACK,",Instruction fetch Cause Fault");
printk_color(RED,BLACK,"\n");
printk_color(RED,BLACK,"CR2:%#018lx\n",cr2);
while (1)
;

View File

@ -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,8 +340,11 @@ ENTRY(_start64)
// ==== CR3
load_cr3:
// apu
movq $__PML4E, %rax //
movq %rax, %cr3
movq switch_seg(%rip), %rax
@ -360,6 +370,21 @@ entry64:
movq _stack_start(%rip), %rsp //rsp
// GDTIDT
leaq GDT_Table(%rip), %r8
leaq GDT_END(%rip), %r9
subq %r8, %r9
movq %r9, %r13 // GDT size
leaq IDT_Table(%rip), %r8
leaq IDT_END(%rip), %r9
subq %r8, %r9
movq %r9, %r12 // IDT size
lgdt GDT_POINTER64(%rip)
lidt IDT_POINTER64(%rip)
// apu
movq $0x1b, %rcx // IA32_APIC_BASE.BSP[8]apu
@ -399,6 +424,10 @@ SetUp_TSS64:
// == 64 ===
//rdx8B rax8B
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
/*
// GDTIDT
leaq GDT_Table(%rip), %r8
leaq GDT_END(%rip), %r9
subq %r8, %r9
movq %r9, %r13 // GDT size
leaq IDT_Table(%rip), %r8
leaq IDT_END(%rip), %r9
subq %r8, %r9
movq %r9, %r12 // IDT size
lgdt GDT_POINTER64(%rip)
lidt IDT_POINTER64(%rip)
*/
lretq
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
// 64TSS
.global TSS64_Table

View File

@ -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)

View File

@ -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,6 +144,32 @@ 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()
{
@ -151,15 +178,21 @@ void system_initialize()
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();
@ -169,18 +202,19 @@ void system_initialize()
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;
system_initialize();
/*

View File

@ -196,16 +196,10 @@ void mm_init()
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,26 +566,76 @@ 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);
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,6 +649,9 @@ 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的页表项的物理地址
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));
// 页面写穿,禁止缓存

View File

@ -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);

View File

@ -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(&current_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;
}

View File

@ -19,7 +19,6 @@
extern unsigned long _stack_start; // 导出内核层栈基地址定义在head.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,7 +216,6 @@ struct process_control_block *get_current_pcb()
return current;
};
#define current_pcb get_current_pcb()
#define GET_CURRENT_PCB \

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

@ -0,0 +1,112 @@
#include "sched.h"
#include <common/kprint.h>
/**
* @brief PCB
*
* @return struct process_control_block*
*/
struct process_control_block *sched_cfs_dequeue()
{
if (list_empty(&sched_cfs_ready_queue.proc_queue.list))
{
return &initial_proc_union.pcb;
}
struct process_control_block *proc = container_of(list_next(&sched_cfs_ready_queue.proc_queue.list), struct process_control_block, list);
list_del(&proc->list);
--sched_cfs_ready_queue.count;
return proc;
}
/**
* @brief PCB加入就绪队列
*
* @param pcb
*/
void sched_cfs_enqueue(struct process_control_block *pcb)
{
struct process_control_block *proc = container_of(list_next(&sched_cfs_ready_queue.proc_queue.list), struct process_control_block, list);
if (proc == &initial_proc_union.pcb)
return;
if (!(list_empty(&sched_cfs_ready_queue.proc_queue.list)))
{
while (proc->virtual_runtime < pcb->virtual_runtime)
{
proc = container_of(list_next(&proc->list), struct process_control_block, list);
}
}
list_append(&proc->list, &pcb->list);
++sched_cfs_ready_queue.count;
}
/**
* @brief
*
*/
void sched_cfs()
{
current_pcb->flags &= ~PROC_NEED_SCHED;
struct process_control_block *proc = sched_cfs_dequeue();
if (current_pcb->virtual_runtime >= proc->virtual_runtime) // 当前进程运行时间大于了下一进程的运行时间,进行切换
{
if (current_pcb->state = PROC_RUNNING) // 本次切换由于时间片到期引发,则再次加入就绪队列,否则交由其它功能模块进行管理
sched_cfs_enqueue(current_pcb);
if (!sched_cfs_ready_queue.cpu_exec_proc_jiffies)
{
switch (proc->priority)
{
case 0:
case 1:
sched_cfs_ready_queue.cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue.count;
break;
case 2:
default:
sched_cfs_ready_queue.cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue.count) << 2;
break;
}
}
switch_proc(current_pcb, proc);
}
else // 不进行切换
{
kdebug("not switch.");
sched_cfs_enqueue(current_pcb);
if (!sched_cfs_ready_queue.cpu_exec_proc_jiffies)
{
switch (proc->priority)
{
case 0:
case 1:
sched_cfs_ready_queue.cpu_exec_proc_jiffies = 4 / sched_cfs_ready_queue.cpu_exec_proc_jiffies;
break;
case 2:
default:
sched_cfs_ready_queue.cpu_exec_proc_jiffies = (4 / sched_cfs_ready_queue.cpu_exec_proc_jiffies) << 2;
break;
}
}
kdebug("hhhh");
}
}
/**
* @brief
*
*/
void sched_init()
{
memset(&sched_cfs_ready_queue, 0, sizeof(struct sched_queue_t));
list_init(&sched_cfs_ready_queue.proc_queue.list);
sched_cfs_ready_queue.count = 1; // 因为存在IDLE进程因此为1
sched_cfs_ready_queue.cpu_exec_proc_jiffies = 4;
sched_cfs_ready_queue.proc_queue.virtual_runtime = 0x7fffffffffffffff;
}

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

@ -0,0 +1,41 @@
#pragma once
#include <common/glib.h>
#include <process/process.h>
struct sched_queue_t
{
long count; // 当前队列中的数量
long cpu_exec_proc_jiffies; // 进程可执行的时间片数量
struct process_control_block proc_queue;
};
// @todo: 用红黑树重写cfs的队列
struct sched_queue_t sched_cfs_ready_queue; // 就绪队列
/**
* @brief
*
*/
void sched_cfs();
/**
* @brief PCB加入就绪队列
*
* @param pcb
*/
void sched_cfs_enqueue(struct process_control_block *pcb);
/**
* @brief PCB
*
* @return struct process_control_block*
*/
struct process_control_block *sched_cfs_dequeue();
/**
* @brief
*
*/
void sched_init();

View File

@ -3,7 +3,7 @@
.align 0x1000 // 4k
.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 // bsp32
movl %eax, %cr3
// enable long mode
movl $0xC0000080, %ecx
rdmsr
bts $8, %eax
wrmsr
// enable PE and paging
mov %cr0, %eax
bts $0, %eax
bts $31, %eax
mov %eax, %cr0
// 64
ljmp *(_apu_code64_vector - _apu_boot_base)(%esi)
.code64
.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

View File

@ -15,10 +15,11 @@ static struct acpi_Processor_Local_APIC_Structure_t *proc_local_apic_structs[MAX
static uint32_t total_processor_num = 0;
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,6 +89,7 @@ void smp_init()
*/
void smp_ap_start()
{
// 切换栈基地址
// 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)
@ -78,15 +102,18 @@ void smp_ap_start()
__asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(stack_start)
: "memory");*/
ksuccess("AP core successfully started!");
++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);
kdebug("IDT_addr = %#018lx", phys_2_virt(IDT_Table));
spin_unlock(&multi_core_starting_lock);
while (1) // 这里要循环hlt原因是当收到中断后核心会被唤醒处理完中断之后不会自动hlt
hlt();
}

View File

@ -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减去相应的数值

2
run.sh
View File

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