mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +00:00
bug: AP处理器发生异常时无法正确处理
This commit is contained in:
parent
5ea38e3b53
commit
32b8a163bb
@ -2,7 +2,7 @@
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
#define CPU_NUM 8
|
||||
#define MAX_CPU_NUM 32 // 操作系统支持的最大处理器数量
|
||||
|
||||
// cpu支持的最大cpuid指令的基础主功能号
|
||||
uint Cpu_cpuid_max_Basic_mop;
|
||||
@ -53,3 +53,9 @@ void cpu_cpuid(uint mop, uint sop, uint *eax, uint*ebx, uint*ecx, uint*edx)
|
||||
*
|
||||
*/
|
||||
void cpu_init(void);
|
||||
|
||||
struct cpu_core_info
|
||||
{
|
||||
uint64_t stack_start; // 栈基地址
|
||||
uint64_t tss_vaddr; // tss地址
|
||||
}cpu_core_info[MAX_CPU_NUM];
|
@ -16,6 +16,7 @@
|
||||
#define cli() __asm__ __volatile__("cli\n\t" :: \
|
||||
: "memory") //关闭外部中断
|
||||
#define nop() __asm__ __volatile__("nop\n\t")
|
||||
#define hlt() __asm__ __volatile__("hlt\n\t")
|
||||
|
||||
//内存屏障
|
||||
#define io_mfence() __asm__ __volatile__("mfence\n\t" :: \
|
||||
|
@ -80,7 +80,7 @@ bool acpi_get_MADT(const struct acpi_system_description_table_header_t *_iter_da
|
||||
//*(struct acpi_Multiple_APIC_Description_Table_t *)_data = *(struct acpi_Multiple_APIC_Description_Table_t *)_iter_data;
|
||||
// 返回MADT的虚拟地址
|
||||
*(ul *)_data = (ul)_iter_data;
|
||||
acpi_madt_vaddr = _iter_data;
|
||||
acpi_madt_vaddr = (ul)_iter_data;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,46 @@ void apic_io_apic_init()
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化AP处理器的Local apic
|
||||
*
|
||||
*/
|
||||
void apic_init_ap_core_local_apic()
|
||||
{
|
||||
kinfo("Initializing AP-core's local apic...");
|
||||
uint eax, edx;
|
||||
// 启用xAPIC 和x2APIC
|
||||
__asm__ __volatile__("movq $0x1b, %%rcx \n\t" // 读取IA32_APIC_BASE寄存器
|
||||
"rdmsr \n\t"
|
||||
"bts $10, %%rax \n\t"
|
||||
"bts $11, %%rax \n\t"
|
||||
"wrmsr \n\t"
|
||||
"movq $0x1b, %%rcx \n\t"
|
||||
"rdmsr \n\t"
|
||||
: "=a"(eax), "=d"(edx)::"memory");
|
||||
|
||||
// kdebug("After enable xAPIC and x2APIC: edx=%#010x, eax=%#010x", edx, eax);
|
||||
|
||||
// 检测是否成功启用xAPIC和x2APIC
|
||||
if (eax & 0xc00)
|
||||
kinfo("xAPIC & x2APIC enabled!");
|
||||
// 设置SVR寄存器,开启local APIC、禁止EOI广播
|
||||
|
||||
__asm__ __volatile__("movq $0x80f, %%rcx \n\t"
|
||||
"rdmsr \n\t"
|
||||
"bts $8, %%rax \n\t"
|
||||
"bts $12, %%rax \n\t"
|
||||
"movq $0x80f, %%rcx \n\t"
|
||||
"wrmsr \n\t"
|
||||
"movq $0x80f , %%rcx \n\t"
|
||||
"rdmsr \n\t"
|
||||
: "=a"(eax), "=d"(edx)::"memory", "rcx");
|
||||
|
||||
if (eax & 0x100)
|
||||
kinfo("APIC Software Enabled.");
|
||||
if (eax & 0x1000)
|
||||
kinfo("EOI-Broadcast Suppression Enabled.");
|
||||
}
|
||||
/**
|
||||
* @brief 初始化local apic
|
||||
*
|
||||
@ -114,7 +154,7 @@ void apic_local_apic_init()
|
||||
|
||||
cpu_cpuid(1, 0, &a, &b, &c, &d);
|
||||
|
||||
//kdebug("CPUID 0x01, eax:%#010lx, ebx:%#010lx, ecx:%#010lx, edx:%#010lx", a, b, c, d);
|
||||
// kdebug("CPUID 0x01, eax:%#010lx, ebx:%#010lx, ecx:%#010lx, edx:%#010lx", a, b, c, d);
|
||||
|
||||
// 判断是否支持APIC和xAPIC
|
||||
if ((1 << 9) & d)
|
||||
@ -152,7 +192,7 @@ void apic_local_apic_init()
|
||||
"rdmsr \n\t"
|
||||
: "=a"(eax), "=d"(edx)::"memory");
|
||||
|
||||
//kdebug("After enable xAPIC and x2APIC: edx=%#010x, eax=%#010x", edx, eax);
|
||||
// kdebug("After enable xAPIC and x2APIC: edx=%#010x, eax=%#010x", edx, eax);
|
||||
|
||||
// 检测是否成功启用xAPIC和x2APIC
|
||||
if (eax & 0xc00)
|
||||
@ -174,7 +214,7 @@ void apic_local_apic_init()
|
||||
__asm__ __volatile__("movq $0x80f, %%rcx \n\t"
|
||||
"rdmsr \n\t"
|
||||
"bts $8, %%rax \n\t"
|
||||
"bts $12, %%rax \n\t"
|
||||
// "bts $12, %%rax \n\t"
|
||||
"movq $0x80f, %%rcx \n\t"
|
||||
"wrmsr \n\t"
|
||||
"movq $0x80f , %%rcx \n\t"
|
||||
@ -194,7 +234,7 @@ void apic_local_apic_init()
|
||||
:
|
||||
:"memory");
|
||||
*/
|
||||
//kdebug("After setting SVR: edx=%#010x, eax=%#010x", edx, eax);
|
||||
// kdebug("After setting SVR: edx=%#010x, eax=%#010x", edx, eax);
|
||||
|
||||
if (eax & 0x100)
|
||||
kinfo("APIC Software Enabled.");
|
||||
@ -205,12 +245,13 @@ void apic_local_apic_init()
|
||||
// Table 10-6. Local APIC Register Address Map Supported by x2APIC
|
||||
// 获取 Local APIC ID
|
||||
// 0x802处是x2APIC ID 位宽32bits 的 Local APIC ID register
|
||||
/*
|
||||
__asm__ __volatile__("movq $0x802, %%rcx \n\t"
|
||||
"rdmsr \n\t"
|
||||
: "=a"(eax), "=d"(edx)::"memory");
|
||||
|
||||
//kdebug("get Local APIC ID: edx=%#010x, eax=%#010x", edx, eax);
|
||||
//kdebug("local_apic_id=%#018lx", *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_ID));
|
||||
*/
|
||||
// kdebug("get Local APIC ID: edx=%#010x, eax=%#010x", edx, eax);
|
||||
// kdebug("local_apic_id=%#018lx", *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_ID));
|
||||
|
||||
// 获取Local APIC Version
|
||||
// 0x803处是 Local APIC Version register
|
||||
|
@ -269,6 +269,13 @@ ul apic_ioapic_read_rte(unsigned char index);
|
||||
*/
|
||||
void apic_ioapic_write_rte(unsigned char index, ul value);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始化AP处理器的Local apic
|
||||
*
|
||||
*/
|
||||
void apic_init_ap_core_local_apic();
|
||||
|
||||
/**
|
||||
* @brief 初始化apic控制器
|
||||
*
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @author longjin
|
||||
* @brief 门定义
|
||||
* @date 2022-01-24
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -20,11 +20,10 @@ struct gate_struct
|
||||
unsigned char x[16];
|
||||
};
|
||||
|
||||
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 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];
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始化中段描述符表内的门描述符(每个16B)
|
||||
* @param gate_selector_addr IDT表项的地址
|
||||
@ -35,7 +34,7 @@ extern unsigned int TSS64_Table[26];
|
||||
|
||||
void set_gate(ul *gate_selector_addr, ul attr, unsigned char ist, ul *code_addr)
|
||||
{
|
||||
ul __d0=0, __d1=0;
|
||||
ul __d0 = 0, __d1 = 0;
|
||||
ul tmp_code_addr = *code_addr;
|
||||
__d0 = attr << 40; //设置P、DPL、Type
|
||||
|
||||
@ -52,14 +51,16 @@ void set_gate(ul *gate_selector_addr, ul attr, unsigned char ist, ul *code_addr)
|
||||
|
||||
__d1 = (0xffffffff & tmp_code_addr); //设置段内偏移[63:32]
|
||||
|
||||
|
||||
*gate_selector_addr = __d0;
|
||||
*(gate_selector_addr + 1) = __d1;
|
||||
}
|
||||
|
||||
void set_tss_descriptor(unsigned int n, void *addr)
|
||||
{
|
||||
|
||||
|
||||
|
||||
*(unsigned long *)(GDT_Table + n) = (103UL & 0xffff) | (((unsigned long)addr & 0xffff) << 16) | (((unsigned long)addr >> 16 & 0xff) << 32) | ((unsigned long)0x89 << 40) | ((103UL >> 16 & 0xf) << 48) | (((unsigned long)addr >> 24 & 0xff) << 56); /////89 is attribute
|
||||
*(unsigned long *)(GDT_Table + n + 1) = ((unsigned long)addr >> 32 & 0xffffffff) | 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 加载任务状态段寄存器
|
||||
@ -69,48 +70,48 @@ void set_gate(ul *gate_selector_addr, ul attr, unsigned char ist, ul *code_addr)
|
||||
#define load_TR(n) \
|
||||
do \
|
||||
{ \
|
||||
__asm__ __volatile__("ltr %%ax" ::"a"(n << 3)); \
|
||||
__asm__ __volatile__("ltr %%ax" ::"a"((n)<< 3)); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 设置中断门
|
||||
*
|
||||
*
|
||||
* @param n 中断号
|
||||
* @param ist ist
|
||||
* @param addr 服务程序的地址
|
||||
*/
|
||||
void set_intr_gate(unsigned int n, unsigned char ist, void *addr)
|
||||
{
|
||||
set_gate((ul*)(IDT_Table + n), 0x8E, ist, (ul*)(&addr)); // p=1,DPL=0, type=E
|
||||
set_gate((ul *)(IDT_Table + n), 0x8E, ist, (ul *)(&addr)); // p=1,DPL=0, type=E
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置64位,DPL=0的陷阱门
|
||||
*
|
||||
*
|
||||
* @param n 中断号
|
||||
* @param ist ist
|
||||
* @param addr 服务程序的地址
|
||||
*/
|
||||
void set_trap_gate(unsigned int n, unsigned char ist, void *addr)
|
||||
{
|
||||
set_gate((ul*)(IDT_Table + n), 0x8F, ist, (ul*)(&addr)); // p=1,DPL=0, type=F
|
||||
set_gate((ul *)(IDT_Table + n), 0x8F, ist, (ul *)(&addr)); // p=1,DPL=0, type=F
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置64位,DPL=3的陷阱门
|
||||
*
|
||||
*
|
||||
* @param n 中断号
|
||||
* @param ist ist
|
||||
* @param addr 服务程序的地址
|
||||
*/
|
||||
void set_system_trap_gate(unsigned int n, unsigned char ist, void *addr)
|
||||
{
|
||||
set_gate((ul*)(IDT_Table + n), 0xEF, ist, (ul*)(&addr)); // p=1,DPL=3, type=F
|
||||
set_gate((ul *)(IDT_Table + n), 0xEF, ist, (ul *)(&addr)); // p=1,DPL=3, type=F
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化TSS表的内容
|
||||
*
|
||||
*
|
||||
*/
|
||||
void set_TSS64(ul rsp0, ul rsp1, ul rsp2, ul ist1, ul ist2, ul ist3, ul ist4, ul ist5, ul ist6, ul ist7)
|
||||
{
|
||||
|
@ -381,7 +381,7 @@ switch_seg:
|
||||
|
||||
.quad entry64
|
||||
|
||||
.global entry64
|
||||
|
||||
entry64:
|
||||
|
||||
movq $0x10, %rax
|
||||
@ -590,7 +590,7 @@ GDT_Table:
|
||||
.quad 0x0000f20000000000 // 6 用户64位数据段描述符 0x30
|
||||
.quad 0x00cf9a000000ffff // 7 内核32位代码段描述符 0x38
|
||||
.quad 0x00cf92000000ffff // 8 内核32位数据段描述符 0x40
|
||||
.fill 10, 8, 0 // 10-11 TSS(跳过了第9段) 重复十次填充8字节的空间,赋值为0
|
||||
.fill 100, 8, 0 // 10-11 TSS(跳过了第9段) 重复十次填充8字节的空间,赋值为0 长模式下,每个TSS长度为128bit
|
||||
GDT_END:
|
||||
|
||||
GDT_POINTER:
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mm/slab.h"
|
||||
#include "process/process.h"
|
||||
#include "syscall/syscall.h"
|
||||
#include "smp/smp.h"
|
||||
|
||||
#include "driver/multiboot2/multiboot2.h"
|
||||
#include "driver/acpi/acpi.h"
|
||||
@ -148,9 +149,12 @@ void system_initialize()
|
||||
load_TR(10); // 加载TR寄存器
|
||||
ul tss_item_addr = 0x7c00;
|
||||
|
||||
set_TSS64(_stack_start, _stack_start, _stack_start, tss_item_addr, tss_item_addr,
|
||||
set_TSS64((ul)TSS64_Table, _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 = (ul)TSS64_Table;
|
||||
|
||||
// 初始化中断描述符表
|
||||
sys_vector_init();
|
||||
|
||||
@ -161,6 +165,9 @@ void system_initialize()
|
||||
// 初始化中断模块
|
||||
irq_init();
|
||||
|
||||
smp_init();
|
||||
|
||||
hlt();
|
||||
// 先初始化系统调用模块
|
||||
syscall_init();
|
||||
|
||||
@ -170,13 +177,13 @@ void system_initialize()
|
||||
// ata_init();
|
||||
pci_init();
|
||||
ahci_init();
|
||||
|
||||
smp_init();
|
||||
|
||||
// test_slab();
|
||||
// test_mm();
|
||||
|
||||
// 再初始化进程模块。顺序不能调转
|
||||
// process_init();
|
||||
|
||||
}
|
||||
|
||||
//操作系统内核从这里开始执行
|
||||
|
@ -154,7 +154,7 @@ struct thread_struct initial_thread;
|
||||
// 初始化 初始进程的union ,并将其链接到.data.init_proc段内
|
||||
union proc_union initial_proc_union __attribute__((__section__(".data.init_proc_union"))) = {INITIAL_PROC(initial_proc_union.pcb)};
|
||||
|
||||
struct process_control_block *initial_proc[CPU_NUM] = {&initial_proc_union.pcb, 0};
|
||||
struct process_control_block *initial_proc[MAX_CPU_NUM] = {&initial_proc_union.pcb, 0};
|
||||
|
||||
struct mm_struct initial_mm = {0};
|
||||
struct thread_struct initial_thread =
|
||||
@ -211,7 +211,7 @@ struct tss_struct
|
||||
.io_map_base_addr = 0 \
|
||||
}
|
||||
// 为每个核心初始化初始进程的tss
|
||||
struct tss_struct initial_tss[CPU_NUM] = {[0 ... CPU_NUM - 1] = INITIAL_TSS};
|
||||
struct tss_struct initial_tss[MAX_CPU_NUM] = {[0 ... MAX_CPU_NUM - 1] = INITIAL_TSS};
|
||||
|
||||
// 获取当前的pcb
|
||||
struct process_control_block *get_current_pcb()
|
||||
|
@ -1,11 +1,14 @@
|
||||
#include "smp.h"
|
||||
#include "../common/kprint.h"
|
||||
#include "../driver/interrupt/apic/apic.h"
|
||||
|
||||
extern void apic_local_apic_init();
|
||||
#include "../exception/gate.h"
|
||||
#include "../common/cpu.h"
|
||||
#include "../mm/slab.h"
|
||||
#include "../process/process.h"
|
||||
|
||||
static struct acpi_Processor_Local_APIC_Structure_t *proc_local_apic_structs[MAX_SUPPORTED_PROCESSOR_NUM];
|
||||
static uint32_t total_processor_num = 0;
|
||||
int current_starting_cpu = 0;
|
||||
|
||||
void smp_init()
|
||||
{
|
||||
@ -17,31 +20,57 @@ void smp_init()
|
||||
for (int i = 0; i < total_processor_num; ++i)
|
||||
proc_local_apic_structs[i] = (struct acpi_Processor_Local_APIC_Structure_t *)(tmp_vaddr[i]);
|
||||
|
||||
for (int i = 0; i < total_processor_num; ++i)
|
||||
{
|
||||
kdebug("[core %d] acpi processor UID=%d, APIC ID=%d, flags=%#010lx", i, proc_local_apic_structs[i]->ACPI_Processor_UID, proc_local_apic_structs[i]->ACPI_ID, proc_local_apic_structs[i]->flags);
|
||||
}
|
||||
|
||||
//*(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);
|
||||
wrmsr(0x830, 0xc4500); // init IPI
|
||||
|
||||
// 先init ipi, 然后连续发送两次start-up IPI
|
||||
// x2APIC下,ICR寄存器地址为0x830
|
||||
// xAPIC下则为0xfee00300(31-0) 0xfee00310 (63-32)
|
||||
wrmsr(0x830, 0xc4500); // init IPI
|
||||
wrmsr(0x830, 0xc4620); // start-up IPI
|
||||
wrmsr(0x830, 0xc4620); // start-up IPI
|
||||
struct INT_CMD_REG icr_entry;
|
||||
icr_entry.dest_mode = DEST_PHYSICAL;
|
||||
icr_entry.deliver_status = IDLE;
|
||||
icr_entry.res_1 = 0;
|
||||
icr_entry.level = ICR_LEVEL_DE_ASSERT;
|
||||
icr_entry.trigger = EDGE_TRIGGER;
|
||||
icr_entry.res_2 = 0;
|
||||
icr_entry.res_3 = 0;
|
||||
|
||||
for (int i = 1; i < total_processor_num; ++i) // i从1开始,不初始化bsp
|
||||
{
|
||||
current_starting_cpu = i;
|
||||
kdebug("[core %d] acpi processor UID=%d, APIC ID=%d, flags=%#010lx", i, proc_local_apic_structs[i]->ACPI_Processor_UID, proc_local_apic_structs[i]->ACPI_ID, proc_local_apic_structs[i]->flags);
|
||||
// 为每个AP处理器分配栈空间、tss空间
|
||||
cpu_core_info[i].stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE;
|
||||
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_TSS64(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);
|
||||
kdebug("GDT Table %#018lx, \t %#018lx", GDT_Table[10 + i * 2], GDT_Table[10 + i * 2 + 1]);
|
||||
|
||||
icr_entry.vector = 0x20;
|
||||
icr_entry.deliver_mode = ICR_Start_up;
|
||||
icr_entry.dest_shorthand = ICR_No_Shorthand;
|
||||
icr_entry.destination.x2apic_destination = current_starting_cpu;
|
||||
|
||||
// 先init ipi, 然后连续发送两次start-up IPI
|
||||
// x2APIC下,ICR寄存器地址为0x830
|
||||
// xAPIC下则为0xfee00300(31-0) 0xfee00310 (63-32)
|
||||
|
||||
wrmsr(0x830, *(ul *)&icr_entry); // start-up IPI
|
||||
wrmsr(0x830, *(ul *)&icr_entry); // start-up IPI
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief AP处理器启动后执行的第一个函数
|
||||
*
|
||||
*
|
||||
*/
|
||||
void smp_ap_start()
|
||||
{
|
||||
ksuccess("AP core successfully started!");
|
||||
kinfo("Initializing AP's local apic...");
|
||||
apic_local_apic_init();
|
||||
while(1);
|
||||
kdebug("current=%d", current_starting_cpu);
|
||||
load_TR(10 + current_starting_cpu * 2);
|
||||
apic_init_ap_core_local_apic();
|
||||
int a =1/0; // 在这儿会出现异常,cs fs gs ss寄存器会被改变
|
||||
|
||||
hlt();
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
#include "../driver/acpi/acpi.h"
|
||||
#include "../driver/interrupt/apic/apic.h"
|
||||
|
||||
#define MAX_SUPPORTED_PROCESSOR_NUM 1024 // 操作系统支持的最大处理器数量
|
||||
#define MAX_SUPPORTED_PROCESSOR_NUM 1024
|
||||
|
||||
extern uchar _apu_boot_start[];
|
||||
extern uchar _apu_boot_end[];
|
||||
|
2
run.sh
2
run.sh
@ -93,7 +93,7 @@ if [ $flag_can_run -eq 1 ]; then
|
||||
bochs -q -f ${bochsrc} -rc ./tools/bochsinit
|
||||
else
|
||||
qemu-system-x86_64 -cdrom ${iso} -m 512M -smp 2,cores=2,threads=1,sockets=1 \
|
||||
-monitor stdio -s -S -cpu IvyBridge --enable-kvm \
|
||||
-monitor stdio -d cpu_reset,guest_errors -s -S -cpu IvyBridge --enable-kvm \
|
||||
-drive id=disk,file=bin/disk.img,if=none \
|
||||
-device ahci,id=ahci \
|
||||
-device ide-hd,drive=disk,bus=ahci.0 \
|
||||
|
Loading…
x
Reference in New Issue
Block a user