bug: AP处理器发生异常时无法正确处理

This commit is contained in:
fslongjin 2022-04-05 14:40:26 +08:00
parent 5ea38e3b53
commit 32b8a163bb
12 changed files with 143 additions and 51 deletions

View File

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

View File

@ -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" :: \

View File

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

View File

@ -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
*
@ -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"
@ -205,10 +245,11 @@ 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));

View File

@ -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控制器
*

View File

@ -24,7 +24,6 @@ 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表项的地址
@ -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,7 +70,7 @@ 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)
/**

View File

@ -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) 80
.fill 100, 8, 0 // 10-11 TSS(9) 80 TSS128bit
GDT_END:
GDT_POINTER:

View File

@ -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();
@ -171,12 +178,12 @@ void system_initialize()
pci_init();
ahci_init();
smp_init();
// test_slab();
// test_mm();
// 再初始化进程模块。顺序不能调转
// process_init();
}
//操作系统内核从这里开始执行

View File

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

View File

@ -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,21 +20,44 @@ 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
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, 0xc4500); // init IPI
wrmsr(0x830, 0xc4620); // start-up IPI
wrmsr(0x830, 0xc4620); // start-up IPI
wrmsr(0x830, *(ul *)&icr_entry); // start-up IPI
wrmsr(0x830, *(ul *)&icr_entry); // start-up IPI
}
}
/**
@ -41,7 +67,10 @@ void smp_init()
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();
}

View File

@ -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
View File

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