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

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

@ -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=1DPL=0, type=E
set_gate((ul *)(IDT_Table + n), 0x8E, ist, (ul *)(&addr)); // p=1DPL=0, type=E
}
/**
* @brief 64DPL=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=1DPL=0, type=F
set_gate((ul *)(IDT_Table + n), 0x8F, ist, (ul *)(&addr)); // p=1DPL=0, type=F
}
/**
* @brief 64DPL=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=1DPL=3, type=F
set_gate((ul *)(IDT_Table + n), 0xEF, ist, (ul *)(&addr)); // p=1DPL=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)
{

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();
@ -170,13 +177,13 @@ void system_initialize()
// ata_init();
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,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();
}

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 \